Search in sources :

Example 21 with ArrayProperty

use of io.swagger.models.properties.ArrayProperty in project swagger-core by swagger-api.

the class ModelResolver method resolveProperty.

public Property resolveProperty(JavaType propType, ModelConverterContext context, Annotation[] annotations, Iterator<ModelConverter> next) {
    LOGGER.debug("resolveProperty {}", propType);
    Property property = null;
    if (propType.isContainerType()) {
        JavaType keyType = propType.getKeyType();
        JavaType valueType = propType.getContentType();
        if (keyType != null && valueType != null) {
            property = new MapProperty().additionalProperties(context.resolveProperty(valueType, new Annotation[] {}));
        } else if (valueType != null) {
            Property items = context.resolveProperty(valueType, new Annotation[] {});
            // If property is XmlElement annotated, then use the name provided by annotation | https://github.com/swagger-api/swagger-core/issues/2047
            if (annotations != null && annotations.length > 0) {
                for (Annotation annotation : annotations) {
                    if (annotation instanceof XmlElement) {
                        XmlElement xmlElement = (XmlElement) annotation;
                        if (xmlElement != null && xmlElement.name() != null && !"".equals(xmlElement.name()) && !"##default".equals(xmlElement.name())) {
                            Xml xml = items.getXml() != null ? items.getXml() : new Xml();
                            xml.setName(xmlElement.name());
                            items.setXml(xml);
                        }
                    }
                }
            }
            ArrayProperty arrayProperty = new ArrayProperty().items(items);
            if (_isSetType(propType.getRawClass())) {
                arrayProperty.setUniqueItems(true);
            }
            property = arrayProperty;
        }
    } else {
        property = PrimitiveType.createProperty(propType);
    }
    if (property == null) {
        if (propType.isEnumType()) {
            property = new StringProperty();
            _addEnumProps(propType.getRawClass(), property);
        } else if (_isOptionalType(propType)) {
            property = context.resolveProperty(propType.containedType(0), null);
        } else {
            // complex type
            Model innerModel = context.resolve(propType);
            if (innerModel instanceof ComposedModel) {
                innerModel = ((ComposedModel) innerModel).getChild();
            }
            if (innerModel instanceof ModelImpl) {
                ModelImpl mi = (ModelImpl) innerModel;
                property = new RefProperty(StringUtils.isNotEmpty(mi.getReference()) ? mi.getReference() : mi.getName());
            }
        }
    }
    return property;
}
Also used : JavaType(com.fasterxml.jackson.databind.JavaType) ArrayProperty(io.swagger.models.properties.ArrayProperty) Xml(io.swagger.models.Xml) ComposedModel(io.swagger.models.ComposedModel) MapProperty(io.swagger.models.properties.MapProperty) Model(io.swagger.models.Model) RefModel(io.swagger.models.RefModel) ComposedModel(io.swagger.models.ComposedModel) ApiModel(io.swagger.annotations.ApiModel) XmlElement(javax.xml.bind.annotation.XmlElement) StringProperty(io.swagger.models.properties.StringProperty) ModelImpl(io.swagger.models.ModelImpl) JsonProperty(com.fasterxml.jackson.annotation.JsonProperty) StringProperty(io.swagger.models.properties.StringProperty) ArrayProperty(io.swagger.models.properties.ArrayProperty) Property(io.swagger.models.properties.Property) MapProperty(io.swagger.models.properties.MapProperty) UUIDProperty(io.swagger.models.properties.UUIDProperty) ApiModelProperty(io.swagger.annotations.ApiModelProperty) AbstractNumericProperty(io.swagger.models.properties.AbstractNumericProperty) RefProperty(io.swagger.models.properties.RefProperty) IntegerProperty(io.swagger.models.properties.IntegerProperty) Annotation(java.lang.annotation.Annotation) RefProperty(io.swagger.models.properties.RefProperty)

Example 22 with ArrayProperty

use of io.swagger.models.properties.ArrayProperty in project swagger-core by swagger-api.

the class ModelResolver method resolve.

