/**
   * Saves the swagger file as a registry artifact.
   *
   * @param inputStream input stream to read content.
   * @param commonLocation root location of the swagger artifacts.
   * @param sourceUrl source URL.
   * @throws RegistryException If a failure occurs when adding the swagger to registry.
   */
  public boolean processSwagger(InputStream inputStream, String commonLocation, String sourceUrl)
      throws RegistryException {
    // create a collection if not exists.
    createCollection(commonLocation);

    // Reading resource content and content details.
    ByteArrayOutputStream swaggerContentStream = CommonUtil.readSourceContent(inputStream);
    JsonObject swaggerDocObject = getSwaggerObject(swaggerContentStream.toString());
    String swaggerVersion = getSwaggerVersion(swaggerDocObject);
    documentVersion =
        requestContext.getResource().getProperty(RegistryConstants.VERSION_PARAMETER_NAME);
    if (documentVersion == null) {
      documentVersion = CommonConstants.SWAGGER_DOC_VERSION_DEFAULT_VALUE;
      requestContext
          .getResource()
          .setProperty(RegistryConstants.VERSION_PARAMETER_NAME, documentVersion);
    }
    String swaggerResourcePath = getSwaggerDocumentPath(commonLocation, swaggerDocObject);

    /*
    Switches from the swagger version and process document adding process and the REST Service creation process
    using the relevant documents.
     */
    if (SwaggerConstants.SWAGGER_VERSION_12.equals(swaggerVersion)) {
      if (addSwaggerDocumentToRegistry(
          swaggerContentStream, swaggerResourcePath, documentVersion)) {
        List<JsonObject> resourceObjects =
            addResourceDocsToRegistry(swaggerDocObject, sourceUrl, swaggerResourcePath);
        restServiceElement =
            (resourceObjects != null)
                ? RESTServiceUtils.createRestServiceArtifact(
                    swaggerDocObject,
                    swaggerVersion,
                    endpointUrl,
                    resourceObjects,
                    swaggerResourcePath,
                    documentVersion)
                : null;
      } else {
        return false;
      }

    } else if (SwaggerConstants.SWAGGER_VERSION_2.equals(swaggerVersion)) {
      if (addSwaggerDocumentToRegistry(
          swaggerContentStream, swaggerResourcePath, documentVersion)) {
        createEndpointElement(swaggerDocObject, swaggerVersion);
        restServiceElement =
            RESTServiceUtils.createRestServiceArtifact(
                swaggerDocObject,
                swaggerVersion,
                endpointUrl,
                null,
                swaggerResourcePath,
                documentVersion);
      } else {
        return false;
      }
    }

    /*
    If REST Service content is not empty, saves the REST service and adds the relevant associations.
     */
    if (restServiceElement != null) {
      String servicePath =
          RESTServiceUtils.addServiceToRegistry(requestContext, restServiceElement);
      registry.addAssociation(servicePath, swaggerResourcePath, CommonConstants.DEPENDS);
      registry.addAssociation(swaggerResourcePath, servicePath, CommonConstants.USED_BY);

      if (endpointUrl != null) {
        String endpointPath =
            RESTServiceUtils.addEndpointToRegistry(
                requestContext, endpointElement, endpointLocation);
        registry.addAssociation(servicePath, endpointPath, CommonConstants.DEPENDS);
        registry.addAssociation(endpointPath, servicePath, CommonConstants.USED_BY);
      }
    } else {
      log.warn("Service content is null. Cannot create the REST Service artifact.");
    }

    CommonUtil.closeOutputStream(swaggerContentStream);

    return true;
  }
  /**
   * Extracts the data from swagger and creates an REST Service registry artifact. In 5.1.0 please
   * remove this method.
   *
   * @param swaggerDocObject swagger Json Object.
   * @param swaggerVersion swagger version.
   * @param resourceObjects swagger resource object list.
   * @return The API metadata
   * @throws RegistryException If swagger content is invalid.
   */
  public static OMElement createRestServiceArtifact(
      JsonObject swaggerDocObject,
      String swaggerVersion,
      String endpointURL,
      List<JsonObject> resourceObjects,
      String swaggerPath)
      throws RegistryException {

    if (swaggerDocObject == null || swaggerVersion == null) {
      throw new IllegalArgumentException(
          "Arguments are invalid. cannot create the REST service artifact. ");
    }

    OMElement data = factory.createOMElement(CommonConstants.SERVICE_ELEMENT_ROOT, namespace);
    OMElement overview = factory.createOMElement(OVERVIEW, namespace);
    OMElement provider = factory.createOMElement(PROVIDER, namespace);
    OMElement name = factory.createOMElement(NAME, namespace);
    OMElement context = factory.createOMElement(CONTEXT, namespace);
    OMElement apiVersion = factory.createOMElement(VERSION, namespace);
    OMElement endpoint = factory.createOMElement(ENDPOINT_URL, namespace);
    OMElement transports = factory.createOMElement(TRANSPORTS, namespace);
    OMElement description = factory.createOMElement(DESCRIPTION, namespace);
    List<OMElement> uriTemplates = null;

    JsonObject infoObject = swaggerDocObject.get(SwaggerConstants.INFO).getAsJsonObject();
    // get api name.
    String apiName = getChildElementText(infoObject, SwaggerConstants.TITLE).replaceAll("\\s", "");
    name.setText(apiName);
    context.setText("/" + apiName);
    // get api description.
    description.setText(getChildElementText(infoObject, SwaggerConstants.DESCRIPTION));
    // get api provider. (Current logged in user) : Alternative - CurrentSession.getUser();
    provider.setText(CarbonContext.getThreadLocalCarbonContext().getUsername());
    endpoint.setText(endpointURL);

    if (SwaggerConstants.SWAGGER_VERSION_2.equals(swaggerVersion)) {
      apiVersion.setText(getChildElementText(infoObject, SwaggerConstants.VERSION));
      transports.setText(getChildElementText(swaggerDocObject, SwaggerConstants.SCHEMES));
      uriTemplates = createURITemplateFromSwagger2(swaggerDocObject);
    } else if (SwaggerConstants.SWAGGER_VERSION_12.equals(swaggerVersion)) {
      apiVersion.setText(getChildElementText(swaggerDocObject, SwaggerConstants.API_VERSION));
      uriTemplates = createURITemplateFromSwagger12(resourceObjects);
    }

    overview.addChild(provider);
    overview.addChild(name);
    overview.addChild(context);
    overview.addChild(apiVersion);
    overview.addChild(description);
    overview.addChild(endpoint);
    data.addChild(overview);

    OMElement interfaceElement = factory.createOMElement(INTERFACE, namespace);
    OMElement swagger = factory.createOMElement(SWAGGER, namespace);
    swagger.setText(swaggerPath);
    interfaceElement.addChild(swagger);
    interfaceElement.addChild(transports);
    data.addChild(interfaceElement);
    if (uriTemplates != null) {
      for (OMElement uriTemplate : uriTemplates) {
        data.addChild(uriTemplate);
      }
    }

    return data;
  }
  /**
   * Generates the service endpoint element from the swagger object.
   *
   * @param swaggerObject swagger document object.
   * @param swaggerVersion swagger version.
   */
  private void createEndpointElement(JsonObject swaggerObject, String swaggerVersion)
      throws RegistryException {
    /*
    Extracting endpoint url from the swagger document.
     */
    if (SwaggerConstants.SWAGGER_VERSION_12.equals(swaggerVersion)) {
      JsonElement endpointUrlElement = swaggerObject.get(SwaggerConstants.BASE_PATH);
      if (endpointUrlElement == null) {
        log.warn(
            "Endpoint url is not specified in the swagger document. Endpoint creation might fail. ");
        return;
      } else {
        endpointUrl = endpointUrlElement.getAsString();
      }
    } else if (SwaggerConstants.SWAGGER_VERSION_2.equals(swaggerVersion)) {
      JsonElement transportsElement = swaggerObject.get(SwaggerConstants.SCHEMES);
      JsonArray transports =
          (transportsElement != null) ? transportsElement.getAsJsonArray() : null;
      String transport =
          (transports != null) ? transports.get(0).getAsString() + "://" : DEFAULT_TRANSPORT;
      JsonElement hostElement = swaggerObject.get(SwaggerConstants.HOST);
      String host = (hostElement != null) ? hostElement.getAsString() : null;
      if (host == null) {
        log.warn(
            "Endpoint(host) url is not specified in the swagger document. "
                + "The host serving the documentation is to be used(including the port) as endpoint host");

        if (requestContext.getSourceURL() != null) {
          URL sourceURL = null;
          try {
            sourceURL = new URL(requestContext.getSourceURL());
          } catch (MalformedURLException e) {
            throw new RegistryException("Error in parsing the source URL. ", e);
          }
          host = sourceURL.getAuthority();
        }
      }

      if (host == null) {
        log.warn(
            "Can't derive the endpoint(host) url when uploading swagger from file. "
                + "Endpoint creation might fail. ");
        return;
      }

      JsonElement basePathElement = swaggerObject.get(SwaggerConstants.BASE_PATH);
      String basePath =
          (basePathElement != null) ? basePathElement.getAsString() : DEFAULT_BASE_PATH;

      endpointUrl = transport + host + basePath;
    }
    /*
    Creating endpoint artifact
     */
    OMFactory factory = OMAbstractFactory.getOMFactory();
    endpointLocation = EndpointUtils.deriveEndpointFromUrl(endpointUrl);
    String endpointName = EndpointUtils.deriveEndpointNameWithNamespaceFromUrl(endpointUrl);
    String endpointContent =
        EndpointUtils.getEndpointContentWithOverview(
            endpointUrl, endpointLocation, endpointName, documentVersion);
    try {
      endpointElement = AXIOMUtil.stringToOM(factory, endpointContent);
    } catch (XMLStreamException e) {
      throw new RegistryException("Error in creating the endpoint element. ", e);
    }
  }