Skip to content

Commit ba7a162

Browse files
authored
schema validation (#339)
1 parent 4f0a9e1 commit ba7a162

File tree

7 files changed

+178
-3
lines changed

7 files changed

+178
-3
lines changed

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

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

2121
package com.arangodb.entity;
2222

23+
import com.arangodb.model.CollectionValidation;
24+
2325
/**
2426
* @author Mark Vollmary
2527
* @see <a href="https://www.arangodb.com/docs/stable/http/collection-creating.html">API Documentation</a>
@@ -33,6 +35,7 @@ public class CollectionEntity implements Entity {
3335
private Boolean isSystem;
3436
private CollectionStatus status;
3537
private CollectionType type;
38+
private CollectionValidation validation;
3639

3740
public CollectionEntity() {
3841
super();
@@ -66,4 +69,8 @@ public CollectionType getType() {
6669
return type;
6770
}
6871

72+
public CollectionValidation getValidation() {
73+
return validation;
74+
}
75+
6976
}

src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
import com.arangodb.entity.*;
2424
import com.arangodb.entity.arangosearch.*;
2525
import com.arangodb.entity.arangosearch.analyzer.*;
26+
import com.arangodb.model.CollectionValidation;
2627
import com.arangodb.velocypack.VPackDeserializer;
28+
import com.arangodb.velocypack.VPackParser;
2729
import com.arangodb.velocypack.VPackSlice;
2830
import com.arangodb.velocystream.Response;
2931
import org.slf4j.Logger;
@@ -258,4 +260,13 @@ protected static FieldLink deserializeField(final Entry<String, VPackSlice> fiel
258260
return null;
259261
};
260262

263+
public static final VPackDeserializer<CollectionValidation> COLLECTION_VALIDATION = (parent, vpack, context) -> {
264+
VPackParser parser = new VPackParser.Builder().build();
265+
CollectionValidation collectionValidation = new CollectionValidation();
266+
collectionValidation.setLevel(CollectionValidation.Level.of(vpack.get("level").getAsString()));
267+
collectionValidation.setRule(parser.toJson(vpack.get("rule"), true));
268+
collectionValidation.setMessage(vpack.get("message").getAsString());
269+
return collectionValidation;
270+
};
271+
261272
}

src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.arangodb.entity.arangosearch.ConsolidationType;
2828
import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer;
2929
import com.arangodb.internal.velocystream.internal.AuthenticationRequest;
30+
import com.arangodb.model.CollectionValidation;
3031
import com.arangodb.model.TraversalOptions;
3132
import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions;
3233
import com.arangodb.velocypack.VPackModule;
@@ -66,6 +67,7 @@ public <C extends VPackSetupContext<C>> void setup(final C context) {
6667
context.registerSerializer(ArangoSearchPropertiesOptions.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES_OPTIONS);
6768
context.registerSerializer(ArangoSearchProperties.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES);
6869
context.registerSerializer(ConsolidationType.class, VPackSerializers.CONSOLIDATE_TYPE);
70+
context.registerSerializer(CollectionValidation.class, VPackSerializers.COLLECTION_VALIDATION);
6971

7072
context.registerDeserializer(Response.class, VPackDeserializers.RESPONSE);
7173
context.registerDeserializer(CollectionType.class, VPackDeserializers.COLLECTION_TYPE);
@@ -84,6 +86,7 @@ public <C extends VPackSetupContext<C>> void setup(final C context) {
8486
context.registerDeserializer(ArangoSearchProperties.class, VPackDeserializers.ARANGO_SEARCH_PROPERTIES);
8587
context.registerDeserializer(ArangoSearchPropertiesEntity.class, VPackDeserializers.ARANGO_SEARCH_PROPERTIES_ENTITY);
8688
context.registerDeserializer(ConsolidationPolicy.class, VPackDeserializers.CONSOLIDATE);
89+
context.registerDeserializer(CollectionValidation.class, VPackDeserializers.COLLECTION_VALIDATION);
8790
}
8891

8992
@Override

src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,11 @@
2323
import com.arangodb.entity.*;
2424
import com.arangodb.entity.arangosearch.*;
2525
import com.arangodb.internal.velocystream.internal.AuthenticationRequest;
26+
import com.arangodb.model.CollectionValidation;
2627
import com.arangodb.model.TraversalOptions;
2728
import com.arangodb.model.TraversalOptions.Order;
2829
import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions;
29-
import com.arangodb.velocypack.VPackBuilder;
30-
import com.arangodb.velocypack.VPackSerializer;
31-
import com.arangodb.velocypack.ValueType;
30+
import com.arangodb.velocypack.*;
3231
import com.arangodb.velocystream.Request;
3332

3433
import java.util.Collection;
@@ -224,4 +223,14 @@ private static void serializeFieldLinks(final VPackBuilder builder, final Collec
224223

225224
public static final VPackSerializer<ConsolidationType> CONSOLIDATE_TYPE = (builder, attribute, value, context) -> builder.add(attribute, value.toString().toLowerCase());
226225

226+
public static final VPackSerializer<CollectionValidation> COLLECTION_VALIDATION = (builder, attribute, value, context) -> {
227+
VPackParser parser = new VPackParser.Builder().build();
228+
VPackSlice rule = parser.fromJson(value.getRule(), true);
229+
final Map<String, Object> doc = new HashMap<>();
230+
doc.put("message", value.getMessage());
231+
doc.put("level", value.getLevel().getValue());
232+
doc.put("rule", rule);
233+
context.serialize(builder, attribute, doc);
234+
};
235+
227236
}

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ public class CollectionCreateOptions {
4747
private String shardingStrategy; // cluster option
4848
private String smartJoinAttribute; // enterprise option
4949

50+
private CollectionValidation validation;
51+
5052
public CollectionCreateOptions() {
5153
super();
5254
replicationFactor = new ReplicationFactor();
@@ -323,4 +325,13 @@ public CollectionCreateOptions distributeShardsLike(final String distributeShard
323325
return this;
324326
}
325327

328+
public CollectionValidation getValidation() {
329+
return validation;
330+
}
331+
332+
public CollectionCreateOptions setValidation(final CollectionValidation validation) {
333+
this.validation = validation;
334+
return this;
335+
}
336+
326337
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* DISCLAIMER
3+
*
4+
* Copyright 2016 ArangoDB GmbH, Cologne, Germany
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*
18+
* Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
*/
20+
21+
22+
package com.arangodb.model;
23+
24+
25+
/**
26+
* @author Michele Rastelli
27+
*/
28+
public class CollectionValidation {
29+
private String rule;
30+
private Level level;
31+
private String message;
32+
33+
public String getRule() {
34+
return rule;
35+
}
36+
37+
public CollectionValidation setRule(String rule) {
38+
this.rule = rule;
39+
return this;
40+
}
41+
42+
public Level getLevel() {
43+
return level;
44+
}
45+
46+
public CollectionValidation setLevel(Level level) {
47+
this.level = level;
48+
return this;
49+
}
50+
51+
public String getMessage() {
52+
return message;
53+
}
54+
55+
public CollectionValidation setMessage(String message) {
56+
this.message = message;
57+
return this;
58+
}
59+
60+
public enum Level {
61+
NONE("none"),
62+
NEW("new"),
63+
MODERATE("moderate"),
64+
STRICT("strict");
65+
66+
private final String value;
67+
68+
public static Level of(String label) {
69+
for (Level e : values()) {
70+
if (e.value.equals(label)) {
71+
return e;
72+
}
73+
}
74+
return null;
75+
}
76+
77+
Level(String value) {
78+
this.value = value;
79+
}
80+
81+
public String getValue() {
82+
return value;
83+
}
84+
}
85+
86+
}

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,54 @@ public void createCollectionWithKeyTypeUuid() {
295295
createCollectionWithKeyType(KeyType.uuid);
296296
}
297297

298+
@Test
299+
public void createCollectionWithJsonSchema() {
300+
assumeTrue(isAtLeastVersion(3, 7));
301+
String name = "collection-" + rnd();
302+
String rule = ("{ " +
303+
" \"properties\": {" +
304+
" \"number\": {" +
305+
" \"type\": \"number\"" +
306+
" }" +
307+
" }" +
308+
" }")
309+
.replaceAll("\\s", "");
310+
String message = "The document has problems!";
311+
312+
final CollectionEntity result = db
313+
.createCollection(name, new CollectionCreateOptions()
314+
.setValidation(
315+
new CollectionValidation()
316+
.setLevel(CollectionValidation.Level.NEW)
317+
.setMessage(message)
318+
.setRule(rule)
319+
)
320+
);
321+
assertThat(result.getValidation().getLevel(), is(CollectionValidation.Level.NEW));
322+
assertThat(result.getValidation().getRule(), is(rule));
323+
assertThat(result.getValidation().getMessage(), is(message));
324+
325+
CollectionPropertiesEntity props = db.collection(name).getProperties();
326+
assertThat(props.getValidation().getLevel(), is(CollectionValidation.Level.NEW));
327+
assertThat(props.getValidation().getRule(), is(rule));
328+
assertThat(props.getValidation().getMessage(), is(message));
329+
330+
BaseDocument doc = new BaseDocument();
331+
doc.addAttribute("number", 33);
332+
db.collection(name).insertDocument(doc);
333+
334+
try {
335+
BaseDocument wrongDoc = new BaseDocument();
336+
doc.addAttribute("number", "notANumber");
337+
db.collection(name).insertDocument(doc);
338+
fail();
339+
} catch (ArangoDBException e) {
340+
assertThat(e.getMessage(), containsString(message));
341+
assertThat(e.getResponseCode(), is(500));
342+
assertThat(e.getErrorNum(), is(1620));
343+
}
344+
}
345+
298346
@Test(expected = ArangoDBException.class)
299347
public void deleteCollection() {
300348
String name = "collection-" + rnd();

0 commit comments

Comments
 (0)