org.wso2.carbon.apimgt.migration.util.ResourceUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.apimgt.migration.util.ResourceUtil.java

Source

/*
 * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 * 
 * WSO2 Inc. licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.wso2.carbon.apimgt.migration.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.RegistryConstants;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.exceptions.RegistryException;

public class ResourceUtil {

    private static final Log log = LogFactory.getLog(ResourceUtil.class);

    /**
     * Get all the parameters related to each resource. The parameter array is
     * an array which is part of the operations object inside each resource.
     * 
     * @param resource api-doc which contains swagger 1.1 info
     * @return map of parameter array related to all the http methods for each resource.
      *      the key for the map is resourcepath_httpmethod
     */
    public static Map<String, JSONArray> getAllParametersForResources(JSONObject resource) {
        Map<String, JSONArray> parameters = new HashMap<String, JSONArray>();

        String resourcePath = (String) resource.get(Constants.API_DOC_11_RESOURCE_PATH);
        String apiVersion = (String) resource.get(Constants.API_DOC_11_API_VERSION);
        String resourcePathPrefix = resourcePath + "/" + apiVersion;

        String key = null;

        JSONArray apis = (JSONArray) resource.get(Constants.API_DOC_11_APIS);
        for (int i = 0; i < apis.size(); i++) {

            JSONObject apiInfo = (JSONObject) apis.get(i);
            String path = (String) apiInfo.get(Constants.API_DOC_11_PATH);
            JSONArray operations = (JSONArray) apiInfo.get(Constants.API_DOC_11_OPERATIONS);

            for (int j = 0; j < operations.size(); j++) {
                JSONObject operation = (JSONObject) operations.get(j);
                String httpMethod = (String) operation.get(Constants.API_DOC_11_METHOD);
                JSONArray parameterArray = (JSONArray) operation.get(Constants.API_DOC_11_PARAMETERS);

                // get the key by removing the "apiVersion" and "resourcePath"
                // from the "path" variable
                // and concat the http method
                String keyPrefix = path.substring(resourcePathPrefix.length());
                if (keyPrefix.isEmpty()) {
                    keyPrefix = "/*";
                }
                key = keyPrefix + "_" + httpMethod.toLowerCase();

                parameters.put(key, parameterArray);
            }
        }

        return parameters;

    }

    /**
     * Get all the operation object related to each resource. Method is inside the operation object
     * this object contains the nickname, description related to that resource method
     * @param resource
     *            api-doc which contains swagger 1.1 info
     * @return map of operations array related to all the http methods for each
     *         resource. the key for
     *         the map is resourcepath_httpmethod
     */
    private static Map<String, JSONObject> getAllOperationsForResources(JSONObject resource) {
        Map<String, JSONObject> parameters = new HashMap<String, JSONObject>();

        String resourcePath = (String) resource.get(Constants.API_DOC_11_RESOURCE_PATH);
        String apiVersion = (String) resource.get(Constants.API_DOC_11_API_VERSION);
        String resourcePathPrefix = resourcePath + "/" + apiVersion;

        String key = null;

        JSONArray apis = (JSONArray) resource.get(Constants.API_DOC_11_APIS);
        for (int i = 0; i < apis.size(); i++) {

            JSONObject apiInfo = (JSONObject) apis.get(i);
            String path = (String) apiInfo.get(Constants.API_DOC_11_PATH);
            JSONArray operations = (JSONArray) apiInfo.get(Constants.API_DOC_11_OPERATIONS);

            for (int j = 0; j < operations.size(); j++) {
                JSONObject operation = (JSONObject) operations.get(j);
                String httpMethod = (String) operation.get(Constants.API_DOC_11_METHOD);
                JSONArray parameterArray = (JSONArray) operation.get(Constants.API_DOC_11_PARAMETERS);

                // get the key by removing the "apiVersion" and "resourcePath"
                // from the "path" variable
                // and concat the http method
                String keyPrefix = path.substring(resourcePathPrefix.length());
                if (keyPrefix.isEmpty()) {
                    keyPrefix = "/*";
                }
                key = keyPrefix + "_" + httpMethod.toLowerCase();

                parameters.put(key, operation);
            }
        }

        return parameters;
    }

    /**
     * Get all the apis as a map. key for map is the full resource path for that api. key is created
     * using 'basepath + apis[i].path' values in the api-doc.json file (swagger 1.1 doc) 
     * 
     * @param resource
     *            api-doc which contains swagger 1.1 info
     * @return map of apis in the swagger 1.1 doc. key is the full resource path for that resource
     */
    public static Map<String, JSONObject> getAllAPIsByResourcePath(JSONObject resource) {
        Map<String, JSONObject> parameters = new HashMap<String, JSONObject>();

        String basePath = (String) resource.get(Constants.API_DOC_11_BASE_PATH);
        String key = null;

        JSONArray apis = (JSONArray) resource.get(Constants.API_DOC_11_APIS);
        for (int i = 0; i < apis.size(); i++) {

            JSONObject apiInfo = (JSONObject) apis.get(i);
            String path = (String) apiInfo.get(Constants.API_DOC_11_PATH);
            key = basePath + path;
            parameters.put(key, apiInfo);
        }

        return parameters;

    }

    private static JSONArray getDefaultParameters() {
        JSONParser parser = new JSONParser();
        JSONArray defaultParam = new JSONArray();
        try {
            defaultParam = (JSONArray) parser.parse(Constants.DEFAULT_PARAM_ARRAY);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return defaultParam;

    }

    /**
     * Modify the resource in registry location '1.2' to be compatible with the
     * AM 1.8. add the
     * parameters to operations element, add 'nickname' variable and the
     * 'basePath' variable
     * 
     * @param resource
     *            resource inside the 1.2 location
     * @param allParameters
     *            map containing all the parameters extracted from api-doc
     *            containing
     *            resources for swagger 1.1
     * @param allOperations 
     * @param basePath
     *            base path for the resource
     * @return modified resource for the api
     */
    public static String getUpdatedSwagger12Resource(JSONObject resource, Map<String, JSONArray> allParameters,
            Map<String, JSONObject> allOperations, String basePath) {

        JSONArray apis = (JSONArray) resource.get(Constants.API_DOC_12_APIS);
        for (int i = 0; i < apis.size(); i++) {
            JSONObject apiInfo = (JSONObject) apis.get(i);
            String path = (String) apiInfo.get(Constants.API_DOC_12_PATH);
            JSONArray operations = (JSONArray) apiInfo.get(Constants.API_DOC_12_OPERATIONS);

            for (int j = 0; j < operations.size(); j++) {
                JSONObject operation = (JSONObject) operations.get(j);
                String method = (String) operation.get(Constants.API_DOC_12_METHOD);

                // nickname is method name + "_" + path without starting "/"
                // symbol
                String nickname = method.toLowerCase() + "_" + path.substring(1);
                // add nickname variable
                operation.put(Constants.API_DOC_12_NICKNAME, nickname);
                String key = path + "_" + method.toLowerCase();

                JSONArray parameters = new JSONArray();
                if (allParameters.containsKey(key)) {
                    parameters = allParameters.get(key);

                    //setting the 'type' to 'string' if this variable is missing
                    for (int m = 0; m < parameters.size(); m++) {
                        JSONObject para = (JSONObject) parameters.get(m);
                        if (!para.containsKey("type")) {
                            para.put("type", "string");
                        }
                    }

                } else {
                    parameters = getDefaultParameters();

                }
                //if there are parameters already in this 
                JSONArray existingParams = (JSONArray) operation.get(Constants.API_DOC_12_PARAMETERS);
                if (existingParams.isEmpty()) {
                    JSONParser parser = new JSONParser();
                    if (path.contains("{")) {
                        List<String> urlParams = ResourceUtil.getURLTemplateParams(path);
                        for (String p : urlParams) {
                            try {
                                JSONObject paramObj = (JSONObject) parser
                                        .parse(Constants.DEFAULT_PARAM_FOR_URL_TEMPLATE);
                                paramObj.put("name", p);
                                parameters.add(paramObj);
                            } catch (ParseException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    }
                    // add parameters array
                    operation.put(Constants.API_DOC_12_PARAMETERS, parameters);
                } else {
                    for (int k = 0; k < existingParams.size(); k++) {
                        parameters.add(existingParams.get(k));
                    }
                    operation.put(Constants.API_DOC_12_PARAMETERS, parameters);
                }

                //updating the resource description and nickname using values in the swagger 1.1 doc
                if (allOperations.containsKey(key)) {

                    //update info related to object
                    JSONObject operationObj11 = allOperations.get(key);
                    //add summery
                    if (operationObj11.containsKey("summary")) {
                        operation.put("summary", operationObj11.get("summery"));
                    }

                }
            }
        }

        // add basePath variable
        resource.put(Constants.API_DOC_12_BASE_PATH, basePath);

        return resource.toJSONString();
    }

    /**
     * location for the swagger 1.2 resources
     * @param apiName
     * @param apiVersion
     * @param apiProvider
     * @return
     */
    public static String getSwagger12ResourceLocation(String apiName, String apiVersion, String apiProvider) {
        return APIConstants.API_DOC_LOCATION + RegistryConstants.PATH_SEPARATOR + apiName + "-" + apiVersion + "-"
                + apiProvider + RegistryConstants.PATH_SEPARATOR + APIConstants.API_DOC_1_2_LOCATION;
    }

    /**
     * update all the the swagger document in the registry related to an api
     * @param apiDocJson
     * @param docResourcePaths
     * @param re
     * @throws ParseException
     * @throws RegistryException
     */
    public static void updateAPISwaggerDocs(String apiDocJson, String[] docResourcePaths, Registry re)
            throws ParseException, RegistryException {

        JSONParser parser = new JSONParser();
        JSONObject apiDoc11 = (JSONObject) parser.parse(apiDocJson);

        Map<String, JSONArray> allParameters = ResourceUtil.getAllParametersForResources(apiDoc11);

        Map<String, JSONObject> allOperations = ResourceUtil.getAllOperationsForResources(apiDoc11);

        Map<String, JSONObject> apisByPath = ResourceUtil.getAllAPIsByResourcePath(apiDoc11);

        //this collection holds description given for each resource against the resource name.
        //descriptions added resources in an api in AM 1.7 are stored in api-doc 1.1. this desciption
        //is showed in am 1.7 api console in the store applicatoin. AM 1.8 uses descriptions in
        // api-doc in 1.2 resource folder. following map collects this value from api-doc 1.1 and 
        // store it to add to api-doc 1.2 
        Map<String, String> descriptionsForResource = new HashMap<String, String>();

        String basePath = (String) apiDoc11.get(Constants.API_DOC_11_BASE_PATH);
        String resourcePath = (String) apiDoc11.get(Constants.API_DOC_11_RESOURCE_PATH);
        String apiVersion = (String) apiDoc11.get(Constants.API_DOC_11_API_VERSION);

        resourcePath = resourcePath.endsWith("/") ? resourcePath : resourcePath + "/";
        String basePathForResource = basePath + resourcePath + apiVersion;

        String apidoc12path = "";

        //update each resource in the 1.2 folder except the api-doc resource
        for (String docResourcePath : docResourcePaths) {
            String resourceName = docResourcePath.substring(docResourcePath.lastIndexOf("/"));

            if (resourceName.equals(APIConstants.API_DOC_1_2_RESOURCE_NAME)) {
                //store api-doc in 1.2 folder for future use
                apidoc12path = docResourcePath;
                continue;
            }

            Resource resource = re.get(docResourcePath);
            JSONObject apiDoc = (JSONObject) parser.parse(new String((byte[]) resource.getContent()));

            String description = "";
            //generate the key to query the descriptionsForResource map
            JSONArray apisInResource = (JSONArray) apiDoc.get(Constants.API_DOC_12_APIS);
            JSONObject apiTemp = (JSONObject) apisInResource.get(0);
            String path = (String) apiTemp.get(Constants.API_DOC_12_PATH);

            String key = "";
            if (path.equals("/*")) {
                key = basePathForResource;
            } else {
                key = basePathForResource + path;
            }

            //get the description for that resource. query the api list generated using api-doc 1.1
            if (apisByPath.containsKey(key)) {
                JSONObject apiInfo = apisByPath.get(key);
                description = (String) apiInfo.get("description");
                descriptionsForResource.put(resourceName, description);
            }

            String updatedJson = ResourceUtil.getUpdatedSwagger12Resource(apiDoc, allParameters, allOperations,
                    basePathForResource);
            log.info("\t update " + resourceName.substring(1));
            Resource res = re.get(docResourcePath);
            res.setContent(updatedJson);
            //update the registry
            re.put(docResourcePath, res);

        }

        //update the api-doc. add the descriptions to each api resource
        ResourceUtil.updateSwagger12APIdoc(apidoc12path, descriptionsForResource, re, parser);

    }

    /**
     * update the swagger 1.2 api-doc. This method updates the descriptions 
     * @param apidoc12path
     * @param descriptionsForResource
     * @param re
     * @param parser
     * @throws RegistryException
     * @throws ParseException
     */
    private static void updateSwagger12APIdoc(String apidoc12path, Map<String, String> descriptionsForResource,
            Registry re, JSONParser parser) throws RegistryException, ParseException {
        Resource res = re.get(apidoc12path);
        JSONObject api12Doc = (JSONObject) parser.parse(new String((byte[]) res.getContent()));
        JSONArray apis = (JSONArray) api12Doc.get(Constants.API_DOC_12_APIS);
        for (int j = 0; j < apis.size(); j++) {
            JSONObject api = (JSONObject) apis.get(j);

            // get the resource name for each api in api-doc 1.2
            String resPathName = (String) api.get(Constants.API_DOC_12_PATH);
            if (descriptionsForResource.containsKey(resPathName)) {
                // if the descrption is available for that resource update it
                api.put("description", descriptionsForResource.get(resPathName));
            }
        }
        log.info("\t update api-doc");
        res.setContent(api12Doc.toJSONString());
        // update the registry
        re.put(apidoc12path, res);
    }

    /**
     * remove header and body parameters 
     * @param docResourcePaths
     * @param registry
     * @throws RegistryException
     * @throws ParseException
     */
    public static void updateSwagger12ResourcesForAM18(String[] docResourcePaths, Registry registry)
            throws RegistryException, ParseException {
        JSONParser parser = new JSONParser();
        for (String docResourcePath : docResourcePaths) {

            String resourceName = docResourcePath.substring(docResourcePath.lastIndexOf("/"));

            //modify this if api-doc resource needed to be changed
            if (resourceName.equals(APIConstants.API_DOC_1_2_RESOURCE_NAME)) {
                continue;
            }

            Resource resource = registry.get(docResourcePath);
            JSONObject resourceDoc = (JSONObject) parser.parse(new String((byte[]) resource.getContent()));
            JSONArray apis = (JSONArray) resourceDoc.get(Constants.API_DOC_12_APIS);
            for (int j = 0; j < apis.size(); j++) {
                JSONObject api = (JSONObject) apis.get(j);
                JSONArray operations = (JSONArray) api.get("operations");

                for (int k = 0; k < operations.size(); k++) {
                    JSONObject operation = (JSONObject) operations.get(k);
                    JSONArray parameters = (JSONArray) operation.get("parameters");
                    String method = (String) operation.get("method");
                    JSONArray parametersNew = new JSONArray();
                    //remove header and body parameters
                    for (int l = 0; l < parameters.size(); l++) {
                        JSONObject parameter = (JSONObject) parameters.get(l);
                        /*
                        if(parameter.get("paramType").equals("header") ||
                              parameter.get("paramType").equals("body")){
                           continue;
                        } */
                        if (parameter.get("paramType").equals("header")) {
                            continue;
                        }
                        if (parameter.get("paramType").equals("body")) {

                            //only remove body of a GET and DELETE
                            if ("GET".equalsIgnoreCase(method) || "DELETE".equalsIgnoreCase(method)) {
                                continue;
                            }
                        }
                        parametersNew.add(parameter);
                    }
                    operation.put("parameters", parametersNew);
                }

            }

            resource.setContent(resourceDoc.toJSONString());
            //update the registry
            registry.put(docResourcePath, resource);
        }

    }

    /**
     * extract the parameters from the url tempate.
     * @param url
     * @return
     */
    public static List<String> getURLTemplateParams(String url) {
        boolean endVal = false;

        List<String> params = new ArrayList<String>();
        if (url.contains("{")) {

            int start = 0;
            int end = 0;
            for (int i = 0; i < url.length(); i++) {
                if (url.charAt(i) == '{')
                    start = i;
                else if (url.charAt(i) == '}') {
                    end = i;
                    endVal = true;
                }

                if (endVal) {
                    params.add(url.substring(start + 1, end));
                    endVal = false;
                }
            }

        }
        return params;
    }

    /**
     * location for the swagger v2.0 resources
     * TODO check the correct swagger 2 location and the resource name. Currently it is /2.0/swagger.json
     * @param apiName name of the API
     * @param apiVersion version of the API
     * @param apiProvider provider name of the API
     * @return swagger v2.0 resource location as a string
     */
    public static String getSwagger2ResourceLocation(String apiName, String apiVersion, String apiProvider) {
        return APIConstants.API_DOC_LOCATION + RegistryConstants.PATH_SEPARATOR + apiName + "-" + apiVersion + "-"
                + apiProvider + RegistryConstants.PATH_SEPARATOR + "2.0" + RegistryConstants.PATH_SEPARATOR
                + "swagger.json";
    }

}