org.wso2.carbon.apimgt.impl.soaptorest.util.SequenceUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.apimgt.impl.soaptorest.util.SequenceUtils.java

Source

/*
 * Copyright (c) 2018, 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.impl.soaptorest.util;

import org.apache.commons.lang3.StringUtils;
import org.json.JSONException;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.api.model.APIIdentifier;
import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.impl.internal.ServiceReferenceHolder;
import org.wso2.carbon.apimgt.impl.soaptorest.template.SOAPToRESTAPIConfigContext;
import org.wso2.carbon.apimgt.impl.template.ConfigContext;
import org.wso2.carbon.apimgt.impl.utils.APIUtil;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.registry.api.Resource;
import org.wso2.carbon.registry.core.Collection;
import org.wso2.carbon.registry.core.RegistryConstants;
import org.wso2.carbon.registry.core.ResourceImpl;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.service.RegistryService;
import org.wso2.carbon.registry.core.session.UserRegistry;
import org.wso2.carbon.registry.core.utils.RegistryUtils;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import static org.wso2.carbon.apimgt.impl.utils.APIUtil.handleException;

/**
 * Util class used for sequence generation of the soap to rest converted operations.
 */
public class SequenceUtils {
    private static final Logger log = LoggerFactory.getLogger(SequenceUtils.class);

    /**
     * Saves the converted api sequence in the registry for the given resource path
     *
     * @param registry     user registry reference
     * @param sequence     sequence to be saved
     * @param method       http method of the operation
     * @param resourcePath registry resource path
     * @throws APIManagementException throws errors on if the resource persistence gets unsuccessful
     */
    public static void saveRestToSoapConvertedSequence(UserRegistry registry, String sequence, String method,
            String resourcePath) throws APIManagementException {
        try {
            Resource regResource;
            if (!registry.resourceExists(resourcePath)) {
                regResource = registry.newResource();
            } else {
                regResource = registry.get(resourcePath);
            }
            regResource.setContent(sequence);
            regResource.addProperty(SOAPToRESTConstants.METHOD, method);
            regResource.setMediaType("text/xml");
            registry.put(resourcePath, regResource);
        } catch (RegistryException e) {
            handleException("Error occurred while accessing the registry to save api sequence", e);
        } catch (org.wso2.carbon.registry.api.RegistryException e) {
            handleException("Error occurred while saving api sequence", e);
        }
    }

    /**
     * Updates the api sequences where user will be able to edits the generated sequences
     * <p>
     * Note: this method is directly invoked from the jaggery layer
     *
     * @param name     api name
     * @param version  api version
     * @param provider api provider
     * @param seqType  to identify the sequence is whether in/out sequence
     * @param content  sequence content
     * @throws APIManagementException throws exceptions on unsuccessful persistence in registry or json parsing of the content
     */
    public static void updateRestToSoapConvertedSequences(String name, String version, String provider,
            String seqType, String content) throws APIManagementException {
        provider = (provider != null ? provider.trim() : null);
        name = (name != null ? name.trim() : null);
        version = (version != null ? version.trim() : null);

        boolean isTenantFlowStarted = false;

        JSONParser jsonParser = new JSONParser();
        try {
            String tenantDomain = MultitenantUtils.getTenantDomain(APIUtil.replaceEmailDomainBack(provider));
            if (tenantDomain != null && !MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
                isTenantFlowStarted = true;
                PrivilegedCarbonContext.startTenantFlow();
                PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
            }
            RegistryService registryService = ServiceReferenceHolder.getInstance().getRegistryService();
            int tenantId;
            UserRegistry registry;
            tenantId = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager()
                    .getTenantId(tenantDomain);
            APIUtil.loadTenantRegistry(tenantId);
            registry = registryService.getGovernanceSystemRegistry(tenantId);

            JSONObject sequences = (JSONObject) jsonParser.parse(content);
            for (Object sequence : sequences.keySet()) {
                String sequenceContent = (String) ((JSONObject) sequences.get(sequence)).get("content");
                String resourcePath = APIConstants.API_LOCATION + RegistryConstants.PATH_SEPARATOR + provider
                        + RegistryConstants.PATH_SEPARATOR + name + RegistryConstants.PATH_SEPARATOR + version
                        + RegistryConstants.PATH_SEPARATOR + SOAPToRESTConstants.SOAP_TO_REST_RESOURCE
                        + RegistryConstants.PATH_SEPARATOR + seqType + RegistryConstants.PATH_SEPARATOR + sequence
                        + ".xml";

                Resource regResource;
                if (registry.resourceExists(resourcePath)) {
                    regResource = registry.get(resourcePath);
                    regResource.setContent(sequenceContent);
                    if (log.isDebugEnabled()) {
                        log.debug("Api sequence content for " + resourcePath + " is: " + sequenceContent);
                    }
                    regResource.setMediaType("text/xml");
                    registry.put(resourcePath, regResource);
                }
            }
        } catch (ParseException e) {
            handleException("Error occurred while parsing the sequence json", e);
        } catch (UserStoreException e) {
            handleException("Error while reading tenant information", e);
        } catch (RegistryException e) {
            handleException("Error when create registry instance", e);
        } catch (org.wso2.carbon.registry.api.RegistryException e) {
            handleException("Error while creating registry resource", e);
        } finally {
            if (isTenantFlowStarted) {
                PrivilegedCarbonContext.endTenantFlow();
            }
        }
    }

