Skip to content

Commit b86f1c5

Browse files
committed
[DE-378] computed values
1 parent 65b4915 commit b86f1c5

File tree

5 files changed

+201
-12
lines changed

5 files changed

+201
-12
lines changed

src/main/java/com/arangodb/entity/CollectionEntity.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
package com.arangodb.entity;
2222

2323
import com.arangodb.model.CollectionSchema;
24+
import com.arangodb.model.ComputedValue;
25+
26+
import java.util.List;
2427

2528
/**
2629
* @author Mark Vollmary
@@ -40,6 +43,7 @@ public class CollectionEntity implements Entity {
4043
private CollectionStatus status;
4144
private CollectionType type;
4245
private CollectionSchema schema;
46+
private List<ComputedValue> computedValues;
4347

4448
public CollectionEntity() {
4549
super();
@@ -90,4 +94,12 @@ public CollectionSchema getSchema() {
9094
return schema;
9195
}
9296

97+
/**
98+
* @return A list of computed values.
99+
* @since ArangoDB 3.10
100+
*/
101+
public List<ComputedValue> getComputedValues() {
102+
return computedValues;
103+
}
104+
93105
}

src/main/java/com/arangodb/model/CollectionCreateOptions.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020

2121
package com.arangodb.model;
2222

23-
import com.arangodb.entity.CollectionType;
24-
import com.arangodb.entity.KeyOptions;
25-
import com.arangodb.entity.KeyType;
26-
import com.arangodb.entity.MinReplicationFactor;
27-
import com.arangodb.entity.ReplicationFactor;
23+
import com.arangodb.entity.*;
24+
25+
import java.util.ArrayList;
26+
import java.util.Collections;
27+
import java.util.List;
2828

2929
/**
3030
* @author Mark Vollmary
@@ -40,6 +40,8 @@ public class CollectionCreateOptions {
4040
private Integer writeConcern;
4141
private KeyOptions keyOptions;
4242
private Boolean waitForSync;
43+
private List<ComputedValue> computedValues = new ArrayList<>();
44+
4345
/**
4446
* @deprecated MMFiles only
4547
*/
@@ -414,4 +416,14 @@ public CollectionCreateOptions setSchema(final CollectionSchema schema) {
414416
return this;
415417
}
416418

419+
/**
420+
* @param computedValues An optional list of computed values.
421+
* @return options
422+
* @since ArangoDB 3.10
423+
*/
424+
public CollectionCreateOptions computedValues(final ComputedValue... computedValues) {
425+
Collections.addAll(this.computedValues, computedValues);
426+
return this;
427+
}
428+
417429
}

src/main/java/com/arangodb/model/CollectionPropertiesOptions.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020

2121
package com.arangodb.model;
2222

