Skip to content

Commit fe8bd1b

Browse files
committed
Implement new Schema annotation fields
- examples - comment - if/then/elseSchema - dependentSchemas - prefixItems - contains/minContains/maxContains - patternProperties - propertyNames - constValue - dependentRequired - contentEncoding/contentMediaType/contentSchema
1 parent 8d98138 commit fe8bd1b

File tree

2 files changed

+119
-12
lines changed

2 files changed

+119
-12
lines changed

core/src/main/java/io/smallrye/openapi/runtime/io/schema/SchemaConstant.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,18 @@ public class SchemaConstant {
107107
public static final String PROP_PREFIX_ITEMS = "prefixItems";
108108
public static final String PROP_CONTAINS = "contains";
109109
public static final String PROP_PATTERN_PROPERTIES = "patternProperties";
110+
public static final String PROP_IF_SCHEMA = "ifSchema";
111+
public static final String PROP_THEN_SCHEMA = "thenSchema";
112+
public static final String PROP_ELSE_SCHEMA = "elseSchema";
113+
public static final String PROP_CONST_VALUE = "constValue";
114+
public static final String PROP_COMMENT_FIELD = "comment";
110115

111116
// Only in SchemaFactory ?
112117
public static final String PROP_REQUIRED_PROPERTIES = "requiredProperties";
113118
public static final String PROP_PROPERTIES = "properties";
114119
public static final String PROP_NOT = "not";
120+
public static final String PROP_REGEX = "regex";
121+
public static final String PROP_REQUIRES = "requires";
115122

116123
public static final String DIALECT_OAS31 = "https://spec.openapis.org/oas/3.1/dialect/base";
117124
public static final String DIALECT_JSON_2020_12 = "https://json-schema.org/draft/2020-12/schema";

core/src/main/java/io/smallrye/openapi/runtime/io/schema/SchemaFactory.java

Lines changed: 112 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.smallrye.openapi.runtime.io.schema;
22

3+
import static java.util.Arrays.asList;
4+
35
import java.math.BigDecimal;
46
import java.util.ArrayList;
57
import java.util.Arrays;
@@ -154,6 +156,12 @@ public static Schema readSchema(final AnnotationScannerContext context,
154156
types -> readClassSchemas(context, types, false), defaults));
155157
schema.setAllOf(SchemaFactory.<Type[], List<Schema>> readAttr(context, annotation, SchemaConstant.PROP_ALL_OF,
156158
types -> readClassSchemas(context, types, true), defaults));
159+
schema.setIfSchema(SchemaFactory.<Type, Schema> readAttr(context, annotation, SchemaConstant.PROP_IF_SCHEMA,
160+
types -> readClassSchema(context, types, true), defaults));
161+
schema.setThenSchema(SchemaFactory.<Type, Schema> readAttr(context, annotation, SchemaConstant.PROP_THEN_SCHEMA,
162+
types -> readClassSchema(context, types, true), defaults));
163+
schema.setElseSchema(SchemaFactory.<Type, Schema> readAttr(context, annotation, SchemaConstant.PROP_ELSE_SCHEMA,
164+
types -> readClassSchema(context, types, true), defaults));
157165
schema.setTitle(readAttr(context, annotation, SchemaConstant.PROP_TITLE, defaults));
158166
schema.setMultipleOf(SchemaFactory.<Double, BigDecimal> readAttr(context, annotation, SchemaConstant.PROP_MULTIPLE_OF,
159167
BigDecimal::valueOf, defaults));
@@ -191,14 +199,32 @@ public static Schema readSchema(final AnnotationScannerContext context,
191199

192200
final SchemaType type = readSchemaType(context, annotation, schema, defaults);
193201
SchemaImpl.setType(schema, type);
194-
schema.setExamples(wrapInList(parseSchemaAttr(context, annotation, SchemaConstant.PROP_EXAMPLE, defaults, type)));
202+
203+
Object example = parseSchemaAttr(context, annotation, SchemaConstant.PROP_EXAMPLE, defaults, type);
204+
List<Object> examples = SchemaFactory.<String[], List<Object>> readAttr(context, annotation,
205+
SchemaConstant.PROP_EXAMPLES,
206+
egs -> Arrays.stream(egs)
207+
.map(e -> parseValue(context, e, type))
208+
.collect(Collectors.toCollection(ArrayList::new)),
209+
defaults);
210+
if (examples != null) {
211+
if (example != null) {
212+
examples.add(example);
213+
}
214+
schema.setExamples(examples);
215+
} else {
216+
schema.setExamples(wrapInList(example));
217+
}
218+
195219
schema.setDefaultValue(
196220
parseSchemaAttr(context, annotation, SchemaConstant.PROP_DEFAULT_VALUE, defaults, type));
197221
schema.setDiscriminator(context.io().discriminatorIO().read(annotation));
198222
schema.setMaxItems(readAttr(context, annotation, SchemaConstant.PROP_MAX_ITEMS, defaults));
199223
schema.setMinItems(readAttr(context, annotation, SchemaConstant.PROP_MIN_ITEMS, defaults));
200224
schema.setUniqueItems(readAttr(context, annotation, SchemaConstant.PROP_UNIQUE_ITEMS, defaults));
201225
schema.setExtensions(context.io().extensionIO().readExtensible(annotation));
226+
schema.setComment(readAttr(context, annotation, SchemaConstant.PROP_COMMENT_FIELD, defaults));
227+
schema.setConstValue(parseSchemaAttr(context, annotation, SchemaConstant.PROP_CONST_VALUE, defaults, type));
202228

203229
schema.setProperties(SchemaFactory.<AnnotationInstance[], Map<String, Schema>> readAttr(context, annotation,
204230
SchemaConstant.PROP_PROPERTIES, properties -> {
@@ -215,17 +241,35 @@ public static Schema readSchema(final AnnotationScannerContext context,
215241
return propertySchemas;
216242
}, defaults));
217243

218-
Type additionalProperties = readAttr(context, annotation, "additionalProperties", defaults);
244+
schema.setAdditionalPropertiesSchema(
245+
SchemaFactory.<Type, Schema> readAttr(context, annotation, SchemaConstant.PROP_ADDITIONAL_PROPERTIES,
246+
types -> readClassSchema(context, types, true), defaults));
219247

220-
if (additionalProperties != null) {
221-
if (additionalProperties.name().equals(SchemaConstant.DOTNAME_TRUE_SCHEMA)) {
222-
schema.setAdditionalPropertiesSchema(new SchemaImpl().booleanSchema(Boolean.TRUE));
223-
} else if (additionalProperties.name().equals(SchemaConstant.DOTNAME_FALSE_SCHEMA)) {
224-
schema.setAdditionalPropertiesSchema(new SchemaImpl().booleanSchema(Boolean.FALSE));
225-
} else {
226-
schema.setAdditionalPropertiesSchema(readClassSchema(context, additionalProperties, true));
227-
}
228-
}
248+
schema.setDependentRequired(SchemaFactory.<AnnotationInstance[], Map<String, List<String>>> readAttr(context,
249+
annotation, SchemaConstant.PROP_DEPENDENT_REQUIRED,
250+
annos -> readDependentRequired(context, annos), defaults));
251+
252+
schema.setDependentSchemas(SchemaFactory.<AnnotationInstance[], Map<String, Schema>> readAttr(context, annotation,
253+
SchemaConstant.PROP_DEPENDENT_SCHEMAS,
254+
annos -> readDependentSchemas(context, annos), defaults));
255+
256+
schema.setContentEncoding(readAttr(context, annotation, SchemaConstant.PROP_CONTENT_ENCODING, defaults));
257+
schema.setContentMediaType(readAttr(context, annotation, SchemaConstant.PROP_CONTENT_MEDIA_TYPE, defaults));
258+
schema.setContentSchema(SchemaFactory.<Type, Schema> readAttr(context, annotation, SchemaConstant.PROP_CONTENT_SCHEMA,
259+
types -> readClassSchema(context, types, true), defaults));
260+
261+
schema.setContains(SchemaFactory.<Type, Schema> readAttr(context, annotation, SchemaConstant.PROP_CONTAINS,
262+
types -> readClassSchema(context, types, true), defaults));
263+
schema.setMaxContains(readAttr(context, annotation, SchemaConstant.PROP_MAX_CONTAINS, defaults));
264+
schema.setMinContains(readAttr(context, annotation, SchemaConstant.PROP_MIN_CONTAINS, defaults));
265+
schema.setPrefixItems(
266+
SchemaFactory.<Type[], List<Schema>> readAttr(context, annotation, SchemaConstant.PROP_PREFIX_ITEMS,
267+
types -> readClassSchemas(context, types, true), defaults));
268+
schema.setPropertyNames(SchemaFactory.<Type, Schema> readAttr(context, annotation, SchemaConstant.PROP_PROPERTY_NAMES,
269+
types -> readClassSchema(context, types, true), defaults));
270+
schema.setPatternProperties(SchemaFactory.<AnnotationInstance[], Map<String, Schema>> readAttr(context, annotation,
271+
SchemaConstant.PROP_PATTERN_PROPERTIES,
272+
annos -> readPatternProperties(context, annos), defaults));
229273

230274
List<Object> enumeration = readAttr(context, annotation, SchemaConstant.PROP_ENUMERATION, (Object[] values) -> {
231275
List<Object> parsed = new ArrayList<>(values.length);
@@ -467,7 +511,11 @@ static Schema readClassSchema(final AnnotationScannerContext context, Type type,
467511
return null;
468512
}
469513
Schema schema;
470-
if (type.kind() == Type.Kind.ARRAY) {
514+
if (type.name().equals(SchemaConstant.DOTNAME_TRUE_SCHEMA)) {
515+
schema = new SchemaImpl().booleanSchema(true);
516+
} else if (type.name().equals(SchemaConstant.DOTNAME_FALSE_SCHEMA)) {
517+
schema = new SchemaImpl().booleanSchema(false);
518+
} else if (type.kind() == Type.Kind.ARRAY) {
471519
schema = new SchemaImpl().addType(SchemaType.ARRAY);
472520
ArrayType array = type.asArrayType();
473521
int dimensions = array.dimensions();
@@ -760,4 +808,56 @@ private static BigDecimal tolerantParseBigDecimal(String value) {
760808
return null;
761809
}
762810
}
811+
812+
private static Map<String, List<String>> readDependentRequired(AnnotationScannerContext context,
813+
AnnotationInstance[] requireds) {
814+
if (requireds == null || requireds.length == 0) {
815+
return null;
816+
}
817+
818+
Map<String, List<String>> result = new LinkedHashMap<>();
819+
for (AnnotationInstance required : requireds) {
820+
String name = context.annotations().value(required, SchemaConstant.PROP_NAME);
821+
String[] requires = context.annotations().value(required, SchemaConstant.PROP_REQUIRES);
822+
result.put(name, new ArrayList<>(asList(requires)));
823+
}
824+
825+
return result;
826+
}
827+
828+
private static Map<String, Schema> readDependentSchemas(AnnotationScannerContext context,
829+
AnnotationInstance[] dependentSchemas) {
830+
if (dependentSchemas == null || dependentSchemas.length == 0) {
831+
return null;
832+
}
833+
834+
Map<String, Schema> result = new LinkedHashMap<>();
835+
for (AnnotationInstance dependentSchema : dependentSchemas) {
836+
String name = context.annotations().value(dependentSchema, SchemaConstant.PROP_NAME);
837+
Type schemaClass = context.annotations().value(dependentSchema, SchemaConstant.PROP_SCHEMA);
838+
Schema schema = readClassSchema(context, schemaClass, true);
839+
if (schema != null) {
840+
result.put(name, schema);
841+
}
842+
}
843+
return result;
844+
}
845+
846+
private static Map<String, Schema> readPatternProperties(AnnotationScannerContext context,
847+
AnnotationInstance[] patternProperties) {
848+
if (patternProperties == null || patternProperties.length == 0) {
849+
return null;
850+
}
851+
852+
Map<String, Schema> result = new LinkedHashMap<>();
853+
for (AnnotationInstance patternProperty : patternProperties) {
854+
String regex = context.annotations().value(patternProperty, SchemaConstant.PROP_REGEX);
855+
Type schemaClass = context.annotations().value(patternProperty, SchemaConstant.PROP_SCHEMA);
856+
Schema schema = readClassSchema(context, schemaClass, true);
857+
if (schema != null) {
858+
result.put(regex, schema);
859+
}
860+
}
861+
return result;
862+
}
763863
}

0 commit comments

Comments
 (0)