All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.swagger.parser.processors.ExternalRefProcessor Maven / Gradle / Ivy

There is a newer version: 2.0.0-rc1
Show newest version
package io.swagger.parser.processors;

import io.swagger.models.ArrayModel;
import io.swagger.models.Model;
import io.swagger.models.RefModel;
import io.swagger.models.Swagger;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.RefProperty;
import io.swagger.models.refs.RefFormat;
import io.swagger.parser.ResolverCache;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;

import static io.swagger.parser.util.RefUtils.computeDefinitionName;
import static io.swagger.parser.util.RefUtils.isAnExternalRefFormat;

public final class ExternalRefProcessor {
    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(ExternalRefProcessor.class);

    private final ResolverCache cache;
    private final Swagger swagger;

    public ExternalRefProcessor(ResolverCache cache, Swagger swagger) {
        this.cache = cache;
        this.swagger = swagger;
    }

    public String processRefToExternalDefinition(String $ref, RefFormat refFormat) {
        final Model model = cache.loadRef($ref, refFormat, Model.class);

        String newRef;

        Map definitions = swagger.getDefinitions();

        if (definitions == null) {
            definitions = new HashMap<>();
        }

        final String possiblyConflictingDefinitionName = computeDefinitionName($ref);

        final Model existingModel = definitions.get(possiblyConflictingDefinitionName);

        if (existingModel != null) {
            LOGGER.debug("A model for " + existingModel + " already exists");
        }
        newRef = possiblyConflictingDefinitionName;
        cache.putRenamedRef($ref, newRef);

        if(existingModel == null) {
            // don't overwrite existing model reference
            swagger.addDefinition(newRef, model);
            cache.addReferencedKey(newRef);

            String file = $ref.split("#/")[0];
            if (model instanceof RefModel) {
                RefModel refModel = (RefModel) model;
                if (isAnExternalRefFormat(refModel.getRefFormat())) {
                    refModel.set$ref(processRefToExternalDefinition(refModel.get$ref(), refModel.getRefFormat()));
                } else {
                    processRefToExternalDefinition(file + refModel.get$ref(), RefFormat.RELATIVE);
                }
            }
            //Loop the properties and recursively call this method;
            Map subProps = model.getProperties();
            if (subProps != null) {
                for (Map.Entry prop : subProps.entrySet()) {
                    if (prop.getValue() instanceof RefProperty) {
                        processRefProperty((RefProperty) prop.getValue(), file);
                    } else if (prop.getValue() instanceof ArrayProperty) {
                        ArrayProperty arrayProp = (ArrayProperty) prop.getValue();
                        if (arrayProp.getItems() instanceof RefProperty) {
                            processRefProperty((RefProperty) arrayProp.getItems(), file);
                        }
                    } else if (prop.getValue() instanceof MapProperty) {
                        MapProperty mapProp = (MapProperty) prop.getValue();
                        if (mapProp.getAdditionalProperties() instanceof RefProperty) {
                            processRefProperty((RefProperty) mapProp.getAdditionalProperties(), file);
                        } else if (mapProp.getAdditionalProperties() instanceof ArrayProperty &&
                                ((ArrayProperty) mapProp.getAdditionalProperties()).getItems() instanceof RefProperty) {
                            processRefProperty((RefProperty) ((ArrayProperty) mapProp.getAdditionalProperties()).getItems(), file);
                        }
                    }
                }
            }
            if (model instanceof ArrayModel && ((ArrayModel) model).getItems() instanceof RefProperty) {
                processRefProperty((RefProperty) ((ArrayModel) model).getItems(), file);
            }
        }

        return newRef;
    }

    private void processRefProperty(RefProperty subRef, String externalFile) {
        if (isAnExternalRefFormat(subRef.getRefFormat())) {
            String $ref = constructRef(subRef, externalFile);
            subRef.set$ref($ref);
            if($ref.startsWith("."))
                processRefToExternalDefinition($ref, RefFormat.RELATIVE);
            else {
                processRefToExternalDefinition($ref, RefFormat.URL);
            }

        } else {
            processRefToExternalDefinition(externalFile + subRef.get$ref(), RefFormat.RELATIVE);
        }
    }

    protected String constructRef(RefProperty refProperty, String rootLocation) {
        String ref = refProperty.get$ref();
        return join(rootLocation, ref);
    }

    public static String join(String source, String fragment) {
        try {
            boolean isRelative = false;
            if(source.startsWith("/") || source.startsWith(".")) {
                isRelative = true;
            }
            URI uri = new URI(source);

            if(!source.endsWith("/") && (fragment.startsWith("./") && "".equals(uri.getPath()))) {
                uri = new URI(source + "/");
            }
            else if("".equals(uri.getPath()) && !fragment.startsWith("/")) {
                uri = new URI(source + "/");
            }
            URI f = new URI(fragment);

            URI resolved = uri.resolve(f);

            URI normalized = resolved.normalize();
            if(Character.isAlphabetic(normalized.toString().charAt(0)) && isRelative) {
                return "./" + normalized.toString();
            }
            return normalized.toString();
        }
        catch(Exception e) {
            return source;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy