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

io.swagger.parser.SwaggerResolver Maven / Gradle / Ivy

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

import io.swagger.parser.util.RemoteUrl;

import com.wordnik.swagger.util.Json;
import com.wordnik.swagger.models.*;
import com.wordnik.swagger.models.parameters.*;
import com.wordnik.swagger.models.properties.*;
import com.wordnik.swagger.models.auth.AuthorizationValue;

import com.fasterxml.jackson.databind.JsonNode;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ServiceLoader;
import java.util.*;
import java.io.IOException;

public class SwaggerResolver {
  Logger LOGGER = LoggerFactory.getLogger(SwaggerResolver.class);
  protected Swagger swagger;
  protected Map resolutionMap = new HashMap();

  protected ResolverOptions opts;
  public SwaggerResolver(){}
  public SwaggerResolver(ResolverOptions opts) {
    this.opts = opts;
  }
  public Swagger resolve(Swagger swagger, List auths) {
    if(swagger == null)
      return null;

    this.swagger = swagger;

    // models
    detectModelRefs();

    // operations
    detectOperationRefs();

    applyResolutions(auths);
    return this.swagger;
  }

  public void applyResolutions(List auths) {
    // hosts to call
    Map> hostToObjectMap = new HashMap>();

    for(String path : resolutionMap.keySet()) {
      String[] parts = path.split("#");
      if(parts.length == 2) {
        String host = parts[0];
        String definitionPath = parts[1];
        List objectList = hostToObjectMap.get(host);
        if(objectList == null) {
          objectList = new ArrayList();
          hostToObjectMap.put(host, objectList);
        }
        ResolutionContext ctx = resolutionMap.get(path);

        Object mapping = ctx.object;
        Object target = ctx.parent;
        try {
          String contents = null;
          if(host.startsWith("http"))
            contents = new RemoteUrl().urlToString(host, auths);
          else
            contents = Json.mapper().writeValueAsString(swagger);
          JsonNode location = null;
          String locationName = null;
          if(contents != null) {
            location = Json.mapper().readTree(contents);
            String[] objectPath = definitionPath.split("/");
            for(String objectPathPart : objectPath) {
              LOGGER.debug("getting part " + objectPathPart);
              if(objectPathPart.length() > 0 && location != null) {
                location = location.get(objectPathPart);
                locationName = objectPathPart;
              }
            }
          }
          if(location != null) {
            // convert the node to the proper type
            if(mapping instanceof Property) {
              Model model = Json.mapper().convertValue(location, Model.class);
              if(mapping instanceof RefProperty) {
                RefProperty ref = (RefProperty) mapping;
                ref.set$ref(locationName);
                swagger.addDefinition(locationName, model);
              }
            }
            else if(target instanceof Parameter) {
              if(mapping instanceof RefModel) {
                Model model = Json.mapper().convertValue(location, Model.class);
                RefModel ref = (RefModel) mapping;
                ref.set$ref(locationName);
                swagger.addDefinition(locationName, model);
              }
            }
            else if(target instanceof Operation) {

              // get the operation position
              Operation operation = (Operation) target;
              int position = 0;
              for(Parameter param : operation.getParameters()) {

                if(param instanceof RefParameter) {
                  RefParameter ref = (RefParameter) param;
                  if(ref.getSimpleRef().equals(locationName)) {
                    // found a match!
                    Parameter remoteParam = Json.mapper().convertValue(location, Parameter.class);
                    operation.getParameters().set(position, remoteParam);
                  }
                }
                position += 1;
              }
            }
          }
        }
        catch(Exception e) {
          // failed to get it
          e.printStackTrace();
        }
      }
    }
  }

