![JAR search and dependency download from the Maven repository](/logo.png)
com.mangofactory.swagger.readers.ApiModelReader Maven / Gradle / Ivy
package com.mangofactory.swagger.readers;
import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.TypeResolver;
import com.google.common.base.Optional;
import com.google.common.collect.Maps;
import com.mangofactory.swagger.configuration.SwaggerGlobalSettings;
import com.mangofactory.swagger.core.ModelUtils;
import com.mangofactory.swagger.models.Annotations;
import com.mangofactory.swagger.models.ModelContext;
import com.mangofactory.swagger.models.ModelProvider;
import com.mangofactory.swagger.models.ScalaConverters;
import com.mangofactory.swagger.readers.operation.HandlerMethodResolver;
import com.mangofactory.swagger.readers.operation.ResolvedMethodParameter;
import com.mangofactory.swagger.scanners.RequestMappingContext;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiResponse;
import com.wordnik.swagger.annotations.ApiResponses;
import com.wordnik.swagger.model.Model;
import com.wordnik.swagger.model.ModelProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.method.HandlerMethod;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.google.common.collect.Maps.*;
import static com.google.common.collect.Sets.*;
import static com.mangofactory.swagger.ScalaUtils.*;
import static com.mangofactory.swagger.models.ResolvedTypes.*;
@Component
public class ApiModelReader implements Command {
private static final Logger log = LoggerFactory.getLogger(ApiModelReader.class);
private ModelProvider modelProvider;
@Autowired
public ApiModelReader(ModelProvider modelProvider) {
this.modelProvider = modelProvider;
}
@Override
public void execute(RequestMappingContext context) {
HandlerMethod handlerMethod = context.getHandlerMethod();
log.debug("Reading models for handlerMethod |{}|", handlerMethod.getMethod().getName());
Map modelMap = newHashMap();
SwaggerGlobalSettings swaggerGlobalSettings = (SwaggerGlobalSettings) context.get("swaggerGlobalSettings");
HandlerMethodResolver handlerMethodResolver
= new HandlerMethodResolver(swaggerGlobalSettings.getTypeResolver());
ResolvedType modelType = ModelUtils.handlerReturnType(swaggerGlobalSettings.getTypeResolver(), handlerMethod);
modelType = swaggerGlobalSettings.getAlternateTypeProvider().alternateFor(modelType);
ApiOperation apiOperationAnnotation = handlerMethod.getMethodAnnotation(ApiOperation.class);
if (null != apiOperationAnnotation && Void.class != apiOperationAnnotation.response()) {
modelType = asResolved(swaggerGlobalSettings.getTypeResolver(), apiOperationAnnotation.response());
}
if (!swaggerGlobalSettings.getIgnorableParameterTypes().contains(modelType.getErasedType())) {
ModelContext modelContext = ModelContext.returnValue(modelType);
markIgnorablesAsHasSeen(swaggerGlobalSettings.getTypeResolver(),
swaggerGlobalSettings.getIgnorableParameterTypes(),
modelContext);
Optional model = modelProvider.modelFor(modelContext);
if (model.isPresent() && !"void".equals(model.get().name())) {
log.debug("Swagger generated parameter model id: {}, name: {}, schema: {} models",
model.get().id(),
model.get().name());
modelMap.put(model.get().id(), model.get());
} else {
log.debug("Swagger core did not find any models");
}
populateDependencies(modelContext, modelMap);
}
mergeModelMap(modelMap, readParametersApiModel(handlerMethodResolver, swaggerGlobalSettings, handlerMethod));
mergeModelMap(modelMap, readApiResponses(swaggerGlobalSettings, handlerMethod));
log.debug("Finished reading models for handlerMethod |{}|", handlerMethod.getMethod().getName());
context.put("models", modelMap);
}
private Map readApiResponses(SwaggerGlobalSettings settings, HandlerMethod handlerMethod) {
Optional apiResponses = Annotations.findApiResponsesAnnotations(handlerMethod.getMethod());
Map modelMap = newHashMap();
log.debug("Reading parameters models for handlerMethod |{}|", handlerMethod.getMethod().getName());
if (!apiResponses.isPresent()) {
return modelMap;
}
for (ApiResponse response : apiResponses.get().value()) {
if (!settings.getIgnorableParameterTypes().contains(response.response())) {
ResolvedType modelType = settings.getAlternateTypeProvider()
.alternateFor(asResolved(new TypeResolver(), response.response()));
ModelContext modelContext = ModelContext.inputParam(modelType);
markIgnorablesAsHasSeen(settings.getTypeResolver(), settings.getIgnorableParameterTypes(),
modelContext);
Optional pModel = modelProvider.modelFor(modelContext);
if (pModel.isPresent()) {
log.debug("Swagger generated parameter model id: {}, name: {}, schema: {} models",
pModel.get().id(),
pModel.get().name());
modelMap.put(pModel.get().id(), pModel.get());
} else {
log.debug("Swagger core did not find any parameter models for {}", response.response());
}
populateDependencies(modelContext, modelMap);
}
}
log.debug("Finished reading parameters models for handlerMethod |{}|", handlerMethod.getMethod().getName());
return modelMap;
}
@SuppressWarnings("unchecked")
private void mergeModelMap(Map target, Map source) {
for (Map.Entry sModelEntry : source.entrySet()) {
String sourceModelKey = sModelEntry.getKey();
if (!target.containsKey(sourceModelKey)) {
//if we encounter completely unknown model, just add it
target.put(sModelEntry.getKey(), sModelEntry.getValue());
} else {
//we can encounter a known model with an unknown property
//if (de)serialization is not symmetrical (@JsonIgnore on setter, @JsonProperty on getter).
//In these cases, don't overwrite the entire model entry for that type, just add the unknown property.
Model targetModelValue = target.get(sourceModelKey);
Model sourceModelValue = sModelEntry.getValue();
Map targetProperties = fromScalaMap(targetModelValue.properties());
Map sourceProperties = fromScalaMap(sourceModelValue.properties());
Set newSourcePropKeys = newHashSet(sourceProperties.keySet());
newSourcePropKeys.removeAll(targetProperties.keySet());
Map mergedTargetProperties = Maps.newHashMap(targetProperties);
for (String newProperty : newSourcePropKeys) {
mergedTargetProperties.put(newProperty, sourceProperties.get(newProperty));
}
// uses scala generated copy constructor.
Model mergedModel = targetModelValue.copy(
targetModelValue.id(),
targetModelValue.name(),
targetModelValue.qualifiedType(),
ScalaConverters.toScalaLinkedHashMap(mergedTargetProperties),
targetModelValue.description(),
targetModelValue.baseModel(),
targetModelValue.discriminator(),
targetModelValue.subTypes());
target.put(sourceModelKey, mergedModel);
}
}
}
private void markIgnorablesAsHasSeen(TypeResolver typeResolver, Set ignorableParameterTypes,
ModelContext modelContext) {
for (Class ignorableParameterType : ignorableParameterTypes) {
modelContext.seen(asResolved(typeResolver, ignorableParameterType));
}
}
private Map readParametersApiModel(HandlerMethodResolver handlerMethodResolver,
SwaggerGlobalSettings settings,
HandlerMethod handlerMethod) {
Method method = handlerMethod.getMethod();
Map modelMap = newHashMap();
log.debug("Reading parameters models for handlerMethod |{}|", handlerMethod.getMethod().getName());
List parameterTypes = handlerMethodResolver.methodParameters(handlerMethod);
Annotation[][] annotations = method.getParameterAnnotations();
for (int i = 0; i < annotations.length; i++) {
Annotation[] pAnnotations = annotations[i];
for (Annotation annotation : pAnnotations) {
if (annotation instanceof RequestBody) {
ResolvedMethodParameter pType = parameterTypes.get(i);
if (!settings.getIgnorableParameterTypes()
.contains(pType.getResolvedParameterType().getErasedType())) {
ResolvedType modelType = settings.getAlternateTypeProvider().alternateFor(pType
.getResolvedParameterType());
ModelContext modelContext = ModelContext.inputParam(modelType);
markIgnorablesAsHasSeen(settings.getTypeResolver(), settings.getIgnorableParameterTypes(),
modelContext);
Optional pModel = modelProvider.modelFor(modelContext);
if (pModel.isPresent()) {
log.debug("Swagger generated parameter model id: {}, name: {}, schema: {} models",
pModel.get().id(),
pModel.get().name());
modelMap.put(pModel.get().id(), pModel.get());
} else {
log.debug("Swagger core did not find any parameter models for {}",
pType.getResolvedParameterType());
}
populateDependencies(modelContext, modelMap);
}
}
}
}
log.debug("Finished reading parameters models for handlerMethod |{}|", handlerMethod.getMethod().getName());
return modelMap;
}
private void populateDependencies(ModelContext modelContext, Map modelMap) {
modelMap.putAll(modelProvider.dependencies(modelContext));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy