Skip to content

Commit bc720a4

Browse files
authored
Allow specifying the return type on Update (#345)
* updateDocument with different return type * updateDocuments with different return type
1 parent 5769303 commit bc720a4

File tree

7 files changed

+213
-25
lines changed

7 files changed

+213
-25
lines changed

src/main/java/com/arangodb/ArangoCollection.java

+34
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,23 @@ <T> MultiDocumentEntity<DocumentUpdateEntity<T>> replaceDocuments(
271271
<T> DocumentUpdateEntity<T> updateDocument(String key, T value, DocumentUpdateOptions options)
272272
throws ArangoDBException;
273273

274+
/**
275+
* Partially updates the document identified by document-key. The value must contain a document with the attributes
276+
* to patch (the patch document). All attributes from the patch document will be added to the existing document if
277+
* they do not yet exist, and overwritten in the existing document if they do exist there.
278+
*
279+
* @param key The key of the document
280+
* @param value A representation of a single document (POJO, VPackSlice or String for JSON)
281+
* @param options Additional options, can be null
282+
* @param returnType Type of the returned newDocument and/or oldDocument
283+
* @return information about the document
284+
* @throws ArangoDBException
285+
* @see <a href="https://www.arangodb.com/docs/stable/http/document-working-with-documents.html#update-document">API
286+
* Documentation</a>
287+
*/
288+
<T, U> DocumentUpdateEntity<U> updateDocument(String key, T value, DocumentUpdateOptions options, Class<U> returnType)
289+
throws ArangoDBException;
290+
274291
/**
275292
* Partially updates documents, the documents to update are specified by the _key attributes in the objects on
276293
* values. Vales must contain a list of document updates with the attributes to patch (the patch documents). All
@@ -301,6 +318,23 @@ <T> DocumentUpdateEntity<T> updateDocument(String key, T value, DocumentUpdateOp
301318
<T> MultiDocumentEntity<DocumentUpdateEntity<T>> updateDocuments(
302319
Collection<T> values, DocumentUpdateOptions options) throws ArangoDBException;
303320

321+
/**
322+
* Partially updates documents, the documents to update are specified by the _key attributes in the objects on
323+
* values. Vales must contain a list of document updates with the attributes to patch (the patch documents). All
324+
* attributes from the patch documents will be added to the existing documents if they do not yet exist, and
325+
* overwritten in the existing documents if they do exist there.
326+
*
327+
* @param values A list of documents (POJO, VPackSlice or String for JSON)
328+
* @param options Additional options, can be null
329+
* @param returnType Type of the returned newDocument and/or oldDocument
330+
* @return information about the documents
331+
* @throws ArangoDBException
332+
* @see <a href="https://www.arangodb.com/docs/stable/http/document-working-with-documents.html#update-documents">API
333+
* Documentation</a>
334+
*/
335+
<T, U> MultiDocumentEntity<DocumentUpdateEntity<U>> updateDocuments(
336+
Collection<T> values, DocumentUpdateOptions options, Class<U> returnType) throws ArangoDBException;
337+
304338
/**
305339
* Deletes the document with the given {@code key} from the collection.
306340
*

src/main/java/com/arangodb/async/ArangoCollectionAsync.java

+37
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,25 @@ <T> CompletableFuture<DocumentUpdateEntity<T>> updateDocument(
265265
final T value,
266266
final DocumentUpdateOptions options);
267267

268+
/**
269+
* Partially updates the document identified by document-key. The value must contain a document with the attributes
270+
* to patch (the patch document). All attributes from the patch document will be added to the existing document if
271+
* they do not yet exist, and overwritten in the existing document if they do exist there.
272+
*
273+
* @param key The key of the document
274+
* @param value A representation of a single document (POJO, VPackSlice or String for Json)
275+
* @param options Additional options, can be null
276+
* @param returnType Type of the returned newDocument and/or oldDocument
277+
* @return information about the document
278+
* @see <a href="https://www.arangodb.com/docs/stable/http/document-working-with-documents.html#update-document">API
279+
* Documentation</a>
280+
*/
281+
<T, U> CompletableFuture<DocumentUpdateEntity<U>> updateDocument(
282+
final String key,
283+
final T value,
284+
final DocumentUpdateOptions options,
285+
final Class<U> returnType);
286+
268287
/**
269288
* Partially updates documents, the documents to update are specified by the _key attributes in the objects on
270289
* values. Vales must contain a list of document updates with the attributes to patch (the patch documents). All
@@ -294,6 +313,24 @@ <T> CompletableFuture<MultiDocumentEntity<DocumentUpdateEntity<T>>> updateDocume
294313
final Collection<T> values,
295314
final DocumentUpdateOptions options);
296315

316+
/**
317+
* Partially updates documents, the documents to update are specified by the _key attributes in the objects on
318+
* values. Vales must contain a list of document updates with the attributes to patch (the patch documents). All
319+
* attributes from the patch documents will be added to the existing documents if they do not yet exist, and
320+
* overwritten in the existing documents if they do exist there.
321+
*
322+
* @param values A list of documents (POJO, VPackSlice or String for Json)
323+
* @param options Additional options, can be null
324+
* @param returnType Type of the returned newDocument and/or oldDocument
325+
* @return information about the documents
326+
* @see <a href="https://www.arangodb.com/docs/stable/http/document-working-with-documents.html#update-documents">API
327+
* Documentation</a>
328+
*/
329+
<T, U> CompletableFuture<MultiDocumentEntity<DocumentUpdateEntity<U>>> updateDocuments(
330+
final Collection<T> values,
331+
final DocumentUpdateOptions options,
332+
final Class<U> returnType);
333+
297334
/**
298335
* Removes a document
299336
*

src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java

+21-8
Original file line numberDiff line numberDiff line change
@@ -167,35 +167,48 @@ public <T> CompletableFuture<MultiDocumentEntity<DocumentUpdateEntity<T>>> repla
167167

168168
@Override
169169
public <T> CompletableFuture<DocumentUpdateEntity<T>> updateDocument(final String key, final T value) {
170-
final DocumentUpdateOptions options = new DocumentUpdateOptions();
171-
return executor.execute(updateDocumentRequest(key, value, options),
172-
updateDocumentResponseDeserializer(value, options));
170+
return updateDocument(key, value, new DocumentUpdateOptions());
173171
}
174172

175173
@Override
176174
public <T> CompletableFuture<DocumentUpdateEntity<T>> updateDocument(
177175
final String key,
178176
final T value,
179177
final DocumentUpdateOptions options) {
178+
return updateDocument(key, value, options, (Class<T>) value.getClass());
179+
}
180+
181+
@Override
182+
public <T, U> CompletableFuture<DocumentUpdateEntity<U>> updateDocument(
183+
final String key,
184+
final T value,
185+
final DocumentUpdateOptions options,
186+
final Class<U> returnType) {
180187
return executor.execute(updateDocumentRequest(key, value, options),
181-
updateDocumentResponseDeserializer(value, options));
188+
updateDocumentResponseDeserializer(value, options, returnType));
182189
}
183190

184191
@Override
185192
public <T> CompletableFuture<MultiDocumentEntity<DocumentUpdateEntity<T>>> updateDocuments(
186193
final Collection<T> values) {
187-
final DocumentUpdateOptions params = new DocumentUpdateOptions();
188-
return executor.execute(updateDocumentsRequest(values, params),
189-
updateDocumentsResponseDeserializer(values, params));
194+
return updateDocuments(values, new DocumentUpdateOptions());
190195
}
191196

192197
@Override
193198
public <T> CompletableFuture<MultiDocumentEntity<DocumentUpdateEntity<T>>> updateDocuments(
194199
final Collection<T> values,
195200
final DocumentUpdateOptions options) {
201+
return updateDocuments(values, options, values.isEmpty() ? null : (Class<T>) values.iterator().next().getClass());
202+
}
203+
204+
@Override
205+
public <T, U> CompletableFuture<MultiDocumentEntity<DocumentUpdateEntity<U>>> updateDocuments(
206+
final Collection<T> values,
207+
final DocumentUpdateOptions options,
208+
final Class<U> returnType) {
196209
final DocumentUpdateOptions params = (options != null ? options : new DocumentUpdateOptions());
197210
return executor.execute(updateDocumentsRequest(values, params),
198-
updateDocumentsResponseDeserializer(values, params));
211+
updateDocumentsResponseDeserializer(returnType));
199212
}
200213

201214
@Override

src/main/java/com/arangodb/internal/ArangoCollectionImpl.java

+14-2
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,14 @@ public <T> DocumentUpdateEntity<T> updateDocument(final String key, final T valu
168168
@Override
169169
public <T> DocumentUpdateEntity<T> updateDocument(
170170
final String key, final T value, final DocumentUpdateOptions options) throws ArangoDBException {
171+
return updateDocument(key, value, options, (Class<T>) value.getClass());
172+
}
173+
174+
@Override
175+
public <T, U> DocumentUpdateEntity<U> updateDocument(
176+
final String key, final T value, final DocumentUpdateOptions options, final Class<U> returnType) throws ArangoDBException {
171177
return executor.execute(updateDocumentRequest(key, value, options),
172-
updateDocumentResponseDeserializer(value, options));
178+
updateDocumentResponseDeserializer(value, options, returnType));
173179
}
174180

175181
@Override
@@ -181,9 +187,15 @@ public <T> MultiDocumentEntity<DocumentUpdateEntity<T>> updateDocuments(final Co
181187
@Override
182188
public <T> MultiDocumentEntity<DocumentUpdateEntity<T>> updateDocuments(
183189
final Collection<T> values, final DocumentUpdateOptions options) throws ArangoDBException {
190+
return updateDocuments(values, options, values.isEmpty() ? null : (Class<T>) values.iterator().next().getClass());
191+
}
192+
193+
@Override
194+
public <T, U> MultiDocumentEntity<DocumentUpdateEntity<U>> updateDocuments(
195+
final Collection<T> values, final DocumentUpdateOptions options, final Class<U> returnType) throws ArangoDBException {
184196
final DocumentUpdateOptions params = (options != null ? options : new DocumentUpdateOptions());
185197
return executor
186-
.execute(updateDocumentsRequest(values, params), updateDocumentsResponseDeserializer(values, params));
198+
.execute(updateDocumentsRequest(values, params), updateDocumentsResponseDeserializer(returnType));
187199
}
188200

189201
@Override

src/main/java/com/arangodb/internal/InternalArangoCollection.java

+8-14
Original file line numberDiff line numberDiff line change
@@ -357,18 +357,18 @@ protected <T> Request updateDocumentRequest(final String key, final T value, fin
357357
return request;
358358
}
359359

360-
protected <T> ResponseDeserializer<DocumentUpdateEntity<T>> updateDocumentResponseDeserializer(
361-
final T value, final DocumentUpdateOptions options) {
360+
protected <T, U> ResponseDeserializer<DocumentUpdateEntity<U>> updateDocumentResponseDeserializer(
361+
final T value, final DocumentUpdateOptions options, final Class<U> returnType) {
362362
return response -> {
363363
final VPackSlice body = response.getBody();
364-
final DocumentUpdateEntity<T> doc = util().deserialize(body, DocumentUpdateEntity.class);
364+
final DocumentUpdateEntity<U> doc = util().deserialize(body, DocumentUpdateEntity.class);
365365
final VPackSlice newDoc = body.get(NEW);
366366
if (newDoc.isObject()) {
367-
doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, value.getClass()));
367+
doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, returnType));
368368
}
369369
final VPackSlice oldDoc = body.get(OLD);
370370
if (oldDoc.isObject()) {
371-
doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, value.getClass()));
371+
doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, returnType));
372372
}
373373
if (options == null || Boolean.TRUE != options.getSilent()) {
374374
final Map<DocumentField.Type, String> values = new HashMap<>();
@@ -399,14 +399,8 @@ protected <T> Request updateDocumentsRequest(final Collection<T> values, final D
399399

400400
@SuppressWarnings("unchecked")
401401
protected <T> ResponseDeserializer<MultiDocumentEntity<DocumentUpdateEntity<T>>> updateDocumentsResponseDeserializer(
402-
final Collection<T> values, final DocumentUpdateOptions params) {
402+
final Class<T> returnType) {
403403
return response -> {
404-
Class<T> type = null;
405-
if (Boolean.TRUE == params.getReturnNew() || Boolean.TRUE == params.getReturnOld()) {
406-
if (!values.isEmpty()) {
407-
type = (Class<T>) values.iterator().next().getClass();
408-
}
409-
}
410404
final MultiDocumentEntity<DocumentUpdateEntity<T>> multiDocument = new MultiDocumentEntity<>();
411405
final Collection<DocumentUpdateEntity<T>> docs = new ArrayList<>();
412406
final Collection<ErrorEntity> errors = new ArrayList<>();
@@ -423,11 +417,11 @@ protected <T> ResponseDeserializer<MultiDocumentEntity<DocumentUpdateEntity<T>>>
423417
final DocumentUpdateEntity<T> doc = util().deserialize(next, DocumentUpdateEntity.class);
424418
final VPackSlice newDoc = next.get(NEW);
425419
if (newDoc.isObject()) {
426-
doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, type));
420+
doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, returnType));
427421
}
428422
final VPackSlice oldDoc = next.get(OLD);
429423
if (oldDoc.isObject()) {
430-
doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, type));
424+
doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, returnType));
431425
}
432426
docs.add(doc);
433427
documentsAndErrors.add(doc);

src/test/java/com/arangodb/ArangoCollectionTest.java

+47
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,23 @@ public void updateDocument() {
435435
assertThat(readResult.getProperties().keySet(), hasItem("c"));
436436
}
437437

438+
@Test
439+
public void updateDocumentWithDifferentReturnType() {
440+
final String key = "key-" + UUID.randomUUID().toString();
441+
final BaseDocument doc = new BaseDocument(key);
442+
doc.addAttribute("a", "test");
443+
collection.insertDocument(doc);
444+
445+
final DocumentUpdateEntity<BaseDocument> updateResult = collection
446+
.updateDocument(key, Collections.singletonMap("b", "test"), new DocumentUpdateOptions().returnNew(true), BaseDocument.class);
447+
assertThat(updateResult, is(notNullValue()));
448+
assertThat(updateResult.getKey(), is(key));
449+
BaseDocument updated = updateResult.getNew();
450+
assertThat(updated, is(notNullValue()));
451+
assertThat(updated.getAttribute("a"), is("test"));
452+
assertThat(updated.getAttribute("b"), is("test"));
453+
}
454+
438455
@Test
439456
public void updateDocumentUpdateRev() {
440457
final BaseDocument doc = new BaseDocument();
@@ -2194,6 +2211,36 @@ public void updateDocuments() {
21942211
assertThat(updateResult.getErrors().size(), is(0));
21952212
}
21962213

2214+
@Test
2215+
public void updateDocumentsWithDifferentReturnType() {
2216+
List<String> keys = IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID().toString()).collect(Collectors.toList());
2217+
List<BaseDocument> docs = keys.stream()
2218+
.map(BaseDocument::new)
2219+
.peek(it -> it.addAttribute("a", "test"))
2220+
.collect(Collectors.toList());
2221+
2222+
collection.insertDocuments(docs);
2223+
2224+
List<Map<String, Object>> modifiedDocs = docs.stream()
2225+
.peek(it -> it.addAttribute("b", "test"))
2226+
.map(it -> {
2227+
Map<String, Object> map = new HashMap<>();
2228+
map.put("_key", it.getKey());
2229+
map.put("a", it.getAttribute("a"));
2230+
map.put("b", it.getAttribute("b"));
2231+
return map;
2232+
})
2233+
.collect(Collectors.toList());
2234+
2235+
final MultiDocumentEntity<DocumentUpdateEntity<BaseDocument>> updateResult = collection
2236+
.updateDocuments(modifiedDocs, new DocumentUpdateOptions().returnNew(true), BaseDocument.class);
2237+
assertThat(updateResult.getDocuments().size(), is(3));
2238+
assertThat(updateResult.getErrors().size(), is(0));
2239+
assertThat(updateResult.getDocuments().stream().map(DocumentUpdateEntity::getNew)
2240+
.allMatch(it -> it.getAttribute("a").equals("test") && it.getAttribute("b").equals("test")),
2241+
is(true));
2242+
}
2243+
21972244
@Test
21982245
public void updateDocumentsOne() {
21992246
final Collection<BaseDocument> values = new ArrayList<>();

src/test/java/com/arangodb/async/ArangoCollectionTest.java

+52-1
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@
3131
import java.util.*;
3232
import java.util.concurrent.CompletableFuture;
3333
import java.util.concurrent.ExecutionException;
34+
import java.util.stream.Collectors;
35+
import java.util.stream.IntStream;
3436

3537
import static org.hamcrest.CoreMatchers.notNullValue;
36-
import static org.hamcrest.Matchers.*;
3738
import static org.hamcrest.MatcherAssert.assertThat;
39+
import static org.hamcrest.Matchers.*;
3840
import static org.junit.Assert.fail;
3941
import static org.junit.Assume.assumeTrue;
4042

@@ -284,6 +286,24 @@ public void updateDocument() throws InterruptedException, ExecutionException {
284286
assertThat(readResult.getProperties().keySet(), hasItem("c"));
285287
}
286288

289+
@Test
290+
public void updateDocumentWithDifferentReturnType() throws ExecutionException, InterruptedException {
291+
ArangoCollectionAsync collection = db.collection(COLLECTION_NAME);
292+
final String key = "key-" + UUID.randomUUID().toString();
293+
final BaseDocument doc = new BaseDocument(key);
294+
doc.addAttribute("a", "test");
295+
collection.insertDocument(doc).get();
296+
297+
final DocumentUpdateEntity<BaseDocument> updateResult = collection
298+
.updateDocument(key, Collections.singletonMap("b", "test"), new DocumentUpdateOptions().returnNew(true), BaseDocument.class).get();
299+
assertThat(updateResult, is(notNullValue()));
300+
assertThat(updateResult.getKey(), is(key));
301+
BaseDocument updated = updateResult.getNew();
302+
assertThat(updated, is(notNullValue()));
303+
assertThat(updated.getAttribute("a"), is("test"));
304+
assertThat(updated.getAttribute("b"), is("test"));
305+
}
306+
287307
@Test
288308
public void updateDocumentIfMatch() throws InterruptedException, ExecutionException {
289309
final BaseDocument doc = new BaseDocument();
@@ -1842,6 +1862,37 @@ public void updateDocuments() throws InterruptedException, ExecutionException {
18421862
.get();
18431863
}
18441864

1865+
@Test
1866+
public void updateDocumentsWithDifferentReturnType() throws ExecutionException, InterruptedException {
1867+
ArangoCollectionAsync collection = db.collection(COLLECTION_NAME);
1868+
List<String> keys = IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID().toString()).collect(Collectors.toList());
1869+
List<BaseDocument> docs = keys.stream()
1870+
.map(BaseDocument::new)
1871+
.peek(it -> it.addAttribute("a", "test"))
1872+
.collect(Collectors.toList());
1873+
1874+
collection.insertDocuments(docs).get();
1875+
1876+
List<Map<String, Object>> modifiedDocs = docs.stream()
1877+
.peek(it -> it.addAttribute("b", "test"))
1878+
.map(it -> {
1879+
Map<String, Object> map = new HashMap<>();
1880+
map.put("_key", it.getKey());
1881+
map.put("a", it.getAttribute("a"));
1882+
map.put("b", it.getAttribute("b"));
1883+
return map;
1884+
})
1885+
.collect(Collectors.toList());
1886+
1887+
final MultiDocumentEntity<DocumentUpdateEntity<BaseDocument>> updateResult = collection
1888+
.updateDocuments(modifiedDocs, new DocumentUpdateOptions().returnNew(true), BaseDocument.class).get();
1889+
assertThat(updateResult.getDocuments().size(), is(3));
1890+
assertThat(updateResult.getErrors().size(), is(0));
1891+
assertThat(updateResult.getDocuments().stream().map(DocumentUpdateEntity::getNew)
1892+
.allMatch(it -> it.getAttribute("a").equals("test") && it.getAttribute("b").equals("test")),
1893+
is(true));
1894+
}
1895+
18451896
@Test
18461897
public void updateDocumentsOne() throws InterruptedException, ExecutionException {
18471898
final Collection<BaseDocument> values = new ArrayList<>();

0 commit comments

Comments
 (0)