Skip to content

Commit 6f3bc32

Browse files
committed
initial readOnly - writeOnly validation
* handling ReadWriteContext in `ValidatingVisitor#visit()` * changing type of `Schema#is{Read,Write}Only` to `Boolean` * providing API in Validator.Builder to set the `ReadWriteContext` for the validation * removing some unnecessary getters from `TestSupport`
1 parent b5a408a commit 6f3bc32

File tree

7 files changed

+92
-46
lines changed

7 files changed

+92
-46
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.everit.json.schema;
2+
3+
public enum ReadWriteContext {
4+
READ, WRITE
5+
}

core/src/main/java/org/everit/json/schema/Schema.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,11 @@ public Boolean isNullable() {
226226
return nullable;
227227
}
228228

229-
public boolean isReadOnly() {
229+
public Boolean isReadOnly() {
230230
return readOnly;
231231
}
232232

233-
public boolean isWriteOnly() {
233+
public Boolean isWriteOnly() {
234234
return writeOnly;
235235
}
236236

core/src/main/java/org/everit/json/schema/ValidatingVisitor.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,29 @@ private static boolean isNull(Object obj) {
1919

2020
private ValidationFailureReporter failureReporter;
2121

22+
private final ReadWriteContext readWriteContext;
23+
2224
@Override
2325
void visit(Schema schema) {
2426
if (schema.isNullable() == Boolean.FALSE && isNull(subject)) {
2527
failureReporter.failure("value cannot be null", "nullable");
2628
}
29+
if (readWriteContext == ReadWriteContext.READ
30+
&& schema.isWriteOnly() == Boolean.TRUE
31+
&& subject != null) {
32+
failureReporter.failure("value is write-only", "writeOnly");
33+
} else if (readWriteContext == ReadWriteContext.WRITE
34+
&& schema.isReadOnly() == Boolean.TRUE
35+
&& subject != null) {
36+
failureReporter.failure("value is read-only", "readOnly");
37+
}
2738
super.visit(schema);
2839
}
2940

30-
ValidatingVisitor(Object subject, ValidationFailureReporter failureReporter) {
41+
ValidatingVisitor(Object subject, ValidationFailureReporter failureReporter, ReadWriteContext readWriteContext) {
3142
this.subject = subject;
3243
this.failureReporter = failureReporter;
44+
this.readWriteContext = readWriteContext;
3345
}
3446

3547
@Override void visitNumberSchema(NumberSchema numberSchema) {

core/src/main/java/org/everit/json/schema/Validator.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,20 @@ class ValidatorBuilder {
88

99
private boolean failEarly = false;
1010

11+
private ReadWriteContext readWriteContext;
12+
1113
public ValidatorBuilder failEarly() {
1214
this.failEarly = true;
1315
return this;
1416
}
1517

18+
public ValidatorBuilder readWriteContext(ReadWriteContext readWriteContext) {
19+
this.readWriteContext = readWriteContext;
20+
return this;
21+
}
22+
1623
public Validator build() {
17-
return new DefaultValidator(failEarly);
24+
return new DefaultValidator(failEarly, readWriteContext);
1825
}
1926

2027
}
@@ -32,13 +39,16 @@ class DefaultValidator implements Validator {
3239

3340
private boolean failEarly;
3441

35-
public DefaultValidator(boolean failEarly) {
42+
private final ReadWriteContext readWriteContext;
43+
44+
DefaultValidator(boolean failEarly, ReadWriteContext readWriteContext) {
3645
this.failEarly = failEarly;
46+
this.readWriteContext = readWriteContext;
3747
}
3848

3949
@Override public void performValidation(Schema schema, Object input) {
4050
ValidationFailureReporter failureReporter = createFailureReporter(schema);
41-
ValidatingVisitor visitor = new ValidatingVisitor(input, failureReporter);
51+
ValidatingVisitor visitor = new ValidatingVisitor(input, failureReporter, readWriteContext);
4252
visitor.visit(schema);
4353
visitor.failIfErrorFound();
4454
}

core/src/test/java/org/everit/json/schema/TestSupport.java

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,13 @@ public static class Failure {
4444

4545
private String expectedMessageFragment;
4646

47+
private Validator validator = Validator.builder().build();
48+
4749
public Failure subject(final Schema subject) {
4850
this.subject = subject;
4951
return this;
5052
}
5153

52-
public Schema subject() {
53-
return subject;
54-
}
55-
5654
public Failure expectedViolatedSchema(final Schema expectedViolatedSchema) {
5755
this.expectedViolatedSchema = expectedViolatedSchema;
5856
return this;
@@ -70,41 +68,21 @@ public Failure expectedPointer(final String expectedPointer) {
7068
return this;
7169
}
7270

73-
public String expectedPointer() {
74-
return expectedPointer;
75-
}
76-
7771
public Failure expectedSchemaLocation(String expectedSchemaLocation) {
7872
this.expectedSchemaLocation = expectedSchemaLocation;
7973
return this;
8074
}
8175

82-
public String expectedSchemaLocation() {
83-
return expectedSchemaLocation;
84-
}
85-
8676
public Failure expectedKeyword(final String keyword) {
8777
this.expectedKeyword = keyword;
8878
return this;
8979
}
9080

91-
public String expectedKeyword() {
92-
return expectedKeyword;
93-
}
94-
95-
public String expectedMessageFragment() {
96-
return expectedMessageFragment;
97-
}
98-
9981
public Failure input(final Object input) {
10082
this.input = input;
10183
return this;
10284
}
10385

104-
public Object input() {
105-
return input;
106-
}
107-
10886
public void expect() {
10987
expectFailure(this);
11088
}
@@ -113,6 +91,11 @@ public Failure expectedMessageFragment(String expectedFragment) {
11391
this.expectedMessageFragment = expectedFragment;
11492
return this;
11593
}
94+
95+
public Failure validator(Validator validator) {
96+
this.validator = validator;
97+
return this;
98+
}
11699
}
117100

118101
public static Failure failureOf(Schema subject) {
@@ -180,17 +163,17 @@ public static void expectFailure(final Schema failingSchema, final String expect
180163

181164
public static void expectFailure(final Failure failure) {
182165
try {
183-
failure.subject().validate(failure.input());
184-
Assert.fail(failure.subject() + " did not fail for " + failure.input());
166+
failure.validator.performValidation(failure.subject, failure.input);
167+
Assert.fail(failure.subject + " did not fail for " + failure.input);
185168
} catch (ValidationException e) {
186169
Assert.assertSame(failure.expectedViolatedSchema(), e.getViolatedSchema());
187-
assertEquals(failure.expectedPointer(), e.getPointerToViolation());
188-
assertEquals(failure.expectedSchemaLocation(), e.getSchemaLocation());
189-
if (failure.expectedKeyword() != null) {
190-
assertEquals(failure.expectedKeyword(), e.getKeyword());
170+
assertEquals(failure.expectedPointer, e.getPointerToViolation());
171+
assertEquals(failure.expectedSchemaLocation, e.getSchemaLocation());
172+
if (failure.expectedKeyword != null) {
173+
assertEquals(failure.expectedKeyword, e.getKeyword());
191174
}
192-
if (failure.expectedMessageFragment() != null) {
193-
assertThat(e.getMessage(), containsString(failure.expectedMessageFragment()));
175+
if (failure.expectedMessageFragment != null) {
176+
assertThat(e.getMessage(), containsString(failure.expectedMessageFragment));
194177
}
195178
}
196179
}

core/src/test/java/org/everit/json/schema/ValidatingVisitorTest.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,58 +14,58 @@ public class ValidatingVisitorTest {
1414

1515
private ValidationFailureReporter reporter;
1616

17-
1817
@Before
1918
public void before() {
2019
reporter = mock(ValidationFailureReporter.class);
2120
}
2221

2322
@Test
2423
public void passesTypeCheck_otherType_noRequires() {
25-
ValidatingVisitor subject = new ValidatingVisitor("string", reporter);
24+
ValidatingVisitor subject = new ValidatingVisitor("string", reporter, null);
2625
assertFalse(subject.passesTypeCheck(JSONObject.class, false, null));
2726
verifyZeroInteractions(reporter);
2827
}
2928

3029
@Test
3130
public void passesTypeCheck_otherType_requires() {
32-
ValidatingVisitor subject = new ValidatingVisitor("string", reporter);
31+
ValidatingVisitor subject = new ValidatingVisitor("string", reporter, null);
3332
assertFalse(subject.passesTypeCheck(JSONObject.class, true, null));
3433
verify(reporter).failure(JSONObject.class, "string");
3534
}
3635

3736
@Test
3837
public void passesTypeCheck_otherType_nullPermitted_nullObject() {
39-
ValidatingVisitor subject = new ValidatingVisitor(JSONObject.NULL, reporter);
38+
ValidatingVisitor subject = new ValidatingVisitor(JSONObject.NULL, reporter, null);
4039
assertFalse(subject.passesTypeCheck(JSONObject.class, true, Boolean.TRUE));
4140
verifyZeroInteractions(reporter);
4241
}
4342

4443
@Test
4544
public void passesTypeCheck_otherType_nullPermitted_nullReference() {
46-
ValidatingVisitor subject = new ValidatingVisitor(null, reporter);
45+
ValidatingVisitor subject = new ValidatingVisitor(null, reporter, null);
4746
assertFalse(subject.passesTypeCheck(JSONObject.class, true, Boolean.TRUE));
4847
verifyZeroInteractions(reporter);
4948
}
5049

5150
@Test
5251
public void passesTypeCheck_nullPermitted_nonNullValue() {
53-
ValidatingVisitor subject = new ValidatingVisitor("string", reporter);
52+
ValidatingVisitor subject = new ValidatingVisitor("string", reporter, null);
5453
assertFalse(subject.passesTypeCheck(JSONObject.class, true, Boolean.TRUE));
5554
verify(reporter).failure(JSONObject.class, "string");
5655
}
5756

5857
@Test
5958
public void passesTypeCheck_requiresType_nullableIsNull() {
60-
ValidatingVisitor subject = new ValidatingVisitor(null, reporter);
59+
ValidatingVisitor subject = new ValidatingVisitor(null, reporter, null);
6160
assertFalse(subject.passesTypeCheck(JSONObject.class, true, null));
6261
verify(reporter).failure(JSONObject.class, null);
6362
}
6463

6564
@Test
6665
public void passesTypeCheck_sameType() {
67-
ValidatingVisitor subject = new ValidatingVisitor("string", reporter);
66+
ValidatingVisitor subject = new ValidatingVisitor("string", reporter, null);
6867
assertTrue(subject.passesTypeCheck(String.class, true, Boolean.TRUE));
6968
verifyZeroInteractions(reporter);
7069
}
70+
7171
}

core/src/test/java/org/everit/json/schema/ValidatorTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import static org.junit.Assert.assertTrue;
55
import static org.junit.Assert.fail;
66

7+
import org.everit.json.schema.loader.SchemaLoader;
8+
import org.json.JSONObject;
79
import org.junit.Test;
810

911
public class ValidatorTest {
@@ -34,4 +36,38 @@ public void testFailEarlyMode() {
3436
}
3537
}
3638

39+
@Test
40+
public void readOnlyContext() {
41+
Validator subject = Validator.builder()
42+
.readWriteContext(ReadWriteContext.READ)
43+
.build();
44+
ObjectSchema schema = (ObjectSchema) SchemaLoader.load(ResourceLoader.DEFAULT.readObj("read-write-context.json"));
45+
JSONObject input = new JSONObject("{\"writeOnlyProp\":3}");
46+
TestSupport.failureOf(schema)
47+
.expectedPointer("#/writeOnlyProp")
48+
.expectedSchemaLocation("#/properties/writeOnlyProp")
49+
.expectedKeyword("writeOnly")
50+
.expectedViolatedSchema(schema.getPropertySchemas().get("writeOnlyProp"))
51+
.input(input)
52+
.validator(subject)
53+
.expect();
54+
}
55+
56+
@Test
57+
public void writeOnlyContext() {
58+
Validator subject = Validator.builder()
59+
.readWriteContext(ReadWriteContext.WRITE)
60+
.build();
61+
ObjectSchema schema = (ObjectSchema) SchemaLoader.load(ResourceLoader.DEFAULT.readObj("read-write-context.json"));
62+
JSONObject input = new JSONObject("{\"readOnlyProp\":\"foo\"}");
63+
TestSupport.failureOf(schema)
64+
.expectedPointer("#/readOnlyProp")
65+
.expectedSchemaLocation("#/properties/readOnlyProp")
66+
.expectedKeyword("readOnly")
67+
.expectedViolatedSchema(schema.getPropertySchemas().get("readOnlyProp"))
68+
.input(input)
69+
.validator(subject)
70+
.expect();
71+
}
72+
3773
}

0 commit comments

Comments
 (0)