use of org.wildfly.swarm.microprofile.openapi.api.models.media.SchemaImpl in project wildfly-swarm by wildfly-swarm.
the class OpenApiParser method readSchema.
/**
* Reads a {@link Schema} OpenAPI node.
* @param node
*/
private Schema readSchema(JsonNode node) {
if (node == null || !node.isObject()) {
return null;
}
SchemaImpl model = new SchemaImpl();
model.setRef(JsonUtil.stringProperty(node, OpenApiConstants.PROP_$REF));
model.setFormat(JsonUtil.stringProperty(node, OpenApiConstants.PROP_FORMAT));
model.setTitle(JsonUtil.stringProperty(node, OpenApiConstants.PROP_TITLE));
model.setDescription(JsonUtil.stringProperty(node, OpenApiConstants.PROP_DESCRIPTION));
model.setDefaultValue(readObject(node.get(OpenApiConstants.PROP_DEFAULT)));
model.setMultipleOf(JsonUtil.bigDecimalProperty(node, OpenApiConstants.PROP_MULTIPLE_OF));
model.setMaximum(JsonUtil.bigDecimalProperty(node, OpenApiConstants.PROP_MAXIMUM));
model.setExclusiveMaximum(JsonUtil.booleanProperty(node, OpenApiConstants.PROP_EXCLUSIVE_MAXIMUM));
model.setMinimum(JsonUtil.bigDecimalProperty(node, OpenApiConstants.PROP_MINIMUM));
model.setExclusiveMinimum(JsonUtil.booleanProperty(node, OpenApiConstants.PROP_EXCLUSIVE_MINIMUM));
model.setMaxLength(JsonUtil.intProperty(node, OpenApiConstants.PROP_MAX_LENGTH));
model.setMinLength(JsonUtil.intProperty(node, OpenApiConstants.PROP_MIN_LENGTH));
model.setPattern(JsonUtil.stringProperty(node, OpenApiConstants.PROP_PATTERN));
model.setMaxItems(JsonUtil.intProperty(node, OpenApiConstants.PROP_MAX_ITEMS));
model.setMinItems(JsonUtil.intProperty(node, OpenApiConstants.PROP_MIN_ITEMS));
model.setUniqueItems(JsonUtil.booleanProperty(node, OpenApiConstants.PROP_UNIQUE_ITEMS));
model.setMaxProperties(JsonUtil.intProperty(node, OpenApiConstants.PROP_MAX_PROPERTIES));
model.setMinProperties(JsonUtil.intProperty(node, OpenApiConstants.PROP_MIN_PROPERTIES));
model.setRequired(readStringArray(node.get(OpenApiConstants.PROP_REQUIRED)));
model.setEnumeration(readObjectArray(node.get(OpenApiConstants.PROP_ENUM)));
model.setType(readSchemaType(node.get(OpenApiConstants.PROP_TYPE)));
model.setItems(readSchema(node.get(OpenApiConstants.PROP_ITEMS)));
model.setNot(readSchema(node.get(OpenApiConstants.PROP_NOT)));
model.setAllOf(readSchemaArray(node.get(OpenApiConstants.PROP_ALL_OF)));
model.setProperties(readSchemas(node.get(OpenApiConstants.PROP_PROPERTIES)));
if (node.has(OpenApiConstants.PROP_ADDITIONAL_PROPERTIES) && node.get(OpenApiConstants.PROP_ADDITIONAL_PROPERTIES).isObject()) {
model.setAdditionalProperties(readSchema(node.get(OpenApiConstants.PROP_ADDITIONAL_PROPERTIES)));
} else {
model.setAdditionalProperties(JsonUtil.booleanProperty(node, OpenApiConstants.PROP_ADDITIONAL_PROPERTIES));
}
model.setReadOnly(JsonUtil.booleanProperty(node, OpenApiConstants.PROP_READ_ONLY));
model.setXml(readXML(node.get(OpenApiConstants.PROP_XML)));
model.setExternalDocs(readExternalDocs(node.get(OpenApiConstants.PROP_EXTERNAL_DOCS)));
model.setExample(readObject(node.get(OpenApiConstants.PROP_EXAMPLE)));
model.setOneOf(readSchemaArray(node.get(OpenApiConstants.PROP_ONE_OF)));
model.setAnyOf(readSchemaArray(node.get(OpenApiConstants.PROP_ANY_OF)));
model.setNot(readSchema(node.get(OpenApiConstants.PROP_NOT)));
model.setDiscriminator(readDiscriminator(node.get(OpenApiConstants.PROP_DISCRIMINATOR)));
model.setNullable(JsonUtil.booleanProperty(node, OpenApiConstants.PROP_NULLABLE));
model.setWriteOnly(JsonUtil.booleanProperty(node, OpenApiConstants.PROP_WRITE_ONLY));
model.setDeprecated(JsonUtil.booleanProperty(node, OpenApiConstants.PROP_DEPRECATED));
readExtensions(node, model);
return model;
}
use of org.wildfly.swarm.microprofile.openapi.api.models.media.SchemaImpl in project wildfly-swarm by wildfly-swarm.
the class OpenApiDataObjectScanner method process.
/**
* Build the Schema
*
* @return the OAI schema
*/
public Schema process() {
LOG.debugv("Starting processing with root: {0}", rootClassType.name());
// If top level item is simple
if (isTerminalType(rootClassType)) {
SchemaImpl simpleSchema = new SchemaImpl();
simpleSchema.setType(classTypeFormat.getSchemaType());
simpleSchema.setFormat(classTypeFormat.getFormat().format());
return simpleSchema;
}
// If top level item is not indexed
if (rootClassInfo == null && path.size() == 0) {
// If there's something on the path stack then pre-scanning may have found something.
return null;
}
// If top level is a special item, we need to skip search else it'll try to index fields
// Embedded special items are handled ok.
PathEntry root = PathEntry.rootNode(rootClassType, rootClassInfo, rootSchema);
// For certain special types (map, list, etc) we need to do some pre-processing.
if (isSpecialType(rootClassType)) {
resolveSpecial(root, rootClassType);
} else {
path.push(root);
}
dfs(path.peek());
return rootSchema;
}
use of org.wildfly.swarm.microprofile.openapi.api.models.media.SchemaImpl in project wildfly-swarm by wildfly-swarm.
the class OpenApiDataObjectScanner method process.
/**
* Build a Schema with PrimitiveType as root.
*
* @param primitive root to begin scan
* @return the OAI schema
*/
public static Schema process(PrimitiveType primitive) {
TypeUtil.TypeWithFormat typeFormat = TypeUtil.getTypeFormat(primitive);
Schema primitiveSchema = new SchemaImpl();
primitiveSchema.setType(typeFormat.getSchemaType());
primitiveSchema.setFormat(typeFormat.getFormat().format());
return primitiveSchema;
}
use of org.wildfly.swarm.microprofile.openapi.api.models.media.SchemaImpl in project wildfly-swarm by wildfly-swarm.
the class OpenApiDataObjectScanner method processType.
private Type processType(Type fieldType, TypeResolver typeResolver, Schema schema, PathEntry pathEntry) {
// If it's a terminal type.
if (isTerminalType(fieldType)) {
return fieldType;
}
if (fieldType.kind() == Type.Kind.WILDCARD_TYPE) {
fieldType = TypeUtil.resolveWildcard(fieldType.asWildcardType());
}
if (fieldType.kind() == Type.Kind.ARRAY) {
LOG.debugv("Processing an array {0}", fieldType);
ArrayType arrayType = fieldType.asArrayType();
// TODO handle multi-dimensional arrays.
// Array-type schema
SchemaImpl arrSchema = new SchemaImpl();
schema.type(Schema.SchemaType.ARRAY);
schema.items(arrSchema);
// Only use component (excludes the special name formatting for arrays).
TypeUtil.TypeWithFormat typeFormat = TypeUtil.getTypeFormat(arrayType.component());
arrSchema.setType(typeFormat.getSchemaType());
arrSchema.setFormat(typeFormat.getFormat().format());
// If it's not a terminal type, then push for later inspection.
if (!isTerminalType(arrayType.component()) && indexContains(fieldType)) {
ClassInfo klazz = getClassByName(fieldType);
pushPathPair(pathEntry, fieldType, klazz, arrSchema);
}
return arrayType;
}
if (isA(fieldType, ENUM_TYPE) && indexContains(fieldType)) {
LOG.debugv("Processing an enum {0}", fieldType);
ClassInfo enumKlazz = getClassByName(fieldType);
for (FieldInfo enumField : enumKlazz.fields()) {
// Ignore the hidden enum array as it's not accessible. Add fields that look like enums (of type enumKlazz)
if (!enumField.name().endsWith("$VALUES") && TypeUtil.getName(enumField.type()).equals(enumKlazz.name())) {
// Enum's value fields.
schema.addEnumeration(enumField.name());
}
}
return STRING_TYPE;
}
if (fieldType.kind() == Type.Kind.PARAMETERIZED_TYPE) {
// Parameterised type (e.g. Foo<A, B>)
return readParamType(pathEntry, schema, fieldType.asParameterizedType(), typeResolver);
}
if (fieldType.kind() == Type.Kind.TYPE_VARIABLE || fieldType.kind() == Type.Kind.UNRESOLVED_TYPE_VARIABLE) {
// Resolve type variable to real variable.
return resolveTypeVariable(typeResolver, schema, pathEntry, fieldType);
}
// Raw Collection
if (isA(fieldType, COLLECTION_TYPE)) {
return ARRAY_TYPE_OBJECT;
}
// Raw Map
if (isA(fieldType, MAP_TYPE)) {
return OBJECT_TYPE;
}
// Simple case: bare class or primitive type.
if (indexContains(fieldType)) {
pushFieldToPath(pathEntry, fieldType, schema);
} else {
// If the type is not in Jandex then we don't have easy access to it.
// Future work could consider separate code to traverse classes reachable from this classloader.
LOG.debugv("Encountered type not in Jandex index that is not well-known type. " + "Will not traverse it: {0}", fieldType);
}
return fieldType;
}
use of org.wildfly.swarm.microprofile.openapi.api.models.media.SchemaImpl in project wildfly-swarm by wildfly-swarm.
the class OpenApiDataObjectScanner method readParamType.
private Type readParamType(PathEntry pathEntry, Schema schema, ParameterizedType pType, TypeResolver typeResolver) {
LOG.debugv("Processing parameterized type {0}", pType);
// If it's a collection, we should treat it as an array.
if (isA(pType, COLLECTION_TYPE)) {
// TODO maybe also Iterable?
LOG.debugv("Processing Java Collection. Will treat as an array.");
SchemaImpl arraySchema = new SchemaImpl();
schema.type(Schema.SchemaType.ARRAY);
schema.items(arraySchema);
// Should only have one arg for collection.
Type arg = pType.arguments().get(0);
if (isTerminalType(arg)) {
TypeUtil.TypeWithFormat terminalType = TypeUtil.getTypeFormat(arg);
arraySchema.type(terminalType.getSchemaType());
arraySchema.format(terminalType.getFormat().format());
} else if (arg.kind() == Type.Kind.TYPE_VARIABLE || arg.kind() == Type.Kind.UNRESOLVED_TYPE_VARIABLE || arg.kind() == Type.Kind.WILDCARD_TYPE) {
Type resolved = resolveTypeVariable(typeResolver, arraySchema, pathEntry, arg);
if (indexContains(resolved)) {
arraySchema.type(Schema.SchemaType.OBJECT);
}
} else if (indexContains(arg)) {
arraySchema.type(Schema.SchemaType.OBJECT);
pushFieldToPath(pathEntry, arg, arraySchema);
}
// Representing collection as JSON array
return ARRAY_TYPE_OBJECT;
} else if (isA(pType, MAP_TYPE)) {
LOG.debugv("Processing Map. Will treat as an object.");
schema.type(Schema.SchemaType.OBJECT);
if (pType.arguments().size() == 2) {
Type valueType = pType.arguments().get(1);
SchemaImpl propsSchema = new SchemaImpl();
if (isTerminalType(valueType)) {
TypeUtil.TypeWithFormat tf = TypeUtil.getTypeFormat(valueType);
propsSchema.setType(tf.getSchemaType());
propsSchema.setFormat(tf.getFormat().format());
} else if (valueType.kind() == Type.Kind.TYPE_VARIABLE || valueType.kind() == Type.Kind.UNRESOLVED_TYPE_VARIABLE || valueType.kind() == Type.Kind.WILDCARD_TYPE) {
Type resolved = resolveTypeVariable(typeResolver, propsSchema, pathEntry, valueType);
if (indexContains(resolved)) {
propsSchema.type(Schema.SchemaType.OBJECT);
}
} else if (indexContains(valueType)) {
propsSchema.type(Schema.SchemaType.OBJECT);
pushFieldToPath(pathEntry, valueType, propsSchema);
}
schema.additionalProperties(propsSchema);
}
return OBJECT_TYPE;
} else {
// This attempts to allow us to resolve the types generically.
ClassInfo klazz = getClassByName(pType);
// Build mapping of class's type variables (e.g. A, B) to resolved variables
// Resolved variables could be any type (e.g. String, another param type, etc)
PathEntry pair = new PathEntry(pathEntry, klazz, pType, schema);
path.push(pair);
return pType;
}
}
Aggregations