23+
import java.util.ArrayList;
24+
import java.util.Collections;
25+
import java.util.List;
26+
2327
/**
2428
* @author Mark Vollmary
2529
* @see <a href="https://www.arangodb.com/docs/stable/http/collection-modifying.html#change-properties-of-a-collection">API
@@ -34,6 +38,7 @@ public class CollectionPropertiesOptions {
3438
@Deprecated
3539
private Long journalSize;
3640
private CollectionSchema schema;
41+
private List<ComputedValue> computedValues;
3742

3843
public CollectionPropertiesOptions() {
3944
super();
@@ -87,4 +92,17 @@ public CollectionPropertiesOptions schema(final CollectionSchema schema) {
8792
return this;
8893
}
8994

95+
/**
96+
* @param computedValues An optional list of computed values.
97+
* @return options
98+
* @since ArangoDB 3.10
99+
*/
100+
public CollectionPropertiesOptions computedValues(final ComputedValue... computedValues) {
101+
if(this.computedValues == null) {
102+
this.computedValues = new ArrayList<>();
103+
}
104+
Collections.addAll(this.computedValues, computedValues);
105+
return this;
106+
}
107+
90108
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package com.arangodb.model;
2+
3+
import java.util.Collections;
4+
import java.util.HashSet;
5+
import java.util.Objects;
6+
import java.util.Set;
7+
8+
/**
9+
* @since ArangoDB 3.10
10+
*/
11+
public class ComputedValue {
12+
private String name;
13+
private String expression;
14+
private Boolean overwrite;
15+
private Set<ComputeOn> computeOn;
16+
private Boolean keepNull;
17+
private Boolean failOnWarning;
18+
19+
public enum ComputeOn {
20+
insert, update, replace
21+
}
22+
23+
public ComputedValue() {
24+
super();
25+
}
26+
27+
/**
28+
* @param name (required) The name of the target attribute. Can only be a top-level attribute, but you may return
29+
* a nested object. Cannot be _key, _id, _rev, _from, _to, or a shard key attribute.
30+
* @return this
31+
*/
32+
public ComputedValue name(final String name) {
33+
this.name = name;
34+
return this;
35+
}
36+
37+
/**
38+
* @param expression (required) An AQL RETURN operation with an expression that computes the desired value. See
39+
* <a href="https://github.com/arangodb/docs/blob/main/3.10/data-modeling-documents-computed-values.md#computed-value-expressions">Computed Value Expressions</a>
40+
* for details.
41+
* @return this
42+
*/
43+
public ComputedValue expression(final String expression) {
44+
this.expression = expression;
45+
return this;
46+
}
47+
48+
/**
49+
* @param overwrite (required) Whether the computed value shall take precedence over a user-provided or existing
50+
* attribute.
51+
* @return this
52+
*/
53+
public ComputedValue overwrite(final Boolean overwrite) {
54+
this.overwrite = overwrite;
55+
return this;
56+
}
57+
58+
/**
59+
* @param computeOn (optional) An array of operations to define on which write operations the value shall be
60+
* computed. The default is ["insert", "update", "replace"].
61+
* @return this
62+
*/
63+
public ComputedValue computeOn(final ComputeOn... computeOn) {
64+
if (this.computeOn == null) {
65+
this.computeOn = new HashSet<>();
66+
}
67+
Collections.addAll(this.computeOn, computeOn);
68+
return this;
69+
}
70+
71+
/**
72+
* @param keepNull (optional) Whether the target attribute shall be set if the expression evaluates to null. You
73+
* can set the option to false to not set (or unset) the target attribute if the expression
74+
* returns null. The default is true.
75+
* @return this
76+
*/
77+
public ComputedValue keepNull(final Boolean keepNull) {
78+
this.keepNull = keepNull;
79+
return this;
80+
}
81+
82+
/**
83+
* @param failOnWarning (optional) Whether to let the write operation fail if the expression produces a warning.
84+
* The default is false.
85+
* @return this
86+
*/
87+
public ComputedValue failOnWarning(final Boolean failOnWarning) {
88+
this.failOnWarning = failOnWarning;
89+
return this;
90+
}
91+
92+
@Override
93+
public boolean equals(Object o) {
94+
if (this == o) return true;
95+
if (o == null || getClass() != o.getClass()) return false;
96+
ComputedValue that = (ComputedValue) o;
97+
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);
98+
}
99+
100+
@Override
101+
public int hashCode() {
102+
return Objects.hash(name, expression, overwrite, computeOn, keepNull, failOnWarning);
103+
}
104+
}

src/test/java/com/arangodb/ArangoDatabaseTest.java

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,42 @@ void createCollectionWithJsonSchema(ArangoDatabase db) {
351351
assertThat(e.getErrorNum()).isEqualTo(1620);
352352
}
353353