  public void detectOperationRefs() {
    Map paths = swagger.getPaths();
    if(paths == null) return;

    for(String pathName : paths.keySet()) {
      Path path = paths.get(pathName);
      List operations = path.getOperations();
      for(Operation operation : operations) {
        if(operation.getParameters() != null) {
          for(Parameter parameter : operation.getParameters()) {
            if(parameter instanceof BodyParameter) {
              BodyParameter bp = (BodyParameter) parameter;
              if(bp.getSchema() != null && bp.getSchema() instanceof RefModel) {
                RefModel ref = (RefModel)bp.getSchema();
                if(ref.get$ref().startsWith("http")) {
                  LOGGER.debug("added reference to " + ref.get$ref());
                  resolutionMap.put(ref.get$ref(), new ResolutionContext(ref, bp, "ref"));
                }
              }
            }
            else if(parameter instanceof RefParameter) {
              RefParameter ref = (RefParameter) parameter;
              LOGGER.debug("added reference to " + ref.get$ref());
              resolutionMap.put(ref.get$ref(), new ResolutionContext(ref, operation, "inline"));
            }
          }
        }
        if(operation.getResponses() != null) {
          for(String responseCode : operation.getResponses().keySet()) {
            Response response = operation.getResponses().get(responseCode);
            if(response.getSchema() != null) {
              Property schema = response.getSchema();
              if(schema instanceof RefProperty) {
                RefProperty ref = (RefProperty) schema;
                if(ref.get$ref() != null && ref.get$ref().startsWith("http")) {
                  resolutionMap.put(ref.get$ref(), new ResolutionContext(ref, response, "ref"));
                }
              }
            }
          }
        }
      }
    }
  }

  public void detectModelRefs() {
    Map models = swagger.getDefinitions();
    if(models != null) {
      for(String modelName : models.keySet()) {
        LOGGER.debug("looking at " + modelName);
        Model model = models.get(modelName);
        if(model instanceof RefModel) {
          RefModel ref = (RefModel) model;
          if(ref.get$ref() != null && ref.get$ref().startsWith("http")) {
            LOGGER.debug("added reference to " + ref.get$ref());
            resolutionMap.put(ref.get$ref(), new ResolutionContext(ref, swagger.getDefinitions(), "ref"));
          }
        }
        else if(model instanceof ArrayModel) {
          ArrayModel arrayModel = (ArrayModel) model;
          if(arrayModel.getItems() != null && arrayModel.getItems() instanceof RefProperty) {
            RefProperty ref = (RefProperty)arrayModel.getItems();
            if(ref.get$ref() != null && ref.get$ref().startsWith("http")) {
              LOGGER.debug("added reference to " + ref.get$ref());
              resolutionMap.put(ref.get$ref(), new ResolutionContext(ref, swagger.getDefinitions(), "ref"));
            }
          }
        }
        else if(model instanceof ModelImpl) {
          ModelImpl impl = (ModelImpl) model;
          Map properties = impl.getProperties();
          for(String propertyName : properties.keySet()) {
            Property property = properties.get(propertyName);
            if(property instanceof RefProperty) {
              RefProperty ref = (RefProperty)property;
              if(ref.get$ref() != null && ref.get$ref().startsWith("http")) {
                LOGGER.debug("added reference to " + ref.get$ref());
                resolutionMap.put(ref.get$ref(), new ResolutionContext(ref, impl, "ref"));
              }
            }
            else if(property instanceof ArrayProperty) {
              ArrayProperty arrayProperty = (ArrayProperty) property;
              if(arrayProperty.getItems() != null && arrayProperty.getItems() instanceof RefProperty) {
                RefProperty ref = (RefProperty)arrayProperty.getItems();
                if(ref.get$ref() != null && ref.get$ref().startsWith("http")) {
                  LOGGER.debug("added reference to " + ref.get$ref());
                  resolutionMap.put(ref.get$ref(), new ResolutionContext(ref, arrayProperty, "ref"));
                }
              }
            }
            else if(property instanceof MapProperty) {
              MapProperty mp = (MapProperty) property;
              if(mp.getAdditionalProperties() != null && mp.getAdditionalProperties() instanceof RefProperty) {
                RefProperty ref = (RefProperty)mp.getAdditionalProperties();
                if(ref.get$ref() != null && ref.get$ref().startsWith("http")) {
                  LOGGER.debug("added reference to " + ref.get$ref());
                  resolutionMap.put(ref.get$ref(), new ResolutionContext(ref, mp, "ref"));
                }                
              }
            }
          }
        }
      }
    }
  }

  static class ResolutionContext {
    private Object object, parent;
    private String scope;

    public ResolutionContext(Object object, Object parent, String scope) {
      this.object = object;
      this.parent = parent;
      this.scope = scope;
    }
  }
}