Search in sources :

Example 1 with SchemaImpl

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;
}
Also used : SchemaImpl(org.wildfly.swarm.microprofile.openapi.api.models.media.SchemaImpl)

Example 2 with SchemaImpl

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;
}
Also used : SchemaImpl(org.wildfly.swarm.microprofile.openapi.api.models.media.SchemaImpl)

Example 3 with SchemaImpl

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;
}
Also used : SchemaImpl(org.wildfly.swarm.microprofile.openapi.api.models.media.SchemaImpl) TypeUtil(org.wildfly.swarm.microprofile.openapi.runtime.util.TypeUtil) Schema(org.eclipse.microprofile.openapi.models.media.Schema)

Example 4 with SchemaImpl

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;
}
Also used : ArrayType(org.jboss.jandex.ArrayType) SchemaImpl(org.wildfly.swarm.microprofile.openapi.api.models.media.SchemaImpl) TypeUtil(org.wildfly.swarm.microprofile.openapi.runtime.util.TypeUtil) FieldInfo(org.jboss.jandex.FieldInfo) ClassInfo(org.jboss.jandex.ClassInfo)

Example 5 with SchemaImpl

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;
    }
}
Also used : SchemaImpl(org.wildfly.swarm.microprofile.openapi.api.models.media.SchemaImpl) PrimitiveType(org.jboss.jandex.PrimitiveType) Type(org.jboss.jandex.Type) ParameterizedType(org.jboss.jandex.ParameterizedType) ArrayType(org.jboss.jandex.ArrayType) TypeUtil(org.wildfly.swarm.microprofile.openapi.runtime.util.TypeUtil) ClassInfo(org.jboss.jandex.ClassInfo)

Aggregations

SchemaImpl (org.wildfly.swarm.microprofile.openapi.api.models.media.SchemaImpl)9 Schema (org.eclipse.microprofile.openapi.models.media.Schema)5 TypeUtil (org.wildfly.swarm.microprofile.openapi.runtime.util.TypeUtil)3 AnnotationInstance (org.jboss.jandex.AnnotationInstance)2 ArrayType (org.jboss.jandex.ArrayType)2 ClassInfo (org.jboss.jandex.ClassInfo)2 FieldInfo (org.jboss.jandex.FieldInfo)1 ParameterizedType (org.jboss.jandex.ParameterizedType)1 PrimitiveType (org.jboss.jandex.PrimitiveType)1 Type (org.jboss.jandex.Type)1