Java tutorial
package io.swagger.v3.parser.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.v3.oas.models.Components; import io.swagger.v3.oas.models.ExternalDocumentation; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.callbacks.Callback; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.links.Link; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.ComposedSchema; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.Discriminator; import io.swagger.v3.oas.models.media.Encoding; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.XML; import io.swagger.v3.oas.models.security.OAuthFlow; import io.swagger.v3.oas.models.security.OAuthFlows; import io.swagger.v3.oas.models.security.Scopes; import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.tags.Tag; import io.swagger.v3.oas.models.info.License; import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.parameters.CookieParameter; import io.swagger.v3.oas.models.parameters.HeaderParameter; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.Parameter.StyleEnum; import io.swagger.v3.oas.models.parameters.PathParameter; import io.swagger.v3.oas.models.parameters.QueryParameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.servers.Server; import io.swagger.v3.oas.models.servers.ServerVariable; import io.swagger.v3.oas.models.servers.ServerVariables; import io.swagger.v3.parser.core.models.SwaggerParseResult; import io.swagger.v3.core.util.Json; import org.apache.commons.lang3.StringUtils; import java.math.BigDecimal; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; public class OpenAPIDeserializer { protected static Set<String> ROOT_KEYS = new LinkedHashSet<>( Arrays.asList("openapi", "info", "servers", "paths", "components", "security", "tags", "externalDocs")); protected static Set<String> INFO_KEYS = new LinkedHashSet<>( Arrays.asList("title", "description", "termsOfService", "contact", "license", "version")); protected static Set<String> CONTACT_KEYS = new LinkedHashSet<>(Arrays.asList("name", "url", "email")); protected static Set<String> LICENSE_KEYS = new LinkedHashSet<>(Arrays.asList("name", "url")); protected static Set<String> TAG_KEYS = new LinkedHashSet<>( Arrays.asList("description", "name", "externalDocs")); protected static Set<String> RESPONSE_KEYS = new LinkedHashSet<>( Arrays.asList("$ref", "description", "headers", "content", "links")); protected static Set<String> SERVER_KEYS = new LinkedHashSet<>( Arrays.asList("url", "description", "variables")); protected static Set<String> SERVER_VARIABLE_KEYS = new LinkedHashSet<>( Arrays.asList("enum", "default", "description")); protected static Set<String> PATHITEM_KEYS = new LinkedHashSet<>(Arrays.asList("$ref", "summary", "description", "get", "put", "post", "delete", "head", "patch", "options", "trace", "servers", "parameters")); protected static Set<String> OPERATION_KEYS = new LinkedHashSet<>( Arrays.asList("tags", "summary", "description", "externalDocs", "operationId", "parameters", "requestBody", "responses", "callbacks", "deprecated", "security", "servers")); protected static Set<String> PARAMETER_KEYS = new LinkedHashSet<>( Arrays.asList("$ref", "name", "in", "description", "required", "deprecated", "allowEmptyValue", "style", "explode", "allowReserved", "schema", "example", "examples", "content")); protected static Set<String> REQUEST_BODY_KEYS = new LinkedHashSet<>( Arrays.asList("$ref", "description", "content", "required")); protected static Set<String> SECURITY_SCHEME_KEYS = new LinkedHashSet<>(Arrays.asList("$ref", "type", "name", "in", "description", "flows", "scheme", "bearerFormat", "openIdConnectUrl")); protected static Set<String> EXTERNAL_DOCS_KEYS = new LinkedHashSet<>(Arrays.asList("description", "url")); protected static Set<String> COMPONENTS_KEYS = new LinkedHashSet<>(Arrays.asList("schemas", "responses", "parameters", "examples", "requestBodies", "headers", "securitySchemes", "links", "callbacks")); protected static Set<String> 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<String> EXAMPLE_KEYS = new LinkedHashSet<>( Arrays.asList("$ref", "summary", "description", "value", "externalValue")); protected static Set<String> HEADER_KEYS = new LinkedHashSet<>( Arrays.asList("$ref", "name", "in", "description", "required", "deprecated", "allowEmptyValue", "style", "explode", "allowReserved", "schema", "example", "examples", "content")); protected static Set<String> LINK_KEYS = new LinkedHashSet<>(Arrays.asList("$ref", "operationRef", "operationId", "parameters", "requestBody", "description", "server")); protected static Set<String> MEDIATYPE_KEYS = new LinkedHashSet<>( Arrays.asList("schema", "example", "examples", "encoding")); protected static Set<String> XML_KEYS = new LinkedHashSet<>( Arrays.asList("name", "namespace", "prefix", "attribute", "wrapped")); protected static Set<String> OAUTHFLOW_KEYS = new LinkedHashSet<>( Arrays.asList("authorizationUrl", "tokenUrl", "refreshUrl", "scopes")); protected static Set<String> OAUTHFLOWS_KEYS = new LinkedHashSet<>( Arrays.asList("implicit", "password", "clientCredentials", "authorizationCode")); protected static Set<String> 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"; private final Set<String> operationIDs = new HashSet<>(); public SwaggerParseResult deserialize(JsonNode rootNode) { return deserialize(rootNode, null); } public SwaggerParseResult deserialize(JsonNode rootNode, String path) { SwaggerParseResult result = new SwaggerParseResult(); try { ParseResult rootParse = new ParseResult(); OpenAPI api = parseRoot(rootNode, rootParse, path); 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 path) { 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, false, 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, path)); } else { Server defaultServer = new Server(); defaultServer.setUrl("/"); List<Server> 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<SecurityRequirement> securityRequirements = getSecurityRequirementsList(array, "security", result); if (securityRequirements != null && securityRequirements.size() > 0) { openAPI.setSecurity(securityRequirements); } } Map<String, Object> extensions = getExtensions(rootNode); if (extensions != null && extensions.size() > 0) { openAPI.setExtensions(extensions); } Set<String> 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 String mungedRef(String refString) { // Ref: IETF RFC 3966, Section 5.2.2 if (!refString.contains(":") && // No scheme !refString.startsWith("#") && // Path is not empty !refString.startsWith("/") && // Path is not absolute refString.indexOf(".") > 0) { // Path does not start with dot but contains "." (file extension) return "./" + refString; } return null; } public Map<String, Object> getExtensions(ObjectNode node) { Map<String, Object> extensions = new LinkedHashMap<>(); Set<String> 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<String, Object> extensions = getExtensions(obj); if (extensions != null && extensions.size() > 0) { components.setExtensions(extensions); } Set<String> 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<Tag> getTagList(ArrayNode obj, String location, ParseResult result) { if (obj == null) { return null; } List<Tag> tags = new ArrayList<>(); Set<String> tagsTracker = new HashSet<>(); for (JsonNode item : obj) { if (item.getNodeType().equals(JsonNodeType.OBJECT)) { Tag tag = getTag((ObjectNode) item, location, result); if (tag != null) { tags.add(tag); if (tagsTracker.contains((String) tag.getName())) { result.uniqueTags(location, tag.getName()); } tagsTracker.add(tag.getName()); } } } 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<String, Object> extensions = getExtensions(obj); if (extensions != null && extensions.size() > 0) { tag.setExtensions(extensions); } Set<String> 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<Server> getServersList(ArrayNode obj, String location, ParseResult result, String path) { List<Server> 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, path); if (server != null) { servers.add(server); } else { Server defaultServer = new Server(); defaultServer.setUrl("/"); servers.add(defaultServer); } } } return servers; } public List<Server> getServersList(ArrayNode obj, String location, ParseResult result) { return getServersList(obj, location, result, null); } public Server getServer(ObjectNode obj, String location, ParseResult result) { return getServer(obj, location, result, null); } public Server getServer(ObjectNode obj, String location, ParseResult result, String path) { if (obj == null) { return null; } Server server = new Server(); String value = getString("url", obj, true, location, result); if (StringUtils.isNotBlank(value)) { if (!isValidURL(value) && path != null) { try { final URI absURI = new URI(path); if ("http".equals(absURI.getScheme()) || "https".equals(absURI.getScheme())) { value = absURI.resolve(new URI(value)).toString(); } } catch (URISyntaxException e) { e.printStackTrace(); } } 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<String, Object> extensions = getExtensions(obj); if (extensions != null && extensions.size() > 0) { server.setExtensions(extensions); } Set<String> keys = getKeys(obj); for (String key : keys) { if (!SERVER_KEYS.contains(key) && !key.startsWith("x-")) { result.extra(location, key, obj.get(key)); } } return server; } boolean isValidURL(String urlString) { try { URL url = new URL(urlString); url.toURI(); return true; } catch (Exception exception) { return false; } } public ServerVariables getServerVariables(ObjectNode obj, String location, ParseResult result) { ServerVariables serverVariables = new ServerVariables(); if (obj == null) { return null; } Set<String> 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<String> _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<String, Object> extensions = getExtensions(obj); if (extensions != null && extensions.size() > 0) { serverVariable.setExtensions(extensions); } Set<String> 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<String> pathKeys = getKeys(obj); for (String pathName : pathKeys) { JsonNode pathValue = obj.get(pathName); if (pathName.startsWith("x-")) { Map<String, Object> extensions = getExtensions(obj); if (extensions != null && extensions.size() > 0) { paths.setExtensions(extensions); } } else { if (!pathValue.getNodeType().equals(JsonNodeType.OBJECT)) { result.invalidType(location, pathName, "object", pathValue); } else { if (!pathName.startsWith("/")) { result.warning(location, " Resource " + pathName + " should start with /"); } 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)) { String mungedRef = mungedRef(ref.textValue()); if (mungedRef != null) { pathItem.set$ref(mungedRef); } else { pathItem.set$ref(ref.textValue()); } return pathItem; } else if (ref.getNodeType().equals(JsonNodeType.OBJECT)) { ObjectNode node = (ObjectNode) ref; // extra keys Set<String> 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); } } node = getObject("trace", obj, false, location, result); if (node != null) { Operation operation = getOperation(node, location + "(trace)", result); if (operation != null) { pathItem.setTrace(operation); } } Map<String, Object> extensions = getExtensions(obj); if (extensions != null && extensions.size() > 0) { pathItem.setExtensions(extensions); } Set<String> 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<String, Object> extensions = getExtensions(node); if (extensions != null && extensions.size() > 0) { externalDocs.setExtensions(extensions); } Set<String> 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, Set<String> uniqueValues) { 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(); if (uniqueValues != null && !uniqueValues.add(value)) { result.unique(location, "operationId"); result.invalid(); } } return value; } public String getString(String key, ObjectNode node, boolean required, String location, ParseResult result) { return getString(key, node, required, location, result, null); } public Set<String> getKeys(ObjectNode node) { Set<String> keys = new LinkedHashSet<>(); if (node == null) { return keys; } Iterator<String> 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<String, Object> extensions = getExtensions(node); if (extensions != null && extensions.size() > 0) { info.setExtensions(extensions); } Set<String> 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<String, Object> extensions = getExtensions(node); if (extensions != null && extensions.size() > 0) { license.setExtensions(extensions); } Set<String> 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<String, Object> extensions = getExtensions(node); if (extensions != null && extensions.size() > 0) { contact.setExtensions(extensions); } Set<String> 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<String> 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 encodingObject = getObject("encoding", contentNode, false, location, result); if (encodingObject != null) { mediaType.setEncoding( getEncodingMap(encodingObject, String.format("%s.%s", location, "encoding"), result)); } Map<String, Object> extensions = getExtensions(contentNode); if (extensions != null && extensions.size() > 0) { mediaType.setExtensions(extensions); } ObjectNode examplesObject = getObject("examples", contentNode, false, location, result); if (examplesObject != null) { mediaType .setExamples(getExamples(examplesObject, String.format("%s.%s", location, "examples"), result)); } Object example = getAnyExample("example", contentNode, location, result); if (example != null) { mediaType.setExample(example); } Set<String> 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<String, Encoding> getEncodingMap(ObjectNode node, String location, ParseResult result) { if (node == null) { return null; } Map<String, Encoding> encodings = new LinkedHashMap<>(); Set<String> 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); } else { if (value.equals(Encoding.StyleEnum.FORM.toString())) { encoding.setStyle(Encoding.StyleEnum.FORM); } else if (value.equals(Encoding.StyleEnum.DEEP_OBJECT.toString())) { encoding.setStyle(Encoding.StyleEnum.DEEP_OBJECT); } else if (value.equals(Encoding.StyleEnum.PIPE_DELIMITED.toString())) { encoding.setStyle(Encoding.StyleEnum.PIPE_DELIMITED); } else if (value.equals(Encoding.StyleEnum.SPACE_DELIMITED.toString())) { encoding.setStyle(Encoding.StyleEnum.SPACE_DELIMITED); } 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<String, Object> extensions = getExtensions(node); if (extensions != null && extensions.size() > 0) { encoding.setExtensions(extensions); } Set<String> 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<String, Link> getLinks(ObjectNode obj, String location, ParseResult result) { if (obj == null) { return null; } Map<String, Link> links = new LinkedHashMap<>(); Set<String> 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)) { String mungedRef = mungedRef(ref.textValue()); if (mungedRef != null) { link.set$ref(mungedRef); } else { link.set$ref(ref.textValue()); } return link; } 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)); } String requestBody = getString("requestBody", linkNode, false, location, result); if (requestBody != null) { link.setRequestBody(requestBody); } 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<String, Object> extensions = getExtensions(linkNode); if (extensions != null && extensions.size() > 0) { link.setExtensions(extensions); } Set<String> 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<String, String> getLinkParameters(ObjectNode parametersObject, String location, ParseResult result) { Map<String, String> linkParameters = new LinkedHashMap<>(); Set<String> keys = getKeys(parametersObject); for (String name : keys) { JsonNode value = parametersObject.get(name); linkParameters.put(name, value.asText()); } return linkParameters; } public Map<String, Callback> getCallbacks(ObjectNode node, String location, ParseResult result) { if (node == null) { return null; } Map<String, Callback> callbacks = new LinkedHashMap<>(); Set<String> 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<String> 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)) { String mungedRef = mungedRef(ref.textValue()); if (mungedRef != null) { callback.set$ref(mungedRef); } else { callback.set$ref(ref.textValue()); } return callback; } else { result.invalidType(location, "$ref", "string", node); return null; } } callback.addPathItem(name, getPathItem((ObjectNode) value, location, result)); Map<String, Object> 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<String, Object> extensions = getExtensions(node); if (extensions != null && extensions.size() > 0) { xml.setExtensions(extensions); } Set<String> 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)) { if (v.isInt()) { value = v.intValue(); } } else if (!v.isValueNode()) { result.invalidType(location, key, "integer", node); } return value; } public Map<String, Parameter> getParameters(ObjectNode obj, String location, ParseResult result) { if (obj == null) { return null; } Map<String, Parameter> parameters = new LinkedHashMap<>(); Set<String> 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<Parameter> getParameterList(ArrayNode obj, String location, ParseResult result) { List<Parameter> 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(); String mungedRef = mungedRef(ref.textValue()); if (mungedRef != null) { parameter.set$ref(mungedRef); } else { parameter.set$ref(ref.textValue()); } return parameter; } 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); } if (parameter instanceof QueryParameter) { Boolean allowEmptyValue = getBoolean("allowEmptyValue", obj, false, location, result); if (allowEmptyValue != null) { parameter.setAllowEmptyValue(allowEmptyValue); } } value = getString("style", obj, false, location, result); setStyle(value, parameter, location, obj, result); Boolean explode = getBoolean("explode", obj, false, location, result); if (explode != null) { parameter.setExplode(explode); } else if (parameter.getStyle().equals(StyleEnum.FORM)) { parameter.setExplode(Boolean.TRUE); } else { parameter.setExplode(Boolean.FALSE); } 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)); } Object example = getAnyExample("example", obj, location, result); if (example != null) { parameter.setExample(example); } ObjectNode contentNode = getObject("content", obj, false, location, result); if (contentNode != null) { parameter.setContent(getContent(contentNode, String.format("%s.%s", location, "content"), result)); } Map<String, Object> extensions = getExtensions(obj); if (extensions != null && extensions.size() > 0) { parameter.setExtensions(extensions); } Set<String> 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<String, Header> getHeaders(ObjectNode obj, String location, ParseResult result) { if (obj == null) { return null; } Map<String, Header> headers = new LinkedHashMap<>(); Set<String> 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)) { String mungedRef = mungedRef(ref.textValue()); if (mungedRef != null) { header.set$ref(mungedRef); } else { header.set$ref(ref.textValue()); } return header; } 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 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)); } ObjectNode examplesObject = getObject("examples", headerNode, false, location, result); if (examplesObject != null) { header.setExamples(getExamples(examplesObject, location, result)); } Object example = getAnyExample("example", headerNode, location, result); if (example != null) { header.setExample(example); } ObjectNode contentNode = getObject("content", headerNode, false, location, result); if (contentNode != null) { header.setContent(getContent(contentNode, String.format("%s.%s", location, "content"), result)); } Map<String, Object> extensions = getExtensions(headerNode); if (extensions != null && extensions.size() > 0) { header.setExtensions(extensions); } Set<String> 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 Object getAnyExample(String nodeKey, ObjectNode node, String location, ParseResult result) { JsonNode example = node.get(nodeKey); if (example != null) { if (example.getNodeType().equals(JsonNodeType.STRING)) { String value = getString(nodeKey, node, false, location, result); if (StringUtils.isNotBlank(value)) { return value; } } if (example.getNodeType().equals(JsonNodeType.NUMBER)) { Integer integerExample = getInteger(nodeKey, node, false, location, result); if (integerExample != null) { return integerExample; } else { BigDecimal bigDecimalExample = getBigDecimal(nodeKey, node, false, location, result); if (bigDecimalExample != null) { return bigDecimalExample; } } } else if (example.getNodeType().equals(JsonNodeType.OBJECT)) { ObjectNode objectValue = getObject(nodeKey, node, false, location, result); if (objectValue != null) { return objectValue; } } else if (example.getNodeType().equals(JsonNodeType.ARRAY)) { ArrayNode arrayValue = getArray(nodeKey, node, false, location, result); if (arrayValue != null) { return arrayValue; } } } return null; } public Map<String, SecurityScheme> getSecuritySchemes(ObjectNode obj, String location, ParseResult result) { if (obj == null) { return null; } Map<String, SecurityScheme> securitySchemes = new LinkedHashMap<>(); Set<String> 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)) { String mungedRef = mungedRef(ref.textValue()); if (mungedRef != null) { securityScheme.set$ref(mungedRef); } else { securityScheme.set$ref(ref.textValue()); } return securityScheme; } else { result.invalidType(location, "$ref", "string", node); return null; } } boolean descriptionRequired, bearerFormatRequired, nameRequired, inRequired, schemeRequired, flowsRequired, openIdConnectRequired; descriptionRequired = bearerFormatRequired = nameRequired = inRequired = schemeRequired = flowsRequired = openIdConnectRequired = false; String value = getString("type", node, true, location, result); if (StringUtils.isNotBlank(value)) { if (SecurityScheme.Type.APIKEY.toString().equals(value)) { securityScheme.setType(SecurityScheme.Type.APIKEY); nameRequired = inRequired = true; } else if (SecurityScheme.Type.HTTP.toString().equals(value)) { securityScheme.setType(SecurityScheme.Type.HTTP); schemeRequired = true; } else if (SecurityScheme.Type.OAUTH2.toString().equals(value)) { securityScheme.setType(SecurityScheme.Type.OAUTH2); flowsRequired = true; } else if (SecurityScheme.Type.OPENIDCONNECT.toString().equals(value)) { securityScheme.setType(SecurityScheme.Type.OPENIDCONNECT); openIdConnectRequired = true; } else { result.invalidType(location + ".type", "type", "http|apiKey|oauth2|openIdConnect ", node); } } value = getString("description", node, descriptionRequired, location, result); if (StringUtils.isNotBlank(value)) { securityScheme.setDescription(value); } value = getString("name", node, nameRequired, location, result); if (StringUtils.isNotBlank(value)) { securityScheme.setName(value); } final String securitySchemeIn = getString("in", node, inRequired, location, result); final Optional<SecurityScheme.In> matchingIn = Arrays.stream(SecurityScheme.In.values()) .filter(in -> in.toString().equals(securitySchemeIn)).findFirst(); securityScheme.setIn(matchingIn.orElse(null)); value = getString("scheme", node, schemeRequired, location, result); if (StringUtils.isNotBlank(value)) { securityScheme.setScheme(value); } value = getString("bearerFormat", node, bearerFormatRequired, location, result); if (StringUtils.isNotBlank(value)) { securityScheme.setBearerFormat(value); } ObjectNode flowsObject = getObject("flows", node, flowsRequired, location, result); if (flowsObject != null) { securityScheme.setFlows(getOAuthFlows(flowsObject, location, result)); } value = getString("openIdConnectUrl", node, openIdConnectRequired, location, result); if (StringUtils.isNotBlank(value)) { securityScheme.setOpenIdConnectUrl(value); } Map<String, Object> extensions = getExtensions(node); if (extensions != null && extensions.size() > 0) { securityScheme.setExtensions(extensions); } Set<String> securitySchemeKeys = getKeys(node); for (String key : securitySchemeKeys) { 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("implicit", objectNode, location, result)); } objectNode = getObject("password", node, false, location, result); if (objectNode != null) { oAuthFlows.setPassword(getOAuthFlow("password", objectNode, location, result)); } objectNode = getObject("clientCredentials", node, false, location, result); if (objectNode != null) { oAuthFlows.setClientCredentials(getOAuthFlow("clientCredentials", objectNode, location, result)); } objectNode = getObject("authorizationCode", node, false, location, result); if (objectNode != null) { oAuthFlows.setAuthorizationCode(getOAuthFlow("authorizationCode", objectNode, location, result)); } Map<String, Object> extensions = getExtensions(node); if (extensions != null && extensions.size() > 0) { oAuthFlows.setExtensions(extensions); } Set<String> 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(String oAuthFlowType, ObjectNode node, String location, ParseResult result) { if (node == null) { return null; } OAuthFlow oAuthFlow = new OAuthFlow(); boolean authorizationUrlRequired, tokenUrlRequired, refreshUrlRequired, scopesRequired; authorizationUrlRequired = tokenUrlRequired = refreshUrlRequired = false; scopesRequired = true; switch (oAuthFlowType) { case "implicit": authorizationUrlRequired = true; break; case "password": tokenUrlRequired = true; break; case "clientCredentials": tokenUrlRequired = true; break; case "authorizationCode": authorizationUrlRequired = tokenUrlRequired = true; break; } String value = getString("authorizationUrl", node, authorizationUrlRequired, location, result); if (StringUtils.isNotBlank(value)) { oAuthFlow.setAuthorizationUrl(value); } value = getString("tokenUrl", node, tokenUrlRequired, location, result); if (StringUtils.isNotBlank(value)) { oAuthFlow.setTokenUrl(value); } value = getString("refreshUrl", node, refreshUrlRequired, location, result); if (StringUtils.isNotBlank(value)) { oAuthFlow.setRefreshUrl(value); } ObjectNode scopesObject = getObject("scopes", node, scopesRequired, location, result); Scopes scope = new Scopes(); Set<String> keys = getKeys(scopesObject); for (String name : keys) { JsonNode scopeValue = scopesObject.get(name); if (scopesObject != null) { scope.addString(name, scopeValue.asText()); oAuthFlow.setScopes(scope); } } Map<String, Object> extensions = getExtensions(node); if (extensions != null && extensions.size() > 0) { oAuthFlow.setExtensions(extensions); } Set<String> 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<String, Schema> getSchemas(ObjectNode obj, String location, ParseResult result) { if (obj == null) { return null; } Map<String, Schema> schemas = new LinkedHashMap<>(); Set<String> 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<String, String> mapping = new LinkedHashMap<>(); Set<String> 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) || (anyOfArray != null) || (oneOfArray != null)) { ComposedSchema composedSchema = new ComposedSchema(); if (allOfArray != null) { for (JsonNode n : allOfArray) { if (n.isObject()) { schema = getSchema((ObjectNode) n, location, result); composedSchema.addAllOfItem(schema); } } schema = composedSchema; } if (anyOfArray != null) { for (JsonNode n : anyOfArray) { if (n.isObject()) { schema = getSchema((ObjectNode) n, location, result); composedSchema.addAnyOfItem(schema); } } schema = composedSchema; } if (oneOfArray != null) { for (JsonNode n : oneOfArray) { if (n.isObject()) { schema = getSchema((ObjectNode) n, location, result); composedSchema.addOneOfItem(schema); } } schema = composedSchema; } } if (itemsNode != null) { ArraySchema items = new ArraySchema(); if (itemsNode.getNodeType().equals(JsonNodeType.OBJECT)) { items.setItems(getSchema(itemsNode, location, result)); } else if (itemsNode.getNodeType().equals(JsonNodeType.ARRAY)) { for (JsonNode n : itemsNode) { if (n.isValueNode()) { items.setItems(getSchema(itemsNode, location, result)); } } } schema = items; } if (schema == null) { schema = SchemaTypeUtil.createSchemaByType(node); } JsonNode ref = node.get("$ref"); if (ref != null) { if (ref.getNodeType().equals(JsonNodeType.STRING)) { String mungedRef = mungedRef(ref.textValue()); if (mungedRef != null) { schema.set$ref(mungedRef); } else { schema.set$ref(ref.asText()); } return schema; } 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(pattern)) { 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<String> 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) { for (JsonNode n : enumArray) { if (n.isNumber()) { schema.addEnumItemObject(n.numberValue()); } else if (n.isValueNode()) { schema.addEnumItemObject(n.asText()); } else { result.invalidType(location, "enum", "value", n); } } } value = getString("type", node, false, location, result); if (StringUtils.isNotBlank(value)) { schema.setType(value); } else { // may have an enum where type can be inferred JsonNode enumNode = node.get("enum"); if (enumNode != null && enumNode.isArray()) { String type = inferTypeFromArray((ArrayNode) enumNode); schema.setType(type); } } ObjectNode notObj = getObject("not", node, false, location, result); if (notObj != null) { Schema not = getSchema(notObj, location, result); if (not != null) { schema.setNot(not); } } Map<String, Schema> properties = new LinkedHashMap<>(); ObjectNode propertiesObj = getObject("properties", node, false, location, result); Schema property = null; Set<String> 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); } if (node.get("additionalProperties") != null) { if (node.get("additionalProperties").getNodeType().equals(JsonNodeType.OBJECT)) { ObjectNode additionalPropertiesObj = getObject("additionalProperties", node, false, location, result); if (additionalPropertiesObj != null) { Schema additionalProperties = getSchema(additionalPropertiesObj, location, result); if (additionalProperties != null) { schema.setAdditionalProperties(additionalProperties); } } } else if (node.get("additionalProperties").getNodeType().equals(JsonNodeType.BOOLEAN)) { Boolean additionalProperties = getBoolean("additionalProperties", node, false, 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); } } Object example = getAnyExample("example", node, location, result); if (example != null) { schema.setExample(example); } bool = getBoolean("deprecated", node, false, location, result); if (bool != null) { schema.setDeprecated(bool); } Map<String, Object> extensions = getExtensions(node); if (extensions != null && extensions.size() > 0) { schema.setExtensions(extensions); } Set<String> 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<String, Example> getExamples(ObjectNode obj, String location, ParseResult result) { if (obj == null) { return null; } Map<String, Example> examples = new LinkedHashMap<>(); Set<String> 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<Example> getExampleList(ArrayNode obj, String location, ParseResult result) { List<Example> 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)) { String mungedRef = mungedRef(ref.textValue()); if (mungedRef != null) { example.set$ref(mungedRef); } else { example.set$ref(ref.textValue()); } return example; } 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); } Object sample = getAnyExample("value", node, location, result); if (sample != null) { example.setValue(sample); } value = getString("externalValue", node, false, location, result); if (StringUtils.isNotBlank(value)) { example.setExternalValue(value); } Map<String, Object> extensions = getExtensions(node); if (extensions != null && extensions.size() > 0) { example.setExtensions(extensions); } Set<String> 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<String> keys = getKeys(node); for (String key : keys) { if (key.startsWith("x-")) { Map<String, Object> extensions = getExtensions(node); if (extensions != null && extensions.size() > 0) { apiResponses.setExtensions(extensions); } } else { 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)) { String mungedRef = mungedRef(ref.textValue()); if (mungedRef != null) { apiResponse.set$ref(mungedRef); } else { apiResponse.set$ref(ref.textValue()); } return apiResponse; } 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<String, Header> 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<String, Link> 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<String, Object> extensions = getExtensions(node); if (extensions != null && extensions.size() > 0) { apiResponse.setExtensions(extensions); } Set<String> 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<String> getTagsStrings(ArrayNode nodes, String location, ParseResult result) { if (nodes == null) return null; List<String> 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<String> 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, operationIDs); 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<String, Callback> 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<String, Object> extensions = getExtensions(obj); if (extensions != null && extensions.size() > 0) { operation.setExtensions(extensions); } Set<String> 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<SecurityRequirement> getSecurityRequirementsList(ArrayNode nodes, String location, ParseResult result) { if (nodes == null) return null; List<SecurityRequirement> securityRequirements = new ArrayList<>(); for (JsonNode node : nodes) { if (node.getNodeType().equals(JsonNodeType.OBJECT)) { SecurityRequirement securityRequirement = new SecurityRequirement(); Set<String> keys = getKeys((ObjectNode) node); if (keys.size() == 0) { securityRequirements.add(securityRequirement); } else { for (String key : keys) { if (key != null) { JsonNode value = node.get(key); if (key != null && JsonNodeType.ARRAY.equals(value.getNodeType())) { ArrayNode arrayNode = (ArrayNode) value; List<String> scopes = Stream.generate(arrayNode.elements()::next) .map((n) -> n.asText()).limit(arrayNode.size()) .collect(Collectors.toList()); securityRequirement.addList(key, scopes); } } } if (securityRequirement.size() > 0) { securityRequirements.add(securityRequirement); } } } } return securityRequirements; } public Map<String, RequestBody> getRequestBodies(ObjectNode obj, String location, ParseResult result) { if (obj == null) { return null; } Map<String, RequestBody> bodies = new LinkedHashMap<>(); Set<String> 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)) { String mungedRef = mungedRef(ref.textValue()); if (mungedRef != null) { body.set$ref(mungedRef); } else { body.set$ref(ref.textValue()); } return body; } 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<String, Object> extensions = getExtensions(node); if (extensions != null && extensions.size() > 0) { body.setExtensions(extensions); } Set<String> 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; } public String inferTypeFromArray(ArrayNode an) { if (an.size() == 0) { return "string"; } String type = null; for (int i = 0; i < an.size(); i++) { JsonNode element = an.get(0); if (element.isBoolean()) { if (type == null) { type = "boolean"; } else if (!"boolean".equals(type)) { type = "string"; } } else if (element.isNumber()) { if (type == null) { type = "number"; } else if (!"number".equals(type)) { type = "string"; } } else { type = "string"; } } return type; } protected static class ParseResult { private boolean valid = true; private Map<Location, JsonNode> extra = new LinkedHashMap<>(); private Map<Location, JsonNode> unsupported = new LinkedHashMap<>(); private Map<Location, String> invalidType = new LinkedHashMap<>(); private List<Location> missing = new ArrayList<>(); private List<Location> warnings = new ArrayList<>(); private List<Location> unique = new ArrayList<>(); private List<Location> uniqueTags = 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 warning(String location, String key) { warnings.add(new Location(location, key)); } public void unique(String location, String key) { unique.add(new Location(location, key)); } public void uniqueTags(String location, String key) { uniqueTags.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 boolean isValid() { return this.valid; } public List<String> getMessages() { List<String> messages = new ArrayList<String>(); 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 : warnings) { String location = l.location.equals("") ? "" : l.location + "."; String message = "attribute " + location + l.key; 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); } for (Location l : unique) { String location = l.location.equals("") ? "" : l.location + "."; String message = "attribute " + location + l.key + " is repeated"; messages.add(message); } for (Location l : uniqueTags) { String location = l.location.equals("") ? "" : l.location + "."; String message = "attribute " + location + l.key + " is repeated"; 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; } } }