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

io.swagger.parser.v3.util.OpenAPIDeserializer Maven / Gradle / Ivy

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

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import io.swagger.oas.models.Components;
import io.swagger.oas.models.ExternalDocumentation;
import io.swagger.oas.models.OpenAPI;
import io.swagger.oas.models.Operation;
import io.swagger.oas.models.PathItem;
import io.swagger.oas.models.Paths;
import io.swagger.oas.models.callbacks.Callback;
import io.swagger.oas.models.examples.Example;
import io.swagger.oas.models.links.Link;
import io.swagger.oas.models.info.Contact;
import io.swagger.oas.models.info.Info;
import io.swagger.oas.models.media.ArraySchema;
import io.swagger.oas.models.media.ComposedSchema;
import io.swagger.oas.models.media.Content;
import io.swagger.oas.models.media.Discriminator;
import io.swagger.oas.models.media.Encoding;
import io.swagger.oas.models.media.MediaType;
import io.swagger.oas.models.media.Schema;
import io.swagger.oas.models.media.XML;
import io.swagger.oas.models.security.OAuthFlow;
import io.swagger.oas.models.security.OAuthFlows;
import io.swagger.oas.models.security.Scopes;
import io.swagger.oas.models.security.SecurityScheme;
import io.swagger.oas.models.tags.Tag;
import io.swagger.oas.models.info.License;
import io.swagger.oas.models.headers.Header;
import io.swagger.oas.models.parameters.CookieParameter;
import io.swagger.oas.models.parameters.HeaderParameter;
import io.swagger.oas.models.parameters.Parameter;
import io.swagger.oas.models.parameters.PathParameter;
import io.swagger.oas.models.parameters.QueryParameter;
import io.swagger.oas.models.parameters.RequestBody;
import io.swagger.oas.models.responses.ApiResponse;
import io.swagger.oas.models.responses.ApiResponses;
import io.swagger.oas.models.security.SecurityRequirement;
import io.swagger.oas.models.servers.Server;
import io.swagger.oas.models.servers.ServerVariable;
import io.swagger.oas.models.servers.ServerVariables;
import io.swagger.parser.models.SwaggerParseResult;
import io.swagger.util.Json;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;


public class OpenAPIDeserializer {

    protected static Set ROOT_KEYS = new LinkedHashSet<>(Arrays.asList("openapi", "info", "servers", "paths", "components", "security", "tags",  "externalDocs"));
    protected static Set INFO_KEYS = new LinkedHashSet<>(Arrays.asList("title", "description", "termsOfService", "contact", "license", "version"));
    protected static Set CONTACT_KEYS = new LinkedHashSet<>(Arrays.asList("name", "url", "email"));
    protected static Set LICENSE_KEYS = new LinkedHashSet<>(Arrays.asList("name", "url"));
    protected static Set TAG_KEYS = new LinkedHashSet<>(Arrays.asList("description", "name", "externalDocs"));
    protected static Set RESPONSE_KEYS = new LinkedHashSet<>(Arrays.asList("$ref", "description", "headers", "content", "links"));
    protected static Set SERVER_KEYS = new LinkedHashSet<>(Arrays.asList( "url", "description", "variables"));
    protected static Set SERVER_VARIABLE_KEYS = new LinkedHashSet<>(Arrays.asList( "enum", "default", "description"));
    protected static Set PATHITEM_KEYS = new LinkedHashSet<>(Arrays.asList("$ref", "summary", "description", "get", "put", "post", "delete", "head", "patch", "options", "trace", "servers", "parameters"));
    protected static Set OPERATION_KEYS = new LinkedHashSet<>(Arrays.asList("tags", "summary", "description", "externalDocs", "operationId", "parameters", "requestBody", "responses", "callbacks", "deprecated" ,  "security", "servers"));
    protected static Set PARAMETER_KEYS = new LinkedHashSet<>(Arrays.asList("$ref", "name", "in", "description", "required", "deprecated", "allowEmptyValue", "style", "explode", "allowReserved", "schema", "example", "examples", "content"));
    protected static Set REQUEST_BODY_KEYS = new LinkedHashSet<>(Arrays.asList("$ref", "description", "content", "required"));
    protected static Set SECURITY_SCHEME_KEYS = new LinkedHashSet<>(Arrays.asList("$ref", "type", "name", "in", "description", "flows", "scheme", "bearerFormat" , "openIdConnectUrl"));
    protected static Set EXTERNAL_DOCS_KEYS = new LinkedHashSet<>(Arrays.asList("description", "url"));
    protected static Set COMPONENTS_KEYS = new LinkedHashSet<>(Arrays.asList("schemas", "responses", "parameters", "examples", "requestBodies", "headers", "securitySchemes",  "links", "callbacks"));
    protected static Set SCHEMA_KEYS = new LinkedHashSet<>(Arrays.asList("$ref","title", "multipleOf", "maximum", "format", "exclusiveMaximum", "minimum", "exclusiveMinimum", "maxLength", "minLength", "pattern", "maxItems", "minItems", "uniqueItems", "maxProperties", "minProperties", "required", "enum", "type", "allOf", "oneOf", "anyOf", "not", "items", "properties", "additionalProperties", "description", "format", "default", "nullable", "discriminator", "readOnly", "writeOnly","xml", "externalDocs", "example","deprecated"));
    protected static Set EXAMPLE_KEYS = new LinkedHashSet<>(Arrays.asList("$ref", "summary", "description", "value", "externalValue"));
    protected static Set HEADER_KEYS = new LinkedHashSet<>(Arrays.asList("$ref", "name", "in", "description", "required", "deprecated", "allowEmptyValue", "style", "explode", "allowReserved", "schema", "example", "examples", "content"));
    protected static Set LINK_KEYS = new LinkedHashSet<>(Arrays.asList("$ref", "operationRef", "operationId", "parameters", "requestBody", "description", "server"));
    protected static Set MEDIATYPE_KEYS = new LinkedHashSet<>(Arrays.asList("schema", "example", "examples", "encoding"));
    protected static Set XML_KEYS = new LinkedHashSet<>(Arrays.asList("name", "namespace", "prefix", "attribute", "wrapped"));
    protected static Set OAUTHFLOW_KEYS = new LinkedHashSet<>(Arrays.asList("authorizationUrl", "tokenUrl", "refreshUrl", "scopes"));
    protected static Set OAUTHFLOWS_KEYS = new LinkedHashSet<>(Arrays.asList("implicit", "password", "clientCredential", "authorizationCode"));
    protected static Set ENCODING_KEYS = new LinkedHashSet<>(Arrays.asList("contentType", "headers", "style", "explode", "allowReserved"));


    private static final String QUERY_PARAMETER = "query";
    private static final String COOKIE_PARAMETER = "cookie";
    private static final String PATH_PARAMETER = "path";
    private static final String HEADER_PARAMETER = "header";


    public SwaggerParseResult deserialize(JsonNode rootNode) {
        SwaggerParseResult result = new SwaggerParseResult();
        try {
            ParseResult rootParse = new ParseResult();
            OpenAPI api = parseRoot(rootNode, rootParse);
            result.setOpenAPI(api);
            result.setMessages(rootParse.getMessages());
        } catch (Exception e) {
            result.setMessages(Arrays.asList(e.getMessage()));

        }
        return result;
    }

    public OpenAPI parseRoot(JsonNode node, ParseResult result) {
        String location = "";
        OpenAPI openAPI = new OpenAPI();
        if (node.getNodeType().equals(JsonNodeType.OBJECT)) {
            ObjectNode rootNode = (ObjectNode) node;

            // required
            String value = getString("openapi", rootNode, true, location, result);

            // we don't even try if the version isn't there
            if(value == null || !value.startsWith("3.0")) {
                return null;
            }
            openAPI.setOpenapi(value);

            ObjectNode obj = getObject("info", rootNode, true, location, result);
            if (obj != null) {
                Info info = getInfo(obj, "info", result);
                openAPI.setInfo(info);
            }

            obj = getObject("paths", rootNode, true, location, result);
            if (obj != null) {
                Paths paths = getPaths(obj, "paths", result);
                openAPI.setPaths(paths);
            }

            obj = getObject("components", rootNode, true, location, result);
            if (obj != null) {
                Components components = getComponents(obj, "components", result);
                openAPI.setComponents(components);
            }

            ArrayNode array = getArray("servers", rootNode, false, location, result);
            if (array != null && array.size() > 0) {
                openAPI.setServers(getServersList(array, String.format("%s.%s'", location, "servers"), result));
            }else {
                Server defaultServer = new Server();
                defaultServer.setUrl("/");
                List  servers = new ArrayList<>();
                servers.add(defaultServer);
                openAPI.setServers(servers);
            }

            obj = getObject("externalDocs", rootNode, false, location, result);
            if (obj != null) {
                ExternalDocumentation externalDocs = getExternalDocs(obj, "externalDocs", result);
                openAPI.setExternalDocs(externalDocs);
            }

            array = getArray("tags", rootNode, false, location, result);
            if (array != null && array.size() > 0) {
                openAPI.setTags(getTagList(array, "tags", result));
            }

            array = getArray("security", rootNode, false, location, result);
            if (array != null && array.size() > 0) {
                List securityRequirements = getSecurityRequirementsList(array, "security", result);
                if (securityRequirements != null && securityRequirements. size() > 0) {
                    openAPI.setSecurity(securityRequirements);
                }
            }

            Map  extensions = getExtensions(rootNode);
            if(extensions != null && extensions.size() > 0) {
                openAPI.setExtensions(extensions);
            }

            Set keys = getKeys(rootNode);
            for(String key : keys) {
                if(!ROOT_KEYS.contains(key) && !key.startsWith("x-")) {
                    result.extra(location, key, node.get(key));
                }
            }

        } else {
            result.invalidType(location, "openapi", "object", node);
            result.invalid();
            return null;
        }

        return openAPI;
    }

