Skip to content
This repository was archived by the owner on Dec 25, 2024. It is now read-only.

Commit 9cfae72

Browse files
authored
Java: adds ListSchema (#282)
* Adds and uses FrozenList * Adds ListSchemaTest.java * Adds items validator * Adds items validator test * Adds ArrayTypeSchemaTest.java
1 parent 9fe2b5d commit 9cfae72

24 files changed

Lines changed: 626 additions & 16 deletions

File tree

samples/client/petstore/java/.openapi-generator/FILES

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ src/main/java/org/openapijsonschematools/schemas/DateTimeSchema.java
1010
src/main/java/org/openapijsonschematools/schemas/DecimalSchema.java
1111
src/main/java/org/openapijsonschematools/schemas/DoubleSchema.java
1212
src/main/java/org/openapijsonschematools/schemas/FloatSchema.java
13+
src/main/java/org/openapijsonschematools/schemas/FrozenList.java
1314
src/main/java/org/openapijsonschematools/schemas/FrozenMap.java
1415
src/main/java/org/openapijsonschematools/schemas/Int32Schema.java
1516
src/main/java/org/openapijsonschematools/schemas/Int64Schema.java
1617
src/main/java/org/openapijsonschematools/schemas/IntSchema.java
18+
src/main/java/org/openapijsonschematools/schemas/ListSchema.java
1719
src/main/java/org/openapijsonschematools/schemas/MapSchema.java
1820
src/main/java/org/openapijsonschematools/schemas/NullSchema.java
1921
src/main/java/org/openapijsonschematools/schemas/NumberSchema.java
@@ -26,21 +28,25 @@ src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java
2628
src/main/java/org/openapijsonschematools/schemas/ValidationMetadata.java
2729
src/main/java/org/openapijsonschematools/schemas/validators/AdditionalPropertiesValidator.java
2830
src/main/java/org/openapijsonschematools/schemas/validators/FormatValidator.java
31+
src/main/java/org/openapijsonschematools/schemas/validators/ItemsValidator.java
2932
src/main/java/org/openapijsonschematools/schemas/validators/KeywordValidator.java
3033
src/main/java/org/openapijsonschematools/schemas/validators/PropertiesValidator.java
3134
src/main/java/org/openapijsonschematools/schemas/validators/RequiredValidator.java
3235
src/main/java/org/openapijsonschematools/schemas/validators/TypeValidator.java
3336
src/test/java/org/openapijsonschematools/configurations/JsonSchemaKeywordFlagsTest.java
3437
src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java
38+
src/test/java/org/openapijsonschematools/schemas/ArrayTypeSchemaTest.java
3539
src/test/java/org/openapijsonschematools/schemas/BooleanSchemaTest.java
3640
src/test/java/org/openapijsonschematools/schemas/CustomIsoparserTest.java
41+
src/test/java/org/openapijsonschematools/schemas/ListSchemaTest.java
3742
src/test/java/org/openapijsonschematools/schemas/MapSchemaTest.java
3843
src/test/java/org/openapijsonschematools/schemas/NullSchemaTest.java
3944
src/test/java/org/openapijsonschematools/schemas/NumberSchemaTest.java
4045
src/test/java/org/openapijsonschematools/schemas/ObjectTypeSchemaTest.java
4146
src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java
4247
src/test/java/org/openapijsonschematools/schemas/validators/AdditionalPropertiesValidatorTest.java
4348
src/test/java/org/openapijsonschematools/schemas/validators/FormatValidatorTest.java
49+
src/test/java/org/openapijsonschematools/schemas/validators/ItemsValidatorTest.java
4450
src/test/java/org/openapijsonschematools/schemas/validators/PropertiesValidatorTest.java
4551
src/test/java/org/openapijsonschematools/schemas/validators/RequiredValidatorTest.java
4652
src/test/java/org/openapijsonschematools/schemas/validators/TypeValidatorTest.java

samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/AnyTypeSchema.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public static <T extends FrozenMap> T validate(Map<String, Object> arg, SchemaCo
5252
return Schema.validate(AnyTypeSchema.class, arg, configuration);
5353
}
5454

55-
public static <U extends List> U validate(List<Object> arg, SchemaConfiguration configuration) {
55+
public static <U extends FrozenList> U validate(List<Object> arg, SchemaConfiguration configuration) {
5656
return Schema.validate(AnyTypeSchema.class, arg, configuration);
5757
}
5858
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package org.openapijsonschematools.schemas;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collection;
5+
6+
public class FrozenList<E> extends ArrayList<E> {
7+
/*
8+
A frozen List
9+
Once schema validation has been run, indexed access returns values of the correct type
10+
If values were mutable, the types in those methods would not agree with returned values
11+
*/
12+
public FrozenList(Collection<? extends E> m) {
13+
super(m);
14+
}
15+
16+
public boolean add(E e) {
17+
throw new UnsupportedOperationException();
18+
}
19+
20+
public void add(int index, E element) {
21+
throw new UnsupportedOperationException();
22+
}
23+
24+
public E remove(int index) {
25+
throw new UnsupportedOperationException();
26+
}
27+
28+
public boolean remove(Object o) {
29+
throw new UnsupportedOperationException();
30+
}
31+
32+
public void clear() {
33+
throw new UnsupportedOperationException();
34+
}
35+
36+
public boolean addAll(Collection<? extends E> c) {
37+
throw new UnsupportedOperationException();
38+
}
39+
40+
public boolean addAll(int index, Collection<? extends E> c) {
41+
throw new UnsupportedOperationException();
42+
}
43+
44+
public boolean removeAll(Collection<?> c) {
45+
throw new UnsupportedOperationException();
46+
}
47+
48+
public boolean retainAll(Collection<?> c) {
49+
throw new UnsupportedOperationException();
50+
}
51+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.openapijsonschematools.schemas;
2+
3+
import org.openapijsonschematools.configurations.SchemaConfiguration;
4+
5+
import java.util.LinkedHashSet;
6+
import java.util.List;
7+
8+
public record ListSchema(LinkedHashSet<Class<?>> type) implements Schema {
9+
public static ListSchema withDefaults() {
10+
LinkedHashSet<Class<?>> type = new LinkedHashSet<>();
11+
type.add(FrozenList.class);
12+
return new ListSchema(type);
13+
}
14+
15+
public static FrozenList<Object> validate(List<Object> arg, SchemaConfiguration configuration) {
16+
return Schema.validate(ListSchema.class, arg, configuration);
17+
}
18+
}

samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ private static Object castToAllowedTypes(Object arg, List<Object> pathToItem, Pa
5252
pathToType.put(pathToItem, Double.class);
5353
return arg;
5454
} else if (arg instanceof List) {
55-
pathToType.put(pathToItem, List.class);
55+
pathToType.put(pathToItem, FrozenList.class);
5656
List<Object> argFixed = new ArrayList<>();
5757
int i =0;
5858
for (Object item: ((List<?>) arg).toArray()) {
@@ -62,7 +62,7 @@ private static Object castToAllowedTypes(Object arg, List<Object> pathToItem, Pa
6262
argFixed.add(fixedVal);
6363
i += 1;
6464
}
65-
return argFixed;
65+
return new FrozenList(argFixed);
6666
} else if (arg instanceof ZonedDateTime) {
6767
pathToType.put(pathToItem, String.class);
6868
return arg.toString();
@@ -115,7 +115,7 @@ private static LinkedHashMap<String, Object> getProperties(Object arg, List<Obje
115115
return new FrozenMap(properties);
116116
}
117117

118-
private static List<Object> getItems(Object arg, List<Object> pathToItem, PathToSchemasMap pathToSchemas) {
118+
private static FrozenList<Object> getItems(Object arg, List<Object> pathToItem, PathToSchemasMap pathToSchemas) {
119119
ArrayList<Object> items = new ArrayList<>();
120120
List<Object> castItems = (List<Object>) arg;
121121
int i = 0;
@@ -127,7 +127,7 @@ private static List<Object> getItems(Object arg, List<Object> pathToItem, PathTo
127127
items.add(castItem);
128128
i += 1;
129129
}
130-
return items;
130+
return new FrozenList(items);
131131
}
132132

133133
private static Map<Class<?>, Class<?>> getTypeToOutputClass(Class<?> cls) {
@@ -201,7 +201,7 @@ static <T extends FrozenMap> T validate(Class<?> cls, Map<String, Object> arg, S
201201
return (T) validateObject(cls, arg, configuration);
202202
}
203203

204-
static <U extends List> U validate(Class<?> cls, List<Object> arg, SchemaConfiguration configuration) {
204+
static <U extends FrozenList> U validate(Class<?> cls, List<Object> arg, SchemaConfiguration configuration) {
205205
return (U) validateObject(cls, arg, configuration);
206206
}
207207

samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.openapijsonschematools.schemas.validators.FormatValidator;
77
import org.openapijsonschematools.schemas.validators.PropertiesValidator;
88
import org.openapijsonschematools.schemas.validators.RequiredValidator;
9+
import org.openapijsonschematools.schemas.validators.ItemsValidator;
910

1011
import java.lang.reflect.InvocationTargetException;
1112
import java.lang.reflect.RecordComponent;
@@ -22,6 +23,7 @@ public interface SchemaValidator {
2223
put("format", new FormatValidator());
2324
put("properties", new PropertiesValidator());
2425
put("required", new RequiredValidator());
26+
put("items", new ItemsValidator());
2527
}};
2628

2729
static PathToSchemasMap validate(

samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ static <T extends FrozenMap> T validate(Map<String, Object> arg, SchemaConfigura
5252
return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration);
5353
}
5454

55-
static <U extends List> U validate(List<Object> arg, SchemaConfiguration configuration) {
55+
static <U extends FrozenList> U validate(List<Object> arg, SchemaConfiguration configuration) {
5656
return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration);
5757
}
5858
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.openapijsonschematools.schemas.validators;
2+
3+
import org.openapijsonschematools.schemas.PathToSchemasMap;
4+
import org.openapijsonschematools.schemas.Schema;
5+
import org.openapijsonschematools.schemas.SchemaValidator;
6+
import org.openapijsonschematools.schemas.ValidationMetadata;
7+
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
11+
public class ItemsValidator implements KeywordValidator {
12+
@Override
13+
public PathToSchemasMap validate(Object arg, Object value, Object extra, Class<SchemaValidator> cls, ValidationMetadata validationMetadata) {
14+
if (!(arg instanceof List)) {
15+
return null;
16+
}
17+
List<Object> castArg = (List<Object>) arg;
18+
Class<Schema> itemsSchema = (Class<Schema>) value;
19+
PathToSchemasMap pathToSchemas = new PathToSchemasMap();
20+
// todo add handling for prefixItems
21+
int i = 0;
22+
for(Object itemValue: castArg) {
23+
List<Object> itemPathToItem = new ArrayList<>(validationMetadata.pathToItem());
24+
itemPathToItem.add(i);
25+
ValidationMetadata itemValidationMetadata = new ValidationMetadata(
26+
itemPathToItem,
27+
validationMetadata.configuration(),
28+
validationMetadata.validatedPathToSchemas(),
29+
validationMetadata.seenClasses()
30+
);
31+
if (itemValidationMetadata.validationRanEarlier(itemsSchema)) {
32+
// todo add_deeper_validated_schemas
33+
i +=1;
34+
continue;
35+
}
36+
PathToSchemasMap otherPathToSchemas = SchemaValidator.validate(itemsSchema, itemValue, itemValidationMetadata);
37+
pathToSchemas.update(otherPathToSchemas);
38+
i += 1;
39+
}
40+
return pathToSchemas;
41+
}
42+
}

samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public void testValidateMap() {
8585
public void testValidateList() {
8686
ArrayList<Object> inList = new ArrayList<>();
8787
inList.add(LocalDate.of(2017, 7, 21));
88-
ArrayList<String> validatedValue = AnyTypeSchema.validate(inList, configuration);
88+
FrozenList<String> validatedValue = AnyTypeSchema.validate(inList, configuration);
8989
ArrayList<String> outList = new ArrayList<>();
9090
outList.add( "2017-07-21");
9191
Assert.assertEquals(validatedValue, outList);
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package org.openapijsonschematools.schemas;
2+
3+
import org.junit.Assert;
4+
import org.junit.Test;
5+
import org.openapijsonschematools.configurations.JsonSchemaKeywordFlags;
6+
import org.openapijsonschematools.configurations.SchemaConfiguration;
7+
8+
import java.util.ArrayList;
9+
import java.util.LinkedHashSet;
10+
import java.util.List;
11+
12+
record ArrayWithItemsSchema(LinkedHashSet<Class<?>> type, Class<?> items) implements Schema {
13+
public static ArrayWithItemsSchema withDefaults() {
14+
LinkedHashSet<Class<?>> type = new LinkedHashSet<>();
15+
// can't use ImmutableList because it does not allow null values in entries
16+
// can't use Collections.unmodifiableList because Collections.UnmodifiableList is not public + extensible
17+
type.add(FrozenList.class);
18+
Class<?> items = StringSchema.class;
19+
return new ArrayWithItemsSchema(type, items);
20+
}
21+
22+
public static FrozenList<Object> validate(List<Object> arg, SchemaConfiguration configuration) {
23+
return Schema.validate(ArrayWithItemsSchema.class, arg, configuration);
24+
}
25+
}
26+
27+
public class ArrayTypeSchemaTest {
28+
static final SchemaConfiguration configuration = new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone());
29+
30+
@Test
31+
public void testExceptionThrownForInvalidType() {
32+
Assert.assertThrows(RuntimeException.class, () -> Schema.validate(
33+
ArrayWithItemsSchema.class, (Void) null, configuration
34+
));
35+
}
36+
37+
@Test
38+
public void testValidateArrayWithItemsSchema() {
39+
// map with only item works
40+
List<Object> inList = new ArrayList<>();
41+
inList.add("abc");
42+
FrozenList<Object> validatedValue = ArrayWithItemsSchema.validate(inList, configuration);
43+
List<Object> outList = new ArrayList<>();
44+
outList.add("abc");
45+
Assert.assertEquals(validatedValue, outList);
46+
47+
// map with no items works
48+
inList = new ArrayList<>();
49+
validatedValue = ArrayWithItemsSchema.validate(inList, configuration);
50+
outList = new ArrayList<>();
51+
Assert.assertEquals(validatedValue, outList);
52+
53+
// invalid prop type fails
54+
inList = new ArrayList<>();
55+
inList.add(1);
56+
List<Object> finalInList = inList;
57+
Assert.assertThrows(RuntimeException.class, () -> ArrayWithItemsSchema.validate(
58+
finalInList, configuration
59+
));
60+
}
61+
}

0 commit comments

Comments
 (0)