/** * Copyright © 2006-2016 Web Cohesion (info@webcohesion.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.webcohesion.enunciate.modules.jackson.api.impl; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.webcohesion.enunciate.api.ApiRegistrationContext; import com.webcohesion.enunciate.api.datatype.*; import com.webcohesion.enunciate.facets.FacetFilter; import com.webcohesion.enunciate.javac.decorations.type.DecoratedTypeMirror; import com.webcohesion.enunciate.modules.jackson.model.Member; import com.webcohesion.enunciate.modules.jackson.model.ObjectTypeDefinition; import com.webcohesion.enunciate.modules.jackson.model.TypeDefinition; import com.webcohesion.enunciate.modules.jackson.model.types.JsonClassType; import com.webcohesion.enunciate.modules.jackson.model.types.JsonType; import com.webcohesion.enunciate.modules.jackson.model.types.JsonTypeFactory; import javax.lang.model.element.TypeElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; import java.util.*; /** * @author Ryan Heaton */ public class ObjectDataTypeImpl extends DataTypeImpl { final ObjectTypeDefinition typeDefinition; public ObjectDataTypeImpl(ObjectTypeDefinition typeDefinition, ApiRegistrationContext registrationContext) { super(typeDefinition, registrationContext); this.typeDefinition = typeDefinition; } @Override public BaseType getBaseType() { return BaseType.object; } @Override public List<? extends Value> getValues() { return null; } @Override public List<? extends Property> getProperties() { SortedSet<Member> members = this.typeDefinition.getMembers(); ArrayList<Property> properties = new ArrayList<Property>(members.size()); FacetFilter facetFilter = this.typeDefinition.getContext().getContext().getConfiguration().getFacetFilter(); for (Member member : members) { if (!facetFilter.accept(member)) { continue; } if (member.getChoices().size() > 1) { JsonTypeInfo.As inclusion = member.getSubtypeIdInclusion(); if (inclusion == JsonTypeInfo.As.WRAPPER_ARRAY || inclusion == JsonTypeInfo.As.WRAPPER_OBJECT) { for (Member choice : member.getChoices()) { properties.add(new PropertyImpl(choice, registrationContext)); } } else { properties.add(new PropertyImpl(member, registrationContext)); } } else { properties.add(new PropertyImpl(member, registrationContext)); } } return properties; } public List<? extends Property> getRequiredProperties() { ArrayList<Property> requiredProperties = new ArrayList<Property>(); for (Property property : getProperties()) { if (property.isRequired()) { requiredProperties.add(property); } } return requiredProperties; } @Override public List<DataTypeReference> getSupertypes() { ArrayList<DataTypeReference> supertypes = null; JsonType supertype = this.typeDefinition.getSupertype(); while (supertype != null) { if (supertypes == null) { supertypes = new ArrayList<DataTypeReference>(); } supertypes.add(new DataTypeReferenceImpl(supertype, registrationContext)); supertype = supertype instanceof JsonClassType ? ((JsonClassType) supertype).getTypeDefinition() instanceof ObjectTypeDefinition ? ((ObjectTypeDefinition) ((JsonClassType) supertype).getTypeDefinition()).getSupertype() : null : null; } return supertypes; } @Override public Set<DataTypeReference> getInterfaces() { Set<DataTypeReference> interfaces = new TreeSet<DataTypeReference>(new Comparator<DataTypeReference>() { @Override public int compare(DataTypeReference o1, DataTypeReference o2) { return o1.getSlug().compareTo(o2.getSlug()); } }); gatherInterfaces(this.typeDefinition, interfaces); return interfaces.isEmpty() ? null : interfaces; } private void gatherInterfaces(TypeElement clazz, Set<DataTypeReference> interfaces) { if (clazz == null) { return; } if (clazz.getQualifiedName().contentEquals(Object.class.getName())) { return; } List<? extends TypeMirror> ifaces = clazz.getInterfaces(); for (TypeMirror iface : ifaces) { DecoratedTypeMirror decorated = (DecoratedTypeMirror) iface; decorated = this.typeDefinition.getContext().resolveSyntheticType(decorated); TypeDefinition typeDefinition = this.typeDefinition.getContext().findTypeDefinition(((DeclaredType) decorated).asElement()); if (typeDefinition != null) { interfaces.add(new DataTypeReferenceImpl(new JsonClassType(typeDefinition), registrationContext)); } } TypeMirror superclass = clazz.getSuperclass(); if (superclass instanceof DeclaredType) { gatherInterfaces((TypeElement) ((DeclaredType) superclass).asElement(), interfaces); } } @Override public List<DataTypeReference> getSubtypes() { ArrayList<DataTypeReference> subtypes = new ArrayList<DataTypeReference>(); for (TypeDefinition td : this.typeDefinition.getContext().getTypeDefinitions()) { if (td instanceof ObjectTypeDefinition && !td.getQualifiedName().contentEquals(this.typeDefinition.getQualifiedName()) && ((DecoratedTypeMirror)td.asType()).isInstanceOf(this.typeDefinition)) { subtypes.add(new DataTypeReferenceImpl(JsonTypeFactory.getJsonType(td.asType(), this.typeDefinition.getContext()), registrationContext)); } } return subtypes.isEmpty() ? null : subtypes; } @Override public Example getExample() { return this.typeDefinition.getContext().isDisableExamples() ? null : new DataTypeExampleImpl(this.typeDefinition); } }