public Model resolve(JavaType type, ModelConverterContext context, Iterator<ModelConverter> next) {
    if (type.isEnumType() || PrimitiveType.fromType(type) != null) {
        // We don't build models for primitive types
        return null;
    }
    final BeanDescription beanDesc = _mapper.getSerializationConfig().introspect(type);
    // Couple of possibilities for defining
    String name = _typeName(type, beanDesc);
    if ("Object".equals(name)) {
        return new ModelImpl();
    }
    /**
         * --Preventing parent/child hierarchy creation loops - Comment 1--
         * Creating a parent model will result in the creation of child models. Creating a child model will result in
         * the creation of a parent model, as per the second If statement following this comment.
         *
         * By checking whether a model has already been resolved (as implemented below), loops of parents creating
         * children and children creating parents can be short-circuited. This works because currently the
         * ModelConverterContextImpl will return null for a class that already been processed, but has not yet been
         * defined. This logic works in conjunction with the early immediate definition of model in the context
         * implemented later in this method (See "Preventing parent/child hierarchy creation loops - Comment 2") to
         * prevent such
         */
    Model resolvedModel = context.resolve(type.getRawClass());
    if (resolvedModel != null) {
        if (!(resolvedModel instanceof ModelImpl || resolvedModel instanceof ComposedModel) || (resolvedModel instanceof ModelImpl && ((ModelImpl) resolvedModel).getName().equals(name))) {
            return resolvedModel;
        } else if (resolvedModel instanceof ComposedModel) {
            Model childModel = ((ComposedModel) resolvedModel).getChild();
            if (childModel != null && (!(childModel instanceof ModelImpl) || ((ModelImpl) childModel).getName().equals(name))) {
                return resolvedModel;
            }
        }
    }
    final ModelImpl model = new ModelImpl().type(ModelImpl.OBJECT).name(name).description(_description(beanDesc.getClassInfo()));
    if (!type.isContainerType()) {
        // define the model here to support self/cyclic referencing of models
        context.defineModel(name, model, type, null);
    }
    if (type.isContainerType()) {
        // We treat collections as primitive types, just need to add models for values (if any)
        context.resolve(type.getContentType());
        return null;
    }
    // if XmlRootElement annotation, construct an Xml object and attach it to the model
    XmlRootElement rootAnnotation = beanDesc.getClassAnnotations().get(XmlRootElement.class);
    if (rootAnnotation != null && !"".equals(rootAnnotation.name()) && !"##default".equals(rootAnnotation.name())) {
        LOGGER.debug("{}", rootAnnotation);
        Xml xml = new Xml().name(rootAnnotation.name());
        if (rootAnnotation.namespace() != null && !"".equals(rootAnnotation.namespace()) && !"##default".equals(rootAnnotation.namespace())) {
            xml.namespace(rootAnnotation.namespace());
        }
        model.xml(xml);
    }
    final XmlAccessorType xmlAccessorTypeAnnotation = beanDesc.getClassAnnotations().get(XmlAccessorType.class);
    // see if @JsonIgnoreProperties exist
    Set<String> propertiesToIgnore = new HashSet<String>();
    JsonIgnoreProperties ignoreProperties = beanDesc.getClassAnnotations().get(JsonIgnoreProperties.class);
    if (ignoreProperties != null) {
        propertiesToIgnore.addAll(Arrays.asList(ignoreProperties.value()));
    }
    final ApiModel apiModel = beanDesc.getClassAnnotations().get(ApiModel.class);
    String disc = (apiModel == null) ? "" : apiModel.discriminator();
    if (apiModel != null && StringUtils.isNotEmpty(apiModel.reference())) {
        model.setReference(apiModel.reference());
    }
    if (disc.isEmpty()) {
        // longer method would involve AnnotationIntrospector.findTypeResolver(...) but:
        JsonTypeInfo typeInfo = beanDesc.getClassAnnotations().get(JsonTypeInfo.class);
        if (typeInfo != null) {
            disc = typeInfo.property();
        }
    }
    if (!disc.isEmpty()) {
        model.setDiscriminator(disc);
    }
    List<Property> props = new ArrayList<Property>();
    for (BeanPropertyDefinition propDef : beanDesc.findProperties()) {
        Property property = null;
        String propName = propDef.getName();
        Annotation[] annotations = null;
        // it's ugly but gets around https://github.com/swagger-api/swagger-core/issues/415
        if (propDef.getPrimaryMember() != null) {
            java.lang.reflect.Member member = propDef.getPrimaryMember().getMember();
            if (member != null) {
                String altName = member.getName();
                if (altName != null) {
                    final int length = altName.length();
                    for (String prefix : Arrays.asList("get", "is")) {
                        final int offset = prefix.length();
                        if (altName.startsWith(prefix) && length > offset && !Character.isUpperCase(altName.charAt(offset))) {
                            propName = altName;
                            break;
                        }
                    }
                }
            }
        }
        PropertyMetadata md = propDef.getMetadata();
        boolean hasSetter = false, hasGetter = false;
        try {
            if (propDef.getSetter() == null) {
                hasSetter = false;
            } else {
                hasSetter = true;
            }
        } catch (IllegalArgumentException e) {
            //com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder would throw IllegalArgumentException
            // if there are overloaded setters. If we only want to know whether a set method exists, suppress the exception
            // is reasonable.
            // More logs might be added here
            hasSetter = true;
        }
        if (propDef.getGetter() != null) {
            JsonProperty pd = propDef.getGetter().getAnnotation(JsonProperty.class);
            if (pd != null) {
                hasGetter = true;
            }
        }
        Boolean isReadOnly = null;
        if (!hasSetter & hasGetter) {
            isReadOnly = Boolean.TRUE;
        } else {
            isReadOnly = Boolean.FALSE;
        }
        final AnnotatedMember member = propDef.getPrimaryMember();
        Boolean allowEmptyValue = null;
        if (member != null && !ignore(member, xmlAccessorTypeAnnotation, propName, propertiesToIgnore)) {
            List<Annotation> annotationList = new ArrayList<Annotation>();
            for (Annotation a : member.annotations()) {
                annotationList.add(a);
            }
            annotations = annotationList.toArray(new Annotation[annotationList.size()]);
            ApiModelProperty mp = member.getAnnotation(ApiModelProperty.class);
            if (mp != null && mp.readOnly()) {
                isReadOnly = mp.readOnly();
            }
            if (mp != null && mp.allowEmptyValue()) {
                allowEmptyValue = mp.allowEmptyValue();
            } else {
                allowEmptyValue = null;
            }
            JavaType propType = member.getType(beanDesc.bindingsForBeanType());
            // allow override of name from annotation
            if (mp != null && !mp.name().isEmpty()) {
                propName = mp.name();
            }
            if (mp != null && !mp.dataType().isEmpty()) {
                String or = mp.dataType();
                JavaType innerJavaType = null;
                LOGGER.debug("overriding datatype from {} to {}", propType, or);
                if (or.toLowerCase().startsWith("list[")) {
                    String innerType = or.substring(5, or.length() - 1);
                    ArrayProperty p = new ArrayProperty();
                    Property primitiveProperty = PrimitiveType.createProperty(innerType);
                    if (primitiveProperty != null) {
                        p.setItems(primitiveProperty);
                    } else {
                        innerJavaType = getInnerType(innerType);
                        p.setItems(context.resolveProperty(innerJavaType, annotations));
                    }
                    property = p;
                } else if (or.toLowerCase().startsWith("map[")) {
                    int pos = or.indexOf(",");
                    if (pos > 0) {
                        String innerType = or.substring(pos + 1, or.length() - 1);
                        MapProperty p = new MapProperty();
                        Property primitiveProperty = PrimitiveType.createProperty(innerType);
                        if (primitiveProperty != null) {
                            p.setAdditionalProperties(primitiveProperty);
                        } else {
                            innerJavaType = getInnerType(innerType);
                            p.setAdditionalProperties(context.resolveProperty(innerJavaType, annotations));
                        }
                        property = p;
                    }
                } else {
                    Property primitiveProperty = PrimitiveType.createProperty(or);
                    if (primitiveProperty != null) {
                        property = primitiveProperty;
                    } else {
                        innerJavaType = getInnerType(or);
                        property = context.resolveProperty(innerJavaType, annotations);
                    }
                }
                if (innerJavaType != null) {
                    context.resolve(innerJavaType);
                }
            }
            // no property from override, construct from propType
            if (property == null) {
                if (mp != null && StringUtils.isNotEmpty(mp.reference())) {
                    property = new RefProperty(mp.reference());
                } else if (member.getAnnotation(JsonIdentityInfo.class) != null) {
                    property = GeneratorWrapper.processJsonIdentity(propType, context, _mapper, member.getAnnotation(JsonIdentityInfo.class), member.getAnnotation(JsonIdentityReference.class));
                }
                if (property == null) {
                    JsonUnwrapped uw = member.getAnnotation(JsonUnwrapped.class);
                    if (uw != null && uw.enabled()) {
                        handleUnwrapped(props, context.resolve(propType), uw.prefix(), uw.suffix());
                    } else {
                        property = context.resolveProperty(propType, annotations);
                    }
                }
            }
            if (property != null) {
                property.setName(propName);
                if (mp != null && !mp.access().isEmpty()) {
                    property.setAccess(mp.access());
                }
                Boolean required = md.getRequired();
                if (required != null) {
                    property.setRequired(required);
                }
                String description = _intr.findPropertyDescription(member);
                if (description != null && !"".equals(description)) {
                    property.setDescription(description);
                }
                Integer index = _intr.findPropertyIndex(member);
                if (index != null) {
                    property.setPosition(index);
                }
                property.setDefault(_findDefaultValue(member));
                property.setExample(_findExampleValue(member));
                property.setReadOnly(_findReadOnly(member));
                if (allowEmptyValue != null) {
                    property.setAllowEmptyValue(allowEmptyValue);
                }
                if (property.getReadOnly() == null) {
                    if (isReadOnly) {
                        property.setReadOnly(isReadOnly);
                    }
                }
                if (mp != null) {
                    final AllowableValues allowableValues = AllowableValuesUtils.create(mp.allowableValues());
                    if (allowableValues != null) {
                        final Map<PropertyBuilder.PropertyId, Object> args = allowableValues.asPropertyArguments();
                        PropertyBuilder.merge(property, args);
                    }
                }
                JAXBAnnotationsHelper.apply(member, property);
                applyBeanValidatorAnnotations(property, annotations);
                props.add(property);
            }
        }
    }
    Collections.sort(props, getPropertyComparator());
    Map<String, Property> modelProps = new LinkedHashMap<String, Property>();
    for (Property prop : props) {
        modelProps.put(prop.getName(), prop);
    }
    model.setProperties(modelProps);
    /**
         * --Preventing parent/child hierarchy creation loops - Comment 2--
         * Creating a parent model will result in the creation of child models, as per the first If statement following
         * this comment. Creating a child model will result in the creation of a parent model, as per the second If
         * statement following this comment.
         *
         * The current model must be defined in the context immediately. This done to help prevent repeated
         * loops where  parents create children and children create parents when a hierarchy is present. This logic
         * works in conjunction with the "early checking" performed earlier in this method
         * (See "Preventing parent/child hierarchy creation loops - Comment 1"), to prevent repeated creation loops.
         *
         *
         * As an aside, defining the current model in the context immediately also ensures that child models are
         * available for modification by resolveSubtypes, when their parents are created.
         */
    Class<?> currentType = type.getRawClass();
    context.defineModel(name, model, currentType, null);
    /**
         * This must be done after model.setProperties so that the model's set
         * of properties is available to filter from any subtypes
         **/
    if (!resolveSubtypes(model, beanDesc, context)) {
        model.setDiscriminator(null);
    }
    if (apiModel != null) {
        /**
             * Check if the @ApiModel annotation has a parent property containing a value that should not be ignored
             */
        Class<?> parentClass = apiModel.parent();
        if (parentClass != null && !parentClass.equals(Void.class) && !this.shouldIgnoreClass(parentClass)) {
            JavaType parentType = _mapper.constructType(parentClass);
            final BeanDescription parentBeanDesc = _mapper.getSerializationConfig().introspect(parentType);
            /**
                 * Retrieve all the sub-types of the parent class and ensure that the current type is one of those types
                 */
            boolean currentTypeIsParentSubType = false;
            List<NamedType> subTypes = _intr.findSubtypes(parentBeanDesc.getClassInfo());
            if (subTypes != null) {
                for (NamedType subType : subTypes) {
                    if (subType.getType().equals(currentType)) {
                        currentTypeIsParentSubType = true;
                        break;
                    }
                }
            }
            /**
                 Retrieve the subTypes from the parent class @ApiModel annotation and ensure that the current type
                 is one of those types.
                 */
            boolean currentTypeIsParentApiModelSubType = false;
            final ApiModel parentApiModel = parentBeanDesc.getClassAnnotations().get(ApiModel.class);
            if (parentApiModel != null) {
                Class<?>[] apiModelSubTypes = parentApiModel.subTypes();
                if (apiModelSubTypes != null) {
                    for (Class<?> subType : apiModelSubTypes) {
                        if (subType.equals(currentType)) {
                            currentTypeIsParentApiModelSubType = true;
                            break;
                        }
                    }
                }
            }
            /**
                 If the current type is a sub-type of the parent class and is listed in the subTypes property of the
                 parent class @ApiModel annotation, then do the following:
                 1. Resolve the model for the parent class. This will result in the parent model being created, and the
                 current child model being updated to be a ComposedModel referencing the parent.
                 2. Resolve and return the current child type again. This will return the new ComposedModel from the
                 context, which was created in step 1 above. Admittedly, there is a small chance that this may result
                 in a stack overflow, if the context does not correctly cache the model for the current type. However,
                 as context caching is assumed elsewhere to avoid cyclical model creation, this was deemed to be
                 sufficient.
                 */
            if (currentTypeIsParentSubType && currentTypeIsParentApiModelSubType) {
                context.resolve(parentClass);
                return context.resolve(currentType);
            }
        }
    }
    return model;
}
Also used : ApiModelProperty(io.swagger.annotations.ApiModelProperty) JsonProperty(com.fasterxml.jackson.annotation.JsonProperty) ComposedModel(io.swagger.models.ComposedModel) MapProperty(io.swagger.models.properties.MapProperty) ArrayList(java.util.ArrayList) AnnotatedMember(com.fasterxml.jackson.databind.introspect.AnnotatedMember) AllowableValues(io.swagger.util.AllowableValues) LinkedHashMap(java.util.LinkedHashMap) PropertyMetadata(com.fasterxml.jackson.databind.PropertyMetadata) HashSet(java.util.HashSet) XmlRootElement(javax.xml.bind.annotation.XmlRootElement) ArrayProperty(io.swagger.models.properties.ArrayProperty) BeanDescription(com.fasterxml.jackson.databind.BeanDescription) JsonIdentityReference(com.fasterxml.jackson.annotation.JsonIdentityReference) JavaType(com.fasterxml.jackson.databind.JavaType) XmlAccessorType(javax.xml.bind.annotation.XmlAccessorType) NamedType(com.fasterxml.jackson.databind.jsontype.NamedType) ApiModel(io.swagger.annotations.ApiModel) JsonIgnoreProperties(com.fasterxml.jackson.annotation.JsonIgnoreProperties) RefProperty(io.swagger.models.properties.RefProperty) BeanPropertyDefinition(com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition) ModelImpl(io.swagger.models.ModelImpl) JsonUnwrapped(com.fasterxml.jackson.annotation.JsonUnwrapped) JsonProperty(com.fasterxml.jackson.annotation.JsonProperty) StringProperty(io.swagger.models.properties.StringProperty) ArrayProperty(io.swagger.models.properties.ArrayProperty) Property(io.swagger.models.properties.Property) MapProperty(io.swagger.models.properties.MapProperty) UUIDProperty(io.swagger.models.properties.UUIDProperty) ApiModelProperty(io.swagger.annotations.ApiModelProperty) AbstractNumericProperty(io.swagger.models.properties.AbstractNumericProperty) RefProperty(io.swagger.models.properties.RefProperty) IntegerProperty(io.swagger.models.properties.IntegerProperty) JsonTypeInfo(com.fasterxml.jackson.annotation.JsonTypeInfo) Annotation(java.lang.annotation.Annotation) JsonIdentityInfo(com.fasterxml.jackson.annotation.JsonIdentityInfo) Xml(io.swagger.models.Xml) Model(io.swagger.models.Model) RefModel(io.swagger.models.RefModel) ComposedModel(io.swagger.models.ComposedModel) ApiModel(io.swagger.annotations.ApiModel)