354+
@ParameterizedTest(name = "{index}")
355+
@MethodSource("dbs")
356+
void createCollectionWithComputedFields(ArangoDatabase db) {
357+
assumeTrue(isAtLeastVersion(3, 10));
358+
String cName = "collection-" + rnd();
359+
ComputedValue cv = new ComputedValue()
360+
.name("foo")
361+
.expression("RETURN 11")
362+
.overwrite(false)
363+
.computeOn(ComputedValue.ComputeOn.insert)
364+
.keepNull(false)
365+
.failOnWarning(true);
366+
367+
final CollectionEntity result = db.createCollection(cName, new CollectionCreateOptions().computedValues(cv));
368+
369+
assertThat(result).isNotNull();
370+
assertThat(result.getComputedValues())
371+
.hasSize(1)
372+
.contains(cv);
373+
374+
ComputedValue cv2 = new ComputedValue()
375+
.name("bar")
376+
.expression("RETURN 22")
377+
.overwrite(true)
378+
.computeOn(ComputedValue.ComputeOn.update, ComputedValue.ComputeOn.replace)
379+
.keepNull(true)
380+
.failOnWarning(false);
381+
382+
db.collection(cName).changeProperties(new CollectionPropertiesOptions().computedValues(cv2));
383+
384+
CollectionPropertiesEntity props = db.collection(cName).getProperties();
385+
assertThat(props.getComputedValues())
386+
.hasSize(1)
387+
.contains(cv2);
388+
}
389+
354390
@ParameterizedTest(name = "{index}")
355391
@MethodSource("dbs")
356392
void deleteCollection(ArangoDatabase db) {
@@ -718,15 +754,17 @@ void queryWithCache(ArangoDatabase db) {
718754
@ParameterizedTest(name = "{index}")
719755
@MethodSource("dbs")
720756
void queryWithMemoryLimit(ArangoDatabase db) {
721-
Throwable thrown = catchThrowable(() -> db.query("RETURN 1..100000", null, new AqlQueryOptions().memoryLimit(32 * 1024L), String.class));
757+
Throwable thrown = catchThrowable(() -> db.query("RETURN 1..100000", null,
758+
new AqlQueryOptions().memoryLimit(32 * 1024L), String.class));
722759
assertThat(thrown).isInstanceOf(ArangoDBException.class);
723760
assertThat(((ArangoDBException) thrown).getErrorNum()).isEqualTo(32);
724761
}
725762

726763
@ParameterizedTest(name = "{index}")
727764
@MethodSource("dbs")
728765
void queryWithFailOnWarningTrue(ArangoDatabase db) {
729-
Throwable thrown = catchThrowable(() -> db.query("RETURN 1 / 0", null, new AqlQueryOptions().failOnWarning(true), String.class));
766+
Throwable thrown = catchThrowable(() -> db.query("RETURN 1 / 0", null,
767+
new AqlQueryOptions().failOnWarning(true), String.class));
730768
assertThat(thrown).isInstanceOf(ArangoDBException.class);
731769
}
732770

@@ -742,7 +780,8 @@ void queryWithFailOnWarningFalse(ArangoDatabase db) {
742780
@MethodSource("dbs")
743781
void queryWithTimeout(ArangoDatabase db) {
744782
assumeTrue(isAtLeastVersion(3, 6));
745-
Throwable thrown = catchThrowable(() -> db.query("RETURN SLEEP(1)", null, new AqlQueryOptions().maxRuntime(0.1), String.class).next());
783+
Throwable thrown = catchThrowable(() -> db.query("RETURN SLEEP(1)", null,
784+
new AqlQueryOptions().maxRuntime(0.1), String.class).next());
746785
assertThat(thrown).isInstanceOf(ArangoDBException.class);
747786
assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(410);
748787
}
@@ -1098,7 +1137,8 @@ void createGraphReplicationFaktor(ArangoDatabase db) {
10981137
final String edgeCollection = "edge-" + rnd();
10991138
final String fromCollection = "from-" + rnd();
11001139
final String toCollection = "to-" + rnd();
1101-
final Collection<EdgeDefinition> edgeDefinitions = Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection));
1140+
final Collection<EdgeDefinition> edgeDefinitions =
1141+
Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection));
11021142
final GraphEntity result = db.createGraph(name, edgeDefinitions, new GraphCreateOptions().replicationFactor(2));
11031143
assertThat(result).isNotNull();
11041144
for (final String collection : Arrays.asList(edgeCollection, fromCollection, toCollection)) {
@@ -1115,7 +1155,8 @@ void createGraphNumberOfShards(ArangoDatabase db) {
11151155
final String edgeCollection = "edge-" + rnd();
11161156
final String fromCollection = "from-" + rnd();
11171157
final String toCollection = "to-" + rnd();
1118-
final Collection<EdgeDefinition> edgeDefinitions = Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection));
1158+
final Collection<EdgeDefinition> edgeDefinitions =
1159+
Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection));
11191160
final GraphEntity result = db
11201161
.createGraph(name, edgeDefinitions, new GraphCreateOptions().numberOfShards(2));
11211162
assertThat(result).isNotNull();
@@ -1322,8 +1363,10 @@ void executeTraversal(ArangoDatabase db) {
13221363
db.collection(ENAMES).insertDocument(edge, null);
13231364
}
13241365

1325-
final TraversalOptions options = new TraversalOptions().edgeCollection(ENAMES).startVertex(CNAME1 + "/" + k1).direction(Direction.outbound);
1326-
final TraversalEntity<BaseDocument, BaseEdgeDocument> traversal = db.executeTraversal(BaseDocument.class, BaseEdgeDocument.class, options);
1366+
final TraversalOptions options =
1367+
new TraversalOptions().edgeCollection(ENAMES).startVertex(CNAME1 + "/" + k1).direction(Direction.outbound);
1368+
final TraversalEntity<BaseDocument, BaseEdgeDocument> traversal = db.executeTraversal(BaseDocument.class,
1369+
BaseEdgeDocument.class, options);
13271370
assertThat(traversal).isNotNull();
13281371

13291372
final Collection<BaseDocument> vertices = traversal.getVertices();

0 commit comments

Comments
 (0)