    /**
     * Updates resource policy resource for the given resource id from the registry.
     *
     * @param identifier API identifier
     * @param resourceId Resource identifier
     * @param content    resource policy content
     * @throws APIManagementException
     */
    public static void updateResourcePolicyFromRegistryResourceId(APIIdentifier identifier, String resourceId,
            String content) throws APIManagementException {

        boolean isTenantFlowStarted = false;
        try {
            String tenantDomain = MultitenantUtils
                    .getTenantDomain(APIUtil.replaceEmailDomainBack(identifier.getProviderName()));
            if (tenantDomain != null && !MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
                isTenantFlowStarted = true;
                PrivilegedCarbonContext.startTenantFlow();
                PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
            }
            RegistryService registryService = ServiceReferenceHolder.getInstance().getRegistryService();
            int tenantId = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager()
                    .getTenantId(tenantDomain);
            APIUtil.loadTenantRegistry(tenantId);
            UserRegistry registry = registryService.getGovernanceSystemRegistry(tenantId);
            String resourcePath = APIConstants.API_LOCATION + RegistryConstants.PATH_SEPARATOR
                    + identifier.getProviderName() + RegistryConstants.PATH_SEPARATOR + identifier.getApiName()
                    + RegistryConstants.PATH_SEPARATOR + identifier.getVersion() + RegistryConstants.PATH_SEPARATOR
                    + SOAPToRESTConstants.SOAP_TO_REST_RESOURCE;
            Collection collection = (Collection) registry.get(resourcePath);
            String[] resources = collection.getChildren();

            if (resources == null) {
                handleException("Cannot find any resource policies at the path: " + resourcePath);
            }
            for (String path : resources) {
                Collection resourcePolicyCollection = (Collection) registry.get(path);
                String[] resourcePolicies = resourcePolicyCollection.getChildren();
                if (resourcePolicies == null) {
                    if (log.isDebugEnabled()) {
                        log.debug("Cannot find resource policies under path: " + path);
                    }
                    continue;
                }
                for (String resourcePolicyPath : resourcePolicies) {
                    Resource resource = registry.get(resourcePolicyPath);
                    if (StringUtils.isNotEmpty(resourceId)
                            && resourceId.equals(((ResourceImpl) resource).getUUID())) {
                        resource.setContent(content);
                        resource.setMediaType(SOAPToRESTConstants.TEXT_XML);
                        registry.put(resourcePolicyPath, resource);
                        break;
                    }
                }
            }
            if (log.isDebugEnabled()) {
                log.debug("Number of REST resources for " + resourcePath + " is: " + resources.length);
            }
        } catch (UserStoreException e) {
            handleException("Error while reading tenant information", e);
        } catch (RegistryException e) {
            handleException("Error when create registry instance", e);
        } catch (org.wso2.carbon.registry.api.RegistryException e) {
            handleException("Error while setting the resource policy content for the registry resource", e);
        } finally {
            if (isTenantFlowStarted) {
                PrivilegedCarbonContext.endTenantFlow();
            }
        }
    }

    /**
     * Gets resource policy resource for the given resource id from the registry.
     *
     * @param identifier API identifier
     * @param resourceId Resource identifier
     * @return resource policy string for the given resource id
     * @throws APIManagementException
     */
    public static String getResourcePolicyFromRegistryResourceId(APIIdentifier identifier, String resourceId)
            throws APIManagementException {

        boolean isTenantFlowStarted = false;
        String response = null;
        try {
            String tenantDomain = MultitenantUtils
                    .getTenantDomain(APIUtil.replaceEmailDomainBack(identifier.getProviderName()));
            if (tenantDomain != null && !MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
                isTenantFlowStarted = true;
                PrivilegedCarbonContext.startTenantFlow();
                PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
            }
            RegistryService registryService = ServiceReferenceHolder.getInstance().getRegistryService();
            int tenantId = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager()
                    .getTenantId(tenantDomain);
            APIUtil.loadTenantRegistry(tenantId);
            UserRegistry registry = registryService.getGovernanceSystemRegistry(tenantId);
            String resourcePath = APIConstants.API_LOCATION + RegistryConstants.PATH_SEPARATOR
                    + identifier.getProviderName() + RegistryConstants.PATH_SEPARATOR + identifier.getApiName()
                    + RegistryConstants.PATH_SEPARATOR + identifier.getVersion() + RegistryConstants.PATH_SEPARATOR
                    + SOAPToRESTConstants.SOAP_TO_REST_RESOURCE;
            Collection collection = (Collection) registry.get(resourcePath);
            String[] resources = collection.getChildren();

            if (resources == null) {
                handleException("Cannot find any resource policies at the path: " + resourcePath);
            }
            for (String path : resources) {
                Collection resourcePolicyCollection = (Collection) registry.get(path);
                String[] resourcePolicies = resourcePolicyCollection.getChildren();
                if (resourcePolicies == null) {
                    if (log.isDebugEnabled()) {
                        log.debug("Cannot find resource policies under path: " + path);
                    }
                    continue;
                }
                for (String resourcePolicyPath : resourcePolicies) {
                    Resource resource = registry.get(resourcePolicyPath);
                    if (StringUtils.isNotEmpty(resourceId)
                            && resourceId.equals(((ResourceImpl) resource).getUUID())) {
                        JSONObject resultJson = new JSONObject();
                        Resource resourcePolicyResource = registry.get(resourcePolicyPath);
                        String content = new String((byte[]) resourcePolicyResource.getContent(),
                                Charset.defaultCharset());
                        String resourceName = ((ResourceImpl) resource).getName();
                        resourceName = resourceName.replaceAll(
                                SOAPToRESTConstants.SequenceGen.XML_FILE_RESOURCE_PREFIX,
                                SOAPToRESTConstants.EMPTY_STRING);
                        String httpMethod = resource.getProperty(SOAPToRESTConstants.METHOD);
                        Map<String, String> resourceMap = new HashMap<>();
                        resourceMap.put(SOAPToRESTConstants.RESOURCE_ID, ((ResourceImpl) resource).getUUID());
                        resourceMap.put(SOAPToRESTConstants.METHOD, httpMethod);
                        resourceMap.put(SOAPToRESTConstants.CONTENT, content);
                        resultJson.put(resourceName, resourceMap);
                        response = resultJson.toJSONString();
                    }
                }
            }
        } catch (UserStoreException e) {
            handleException("Error while reading tenant information.", e);
        } catch (RegistryException e) {
            handleException("Error when create registry instance.", e);
        } catch (org.wso2.carbon.registry.api.RegistryException e) {
            handleException("Error while retrieving resource policy resource content from the registry.", e);
        } finally {
            if (isTenantFlowStarted) {
                PrivilegedCarbonContext.endTenantFlow();
            }
        }
        return response;
    }

    /**
     * Gets soap to rest converted sequence from the registry
     * <p>
     * Note: this method is directly invoked from the jaggery layer
     *
     * @param name     api name
     * @param version  api version
     * @param provider api provider
     * @param seqType  to identify the sequence is whether in/out sequence
     * @return converted sequences string for a given operation
     * @throws APIManagementException throws exceptions on unsuccessful retrieval of resources in registry
     */
    public static String getRestToSoapConvertedSequence(String name, String version, String provider,
            String seqType) throws APIManagementException {
        JSONObject resultJson = new JSONObject();

        provider = (provider != null ? provider.trim() : null);
        name = (name != null ? name.trim() : null);
        version = (version != null ? version.trim() : null);

        boolean isTenantFlowStarted = false;

        try {
            String tenantDomain = MultitenantUtils.getTenantDomain(APIUtil.replaceEmailDomainBack(provider));
            if (tenantDomain != null && !MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
                isTenantFlowStarted = true;
                PrivilegedCarbonContext.startTenantFlow();
                PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
            }
            RegistryService registryService = ServiceReferenceHolder.getInstance().getRegistryService();
            int tenantId;
            UserRegistry registry;

            try {
                tenantId = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager()
                        .getTenantId(tenantDomain);
                APIUtil.loadTenantRegistry(tenantId);
                registry = registryService.getGovernanceSystemRegistry(tenantId);
                String resourcePath = APIConstants.API_LOCATION + RegistryConstants.PATH_SEPARATOR + provider
                        + RegistryConstants.PATH_SEPARATOR + name + RegistryConstants.PATH_SEPARATOR + version
                        + RegistryConstants.PATH_SEPARATOR + SOAPToRESTConstants.SOAP_TO_REST_RESOURCE
                        + RegistryConstants.PATH_SEPARATOR + seqType;

                Collection collection = (Collection) registry.get(resourcePath);
                String[] resources = collection.getChildren();

                if (log.isDebugEnabled()) {
                    log.debug("Number of REST resources for " + resourcePath + " is: " + resources.length);
                }

                for (String path : resources) {
                    Resource resource = registry.get(path);
                    String content = new String((byte[]) resource.getContent(), Charset.defaultCharset());
                    String resourceName = ((ResourceImpl) resource).getName();
                    resourceName = resourceName.replaceAll(SOAPToRESTConstants.SequenceGen.XML_FILE_RESOURCE_PREFIX,
                            SOAPToRESTConstants.EMPTY_STRING);
                    String httpMethod = resource.getProperty(SOAPToRESTConstants.METHOD);
                    Map<String, String> resourceMap = new HashMap<>();
                    resourceMap.put(SOAPToRESTConstants.RESOURCE_ID, ((ResourceImpl) resource).getUUID());
                    resourceMap.put(SOAPToRESTConstants.METHOD, httpMethod);
                    resourceMap.put(SOAPToRESTConstants.CONTENT, content);
                    resultJson.put(resourceName, resourceMap);
                }

            } catch (RegistryException e) {
                handleException("Error when create registry instance", e);
            } catch (UserStoreException e) {
                handleException("Error while reading tenant information", e);
            } catch (org.wso2.carbon.registry.api.RegistryException e) {
                handleException("Error while creating registry resource", e);
            }
        } finally {
            if (isTenantFlowStarted) {
                PrivilegedCarbonContext.endTenantFlow();
            }
        }
        if (log.isDebugEnabled()) {
            log.debug("Saved sequence for type " + seqType + " for api:" + provider + "-" + name + "-" + version
                    + " is: " + resultJson.toJSONString());
        }
        return resultJson.toJSONString();
    }

    /**
     * Gets the velocity template config context with sequence data populated
     *
     * @param registry      user registry reference
     * @param resourcePath  registry resource path
     * @param seqType       sequence type whether in or out sequence
     * @param configContext velocity template config context
     * @return {@link ConfigContext} sequences populated velocity template config context
     * @throws org.wso2.carbon.registry.api.RegistryException throws when getting registry resource content
     */
    public static ConfigContext getSequenceTemplateConfigContext(UserRegistry registry, String resourcePath,
            String seqType, ConfigContext configContext) throws org.wso2.carbon.registry.api.RegistryException {
        Resource regResource;
        if (registry.resourceExists(resourcePath)) {
            regResource = registry.get(resourcePath);
            String[] resources = ((Collection) regResource).getChildren();
            JSONObject pathObj = new JSONObject();
            if (resources != null) {
                for (String path : resources) {
                    Resource resource = registry.get(path);
                    String method = resource.getProperty(SOAPToRESTConstants.METHOD);
                    String resourceName = ((ResourceImpl) resource).getName();
                    resourceName = resourceName.replaceAll(SOAPToRESTConstants.SequenceGen.XML_FILE_RESOURCE_PREFIX,
                            SOAPToRESTConstants.EMPTY_STRING);
                    resourceName = resourceName.replaceAll(
                            SOAPToRESTConstants.SequenceGen.RESOURCE_METHOD_SEPERATOR + method,
                            SOAPToRESTConstants.EMPTY_STRING);
                    resourceName = SOAPToRESTConstants.SequenceGen.PATH_SEPARATOR + resourceName;
                    String content = RegistryUtils.decodeBytes((byte[]) resource.getContent());
                    JSONObject contentObj = new JSONObject();
                    contentObj.put(method, content);
                    pathObj.put(resourceName, contentObj);
                }
            } else {
                log.error("No sequences were found on the resource path: " + resourcePath);
            }
            configContext = new SOAPToRESTAPIConfigContext(configContext, pathObj, seqType);
        }
        return configContext;
    }

    /**
     * Gets parameter definitions from swagger
     *
     * @param swaggerObj swagger json
     * @param resource   rest resource object
     * @param method     http method
     * @return parameter mapping for a resource from the swagger definitions
     */
    public static List<JSONObject> getResourceParametersFromSwagger(JSONObject swaggerObj, JSONObject resource,
            String method) {
        Map content = (HashMap) resource.get(method);
        JSONArray parameters = (JSONArray) content.get(SOAPToRESTConstants.Swagger.PARAMETERS);
        List<JSONObject> mappingList = new ArrayList<>();
        for (Object param : parameters) {
            String inputType = String.valueOf(((JSONObject) param).get(SOAPToRESTConstants.Swagger.IN));
            if (inputType.equals(SOAPToRESTConstants.Swagger.BODY)) {
                JSONObject schema = (JSONObject) ((JSONObject) param).get(SOAPToRESTConstants.Swagger.SCHEMA);
                String definitionPath = String.valueOf(schema.get(SOAPToRESTConstants.Swagger.REF));
                String definition = definitionPath.replaceAll(SOAPToRESTConstants.Swagger.DEFINITIONS_ROOT,
                        SOAPToRESTConstants.EMPTY_STRING);
                JSONObject definitions = (JSONObject) ((JSONObject) swaggerObj
                        .get(SOAPToRESTConstants.Swagger.DEFINITIONS)).get(definition);
                JSONObject properties = (JSONObject) definitions.get(SOAPToRESTConstants.Swagger.PROPERTIES);

                for (Object property : properties.entrySet()) {
                    Map.Entry entry = (Map.Entry) property;
                    String paramName = String.valueOf(entry.getKey());
                    JSONObject value = (JSONObject) entry.getValue();
                    JSONArray propArray = new JSONArray();
                    if (value.get(SOAPToRESTConstants.Swagger.REF) != null) {
                        String propDefinitionRef = String.valueOf(value.get(SOAPToRESTConstants.Swagger.REF))
                                .replaceAll(SOAPToRESTConstants.Swagger.DEFINITIONS_ROOT,
                                        SOAPToRESTConstants.EMPTY_STRING);
                        getNestedDefinitionsFromSwagger(
                                (JSONObject) swaggerObj.get(SOAPToRESTConstants.Swagger.DEFINITIONS),
                                propDefinitionRef, propDefinitionRef, propArray);
                        JSONObject refObj = new JSONObject();
                        refObj.put(paramName, propArray);
                        if (log.isDebugEnabled()) {
                            log.debug("Properties for from resource parameter: " + paramName + " are: "
                                    + propArray.toJSONString());
                        }
                        mappingList.add(refObj);
                    } else if (String.valueOf(value.get(SOAPToRESTConstants.Swagger.TYPE))
                            .equals(SOAPToRESTConstants.ParamTypes.ARRAY)) {
                        JSONObject arrObj = new JSONObject();
                        arrObj.put(((Map.Entry) property).getKey(), ((Map.Entry) property).getValue());
                        mappingList.add(arrObj);
                        if (log.isDebugEnabled()) {
                            log.debug("Properties for from array type resource parameter: "
                                    + ((Map.Entry) property).getKey() + " are: " + arrObj.toJSONString());
                        }
                    }
                }
            } else {
                JSONObject queryObj = new JSONObject();
                queryObj.put(((JSONObject) param).get(SOAPToRESTConstants.Swagger.NAME), param);
                mappingList.add(queryObj);
                if (log.isDebugEnabled()) {
                    log.debug("Properties for from query type resource parameter: " + queryObj.toJSONString());
                }
            }
        }
        return mappingList;
    }

    /**
     * Gets nested swagger definitions for the complex types
     *
     * @param definitions swagger definition json
     * @param definition  parent definition
     * @param jsonPath    json path to be construct
     * @param propArray   properties for the nested definition
     */
    private static void getNestedDefinitionsFromSwagger(JSONObject definitions, String definition, String jsonPath,
            JSONArray propArray) {
        JSONObject propDefinitions = (JSONObject) (definitions).get(definition);
        JSONObject props;
        if (SOAPToRESTConstants.ParamTypes.ARRAY.equals(propDefinitions.get(SOAPToRESTConstants.TYPE_ATTRIBUTE))) {
            props = (JSONObject) propDefinitions.get(SOAPToRESTConstants.Swagger.ITEMS);
            if (props.get(SOAPToRESTConstants.Swagger.REF) == null) {
                JSONObject arrayProperty = new JSONObject();
                String key = jsonPath + "." + props.get(SOAPToRESTConstants.TYPE_ATTRIBUTE);
                arrayProperty.put(key, props.get(SOAPToRESTConstants.TYPE_ATTRIBUTE));
                arrayProperty.put(SOAPToRESTConstants.TYPE_ATTRIBUTE, SOAPToRESTConstants.ParamTypes.ARRAY);
                arrayProperty.put(SOAPToRESTConstants.SequenceGen.PARAMETER_NAME,
                        props.get(SOAPToRESTConstants.TYPE_ATTRIBUTE));
                arrayProperty.put(SOAPToRESTConstants.SequenceGen.XPATH, jsonPath);
                propArray.add(arrayProperty);
                return;
            }
        } else {
            props = (JSONObject) propDefinitions.get(SOAPToRESTConstants.Swagger.PROPERTIES);
        }
        for (Object property : props.entrySet()) {
            Map.Entry entry = (Map.Entry) property;
            String paramName = String.valueOf(entry.getKey());
            JSONObject value = (JSONObject) entry.getValue();
            if (value.get(SOAPToRESTConstants.Swagger.REF) != null) {
                String propDefinitionRef = String.valueOf(value.get(SOAPToRESTConstants.Swagger.REF))
                        .replaceAll(SOAPToRESTConstants.Swagger.DEFINITIONS_ROOT, SOAPToRESTConstants.EMPTY_STRING);
                jsonPath = definition + "." + propDefinitionRef;
                getNestedDefinitionsFromSwagger(definitions, propDefinitionRef, jsonPath, propArray);
            } else {
                JSONObject nestedProp = new JSONObject();
                String key;
                if (jsonPath.endsWith(definition)) {
                    key = jsonPath + "." + paramName;
                } else {
                    key = definition + "." + paramName;
                }
                nestedProp.put(key, value);
                propArray.add(nestedProp);
            }
            if (log.isDebugEnabled()) {
                log.debug("json path for definition: " + definition + " is: " + jsonPath);
            }
        }
    }

    /**
     * Generate json paths for the elements of a given json
     *
     * @param json                     json payload
     * @param parameterJsonPathMapping map to be populated with the respective json paths
     * @throws JSONException
     */
    public static void listJson(org.json.JSONObject json, Map<String, String> parameterJsonPathMapping)
            throws JSONException {
        listJSONObject(SOAPToRESTConstants.EMPTY_STRING, json, parameterJsonPathMapping);
    }

    private static void listObject(String parent, Object data, Map<String, String> parameterJsonPathMapping)
            throws JSONException {
        if (data instanceof org.json.JSONObject) {
            listJSONObject(parent, (org.json.JSONObject) data, parameterJsonPathMapping);
        } else if (data instanceof org.json.JSONArray) {
            listJSONArray(parent, (org.json.JSONArray) data, parameterJsonPathMapping);
        } else {
            listPrimitive(parent, data, parameterJsonPathMapping);
        }
    }

    private static void listJSONObject(String parent, org.json.JSONObject json,
            Map<String, String> parameterJsonPathMapping) throws JSONException {

        Iterator it = json.keys();
        if (!it.hasNext()) {
            if (log.isDebugEnabled()) {
                log.debug("JSON path of the parameter: " + parent + " and type: object");
            }

            String[] types = parent.split(",");
            if (types.length > 1) {
                parameterJsonPathMapping.put(types[0], types[1]);
            } else {
                parameterJsonPathMapping.put(types[0], "object");
            }
        }
        while (it.hasNext()) {
            String key = (String) it.next();
            Object child = json.get(key);
            String childKey = parent.isEmpty() ? key : parent + "." + key;
            listObject(childKey, child, parameterJsonPathMapping);
        }
    }

    private static void listJSONArray(String parent, org.json.JSONArray json,
            Map<String, String> parameterJsonPathMapping) throws JSONException {

        for (int i = 0; i < json.length(); i++) {
            Object data = json.get(i);
            listObject(parent + ",array", data, parameterJsonPathMapping);
        }
    }

    private static void listPrimitive(String parent, Object obj, Map<String, String> parameterJsonPathMapping) {

        log.debug("JSON path of the parameter: " + parent + " and type: primitive");
        String[] types = parent.split(",");
        if (types.length > 1) {
            parameterJsonPathMapping.put(types[0], types[1]);
        } else {
            parameterJsonPathMapping.put(types[0], "simple");
        }
    }
}