package org.rakam.server.http; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.TypeFactory; import io.swagger.converter.ModelConverter; import io.swagger.converter.ModelConverterContextImpl; import io.swagger.jackson.ModelResolver; import io.swagger.models.Model; import io.swagger.models.properties.Property; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Type; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; public class ModelConverters { static Logger LOGGER = LoggerFactory.getLogger(ModelConverters.class); private final List<ModelConverter> converters; private final Set<String> skippedPackages = new HashSet<String>(); private final Set<String> skippedClasses = new HashSet<String>(); public ModelConverters(ObjectMapper mapper) { converters = new CopyOnWriteArrayList<>(); ModelResolver e = new ModelResolver(mapper); converters.add(e); } public void addConverter(ModelConverter converter) { converters.add(0, converter); } public void removeConverter(ModelConverter converter) { converters.remove(converter); } public void addPackageToSkip(String pkg) { this.skippedPackages.add(pkg); } public void addClassToSkip(String cls) { LOGGER.warn("skipping class " + cls); this.skippedClasses.add(cls); } public Property readAsProperty(Type type) { ModelConverterContextImpl context = new ModelConverterContextImpl( converters); return context.resolveProperty(type, null); } public Map<String, Model> read(Type type) { Map<String, Model> modelMap = new HashMap<>(); if (shouldProcess(type)) { ModelConverterContextImpl context = new ModelConverterContextImpl( converters); Model resolve = context.resolve(type); context.getDefinedModels() .entrySet().stream().filter(entry -> entry.getValue().equals(resolve)) .forEach(entry -> modelMap.put(entry.getKey(), entry.getValue())); } return modelMap; } public Map<String, Model> readAll(Type type) { if (shouldProcess(type)) { ModelConverterContextImpl context = new ModelConverterContextImpl( converters); LOGGER.debug("ModelConverters readAll from " + type); context.resolve(type); return context.getDefinedModels(); } return new HashMap<>(); } private boolean shouldProcess(Type type) { final Class<?> cls = TypeFactory.defaultInstance().constructType(type).getRawClass(); if (cls.isPrimitive()) { return false; } String className = cls.getName(); for (String packageName : skippedPackages) { if (className.startsWith(packageName)) { return false; } } for (String classToSkip : skippedClasses) { if (className.equals(classToSkip)) { return false; } } return true; } }