Example 23 with ArrayProperty

use of io.swagger.models.properties.ArrayProperty in project swagger-core by swagger-api.

the class ModelResolver method applyBeanValidatorAnnotations.

protected void applyBeanValidatorAnnotations(Property property, Annotation[] annotations) {
    Map<String, Annotation> annos = new HashMap<String, Annotation>();
    if (annotations != null) {
        for (Annotation anno : annotations) {
            annos.put(anno.annotationType().getName(), anno);
        }
    }
    if (annos.containsKey("javax.validation.constraints.NotNull")) {
        property.setRequired(true);
    }
    if (annos.containsKey("javax.validation.constraints.Min")) {
        if (property instanceof AbstractNumericProperty) {
            Min min = (Min) annos.get("javax.validation.constraints.Min");
            AbstractNumericProperty ap = (AbstractNumericProperty) property;
            ap.setMinimum(new BigDecimal(min.value()));
        }
    }
    if (annos.containsKey("javax.validation.constraints.Max")) {
        if (property instanceof AbstractNumericProperty) {
            Max max = (Max) annos.get("javax.validation.constraints.Max");
            AbstractNumericProperty ap = (AbstractNumericProperty) property;
            ap.setMaximum(new BigDecimal(max.value()));
        }
    }
    if (annos.containsKey("javax.validation.constraints.Size")) {
        Size size = (Size) annos.get("javax.validation.constraints.Size");
        if (property instanceof AbstractNumericProperty) {
            AbstractNumericProperty ap = (AbstractNumericProperty) property;
            ap.setMinimum(new BigDecimal(size.min()));
            ap.setMaximum(new BigDecimal(size.max()));
        } else if (property instanceof StringProperty) {
            StringProperty sp = (StringProperty) property;
            sp.minLength(new Integer(size.min()));
            sp.maxLength(new Integer(size.max()));
        } else if (property instanceof ArrayProperty) {
            ArrayProperty sp = (ArrayProperty) property;
            sp.setMinItems(size.min());
            sp.setMaxItems(size.max());
        }
    }
    if (annos.containsKey("javax.validation.constraints.DecimalMin")) {
        DecimalMin min = (DecimalMin) annos.get("javax.validation.constraints.DecimalMin");
        if (property instanceof AbstractNumericProperty) {
            AbstractNumericProperty ap = (AbstractNumericProperty) property;
            ap.setMinimum(new BigDecimal(min.value()));
            ap.setExclusiveMinimum(!min.inclusive());
        }
    }
    if (annos.containsKey("javax.validation.constraints.DecimalMax")) {
        DecimalMax max = (DecimalMax) annos.get("javax.validation.constraints.DecimalMax");
        if (property instanceof AbstractNumericProperty) {
            AbstractNumericProperty ap = (AbstractNumericProperty) property;
            ap.setMaximum(new BigDecimal(max.value()));
            ap.setExclusiveMaximum(!max.inclusive());
        }
    }
    if (annos.containsKey("javax.validation.constraints.Pattern")) {
        Pattern pattern = (Pattern) annos.get("javax.validation.constraints.Pattern");
        if (property instanceof StringProperty) {
            StringProperty ap = (StringProperty) property;
            ap.setPattern(pattern.regexp());
        }
    }
}
Also used : Pattern(javax.validation.constraints.Pattern) ArrayProperty(io.swagger.models.properties.ArrayProperty) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Max(javax.validation.constraints.Max) DecimalMax(javax.validation.constraints.DecimalMax) Size(javax.validation.constraints.Size) StringProperty(io.swagger.models.properties.StringProperty) DecimalMin(javax.validation.constraints.DecimalMin) Annotation(java.lang.annotation.Annotation) BigDecimal(java.math.BigDecimal) AbstractNumericProperty(io.swagger.models.properties.AbstractNumericProperty) Min(javax.validation.constraints.Min) DecimalMin(javax.validation.constraints.DecimalMin) DecimalMax(javax.validation.constraints.DecimalMax)

Example 24 with ArrayProperty

use of io.swagger.models.properties.ArrayProperty in project swagger-core by swagger-api.

the class PropertyDeserializer method propertyFromNode.

Property propertyFromNode(JsonNode node) {
    final String type = getString(node, PropertyBuilder.PropertyId.TYPE);
    final String title = getString(node, PropertyBuilder.PropertyId.TITLE);
    final String format = getString(node, PropertyBuilder.PropertyId.FORMAT);
    String description = getString(node, PropertyBuilder.PropertyId.DESCRIPTION);
    JsonNode detailNode = node.get("$ref");
    if (detailNode != null) {
        return new RefProperty(detailNode.asText()).description(description).title(title);
    }
    if (ObjectProperty.isType(type) || node.get("properties") != null) {
        JsonNode example = getDetailNode(node, PropertyBuilder.PropertyId.EXAMPLE);
        detailNode = node.get("additionalProperties");
        if (detailNode != null && detailNode.getNodeType().equals(JsonNodeType.OBJECT)) {
            Property items = propertyFromNode(detailNode);
            if (items != null) {
                MapProperty mapProperty = new MapProperty(items).description(description).title(title);
                mapProperty.setExample(example);
                mapProperty.setMinProperties(getInteger(node, PropertyBuilder.PropertyId.MIN_PROPERTIES));
                mapProperty.setMaxProperties(getInteger(node, PropertyBuilder.PropertyId.MAX_PROPERTIES));
                mapProperty.setVendorExtensionMap(getVendorExtensions(node));
                return mapProperty;
            }
        } else {
            detailNode = node.get("properties");
            String detailNodeType = null;
            Map<String, Property> properties = new LinkedHashMap<String, Property>();
            if (detailNode != null) {
                for (Iterator<Map.Entry<String, JsonNode>> iter = detailNode.fields(); iter.hasNext(); ) {
                    Map.Entry<String, JsonNode> field = iter.next();
                    Property property = propertyFromNode(field.getValue());
                    if (property != null) {
                        properties.put(field.getKey(), property);
                    } else {
                        if ("type".equals(field.getKey()) && field.getValue() != null && "array".equals(field.getValue().asText())) {
                            detailNodeType = "array";
                        }
                        if (("description").equals(field.getKey()) && field.getValue().getNodeType().equals(JsonNodeType.STRING)) {
                            description = field.getValue().asText();
                        }
                    }
                }
            }
            if ("array".equals(detailNodeType)) {
                ArrayProperty ap = new ArrayProperty().description(description).title(title);
                ap.setExample(example);
                PropertyBuilder.merge(ap, argsFromNode(detailNode));
                ap.setDescription(description);
                if (properties.keySet().size() == 1) {
                    String key = properties.keySet().iterator().next();
                    ap.setItems(properties.get(key));
                }
                ap.setVendorExtensionMap(getVendorExtensions(node));
                return ap;
            }
            ObjectProperty objectProperty = new ObjectProperty(properties).description(description).title(title);
            objectProperty.setExample(example);
            objectProperty.setVendorExtensionMap(getVendorExtensions(node));
            List<String> required = getRequired(node, PropertyBuilder.PropertyId.REQUIRED);
            objectProperty.setRequiredProperties(required);
            return objectProperty;
        }
    }
    if (ArrayProperty.isType(type)) {
        detailNode = node.get("items");
        if (detailNode != null) {
            Property subProperty = propertyFromNode(detailNode);
            ArrayProperty arrayProperty = new ArrayProperty().items(subProperty).description(description).title(title);
            arrayProperty.setMinItems(getInteger(node, PropertyBuilder.PropertyId.MIN_ITEMS));
            arrayProperty.setMaxItems(getInteger(node, PropertyBuilder.PropertyId.MAX_ITEMS));
            arrayProperty.setUniqueItems(getBoolean(node, PropertyBuilder.PropertyId.UNIQUE_ITEMS));
            JsonNode example = getDetailNode(node, PropertyBuilder.PropertyId.EXAMPLE);
            arrayProperty.setExample(example);
            arrayProperty.setVendorExtensionMap(getVendorExtensions(node));
            return arrayProperty;
        }
    }
    Map<PropertyBuilder.PropertyId, Object> args = argsFromNode(node);
    Property output = PropertyBuilder.build(type, format, args);
    if (output == null) {
        LOGGER.warn("no property from " + type + ", " + format + ", " + args);
        return null;
    }
    output.setDescription(description);
    return output;
}
Also used : ObjectProperty(io.swagger.models.properties.ObjectProperty) ArrayProperty(io.swagger.models.properties.ArrayProperty) MapProperty(io.swagger.models.properties.MapProperty) JsonNode(com.fasterxml.jackson.databind.JsonNode) RefProperty(io.swagger.models.properties.RefProperty) LinkedHashMap(java.util.LinkedHashMap) ArrayProperty(io.swagger.models.properties.ArrayProperty) RefProperty(io.swagger.models.properties.RefProperty) Property(io.swagger.models.properties.Property) MapProperty(io.swagger.models.properties.MapProperty) ObjectProperty(io.swagger.models.properties.ObjectProperty) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) EnumMap(java.util.EnumMap)