    public Map getExtensions(ObjectNode node){

        Map extensions = new LinkedHashMap<>();

        Set keys = getKeys(node);
        for(String key : keys) {
            if(key.startsWith("x-")) {
                extensions.put(key, Json.mapper().convertValue(node.get(key), Object.class));
            }
        }
        return  extensions;

    }

    public Components getComponents(ObjectNode obj, String location, ParseResult result) {
        if (obj == null) {
            return null;
        }
        Components components = new Components();

        ObjectNode node = getObject("schemas",obj,false, location ,result);
        if(node != null) {
            components.setSchemas(getSchemas(node,String.format("%s.%s'", location, "schemas"),result));
        }

        node = getObject("responses",obj,false, location,result);
        if(node != null) {
            components.setResponses(getResponses(node, String.format("%s.%s'", location, "responses"),result));
        }

        node = getObject("parameters",obj,false, location ,result);
        if(node != null) {
            components.setParameters(getParameters(node, String.format("%s.%s'", location, "parameters"),result));
        }
        node = getObject("examples",obj,false,location,result);
        if(node != null) {
            components.setExamples(getExamples(node, String.format("%s.%s'", location, "examples"),result));
        }

        node = getObject("requestBodies",obj,false,location,result);
        if(node != null) {
            components.setRequestBodies(getRequestBodies(node, String.format("%s.%s'", location, "requestBodies"),result));
        }

        node = getObject("headers",obj,false,location,result);
        if(node != null) {
            components.setHeaders(getHeaders(node, String.format("%s.%s'", location, "headers"),result));
        }

        node = getObject("securitySchemes",obj,false,location,result);
        if(node != null) {
            components.setSecuritySchemes(getSecuritySchemes(node, String.format("%s.%s'", location, "securitySchemes"),result));
        }

        node = getObject("links",obj,false,location,result);
        if(node != null) {
            components.setLinks(getLinks(node, String.format("%s.%s'", location, "links"),result));
        }

        node = getObject("callbacks",obj,false,location,result);
        if(node != null) {
            components.setCallbacks(getCallbacks(node, String.format("%s.%s'", location, "callbacks"),result));
        }
        components.setExtensions(new LinkedHashMap<>());

        Map  extensions = getExtensions(obj);
        if(extensions != null && extensions.size() > 0) {
            components.setExtensions(extensions);
        }

        Set keys = getKeys(obj);
        for(String key : keys) {
            if(!COMPONENTS_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, obj.get(key));
            }
        }


