package com.webcohesion.enunciate.modules.jackson.api.impl; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.webcohesion.enunciate.api.ApiRegistrationContext; import com.webcohesion.enunciate.api.InterfaceDescriptionFile; import com.webcohesion.enunciate.api.datatype.*; import com.webcohesion.enunciate.api.resources.MediaTypeDescriptor; import com.webcohesion.enunciate.facets.FacetFilter; import com.webcohesion.enunciate.javac.decorations.type.DecoratedTypeMirror; import com.webcohesion.enunciate.modules.jackson.EnunciateJacksonContext; import com.webcohesion.enunciate.modules.jackson.model.EnumTypeDefinition; import com.webcohesion.enunciate.modules.jackson.model.ObjectTypeDefinition; import com.webcohesion.enunciate.modules.jackson.model.TypeDefinition; 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 java.io.Reader; import java.util.*; /** * @author Ryan Heaton */ public class SyntaxImpl implements Syntax, Namespace { public static final String SYNTAX_LABEL = "JSON"; private final EnunciateJacksonContext context; private ApiRegistrationContext registrationContext; public SyntaxImpl(EnunciateJacksonContext context, ApiRegistrationContext registrationContext) { this.context = context; this.registrationContext = registrationContext; } @Override public String getId() { return "jackson"; } @Override public int compareTo(Syntax syntax) { return getId().compareTo(syntax.getId()); } @Override public String getSlug() { return "syntax_json"; } @Override public String getLabel() { return SYNTAX_LABEL; } @Override public boolean isEmpty() { return this.context.getTypeDefinitions().isEmpty(); } @Override public List<Namespace> getNamespaces() { return Collections.singletonList((Namespace) this); } @Override public boolean isAssignableToMediaType(String mediaType) { return mediaType != null && (mediaType.equals("*/*") || mediaType.equals("application/*") || mediaType.endsWith("/json") || mediaType.endsWith("+json")); } @Override public MediaTypeDescriptor findMediaTypeDescriptor(String mediaType, DecoratedTypeMirror typeMirror) { if (mediaType == null) { return null; } //if it's a wildcard, we'll return an implicit descriptor. if (mediaType.equals("*/*") || mediaType.equals("application/*")) { mediaType = "application/json"; } if (mediaType.endsWith("/json") || mediaType.endsWith("+json")) { typeMirror = this.context.resolveSyntheticType(typeMirror); DataTypeReference typeReference = findDataTypeReference(typeMirror); return typeReference == null ? null : new MediaTypeDescriptorImpl(mediaType, typeReference); } else { return null; } } private DataTypeReference findDataTypeReference(DecoratedTypeMirror typeMirror) { if (typeMirror == null) { return null; } JsonType jsonType; try { jsonType = JsonTypeFactory.getJsonType(typeMirror, this.context); } catch (Exception e) { jsonType = null; } return jsonType == null ? null : new DataTypeReferenceImpl(jsonType, registrationContext); } @Override public List<DataType> findDataTypes(String name) { if (name != null && !name.isEmpty()) { TypeElement typeElement = this.context.getContext().getProcessingEnvironment().getElementUtils().getTypeElement(name); if (typeElement != null) { TypeDefinition typeDefinition = this.context.findTypeDefinition(typeElement); if (typeDefinition instanceof ObjectTypeDefinition) { return Collections.singletonList((DataType) new ObjectDataTypeImpl((ObjectTypeDefinition) typeDefinition, registrationContext)); } else if (typeDefinition instanceof EnumTypeDefinition) { return Collections.singletonList((DataType) new EnumDataTypeImpl((EnumTypeDefinition) typeDefinition, registrationContext)); } } } return Collections.emptyList(); } @Override public Example parseExample(Reader example) throws Exception { ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); return new CustomExampleImpl(mapper.writeValueAsString(mapper.readTree(example))); } @Override public String getUri() { return null; //json has no namespace uri. } @Override public InterfaceDescriptionFile getSchemaFile() { return null; //todo: json schema? } @Override public List<? extends DataType> getTypes() { Collection<TypeDefinition> typeDefinitions = this.context.getTypeDefinitions(); ArrayList<DataType> dataTypes = new ArrayList<DataType>(); FacetFilter facetFilter = this.context.getContext().getConfiguration().getFacetFilter(); for (TypeDefinition typeDefinition : typeDefinitions) { if (!facetFilter.accept(typeDefinition)) { continue; } if (typeDefinition instanceof ObjectTypeDefinition) { dataTypes.add(new ObjectDataTypeImpl((ObjectTypeDefinition) typeDefinition, registrationContext)); } else if (typeDefinition instanceof EnumTypeDefinition) { dataTypes.add(new EnumDataTypeImpl((EnumTypeDefinition) typeDefinition, registrationContext)); } } Collections.sort(dataTypes, new Comparator<DataType>() { @Override public int compare(DataType o1, DataType o2) { return o1.getLabel().compareTo(o2.getLabel()); } }); return dataTypes; } }