Example 25 with ArrayProperty

use of io.swagger.models.properties.ArrayProperty in project swagger-core by swagger-api.

the class ModelConverterTest method processModelWithPairProperties.

@Test(description = "it should process a model with org.apache.commons.lang3.tuple.Pair properties")
public void processModelWithPairProperties() {
    final ModelWithTuple2.TupleAsMapModelConverter asMapConverter = new ModelWithTuple2.TupleAsMapModelConverter(Json.mapper());
    ModelConverters.getInstance().addConverter(asMapConverter);
    final Map<String, Model> asMap = readAll(ModelWithTuple2.class);
    ModelConverters.getInstance().removeConverter(asMapConverter);
    assertEquals(asMap.size(), 4);
    for (String item : Arrays.asList("MapOfString", "MapOfComplexLeft")) {
        ModelImpl model = (ModelImpl) asMap.get(item);
        assertEquals(model.getType(), "object");
        assertNull(model.getProperties());
        assertNotNull(model.getAdditionalProperties());
    }
    final ModelWithTuple2.TupleAsMapPropertyConverter asPropertyConverter = new ModelWithTuple2.TupleAsMapPropertyConverter(Json.mapper());
    ModelConverters.getInstance().addConverter(asPropertyConverter);
    final Map<String, Model> asProperty = readAll(ModelWithTuple2.class);
    ModelConverters.getInstance().removeConverter(asPropertyConverter);
    assertEquals(asProperty.size(), 2);
    for (Map.Entry<String, Property> entry : asProperty.get("ModelWithTuple2").getProperties().entrySet()) {
        String name = entry.getKey();
        Property property = entry.getValue();
        if ("timesheetStates".equals(name)) {
            assertEquals(property.getClass(), MapProperty.class);
        } else if ("manyPairs".equals(name)) {
            assertEquals(property.getClass(), ArrayProperty.class);
            Property items = ((ArrayProperty) property).getItems();
            assertNotNull(items);
            assertEquals(items.getClass(), MapProperty.class);
            Property stringProperty = ((MapProperty) items).getAdditionalProperties();
            assertNotNull(stringProperty);
            assertEquals(stringProperty.getClass(), StringProperty.class);
        } else if ("complexLeft".equals(name)) {
            assertEquals(property.getClass(), ArrayProperty.class);
            Property items = ((ArrayProperty) property).getItems();
            assertNotNull(items);
            assertEquals(items.getClass(), MapProperty.class);
            Property additionalProperty = ((MapProperty) items).getAdditionalProperties();
            assertNotNull(additionalProperty);
            assertEquals(additionalProperty.getClass(), RefProperty.class);
            assertEquals(((RefProperty) additionalProperty).getSimpleRef(), "ComplexLeft");
        } else {
            fail(String.format("Unexpected property: %s", name));
        }
    }
}
Also used : ArrayProperty(io.swagger.models.properties.ArrayProperty) ModelWithTuple2(io.swagger.models.ModelWithTuple2) MapProperty(io.swagger.models.properties.MapProperty) StringProperty(io.swagger.models.properties.StringProperty) AbstractModelWithApiModel(io.swagger.models.composition.AbstractModelWithApiModel) Model(io.swagger.models.Model) ModelWithApiModel(io.swagger.models.ModelWithApiModel) EmptyModel(io.swagger.models.EmptyModel) JodaDateTimeModel(io.swagger.models.JodaDateTimeModel) JacksonReadonlyModel(io.swagger.models.JacksonReadonlyModel) ModelImpl(io.swagger.models.ModelImpl) Map(java.util.Map) StringProperty(io.swagger.models.properties.StringProperty) ArrayProperty(io.swagger.models.properties.ArrayProperty) LongProperty(io.swagger.models.properties.LongProperty) DecimalProperty(io.swagger.models.properties.DecimalProperty) Property(io.swagger.models.properties.Property) DoubleProperty(io.swagger.models.properties.DoubleProperty) MapProperty(io.swagger.models.properties.MapProperty) ApiModelProperty(io.swagger.annotations.ApiModelProperty) BaseIntegerProperty(io.swagger.models.properties.BaseIntegerProperty) ModelWithUrlProperty(io.swagger.models.composition.ModelWithUrlProperty) RefProperty(io.swagger.models.properties.RefProperty) FloatProperty(io.swagger.models.properties.FloatProperty) IntegerProperty(io.swagger.models.properties.IntegerProperty) Test(org.testng.annotations.Test)