        return  components;
    }

    public List getTagList(ArrayNode obj, String location, ParseResult result) {
        if (obj == null) {
            return null;
        }
        List tags = new ArrayList<>();
        for (JsonNode item : obj) {
            if (item.getNodeType().equals(JsonNodeType.OBJECT)) {
                Tag tag = getTag((ObjectNode) item, location, result);
                if (tag != null) {
                    tags.add(tag);
                }
            }
        }
        return tags;
    }

    public Tag getTag(ObjectNode obj, String location, ParseResult result) {
        if (obj == null) {
            return null;
        }

        Tag tag = new Tag();

        String value = getString("name", obj, true, location, result);
        if(StringUtils.isNotBlank(value)) {
            tag.setName(value);
        }

        value = getString("description", obj, false, location, result);
        if(StringUtils.isNotBlank(value)) {
            tag.setDescription(value);
        }

        ObjectNode docs = getObject("externalDocs",obj,false,location,result);
        ExternalDocumentation externalDocs = getExternalDocs(docs, String.format("%s.%s'", location, "externalDocs"), result);
        if (externalDocs != null) {
            tag.setExternalDocs(externalDocs);
        }

        Map  extensions = getExtensions(obj);
        if(extensions != null && extensions.size() > 0) {
            tag.setExtensions(extensions);
        }

        Set keys = getKeys(obj);
        for(String key : keys) {
            if(!TAG_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, obj.get(key));
            }
        }

        return tag;
    }



    public List getServersList(ArrayNode obj, String location, ParseResult result) {

        List servers = new ArrayList<>();
        if (obj == null) {
            return null;

        }
        for (JsonNode item : obj) {
            if (item.getNodeType().equals(JsonNodeType.OBJECT)) {
                Server server = getServer((ObjectNode) item, location, result);
                if (server != null) {
                    servers.add(server);
                }else{
                    Server defaultServer = new Server();
                    defaultServer.setUrl("/");
                    servers.add(defaultServer);
                }
            }
        }
        return servers;
    }

    public Server getServer(ObjectNode obj, String location, ParseResult result) {
        if (obj == null) {
            return null;
        }

        Server server = new Server();

        String value = getString("url", obj, true, location, result);
        if(StringUtils.isNotBlank(value)) {
            server.setUrl(value);
        }

        value = getString("description", obj, false, location, result);
        if(StringUtils.isNotBlank(value)) {
            server.setDescription(value);
        }
        if (obj.get("variables") != null) {
            ObjectNode variables = getObject("variables", obj, false, location, result);
            ServerVariables serverVariables = getServerVariables(variables, String.format("%s.%s'", location, "variables"), result);
            if (serverVariables != null && serverVariables.size() > 0) {
                server.setVariables(serverVariables);
            }
        }


        Map  extensions = getExtensions(obj);
        if(extensions != null && extensions.size() > 0) {
            server.setExtensions(extensions);
        }

        Set keys = getKeys(obj);
        for(String key : keys) {
            if(!SERVER_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, obj.get(key));
            }
        }


        return server;
    }

    public ServerVariables getServerVariables(ObjectNode obj, String location, ParseResult result){
        ServerVariables serverVariables = new ServerVariables();
        if (obj == null) {
            return null;
        }

        Set serverKeys = getKeys(obj);
        for (String serverName : serverKeys) {
            JsonNode serverValue = obj.get(serverName);
            ObjectNode server = (ObjectNode) serverValue;
            ServerVariable serverVariable = getServerVariable(server, String.format("%s.%s'", location, serverName), result);
            serverVariables.addServerVariable(serverName,serverVariable);
        }

        return serverVariables;
    }

    public ServerVariable getServerVariable(ObjectNode obj, String location, ParseResult result){
        if(obj == null){
            return null;
        }

        ServerVariable serverVariable = new ServerVariable();

        ArrayNode arrayNode = getArray("enum",obj,false,location,result);
        if (arrayNode != null) {
            List _enum = new ArrayList<>();
            for(JsonNode n : arrayNode) {
                if(n.isValueNode()) {
                    _enum.add(n.asText());
                    serverVariable.setEnum(_enum);
                }
                else {
                    result.invalidType(location, "enum", "value", n);
                }
            }
        }
        String value = getString("default", obj, true, String.format("%s.%s'", location, "default"), result);
        if(StringUtils.isNotBlank(value)) {
            serverVariable.setDefault(value);
        }

        value = getString("description", obj, false, String.format("%s.%s'", location, "description"), result);
        if(StringUtils.isNotBlank(value)) {
            serverVariable.setDescription(value);
        }

        Map  extensions = getExtensions(obj);
        if(extensions != null && extensions.size() > 0) {
            serverVariable.setExtensions(extensions);
        }

        Set keys = getKeys(obj);
        for(String key : keys) {
            if(!SERVER_VARIABLE_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, obj.get(key));
            }
        }

        return serverVariable;
    }

    //PathsObject

    public Paths getPaths(ObjectNode obj, String location, ParseResult result) {
        final Paths paths = new Paths();
        if (obj == null) {
            return null;
        }
        Set pathKeys = getKeys(obj);
        for (String pathName : pathKeys) {
            JsonNode pathValue = obj.get(pathName);
            if(pathName.startsWith("x-")) {
                result.unsupported(location, pathName, pathValue);
            } else {
                if (!pathValue.getNodeType().equals(JsonNodeType.OBJECT)) {
                    result.invalidType(location, pathName, "object", pathValue);
                } else {
                    ObjectNode path = (ObjectNode) pathValue;
                    PathItem pathObj = getPathItem(path, String.format("%s.%s'", location, pathName), result);
                    paths.put(pathName, pathObj);
                }
            }
        }
        return paths;
    }

    public PathItem getPathItem(ObjectNode obj, String location, ParseResult result) {


        PathItem pathItem = new PathItem();

        if (obj.get("$ref") != null) {
            JsonNode ref = obj.get("$ref");

            if (ref.getNodeType().equals(JsonNodeType.STRING)) {
                pathItem.set$ref(ref.asText());
                return pathItem.$ref((ref.asText()));
            } else if (ref.getNodeType().equals(JsonNodeType.OBJECT)) {
                ObjectNode node = (ObjectNode) ref;

                // extra keys
                Set keys = getKeys(node);
                for (String key : keys) {
                    result.extra(location, key, node.get(key));
                }
            }
            return null;
        }

        String value = getString("summary", obj, false, location, result);
        if(StringUtils.isNotBlank(value)) {
            pathItem.setSummary(value);
        }

        value = getString("description", obj, false, location, result);
        if(StringUtils.isNotBlank(value)) {
            pathItem.setDescription(value);
        }

        ArrayNode parameters = getArray("parameters", obj, false, location, result);
        if(parameters != null && parameters.size()> 0) {
            pathItem.setParameters(getParameterList(parameters, location, result));
        }

        ArrayNode servers = getArray("servers", obj, false, location, result);
        if(servers != null && servers.size() >0) {
            pathItem.setServers(getServersList(servers, location, result));
        }

        ObjectNode node = getObject("get", obj, false, location, result);
        if (node != null) {
            Operation operation = getOperation(node, location + "(get)", result);
            if (operation != null) {
                pathItem.setGet(operation);
            }
        }
        node = getObject("put", obj, false, location, result);
        if (node != null) {
            Operation operation = getOperation(node, location + "(put)", result);
            if (operation != null) {
                pathItem.setPut(operation);
            }
        }
        node = getObject("post", obj, false, location, result);
        if (node != null) {
            Operation operation = getOperation(node, location + "(post)", result);
            if (operation != null) {
                pathItem.setPost(operation);
            }
        }
        node = getObject("head", obj, false, location, result);
        if (node != null) {
            Operation operation = getOperation(node, location + "(head)", result);
            if (operation != null) {
                pathItem.setHead(operation);
            }
        }
        node = getObject("delete", obj, false, location, result);
        if (node != null) {
            Operation operation = getOperation(node, location + "(delete)", result);
            if (operation != null) {
                pathItem.setDelete(operation);
            }
        }
        node = getObject("patch", obj, false, location, result);
        if (node != null) {
            Operation operation = getOperation(node, location + "(patch)", result);
            if (operation != null) {
                pathItem.setPatch(operation);
            }
        }
        node = getObject("options", obj, false, location, result);
        if (node != null) {
            Operation operation = getOperation(node, location + "(options)", result);
            if (operation != null) {
                pathItem.setOptions(operation);
            }
        }

        Map  extensions = getExtensions(obj);
        if(extensions != null && extensions.size() > 0) {
            pathItem.setExtensions(extensions);
        }

        Set keys = getKeys(obj);
        for(String key : keys) {
            if(!PATHITEM_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, obj.get(key));
            }
        }

        return pathItem;
    }


    public ExternalDocumentation getExternalDocs(ObjectNode node, String location, ParseResult result) {
        ExternalDocumentation externalDocs = null;

        if (node != null) {
            externalDocs = new ExternalDocumentation();

            String value = getString("description", node, false, location, result);
            if(StringUtils.isNotBlank(value)) {
                externalDocs.description(value);
            }

            value = getString("url", node, true, location, result);
            if(StringUtils.isNotBlank(value)) {
                externalDocs.url(value);
            }

            Map  extensions = getExtensions(node);
            if(extensions != null && extensions.size() > 0) {
                externalDocs.setExtensions(extensions);
            }

            Set keys = getKeys(node);
            for(String key : keys) {
                if(!EXTERNAL_DOCS_KEYS.contains(key) && !key.startsWith("x-")) {
                    result.extra(location, key, node.get(key));
                }
            }
        }

        return externalDocs;
    }


    public String getString(String key, ObjectNode node, boolean required, String location, ParseResult result) {
        String value = null;
        JsonNode v = node.get(key);
        if (node == null || v == null) {
            if (required) {
                result.missing(location, key);
                result.invalid();
            }
        } else if (!v.isValueNode()) {
            result.invalidType(location, key, "string", node);
        } else {
            value = v.asText();
        }
        return value;
    }

    public Set getKeys(ObjectNode node) {
        Set keys = new LinkedHashSet<>();
        if (node == null) {
            return keys;
        }

        Iterator it = node.fieldNames();
        while (it.hasNext()) {
            keys.add(it.next());
        }

        return keys;
    }


    public ObjectNode getObject(String key, ObjectNode node, boolean required, String location, ParseResult result) {
        JsonNode value = node.get(key);
        ObjectNode object = null;
        if (value == null) {
            if (required) {
                result.missing(location, key);
                result.invalid();
            }
        } else if (!value.getNodeType().equals(JsonNodeType.OBJECT)) {
            result.invalidType(location, key, "object", value);
            if (required) {
                result.invalid();
            }
        } else {
            object = (ObjectNode) value;
        }
        return object;
    }

    public Info getInfo(ObjectNode node, String location, ParseResult result) {
        if (node == null)
            return null;

        Info info = new Info();

        String value = getString("title", node, true, location, result);
        if(StringUtils.isNotBlank(value)) {
            info.setTitle(value);
        }

        value = getString("description", node, false, location, result);
        if(StringUtils.isNotBlank(value)) {
            info.setDescription(value);
        }

        value = getString("termsOfService", node, false, location, result);
        if(StringUtils.isNotBlank(value)) {
            info.setTermsOfService(value);
        }

        ObjectNode obj = getObject("contact", node, false, "contact", result);
        Contact contact = getContact(obj, String.format("%s.%s'", location, "contact"), result);
        if(obj != null) {
            info.setContact(contact);
        }
        obj = getObject("license", node, false, location, result);
        License license = getLicense(obj, String.format("%s.%s'", location, "license"), result);
        if(obj != null) {
            info.setLicense(license);
        }

        value = getString("version", node, true, location, result);
        if(StringUtils.isNotBlank(value)) {
            info.setVersion(value);
        }

        Map  extensions = getExtensions(node);
        if(extensions != null && extensions.size() > 0) {
            info.setExtensions(extensions);
        }

        Set keys = getKeys(node);
        for(String key : keys) {
            if(!INFO_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, node.get(key));
            }
        }

        return info;
    }

    public License getLicense(ObjectNode node, String location, ParseResult result) {
        if (node == null)
            return null;

        License license = new License();

        String value = getString("name", node, true, location, result);
        if(StringUtils.isNotBlank(value)) {
            license.setName(value);
        }

        value = getString("url", node, false, location, result);
        if(StringUtils.isNotBlank(value)) {
            license.setUrl(value);
        }

        Map  extensions = getExtensions(node);
        if(extensions != null && extensions.size() > 0) {
            license.setExtensions(extensions);
        }

        Set keys = getKeys(node);
        for(String key : keys) {
            if(!LICENSE_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, node.get(key));
            }
        }

        return license;
    }

    public Contact getContact(ObjectNode node, String location, ParseResult result) {
        if (node == null)
            return null;

        Contact contact = new Contact();

        String value = getString("name", node, false, location, result);
        if(StringUtils.isNotBlank(value)) {
            contact.setName(value);
        }

        value = getString("url", node, false, location, result);
        if(StringUtils.isNotBlank(value)) {
            contact.setUrl(value);
        }

        value = getString("email", node, false, location, result);
        if(StringUtils.isNotBlank(value)) {
            contact.setEmail(value);
        }

        Map  extensions = getExtensions(node);
        if(extensions != null && extensions.size() > 0) {
            contact.setExtensions(extensions);
        }

        Set keys = getKeys(node);
        for(String key : keys) {
            if(!CONTACT_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, node.get(key));
            }
        }

        return contact;
    }

    public Content getContent(ObjectNode node, String location, ParseResult result){
        if (node == null) {
            return null;
        }
        Content content = new Content();

        Set keys = getKeys(node);
        for(String key : keys) {
            MediaType mediaType = getMediaType((ObjectNode) node.get(key), location, result);
            if (mediaType != null) {
                content.addMediaType(key, mediaType);
            }
        }

        return content;
    }

    public MediaType getMediaType(ObjectNode contentNode, String location, ParseResult result){
        if (contentNode == null) {
            return null;
        }
        MediaType mediaType = new MediaType();

        ObjectNode schemaObject = getObject("schema",contentNode,false,location,result);
        if(schemaObject != null){
            mediaType.setSchema(getSchema(schemaObject,String.format("%s.%s'", location, "schema"),result));
        }

        ObjectNode examplesObject = getObject("examples",contentNode,false,location,result);
        if(examplesObject != null) {
            mediaType.setExamples(getExamples(examplesObject, String.format("%s.%s'", location, "examples"), result));
        }

        JsonNode exampleNode = contentNode.get("example");
        if(exampleNode != null) {
            String value = getString("example", contentNode, false, location, result);
            if(StringUtils.isNotBlank(value)) {
                mediaType.setExample(value);
            }
        }


        ObjectNode encodingObject = getObject("encoding",contentNode,false,location,result);
        if(encodingObject!=null) {
            mediaType.setEncoding(getEncodingMap(encodingObject, String.format("%s.%s'", location, "encoding"), result));
        }
        Map  extensions = getExtensions(contentNode);
        if(extensions != null && extensions.size() > 0) {
            mediaType.setExtensions(extensions);
        }

        Set keys = getKeys(contentNode);
        for(String key : keys) {
            if(!MEDIATYPE_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, contentNode.get(key));
            }
        }

        return mediaType;
    }

    public Map getEncodingMap(ObjectNode node, String location, ParseResult result){
        if (node == null) {
            return null;
        }
        Map encodings = new LinkedHashMap<>();
        Set keys = getKeys(node);
        for(String key : keys) {
            Encoding encoding = getEncoding((ObjectNode) node.get(key), location, result);
            if (encoding != null) {
                encodings.put(key, encoding);
            }
        }
        return encodings;
    }

    public Encoding getEncoding(ObjectNode node, String location, ParseResult result) {
        if (node == null) {
            return null;
        }

        Encoding encoding = new Encoding();

        String value = getString("contentType", node, true, location, result);
        encoding.setContentType(value);

        value = getString("style", node, false, location, result);

        if (StringUtils.isBlank(value)) {
            encoding.setStyle(Encoding.StyleEnum.FORM.toString());
        } else {
            if (value.equals(Encoding.StyleEnum.FORM.toString())) {
                encoding.setStyle(Encoding.StyleEnum.FORM.toString());
            } else if (value.equals(Encoding.StyleEnum.DEEP_OBJECT.toString())) {
                encoding.setStyle(Encoding.StyleEnum.DEEP_OBJECT.toString());
            } else if (value.equals(Encoding.StyleEnum.PIPE_DELIMITED.toString())) {
                encoding.setStyle(Encoding.StyleEnum.PIPE_DELIMITED.toString());
            } else if (value.equals(Encoding.StyleEnum.SPACE_DELIMITED.toString())) {
                encoding.setStyle(Encoding.StyleEnum.SPACE_DELIMITED.toString());
            } else {
                result.invalidType(location, "style", "string", node);
            }
        }

        Boolean explode = getBoolean("explode", node, false, location, result);
        if (explode != null) {
            encoding.setExplode(explode);
        }

        Boolean allowReserved = getBoolean("allowReserved", node, false, location, result);
        if (allowReserved != null) {
            encoding.setAllowReserved(allowReserved);
        }
        ObjectNode headersObject = getObject("headers", node, false, location, result);
        if (headersObject!= null){
            encoding.setHeaders(getHeaders(headersObject, location, result));
        }

        Map  extensions = getExtensions(node);
        if(extensions != null && extensions.size() > 0) {
            encoding.setExtensions(extensions);
        }

        Set keys = getKeys(node);
        for(String key : keys) {
            if(!ENCODING_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, node.get(key));
            }
        }

        return encoding;
    }

    public Map getLinks(ObjectNode obj, String location, ParseResult result) {
        if (obj == null) {
            return null;
        }
        Map links = new LinkedHashMap<>();


        Set linkKeys = getKeys(obj);
        for(String linkName : linkKeys) {
            JsonNode linkValue = obj.get(linkName);
            if (!linkValue.getNodeType().equals(JsonNodeType.OBJECT)) {
                result.invalidType(location, linkName, "object", linkValue);
            } else {
                ObjectNode link = (ObjectNode) linkValue;
                Link linkObj = getLink(link, String.format("%s.%s'", location, linkName), result);
                if(linkObj !=null) {
                    links.put(linkName, linkObj);
                }
            }

        }
        return links;
    }

    public Link getLink(ObjectNode linkNode, String location, ParseResult result) {
        if (linkNode == null) {
            return null;
        }

        Link link = new Link();

        JsonNode ref = linkNode.get("$ref");
        if (ref != null) {
            if (ref.getNodeType().equals(JsonNodeType.STRING)) {
                link.set$ref(ref.asText());
                return link.$ref(ref.asText());
            } else {
                result.invalidType(location, "$ref", "string", linkNode);
                return null;
            }
        }

        String value = getString("operationRef", linkNode, false, location, result);
        if(StringUtils.isNotBlank(value)){
            link.setOperationRef(value);
        }

        value = getString("operationId", linkNode, false, location, result);
        if(StringUtils.isNotBlank(value)){
            link.setOperationId(value);
        }

        ObjectNode parametersObject = getObject("parameters",linkNode,false,location,result);
        if (parametersObject!= null) {
            link.setParameters(getLinkParameters(parametersObject, location, result));
        }

        ObjectNode headerObject = getObject("headers",linkNode,false,location,result);
        if (headerObject!= null) {
            link.setHeaders(getHeaders(headerObject, location, result));
        }

        ObjectNode serverObject = getObject("server",linkNode,false,location,result);
        if (serverObject!= null) {
             link.setServer(getServer(serverObject, location, result));
        }

        value = getString("description", linkNode, false, location, result);
        if(StringUtils.isNotBlank(value)){
            link.setDescription(value);
        }

        Map  extensions = getExtensions(linkNode);
        if(extensions != null && extensions.size() > 0) {
            link.setExtensions(extensions);
        }

        Set keys = getKeys(linkNode);
        for(String key : keys) {
            if(!LINK_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, linkNode.get(key));
            }
        }

        return link;
    }

    private Map getLinkParameters(ObjectNode parametersObject, String location, ParseResult result) {

        Map  linkParameters = new LinkedHashMap<>();

        Set keys = getKeys(parametersObject);
        for(String name : keys) {
            JsonNode value = parametersObject.get(name);
            linkParameters.put(name, value.asText());
        }

        return linkParameters;
    }

    public Map  getCallbacks(ObjectNode node, String location, ParseResult result){
        if (node == null) {
            return null;
        }
        Map callbacks = new LinkedHashMap<>();
        Set keys = getKeys(node);
        for(String key : keys) {
            Callback callback = getCallback((ObjectNode) node.get(key), location, result);
            if (callback != null) {
                callbacks.put(key, callback);
            }
        }
        return callbacks;
    }

    public Callback getCallback(ObjectNode node,String location, ParseResult result) {
        if (node == null) {
            return null;
        }

        Callback callback = new Callback();

        Set keys = getKeys(node);
        for(String name : keys) {
            JsonNode value = node.get(name);
            if (node!= null){
                JsonNode ref = node.get("$ref");
                if (ref != null) {
                    if (ref.getNodeType().equals(JsonNodeType.STRING)) {
                        PathItem pathItem = new PathItem();
                        return callback.addPathItem(name,pathItem.$ref(ref.asText()));
                    } else {
                        result.invalidType(location, "$ref", "string", node);
                        return null;
                    }
                }
                callback.addPathItem(name,getPathItem((ObjectNode) value,location,result));

                Map  extensions = getExtensions(node);
                if(extensions != null && extensions.size() > 0) {
                    callback.setExtensions(extensions);
                }
            }
        }

        return callback;
    }

    public XML getXml(ObjectNode node, String location, ParseResult result){
        if (node == null) {
            return null;
        }
        XML xml = new XML();

        String value = getString("name", node, false, String.format("%s.%s'", location, "name"), result);
        if(StringUtils.isNotBlank(value)){
            xml.setName(value);
        }

        value = getString("namespace", node, false, String.format("%s.%s'", location, "namespace"), result);
        if(StringUtils.isNotBlank(value)){
            xml.setNamespace(value);
        }

        value = getString("prefix", node, false, String.format("%s.%s'", location, "prefix"), result);
        if(StringUtils.isNotBlank(value)){
            xml.setPrefix(value);
        }

        Boolean attribute = getBoolean("attribute", node, false, location, result);
        if(attribute != null){
            xml.setAttribute(attribute);
        }

        Boolean wrapped = getBoolean("wrapped", node, false, location, result);
        if(wrapped != null){
            xml.setWrapped(wrapped);
        }

        Map  extensions = getExtensions(node);
        if(extensions != null && extensions.size() > 0) {
            xml.setExtensions(extensions);
        }


        Set keys = getKeys(node);
        for(String key : keys) {
            if(!XML_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, node.get(key));
            }
        }



        return xml;

    }

    public ArrayNode getArray(String key, ObjectNode node, boolean required, String location, ParseResult result) {
        JsonNode value = node.get(key);
        ArrayNode arrayNode = null;
        if (value == null) {
            if (required) {
                result.missing(location, key);
                result.invalid();
            }
        } else if (!value.getNodeType().equals(JsonNodeType.ARRAY)) {
            result.invalidType(location, key, "array", value);
        } else {
            arrayNode = (ArrayNode) value;
        }
        return arrayNode;
    }

    public Boolean getBoolean(String key, ObjectNode node, boolean required, String location, ParseResult result) {
        Boolean value = null;
        JsonNode v = node.get(key);
        if (node == null || v == null) {
            if (required) {
                result.missing(location, key);
                result.invalid();
            }
        } else {
            if (v.getNodeType().equals(JsonNodeType.BOOLEAN)) {
                value = v.asBoolean();
            } else if (v.getNodeType().equals(JsonNodeType.STRING)) {
                String stringValue = v.textValue();
                return Boolean.parseBoolean(stringValue);
            }
        }
        return value;
    }

    public BigDecimal getBigDecimal(String key, ObjectNode node, boolean required, String location, ParseResult result) {
        BigDecimal value = null;
        JsonNode v = node.get(key);
        if (node == null || v == null) {
            if (required) {
                result.missing(location, key);
                result.invalid();
            }
        }
        else if(v.getNodeType().equals(JsonNodeType.NUMBER)) {
            value = new BigDecimal(v.asText());
        }
        else if(!v.isValueNode()) {
            result.invalidType(location, key, "double", node);
        }
        return value;
    }



    public Integer getInteger(String key, ObjectNode node, boolean required, String location, ParseResult result) {
        Integer value = null;
        JsonNode v = node.get(key);
        if (node == null || v == null) {
            if (required) {
                result.missing(location, key);
                result.invalid();
            }
        }
        else if(v.getNodeType().equals(JsonNodeType.NUMBER)) {
            value = v.intValue();
        }
        else if(!v.isValueNode()) {
            result.invalidType(location, key, "integer", node);
        }
        return value;
    }

    public Map getParameters(ObjectNode obj, String location, ParseResult result) {
        if (obj == null) {
            return null;
        }
        Map parameters = new LinkedHashMap<>();

        Set parameterKeys = getKeys(obj);
        for(String parameterName : parameterKeys) {
            JsonNode parameterValue = obj.get(parameterName);
            if (parameterValue.getNodeType().equals(JsonNodeType.OBJECT)) {
                ObjectNode parameterObj = (ObjectNode) parameterValue;
                if(parameterObj != null) {
                    Parameter parameter = getParameter(parameterObj, String.format("%s.%s'", location, parameterName), result);
                    if (parameter != null) {
                        parameters.put(parameterName, parameter);
                    }
                }
            }
        }
        return parameters;
    }


    public List getParameterList(ArrayNode obj, String location, ParseResult result) {
        List parameters = new ArrayList<>();
        if (obj == null) {
            return parameters;
        }
        for (JsonNode item : obj) {
            if (item.getNodeType().equals(JsonNodeType.OBJECT)) {
                Parameter parameter = getParameter((ObjectNode) item, location, result);
                if (parameter != null) {
                    parameters.add(parameter);
                }
            }
        }
        return parameters;
    }

    public Parameter getParameter(ObjectNode obj, String location, ParseResult result) {
        if (obj == null) {
            return null;
        }


        Parameter parameter = null;

        JsonNode ref = obj.get("$ref");
        if (ref != null) {
            if (ref.getNodeType().equals(JsonNodeType.STRING)) {
                parameter = new Parameter();
                parameter.set$ref(ref.asText());
                return parameter.$ref(ref.asText());
            } else {
                result.invalidType(location, "$ref", "string", obj);
                return null;
            }
        }

        String l = null;
        JsonNode ln = obj.get("name");
        if(ln != null) {
            l = ln.asText();
        }
        else {
            l = "['unknown']";
        }
        location += ".[" + l + "]";

        String value = getString("in", obj, true, location, result);

        if (StringUtils.isBlank(value)) {
            return null;
        }


        if (QUERY_PARAMETER.equals(value)) {
            parameter = new QueryParameter();
        } else if (HEADER_PARAMETER.equals(value)) {
            parameter = new HeaderParameter();
        } else if (PATH_PARAMETER.equals(value)) {
            parameter = new PathParameter();
        } else if (COOKIE_PARAMETER.equals(value)) {
            parameter = new CookieParameter();
        }

        if (parameter == null) {
            result.invalidType(location, "in", "string", obj);
            return null;
        }


        parameter.setIn(value);

        value = getString("name", obj, true, location, result);
        if (StringUtils.isNotBlank(value)) {
            parameter.setName(value);
        }

        value = getString("description", obj, false, location, result);
        if (StringUtils.isNotBlank(value)) {
            parameter.setDescription(value);
        }

        Boolean required = getBoolean("required", obj, false, location, result);
        if (required != null) {
            parameter.setRequired(required);
        }else {
            parameter.setRequired(false);
        }


        Boolean deprecated = getBoolean("deprecated", obj, false, location, result);
        if (deprecated != null) {
            parameter.setDeprecated(deprecated);
        }

        Boolean allowEmptyValue = getBoolean("allowEmptyValue", obj, false, location, result);
        if (allowEmptyValue != null) {
            parameter.setAllowEmptyValue(allowEmptyValue);
        }

        Boolean explode = getBoolean("explode", obj, false, location, result);
        if (explode != null) {
            parameter.setExplode(explode);
        } else {
            parameter.setExplode(Boolean.FALSE);
        }

        value = getString("style", obj, false, location, result);

        setStyle(value, parameter, location, obj, result);


        ObjectNode parameterObject = getObject("schema",obj,false,location,result);
        if (parameterObject!= null) {
            parameter.setSchema(getSchema(parameterObject,String.format("%s.%s'", location, "schemas"),result));
        }

        ObjectNode examplesObject = getObject("examples",obj,false,location,result);
        if(examplesObject!=null) {
            parameter.setExamples(getExamples(examplesObject, String.format("%s.%s'", location, "examples"), result));
        }

        JsonNode exampleNode = obj.get("example");
        if(exampleNode != null) {
            value = getString("example", obj, false, location, result);
            if(StringUtils.isNotBlank(value)) {
                parameter.setExample(value);
            }
        }

        ObjectNode contentNode = getObject("content",obj,false,location,result);
        if(contentNode!= null) {
            parameter.setContent(getContent(contentNode, String.format("%s.%s'", location, "content"), result));
        }

        Map  extensions = getExtensions(obj);
        if(extensions != null && extensions.size() > 0) {
            parameter.setExtensions(extensions);
        }

        Set keys = getKeys(obj);
        for(String key : keys) {
           if(!PARAMETER_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, obj.get(key));
           }
        }

        return parameter;
    }


    public Map getHeaders(ObjectNode obj, String location, ParseResult result) {
        if (obj == null) {
            return null;
        }
        Map headers = new LinkedHashMap<>();

        Set headerKeys = getKeys(obj);
        for(String headerName : headerKeys) {
            JsonNode headerValue = obj.get(headerName);
            if (!headerValue.getNodeType().equals(JsonNodeType.OBJECT)) {
                result.invalidType(location, headerName, "object", headerValue);
            } else {
                ObjectNode header = (ObjectNode) headerValue;
                Header headerObj = getHeader(header, String.format("%s.%s'", location, headerName), result);
                if(headerObj != null) {
                    headers.put(headerName, headerObj);
                }
            }

        }

        return headers;
    }

    public Header getHeader(ObjectNode headerNode, String location, ParseResult result) {
        if (headerNode == null) {
            return null;
        }

        Header header = new Header();

        JsonNode ref = headerNode.get("$ref");
        if (ref != null) {
            if (ref.getNodeType().equals(JsonNodeType.STRING)) {
                header.set$ref(ref.asText());
                return header.$ref(ref.asText());
            } else {
                result.invalidType(location, "$ref", "string", headerNode);
                return null;
            }
        }



        String value = getString("description", headerNode, false, location, result);
        if (StringUtils.isNotBlank(value)) {
            header.setDescription(value);
        }

        Boolean required = getBoolean("required", headerNode, false, location, result);
        if (required != null) {
            header.setRequired(required);
        }

        Boolean deprecated = getBoolean("deprecated", headerNode, false, location, result);
        if (deprecated != null) {
            header.setDeprecated(deprecated);
        }

        Boolean allowEmptyValue = getBoolean("allowEmptyValue", headerNode, false, location, result);
        if (allowEmptyValue != null) {
            header.setAllowEmptyValue(allowEmptyValue);
        }

        Boolean explode = getBoolean("explode", headerNode, false, location, result);
        if (explode != null) {
            header.setExplode(explode);
        } else {
            header.setExplode(Boolean.FALSE);
        }

        header.setStyle(Header.StyleEnum.SIMPLE);

        ObjectNode headerObject = getObject("schema",headerNode,false,location,result);
        if (headerObject!= null) {
            header.setSchema(getSchema(headerObject, location, result));
        }

        ArrayNode examplesObject = getArray("examples",headerNode,false,location,result);
        if(examplesObject!=null) {
            header.setExamples(getExampleList(examplesObject, location, result));
        }

        JsonNode exampleNode = headerNode.get("example");
        if(exampleNode != null) {
            value = getString("example", headerNode, false, location, result);
            if(StringUtils.isNotBlank(value)) {
                header.setExample(value);
            }
        }

        ObjectNode contentNode = getObject("content",headerNode,false,location,result);
        if (contentNode!= null){
            header.setContent(getContent(contentNode,String.format("%s.%s'", location, "content"),result));
        }

        Map  extensions = getExtensions(headerNode);
        if(extensions != null && extensions.size() > 0) {
            header.setExtensions(extensions);
        }

        Set oAuthFlowKeys = getKeys(headerNode);
        for(String key : oAuthFlowKeys) {
            if(!HEADER_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, headerNode.get(key));
            }
        }

        return header;
    }

    public Map getSecuritySchemes(ObjectNode obj, String location, ParseResult result) {
        if (obj == null) {
            return null;
        }
        Map securitySchemes = new LinkedHashMap<>();

        Set securitySchemeKeys = getKeys(obj);
        for(String securitySchemeName : securitySchemeKeys) {
            JsonNode securitySchemeValue = obj.get(securitySchemeName);
            if (!securitySchemeValue.getNodeType().equals(JsonNodeType.OBJECT)) {
                result.invalidType(location, securitySchemeName, "object", securitySchemeValue);
            } else {
                ObjectNode securityScheme = (ObjectNode) securitySchemeValue;
                SecurityScheme securitySchemeObj = getSecurityScheme(securityScheme, String.format("%s.%s'", location, securitySchemeName), result);
                if (securityScheme != null) {
                    securitySchemes.put(securitySchemeName, securitySchemeObj);
                }
            }
        }
        return securitySchemes;
    }

    public SecurityScheme getSecurityScheme(ObjectNode node, String location, ParseResult result) {
        if (node == null) {
            return null;
        }

        SecurityScheme securityScheme = new SecurityScheme();

        JsonNode ref = node.get("$ref");
        if (ref != null) {
            if (ref.getNodeType().equals(JsonNodeType.STRING)) {
                securityScheme.set$ref(ref.asText());
                return securityScheme.$ref(ref.asText());
            } else {
                result.invalidType(location, "$ref", "string", node);
                return null;
            }
        }

        String value = getString("type", node, true, location, result);
        if (StringUtils.isNotBlank(value)) {
            if (SecurityScheme.Type.APIKEY.toString().equals(value)) {
                securityScheme.setType(SecurityScheme.Type.APIKEY);
            } else if (SecurityScheme.Type.HTTP.toString().equals(value)) {
                securityScheme.setType(SecurityScheme.Type.HTTP);
            } else if (SecurityScheme.Type.OAUTH2.toString().equals(value)) {
                securityScheme.setType(SecurityScheme.Type.OAUTH2);
            } else if (SecurityScheme.Type.OPENIDCONNECT.toString().equals(value)) {
                securityScheme.setType(SecurityScheme.Type.OPENIDCONNECT);
            }else{
                result.invalidType(location + ".type", "type", "http|apiKey|oauth2|openIdConnect ", node);
            }
        }
        value = getString("description", node, false, location, result);
        if (StringUtils.isNotBlank(value)) {
            securityScheme.setDescription(value);
        }

        value = getString("name", node, true, location, result);
        if (StringUtils.isNotBlank(value)) {
            securityScheme.setName(value);
        }

        value = getString("in", node, true, location, result);
        if (StringUtils.isNotBlank(value)) {
            if (QUERY_PARAMETER.equals(value)) {
                securityScheme.setIn(SecurityScheme.In.QUERY);
            } else if (HEADER_PARAMETER.equals(value)) {
                securityScheme.setIn(SecurityScheme.In.HEADER);
            }
        }

        value = getString("scheme", node, true, location, result);
        if (StringUtils.isNotBlank(value)) {
            securityScheme.setScheme(value);
        }

        value = getString("bearerFormat", node, false, location, result);
        if (StringUtils.isNotBlank(value)) {
            securityScheme.setBearerFormat(value);
        }

        ObjectNode flowsObject = getObject("flows",node,true,location,result);
        if (flowsObject!= null) {
            securityScheme.setFlows(getOAuthFlows(flowsObject, location, result));
        }

        value = getString("openIdConnectUrl", node, true, location, result);
        if (StringUtils.isNotBlank(value)) {
            securityScheme.setOpenIdConnectUrl(value);
        }

        Map  extensions = getExtensions(node);
        if(extensions != null && extensions.size() > 0) {
            securityScheme.setExtensions(extensions);
        }

        Set oAuthFlowKeys = getKeys(node);
        for(String key : oAuthFlowKeys) {
            if(!SECURITY_SCHEME_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, node.get(key));
            }
        }

        return securityScheme;
    }

    public OAuthFlows getOAuthFlows(ObjectNode node, String location, ParseResult result) {
        if (node == null) {
            return null;
        }

        OAuthFlows oAuthFlows = new OAuthFlows();

        ObjectNode objectNode = getObject("implicit", node, false, location, result);
        if(objectNode!= null) {
            oAuthFlows.setImplicit(getOAuthFlow(objectNode, location, result));
        }

        objectNode = getObject("password", node, false, location, result);
        if(objectNode!= null) {
            oAuthFlows.setPassword(getOAuthFlow(objectNode, location, result));
        }

        objectNode = getObject("clientCredentials", node, false, location, result);
        if(objectNode!= null) {
            oAuthFlows.setClientCredentials(getOAuthFlow(objectNode, location, result));
        }

        objectNode = getObject("authorizationCode", node, false, location, result);
        if(objectNode!= null) {
            oAuthFlows.setAuthorizationCode(getOAuthFlow(objectNode, location, result));
        }

        Map  extensions = getExtensions(node);
        if(extensions != null && extensions.size() > 0) {
            oAuthFlows.setExtensions(extensions);
        }

        Set oAuthFlowKeys = getKeys(node);
        for(String key : oAuthFlowKeys) {
            if(!OAUTHFLOWS_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, node.get(key));
            }
        }


        return oAuthFlows;
    }

    public OAuthFlow getOAuthFlow(ObjectNode node, String location, ParseResult result) {
        if (node == null) {
            return null;
        }

        OAuthFlow oAuthFlow = new OAuthFlow();

        String value = getString("authorizationUrl", node, true, location, result);
        if (StringUtils.isNotBlank(value)) {
            oAuthFlow.setAuthorizationUrl(value);
        }

        value = getString("tokenUrl", node, true, location, result);
        if (StringUtils.isNotBlank(value)) {
            oAuthFlow.setTokenUrl(value);
        }

        value = getString("refreshUrl", node, false, location, result);
        if (StringUtils.isNotBlank(value)) {
            oAuthFlow.setRefreshUrl(value);
        }

        ObjectNode scopesObject = getObject("scopes",node,true,location,result);

        Scopes scope = new Scopes();
        Set keys = getKeys(scopesObject);
        for(String name : keys) {
            JsonNode scopeValue = scopesObject.get(name);
            if (scopesObject!= null){
                scope.addString(name,scopeValue.asText());
                oAuthFlow.setScopes(scope);
            }
        }

        Map  extensions = getExtensions(node);
        if(extensions != null && extensions.size() > 0) {
            oAuthFlow.setExtensions(extensions);
        }

        Set oAuthFlowKeys = getKeys(node);
        for(String key : oAuthFlowKeys) {
            if(!OAUTHFLOW_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, node.get(key));
            }
        }

        return oAuthFlow;
    }

    public Map getSchemas(ObjectNode obj, String location, ParseResult result) {
        if (obj == null) {
            return null;
        }
        Map schemas = new LinkedHashMap<>();

        Set schemaKeys = getKeys(obj);
        for (String schemaName : schemaKeys) {
            JsonNode schemaValue = obj.get(schemaName);
                if (!schemaValue.getNodeType().equals(JsonNodeType.OBJECT)) {
                    result.invalidType(location, schemaName, "object", schemaValue);
                } else {
                    ObjectNode schema = (ObjectNode) schemaValue;
                    Schema schemaObj = getSchema(schema, String.format("%s.%s'", location, schemaName), result);
                    if(schemaObj != null) {
                        schemas.put(schemaName, schemaObj);
                    }
                }
        }

        return schemas;
    }

    public Discriminator getDiscriminator (ObjectNode node, String location, ParseResult result){
        Discriminator discriminator = new Discriminator();

        String value = getString("propertyName",node,true,location,result);
        if (StringUtils.isNotBlank(value)){
            discriminator.setPropertyName(value);
        }

        ObjectNode mappingNode = getObject("mapping", node,false, location, result);
        if(mappingNode != null){
            Map mapping = new LinkedHashMap<>();
            Set keys = getKeys(mappingNode);
            for(String key : keys) {
                mapping.put(key, mappingNode.get(key).asText());
            }
            discriminator.setMapping(mapping);
        }

        return discriminator;

    }

    public Schema getSchema(ObjectNode node, String location, ParseResult result){
        if(node== null){
            return null;
        }


        Schema schema = null;
        ArrayNode oneOfArray = getArray("oneOf", node, false, location, result);
        ArrayNode allOfArray = getArray("allOf", node, false, location, result);
        ArrayNode anyOfArray = getArray("anyOf", node, false, location, result);
        ObjectNode itemsNode = getObject("items", node, false, location, result);

        if(allOfArray != null) {

            for(JsonNode n : allOfArray) {
                if(n.isObject()) {
                    ComposedSchema allOfList = new ComposedSchema();
                    schema = getSchema((ObjectNode) n,location,result);
                    allOfList.addAllOfItem(schema);
                    schema = allOfList;
                }
            }
        } else if(anyOfArray != null) {

            for(JsonNode n : anyOfArray) {
                if(n.isObject()) {
                    ComposedSchema anyOfList = new ComposedSchema();
                    schema = getSchema((ObjectNode) n,location,result);
                    anyOfList.addAnyOfItem(schema);
                    schema = anyOfList;
                }
            }
        } else if(oneOfArray != null) {

            for(JsonNode n : oneOfArray) {
                if(n.isObject()) {
                    ComposedSchema oneOfList = new ComposedSchema();
                    schema = getSchema((ObjectNode) n,location,result);
                    oneOfList.addOneOfItem(schema);
                    schema = oneOfList;
                }
            }
        } else if(itemsNode != null) {
            ArraySchema items = new ArraySchema();
            for(JsonNode n : itemsNode) {
                if(n.isValueNode()) {
                    items.setItems(getSchema(itemsNode, location,result));
                }
            }
            schema = items;
        } else {
            schema = new Schema();
        }

        JsonNode ref = node.get("$ref");
        if (ref != null) {
            if (ref.getNodeType().equals(JsonNodeType.STRING)) {
                schema.set$ref(ref.asText());
                return schema.$ref(ref.asText());
            } else {
                result.invalidType(location, "$ref", "string", node);
                return null;
            }
        }


        String value = getString("title",node,false,location,result);
        if (StringUtils.isNotBlank(value)) {
            schema.setTitle(value);
        }

        ObjectNode discriminatorNode = getObject("discriminator", node, false, location, result);
        if (discriminatorNode != null) {
            schema.setDiscriminator(getDiscriminator(discriminatorNode,location,result));
        }

        BigDecimal bigDecimal = getBigDecimal("multipleOf",node,false,location,result);
        if(bigDecimal != null) {
            schema.setMultipleOf(bigDecimal);
        }

        bigDecimal = getBigDecimal("maximum", node, false, location, result);
        if(bigDecimal != null) {
            schema.setMaximum(bigDecimal);
        }

        Boolean bool = getBoolean("exclusiveMaximum", node, false, location, result);
        if (bool != null) {
            schema.setExclusiveMaximum(bool);
        }

        bigDecimal = getBigDecimal("minimum", node, false, location, result);
        if(bigDecimal != null) {
            schema.setMinimum(bigDecimal);
        }

        bool = getBoolean("exclusiveMinimum", node, false, location, result);
        if(bool != null) {
            schema.setExclusiveMinimum(bool);
        }

        Integer integer = getInteger("minLength", node, false, location, result);
        if(integer != null){
            schema.setMinLength(integer);
        }

        integer = getInteger("maxLength", node, false, location, result);
        if(integer != null){
            schema.setMaxLength(integer);
        }

        String pattern = getString("pattern", node, false, location, result);
        if (StringUtils.isNotBlank(value)) {
            schema.setPattern(pattern);
        }

        integer = getInteger("maxItems", node, false, location, result);
        if(integer != null) {
            schema.setMaxItems(integer);
        }
        integer = getInteger("minItems", node, false, location, result);
        if(integer != null){
            schema.setMinItems(integer);
        }

        bool = getBoolean("uniqueItems", node, false, location, result);
        if(bool != null){
            schema.setUniqueItems(bool);
        }

        integer = getInteger("maxProperties", node, false, location, result);
        if (integer != null){
            schema.setMaxProperties(integer);
        }

        integer = getInteger("minProperties", node, false, location, result);
        if(integer != null) {
            schema.setMinProperties(integer);
        }

        ArrayNode required = getArray("required", node, false, location, result);
        if(required != null) {
            List requiredList = new ArrayList<>();
            for (JsonNode n : required) {
                if(n.getNodeType().equals(JsonNodeType.STRING)) {
                    requiredList.add(((TextNode) n).textValue());
                }
                else {
                    result.invalidType(location, "required", "string", n);
                }
            }
            if(requiredList.size() > 0) {
                schema.setRequired(requiredList);
            }
        }

        ArrayNode enumArray = getArray("enum", node, false, location, result);
        if(enumArray != null) {
            List _enum = new ArrayList<>();
            for(JsonNode n : enumArray) {
                if(n.isValueNode()) {
                    _enum.add(n.asText());
                }
                else {
                    result.invalidType(location, "enum", "value", n);
                }
            }
            schema.setEnum(_enum);
        }

        value = getString("type",node,false,location,result);
        if (StringUtils.isNotBlank(value)) {
            schema.setType(value);
        }

        ObjectNode notObj = getObject("not", node, false, location, result);
        if(notObj != null) {
            Schema not = getSchema(notObj, location, result);
            if(not != null) {
                schema.setNot(not);
            }
        }



        Map  properties = new LinkedHashMap<>();
        ObjectNode propertiesObj = getObject("properties", node, false, location, result);
        Schema property = null;

        Set keys = getKeys(propertiesObj);
        for(String name : keys) {
            JsonNode propertyValue = propertiesObj.get(name);
            if (!propertyValue.getNodeType().equals(JsonNodeType.OBJECT)) {
                result.invalidType(location, "properties", "object", propertyValue);
            } else {
                if (propertiesObj!= null){
                    property = getSchema((ObjectNode) propertyValue, location, result);
                    if(property != null) {
                        properties.put(name, property);
                    }
                }
            }
        }
        if (propertiesObj != null) {
            schema.setProperties(properties);
        }

        ObjectNode additionalPropertiesObj = getObject("additionalProperties", node, false, location, result);
        if(additionalPropertiesObj != null) {
            Schema additionalProperties = getSchema(additionalPropertiesObj, location, result);
            if(additionalProperties != null) {
                schema.setAdditionalProperties(additionalProperties);
            }
        }
        value = getString("description",node,false,location,result);
        if (StringUtils.isNotBlank(value)) {
            schema.setDescription(value);
        }

        value = getString("format", node, false, location, result);
        if (StringUtils.isNotBlank(value)) {
            schema.setFormat(value);
        }

        value = getString("default", node, false, location, result);
        if (StringUtils.isNotBlank(value)) {
            schema.setDefault(value);
        }

        //discriminator

        bool = getBoolean("nullable", node, false, location, result);
        if(bool != null) {
            schema.setNullable(bool);
        }

        bool = getBoolean("readOnly", node, false, location, result);
        if(bool != null) {
            schema.setReadOnly(bool);
        }

        bool = getBoolean("writeOnly", node, false, location, result);
        if(bool != null){
            schema.setWriteOnly(bool);
        }

        ObjectNode xmlNode = getObject("xml", node, false, location, result);
        if (xmlNode != null) {
            XML xml = getXml(xmlNode, location, result);
            if (xml != null) {
                schema.setXml(xml);
            }
        }

        ObjectNode externalDocs = getObject("externalDocs", node, false, location, result);
        if(externalDocs != null) {
            ExternalDocumentation docs = getExternalDocs(externalDocs, location , result);
            if(docs != null) {
                schema.setExternalDocs(docs);
            }
        }

        ObjectNode exampleObj = getObject("example",node,false,location,result);
        if (exampleObj != null) {
            schema.setExample(exampleObj);
        }

        bool = getBoolean("deprecated", node, false, location, result);
        if(bool != null){
            schema.setDeprecated(bool);
        }

        Map  extensions = getExtensions(node);
        if(extensions != null && extensions.size() > 0) {
            schema.setExtensions(extensions);
        }

        Set schemaKeys = getKeys(node);
        for(String key : schemaKeys) {
            if(!SCHEMA_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, node.get(key));
            }
        }

        return schema;

    }




    public Map getExamples(ObjectNode obj, String location, ParseResult result) {
        if (obj == null) {
            return null;
        }
        Map examples = new LinkedHashMap<>();

        Set exampleKeys = getKeys(obj);
        for(String exampleName : exampleKeys) {
            JsonNode exampleValue = obj.get(exampleName);
            if (!exampleValue.getNodeType().equals(JsonNodeType.OBJECT)) {
                result.invalidType(location, exampleName, "object", exampleValue);
            } else {
                ObjectNode example = (ObjectNode) exampleValue;
                if(example != null) {
                    Example exampleObj = getExample(example, String.format("%s.%s'", location, exampleName), result);
                    if(exampleObj != null) {
                        examples.put(exampleName, exampleObj);
                    }
                }
            }
        }
        return examples;
    }

    public List getExampleList(ArrayNode obj, String location, ParseResult result) {
        List examples = new ArrayList<>();
        if (obj == null) {
            return examples;
        }
        for (JsonNode item : obj) {
            if (item.getNodeType().equals(JsonNodeType.OBJECT)) {
                Example example = getExample((ObjectNode) item, location, result);
                if (example != null) {
                    examples.add(example);
                }
            }
        }
        return examples;
    }

    public Example getExample(ObjectNode node, String location, ParseResult result) {
        if (node == null)
            return null;

        Example example = new Example();

        JsonNode ref = node.get("$ref");
        if (ref != null) {
            if (ref.getNodeType().equals(JsonNodeType.STRING)) {
                example.set$ref(ref.asText());
                return example.$ref((ref.asText()));
            } else {
                result.invalidType(location, "$ref", "string", node);
                return null;
            }
        }

        String value = getString("summary", node, false, location, result);
        if (StringUtils.isNotBlank(value)) {
            example.setSummary(value);
        }

        value = getString("description", node, false, location, result);
        if (StringUtils.isNotBlank(value)) {
            example.setDescription(value);
        }

        JsonNode v = node.get("value");
        if (v.getNodeType().equals(JsonNodeType.STRING)) {
            value = getString("value", node, false, location, result);
            example.setValue(value);
        }else if (v.getNodeType().equals(JsonNodeType.OBJECT)) {
            ObjectNode objectValue = getObject("value", node, false, location, result);
            if(objectValue != null) {
                example.setValue(objectValue.toString());
            }
        }else if (v.getNodeType().equals(JsonNodeType.ARRAY)) {
            ArrayNode arrayValue = getArray("value", node, false, location, result);
            if (arrayValue != null) {
                example.setValue(arrayValue.toString());
            }
        }


        value = getString("externalValue", node, false, location, result);
        if (StringUtils.isNotBlank(value)) {
            example.setExternalValue(value);
        }

        Map  extensions = getExtensions(node);
        if(extensions != null && extensions.size() > 0) {
            example.setExtensions(extensions);
        }

        Set keys = getKeys(node);
        for(String key : keys) {
            if(!EXAMPLE_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, node.get(key));
            }
        }


        return example;
    }


    public void setStyle(String value, Parameter parameter, String location, ObjectNode obj, ParseResult result) {
        if (StringUtils.isBlank(value)) {
            if (QUERY_PARAMETER.equals(parameter.getIn()) || COOKIE_PARAMETER.equals(parameter.getIn())) {
                parameter.setStyle(Parameter.StyleEnum.FORM);
            } else if (PATH_PARAMETER.equals(parameter.getIn()) || HEADER_PARAMETER.equals(parameter.getIn())) {
                parameter.setStyle(Parameter.StyleEnum.SIMPLE);
            }
        } else {
            if (value.equals(Parameter.StyleEnum.FORM.toString())) {
                parameter.setStyle(Parameter.StyleEnum.FORM);
            } else if (value.equals(Parameter.StyleEnum.DEEPOBJECT.toString())) {
                parameter.setStyle(Parameter.StyleEnum.DEEPOBJECT);
            } else if (value.equals(Parameter.StyleEnum.LABEL.toString())) {
                parameter.setStyle(Parameter.StyleEnum.LABEL);
            } else if (value.equals(Parameter.StyleEnum.MATRIX.toString())) {
                parameter.setStyle(Parameter.StyleEnum.MATRIX);
            } else if (value.equals(Parameter.StyleEnum.PIPEDELIMITED.toString())) {
                parameter.setStyle(Parameter.StyleEnum.PIPEDELIMITED);
            } else if (value.equals(Parameter.StyleEnum.SIMPLE.toString())) {
                parameter.setStyle(Parameter.StyleEnum.SIMPLE);
            } else if (value.equals(Parameter.StyleEnum.SPACEDELIMITED.toString())) {
                parameter.setStyle(Parameter.StyleEnum.SPACEDELIMITED);
            } else {
                result.invalidType(location, "style", "string", obj);
            }
        }
    }

    public ApiResponses getResponses(ObjectNode node, String location, ParseResult result) {
        if (node == null) {
            return null;
        }

        ApiResponses apiResponses = new ApiResponses();
        Set keys = getKeys(node);

        for (String key : keys) {
            ObjectNode obj = getObject(key, node, false, String.format("%s.%s'", location, "responses"), result);
            if(obj != null) {
                ApiResponse response = getResponse(obj, String.format("%s.%s'", location, key), result);
                if(response != null) {
                    apiResponses.put(key, response);
                }
            }
        }

        return apiResponses;
    }

    public ApiResponse getResponse(ObjectNode node, String location, ParseResult result) {
        if (node == null) {
            return null;
        }

        ApiResponse apiResponse = new ApiResponse();
        JsonNode ref = node.get("$ref");
        if (ref != null) {
            if (ref.getNodeType().equals(JsonNodeType.STRING)) {
                 apiResponse.set$ref(ref.asText());
                 return apiResponse.$ref((ref.asText()));
            } else {
                result.invalidType(location, "$ref", "string", node);
                return null;
            }
        }

        String value = getString("description", node, true, location, result);
        if (StringUtils.isNotBlank(value)) {
            apiResponse.description(value);
        }


        ObjectNode headerObject = getObject("headers", node, false, location, result);
        if (headerObject != null) {
            Map headers = getHeaders(headerObject, location, result);
            if (headers != null &&  headers.size() > 0) {
                apiResponse.setHeaders(headers);
            }
        }

        ObjectNode linksObj = getObject("links", node, false, location, result);
        if (linksObj != null) {
             Map links = getLinks(linksObj, location, result);
             if(links != null && links.size() > 0) {
                 apiResponse.setLinks(links);
             }
        }

        ObjectNode contentObject = getObject("content", node, false, location, result);
        if (contentObject != null) {
            apiResponse.setContent(getContent(contentObject, String.format("%s.%s'", location, "content"), result));
        }

        Map  extensions = getExtensions(node);
        if(extensions != null && extensions.size() > 0) {
            apiResponse.setExtensions(extensions);
        }

        Set keys = getKeys(node);
        for(String key : keys) {
            if(!RESPONSE_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, node.get(key));
            }
        }


        return apiResponse;
    }

    public List getTagsStrings(ArrayNode nodes, String location, ParseResult result) {
        if (nodes == null)
            return null;

        List tags = new ArrayList<>();

        for (JsonNode node : nodes) {
            if (node.getNodeType().equals(JsonNodeType.STRING)) {
                tags.add(node.textValue());
            }
        }
        return tags;
    }




    public Operation getOperation(ObjectNode obj, String location, ParseResult result) {
        if (obj == null) {
            return null;
        }
        Operation operation = new Operation();

        ArrayNode array = getArray("tags", obj, false, location, result);
        List tags = getTagsStrings(array, String.format("%s.%s'", location, "tags"), result);
        if (tags != null) {
            operation.setTags(tags);
        }
        String value = getString("summary", obj, false, location, result);
        if (StringUtils.isNotBlank(value)) {
            operation.setSummary(value);
        }

        value = getString("description", obj, false, location, result);
        if (StringUtils.isNotBlank(value)) {
            operation.setDescription(value);
        }

        ObjectNode externalDocs = getObject("externalDocs", obj, false, location, result);
        ExternalDocumentation docs = getExternalDocs(externalDocs, String.format("%s.%s'", location, "externalDocs"), result);
        if(docs != null) {
            operation.setExternalDocs(docs);
        }
        value = getString("operationId", obj, false, location, result);
        if (StringUtils.isNotBlank(value)) {
            operation.operationId(value);
        }

        ArrayNode parameters = getArray("parameters", obj, false, location, result);
        if (parameters != null){
            operation.setParameters(getParameterList(parameters, String.format("%s.%s'", location, "parameters"), result));
        }

        final ObjectNode requestObjectNode = getObject("requestBody", obj, false, location, result);
        if (requestObjectNode != null){
            operation.setRequestBody(getRequestBody(requestObjectNode, String.format("%s.%s'", location, "requestBody"), result));
        }

        ObjectNode responsesNode = getObject("responses", obj, true, location, result);
        ApiResponses responses = getResponses(responsesNode, String.format("%s.%s'", location, "responses"), result);
        if(responses != null) {
            operation.setResponses(responses);
        }

        ObjectNode callbacksNode = getObject("callbacks", obj, false, location, result);
        Map callbacks = getCallbacks(callbacksNode, String.format("%s.%s'", location, "callbacks"), result);
        if(callbacks != null){
            operation.setCallbacks(callbacks);
        }

        Boolean deprecated = getBoolean("deprecated", obj, false, location, result);
        if (deprecated != null) {
            operation.setDeprecated(deprecated);
        }

        array = getArray("servers", obj, false, location, result);
        if (array != null && array.size() > 0) {
            operation.setServers(getServersList(array, String.format("%s.%s'", location, "servers"), result));
        }


        array = getArray("security", obj, false, location, result);
        if (array != null) {
            operation.setSecurity(getSecurityRequirementsList(array, String.format("%s.%s'", location, "security"), result));
        }


        Map  extensions = getExtensions(obj);
        if(extensions != null && extensions.size() > 0) {
            operation.setExtensions(extensions);
        }

        Set keys = getKeys(obj);
        for(String key : keys) {
            if(!OPERATION_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, obj.get(key));
            }
        }


        return operation;
    }

    public List getSecurityRequirementsList(ArrayNode nodes, String location, ParseResult result) {
        if (nodes == null)
            return null;

        List securityRequirements = new ArrayList<>();

        for (JsonNode node : nodes) {
            if (node.getNodeType().equals(JsonNodeType.OBJECT)) {
                SecurityRequirement securityRequirement = new SecurityRequirement();
                Set keys = getKeys((ObjectNode) node);
                for (String key : keys) {
                    if (key != null) {
                        securityRequirement.addList(key,node.textValue());
                        if (securityRequirement != null && securityRequirement.size() > 0){
                            securityRequirements.add(securityRequirement);
                        }
                    }
                }
            }
        }
        return securityRequirements;
    }

    public Map getRequestBodies(ObjectNode obj, String location, ParseResult result) {
        if (obj == null) {
            return null;
        }
        Map bodies = new LinkedHashMap<>();

        Set bodyKeys = getKeys(obj);
        for(String bodyName : bodyKeys) {
            JsonNode bodyValue = obj.get(bodyName);
            if (!bodyValue.getNodeType().equals(JsonNodeType.OBJECT)) {
                result.invalidType(location, bodyName, "object", bodyValue);
            } else {
                ObjectNode bodyObj = (ObjectNode) bodyValue;
                RequestBody body = getRequestBody(bodyObj, String.format("%s.%s'", location, bodyName), result);
                if(body != null) {
                    bodies.put(bodyName, body);
                }
            }
        }
        return bodies;
    }


    protected RequestBody getRequestBody(ObjectNode node, String location, ParseResult result) {
        if (node == null){
            return null;
        }
        final RequestBody body = new RequestBody();


        JsonNode ref = node.get("$ref");
        if (ref != null) {
            if (ref.getNodeType().equals(JsonNodeType.STRING)) {
                body.set$ref(ref.asText());
                return body.$ref(ref.asText());
            } else {
                result.invalidType(location, "$ref", "string", node);
                return null;
            }
        }




        final String description = getString("description", node, false, location, result);
        if (StringUtils.isNotBlank(description)) {
            body.setDescription(description);
        }

        final Boolean required = getBoolean("required", node, false, location, result);
        if(required != null) {
            body.setRequired(required);
        }

        final ObjectNode contentNode = getObject("content", node, true, location, result);
        if (contentNode != null) {
            body.setContent(getContent(contentNode, location + ".content", result));
        }

        Map  extensions = getExtensions(node);
        if(extensions != null && extensions.size() > 0) {
            body.setExtensions(extensions);
        }

        Set keys = getKeys(node);
        for(String key : keys) {
            if(!REQUEST_BODY_KEYS.contains(key) && !key.startsWith("x-")) {
                result.extra(location, key, node.get(key));
            }
        }

        return body;
    }


    protected static class ParseResult {
        private boolean valid = true;
        private Map extra = new LinkedHashMap<>();
        private Map unsupported = new LinkedHashMap<>();
        private Map invalidType = new LinkedHashMap<>();
        private List missing = new ArrayList<>();

        public ParseResult() {
        }

        public void unsupported(String location, String key, JsonNode value) {
            unsupported.put(new Location(location, key), value);
        }

        public void extra(String location, String key, JsonNode value) {
            extra.put(new Location(location, key), value);
        }

        public void missing(String location, String key) {
            missing.add(new Location(location, key));
        }

        public void invalidType(String location, String key, String expectedType, JsonNode value) {
            invalidType.put(new Location(location, key), expectedType);
        }

        public void invalid() {
            this.valid = false;
        }

        public List getMessages() {
            List messages = new ArrayList();
            for (Location l : extra.keySet()) {
                String location = l.location.equals("") ? "" : l.location + ".";
                String message = "attribute " + location + l.key + " is unexpected";
                messages.add(message);
            }
            for (Location l : invalidType.keySet()) {
                String location = l.location.equals("") ? "" : l.location + ".";
                String message = "attribute " + location + l.key + " is not of type `" + invalidType.get(l) + "`";
                messages.add(message);
            }
            for (Location l : missing) {
                String location = l.location.equals("") ? "" : l.location + ".";
                String message = "attribute " + location + l.key + " is missing";
                messages.add(message);
            }
            for (Location l : unsupported.keySet()) {
                String location = l.location.equals("") ? "" : l.location + ".";
                String message = "attribute " + location + l.key + " is unsupported";
                messages.add(message);
            }
            return messages;
        }
    }


    protected static class Location {
        private String location;

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof Location)) return false;

            Location location1 = (Location) o;

            if (location != null ? !location.equals(location1.location) : location1.location != null) return false;
            return !(key != null ? !key.equals(location1.key) : location1.key != null);

        }

        @Override
        public int hashCode() {
            int result = location != null ? location.hashCode() : 0;
            result = 31 * result + (key != null ? key.hashCode() : 0);
            return result;
        }

        private String key;

        public Location(String location, String key) {
            this.location = location;
            this.key = key;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy