JsonSchemaParserValidator.java 10.2 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.aemds.guide.service.JsonSchemaVisitor
 *  com.fasterxml.jackson.databind.JsonNode
 *  com.fasterxml.jackson.databind.ObjectMapper
 *  org.apache.commons.lang.StringUtils
 *  org.apache.sling.commons.json.JSONObject
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.aemds.guide.addon.service.impl.jsonschema;

import com.adobe.aemds.guide.addon.service.impl.jsonschema.SchemaWalker;
import com.adobe.aemds.guide.service.JsonSchemaVisitor;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.fge.jackson.JsonLoader;
import com.github.fge.jackson.jsonpointer.JsonPointer;
import com.github.fge.jsonschema.cfg.ValidationConfiguration;
import com.github.fge.jsonschema.cfg.ValidationConfigurationBuilder;
import com.github.fge.jsonschema.core.exceptions.ProcessingException;
import com.github.fge.jsonschema.core.load.Dereferencing;
import com.github.fge.jsonschema.core.load.SchemaLoader;
import com.github.fge.jsonschema.core.load.configuration.LoadingConfiguration;
import com.github.fge.jsonschema.core.load.configuration.LoadingConfigurationBuilder;
import com.github.fge.jsonschema.core.report.ListProcessingReport;
import com.github.fge.jsonschema.core.report.ProcessingMessage;
import com.github.fge.jsonschema.core.report.ProcessingReport;
import com.github.fge.jsonschema.core.tree.SchemaTree;
import com.github.fge.jsonschema.library.Library;
import com.github.fge.jsonschema.library.LibraryBuilder;
import com.github.fge.jsonschema.main.JsonSchema;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
import com.github.fge.jsonschema.main.JsonSchemaFactoryBuilder;
import com.github.fge.jsonschema.processors.syntax.SyntaxValidator;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.sling.commons.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JsonSchemaParserValidator {
    private static final ObjectMapper MAPPER = new ObjectMapper();
    private JsonSchemaFactory schemaFactory;
    private Logger logger;
    private SchemaLoader loader;
    private JsonNode node;
    private SchemaTree tree;
    private JsonSchema schema;
    private JsonNode resolvedNode;
    private Map<String, String> definitions;
    private Boolean includeReferredDefinition;
    private Boolean mergeTitle;

    public JsonSchemaParserValidator(Object jsonSchema) throws IOException, ProcessingException {
        this(jsonSchema, null);
    }

    public JsonNode getResolvedNode() {
        return this.resolvedNode;
    }

    private void setLoadingConfigurationAndLoader(Object[] referredSchemas) throws IOException, ProcessingException {
        ValidationConfiguration validationConfiguration = this.getValidationConfiguration();
        LoadingConfigurationBuilder cfgBuilder = LoadingConfiguration.newBuilder().setEnableCache(true).dereferencing(Dereferencing.INLINE);
        if (referredSchemas != null) {
            for (Object referredSchema : referredSchemas) {
                JsonNode node = null;
                if (referredSchema instanceof File) {
                    node = MAPPER.readTree((File)referredSchema);
                } else if (referredSchema instanceof InputStream) {
                    node = MAPPER.readTree((InputStream)referredSchema);
                } else if (referredSchema instanceof String) {
                    node = MAPPER.readTree((String)referredSchema);
                }
                if (node == null || !node.path("id").isTextual()) continue;
                cfgBuilder.preloadSchema(node);
            }
        }
        LoadingConfiguration loadingConfiguration = cfgBuilder.freeze();
        this.schemaFactory = JsonSchemaFactory.newBuilder().setValidationConfiguration(validationConfiguration).setLoadingConfiguration(loadingConfiguration).freeze();
        this.loader = new SchemaLoader(loadingConfiguration);
    }

    public JsonSchemaParserValidator(Object rootJsonSchema, Object[] referredJsonSchema) throws IOException, ProcessingException {
        this(rootJsonSchema, referredJsonSchema, false, false);
    }

    public JsonSchemaParserValidator(Object rootJsonSchema, Object[] referredJsonSchema, Boolean includeReferredDefinition, Boolean mergeTitle) throws IOException, ProcessingException {
        this.logger = LoggerFactory.getLogger(this.getClass());
        this.loader = null;
        this.definitions = new LinkedHashMap<String, String>();
        this.includeReferredDefinition = false;
        this.mergeTitle = false;
        this.mergeTitle = mergeTitle;
        this.includeReferredDefinition = includeReferredDefinition;
        this.setLoadingConfigurationAndLoader(referredJsonSchema);
        this.node = rootJsonSchema instanceof File ? MAPPER.readTree((File)rootJsonSchema) : (rootJsonSchema instanceof InputStream ? MAPPER.readTree((InputStream)rootJsonSchema) : (rootJsonSchema instanceof String ? MAPPER.readTree((String)rootJsonSchema) : (rootJsonSchema instanceof JSONObject ? MAPPER.readTree(rootJsonSchema.toString()) : null)));
        if (this.node != null) {
            this.tree = this.loader.load(this.node).setPointer(JsonPointer.empty());
            this.schema = this.schemaFactory.getJsonSchema(this.node);
            this.resolvedNode = MAPPER.valueToTree((Object)this.asMap());
        }
    }

    public JsonSchemaParserValidator(Object rootJsonSchema, Object[] referredJsonSchema, Boolean includeReferredDefinition) throws IOException, ProcessingException {
        this(rootJsonSchema, referredJsonSchema, includeReferredDefinition, false);
    }

    private ValidationConfiguration getValidationConfiguration() {
        ValidationConfiguration validationConfiguration = ValidationConfiguration.byDefault();
        Library defaultLib = validationConfiguration.getDefaultLibrary();
        defaultLib = defaultLib.thaw().freeze();
        validationConfiguration = validationConfiguration.thaw().setDefaultLibrary("http://forms.aem.com/draft-04/schema#", defaultLib).freeze();
        return validationConfiguration;
    }

    public void walk(JsonSchemaVisitor visitor) {
        try {
            new SchemaWalker(this.loader).walk(this.tree, visitor);
        }
        catch (Exception ex) {
            this.logger.error("Error while walking json schema ", (Throwable)ex);
        }
    }

    private Map asMap() {
        try {
            return new SchemaWalker(this.loader, this.includeReferredDefinition, this.mergeTitle).walk(this.tree, new JsonSchemaVisitor(){

                public void visitor(String key, Object node) {
                    JsonNode jsonNode = (JsonNode)node;
                    if (key.equals("definitions") && jsonNode.isObject()) {
                        Iterator fieldsIterator = jsonNode.fields();
                        while (fieldsIterator.hasNext()) {
                            Map.Entry field = (Map.Entry)fieldsIterator.next();
                            String prop = (String)field.getKey();
                            JsonNode value = (JsonNode)field.getValue();
                            String title = prop;
                            boolean isObject = false;
                            if (value.has("type") && StringUtils.equals((String)"object", (String)value.get("type").toString())) {
                                isObject = true;
                            }
                            if (value.has("properties")) {
                                isObject = true;
                            }
                            if (!isObject) continue;
                            if (value.has("title") && StringUtils.isNotBlank((String)(title = value.get("title").toString()))) {
                                title = title.replaceAll("^\"|\"$", "");
                            }
                            JsonSchemaParserValidator.this.definitions.put(prop, title);
                        }
                    }
                }
            });
        }
        catch (Exception ex) {
            this.logger.error("Error while walking json schema ", (Throwable)ex);
            return null;
        }
    }

    public boolean isValid() throws IOException, ProcessingException {
        boolean valid = this.schemaFactory.getSyntaxValidator().schemaIsValid(this.node);
        if (valid) {
            int numberOfSyntaxErrors = 0;
            ListProcessingReport report = this.validateAsList("{}");
            Iterator<ProcessingMessage> reportIterator = report.iterator();
            while (reportIterator.hasNext()) {
                JsonNode msg = reportIterator.next().asJson();
                if (!msg.isObject() || !msg.get("domain").asText().equals("syntax") || msg.get("ignored") != null && msg.get("ignored").size() > 0) continue;
                ++numberOfSyntaxErrors;
            }
            valid = numberOfSyntaxErrors == 0;
        }
        return valid;
    }

    public Map<String, String> getDefinitions() {
        return this.definitions;
    }

    public String getValue(String path) {
        JsonNode node = this.getNodeAtPath(path);
        if (node != null) {
            return node.asText();
        }
        this.logger.debug("Unable to resolve JSON Node at path ", (Object)path);
        return null;
    }

    public JsonNode getNodeAtPath(String path) {
        if (this.resolvedNode != null) {
            return this.resolvedNode.at(path);
        }
        this.logger.debug("Unable to resolve JSON Node at path ", (Object)path);
        return null;
    }

    public String validate(String representation) throws IOException, ProcessingException {
        return this.validateAsList(representation).asJson().toString();
    }

    private ListProcessingReport validateAsList(String representation) throws IOException, ProcessingException {
        JsonNode instance = JsonLoader.fromString(representation);
        ListProcessingReport report = new ListProcessingReport();
        report.mergeWith(this.schema.validate(instance, true));
        return report;
    }

    public JsonNode getResolvedDefinitions() {
        return this.resolvedNode.at("/definitions");
    }

}