Aggregations

ArrayProperty (io.swagger.models.properties.ArrayProperty)43 Property (io.swagger.models.properties.Property)30 Test (org.testng.annotations.Test)30 StringProperty (io.swagger.models.properties.StringProperty)23 Model (io.swagger.models.Model)14 MapProperty (io.swagger.models.properties.MapProperty)14 IntegerProperty (io.swagger.models.properties.IntegerProperty)12 RefProperty (io.swagger.models.properties.RefProperty)12 ModelImpl (io.swagger.models.ModelImpl)8 DoubleProperty (io.swagger.models.properties.DoubleProperty)7 LongProperty (io.swagger.models.properties.LongProperty)7 Operation (io.swagger.models.Operation)6 ByteArrayProperty (io.swagger.models.properties.ByteArrayProperty)6 FloatProperty (io.swagger.models.properties.FloatProperty)5 ApiModelProperty (io.swagger.annotations.ApiModelProperty)4 AbstractNumericProperty (io.swagger.models.properties.AbstractNumericProperty)4 BaseIntegerProperty (io.swagger.models.properties.BaseIntegerProperty)4 BooleanProperty (io.swagger.models.properties.BooleanProperty)4 DecimalProperty (io.swagger.models.properties.DecimalProperty)4 Annotation (java.lang.annotation.Annotation)4