SchemaWalker.java 9.19 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.lang3.StringUtils
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.aemds.guide.addon.service.impl.jsonschema;

import com.adobe.aemds.guide.service.JsonSchemaVisitor;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.fge.jackson.jsonpointer.JsonPointer;
import com.github.fge.jsonschema.core.exceptions.ProcessingException;
import com.github.fge.jsonschema.core.load.RefResolver;
import com.github.fge.jsonschema.core.load.SchemaLoader;
import com.github.fge.jsonschema.core.ref.JsonRef;
import com.github.fge.jsonschema.core.report.ProcessingReport;
import com.github.fge.jsonschema.core.tree.SchemaTree;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SchemaWalker {
    private Logger logger;
    public static final List<String> JSON_SCHEMA_PROPERTIES_KEY = Collections.unmodifiableList(Arrays.asList("properties", "patternProperties"));
    public static final List<String> JSON_SCHEMA_OF_KEY = Collections.unmodifiableList(Arrays.asList("oneOf"));
    final Set<JsonRef> refs;
    private static final String JSON_SCHEMA_DEFINITIONS = "definitions";
    private static final String JSON_SCHEMA_REF = "$ref";
    private static final String JSON_SCHEMA_ITEMS = "items";
    private static final String JSON_SCHEMA_ID = "id";
    private static final String JSON_SCHEMA_TYPE = "type";
    private static final String JSON_SCHEMA_TITLE_PROPERTY = "title";
    private static final String JSON_SCHEMA_ARRAY_TYPE = "array";
    private Boolean includeReferredDefinition;
    private Boolean mergeTitle;
    private final RefResolver resolver;
    private final ObjectMapper mapper;

    public SchemaWalker(SchemaLoader loader) {
        this.logger = LoggerFactory.getLogger(this.getClass());
        this.refs = new LinkedHashSet<JsonRef>();
        this.includeReferredDefinition = false;
        this.mergeTitle = false;
        this.mapper = new ObjectMapper();
        this.resolver = new RefResolver(loader);
    }

    public SchemaWalker(SchemaLoader loader, Boolean includeReferredDefinition, Boolean mergeTitle) {
        this.logger = LoggerFactory.getLogger(this.getClass());
        this.refs = new LinkedHashSet<JsonRef>();
        this.includeReferredDefinition = false;
        this.mergeTitle = false;
        this.mapper = new ObjectMapper();
        this.includeReferredDefinition = includeReferredDefinition;
        this.resolver = new RefResolver(loader);
        this.mergeTitle = mergeTitle;
    }

    public Map walk(SchemaTree tree, JsonSchemaVisitor schemaVisitor) throws Exception {
        SchemaTree resolvedTree;
        String referredDefinition = "";
        JsonRef schemaRefName = null;
        JsonRef refName = null;
        try {
            resolvedTree = this.resolver.rawProcess(null, tree);
        }
        catch (ProcessingException ex) {
            this.logger.error("Error in json schema parsing ", (Throwable)ex);
            return null;
        }
        JsonNode schemaNode = resolvedTree.getNode();
        if (schemaNode.path("id").isTextual()) {
            schemaRefName = JsonRef.fromString(schemaNode.path("id").asText());
            this.refs.add(schemaRefName);
        }
        Map schema = (Map)this.mapper.convertValue((Object)schemaNode, Map.class);
        Iterator fieldsIterator = schemaNode.fields();
        while (fieldsIterator.hasNext()) {
            Map.Entry field = (Map.Entry)fieldsIterator.next();
            String key = (String)field.getKey();
            boolean isItemsNodeAtTop = false;
            schemaVisitor.visitor(key, field.getValue());
            if (!JSON_SCHEMA_PROPERTIES_KEY.contains(key) && !"definitions".equalsIgnoreCase(key) && !"items".equalsIgnoreCase(key) || !schemaNode.path(key).isObject()) continue;
            if ("items".equalsIgnoreCase(key)) {
                schemaNode = schemaNode.path(key);
                for (String propKey : JSON_SCHEMA_PROPERTIES_KEY) {
                    if (!schemaNode.has(propKey)) continue;
                    isItemsNodeAtTop = true;
                    key = propKey;
                    break;
                }
            }
            Iterator fields = schemaNode.path(key).fieldNames();
            LinkedHashMap children = new LinkedHashMap();
            while (fields.hasNext()) {
                String prop = (String)fields.next();
                JsonNode node = schemaNode.path(key);
                JsonNode refNode = null;
                boolean isCyclicReference = false;
                boolean isPropertyTypeArray = false;
                if (node.path(prop).isObject()) {
                    refNode = node.path(prop);
                    if (refNode.path("type").isTextual() && refNode.path("type").asText().equalsIgnoreCase("array") && refNode.path("items").isObject() && refNode.path("items").path("$ref").isTextual()) {
                        isPropertyTypeArray = true;
                        JsonNode itemsNode = refNode.path("items");
                        if (itemsNode != null && itemsNode.path("$ref").isTextual()) {
                            refName = JsonRef.fromString(itemsNode.path("$ref").textValue());
                            if (!this.refs.add(refName)) {
                                isCyclicReference = true;
                            } else {
                                referredDefinition = itemsNode.path("$ref").textValue();
                            }
                        }
                    }
                    if (refNode != null && refNode.path("$ref").isTextual()) {
                        refName = JsonRef.fromString(refNode.path("$ref").textValue());
                        if (!this.refs.add(refName)) {
                            isCyclicReference = true;
                        } else {
                            referredDefinition = refNode.path("$ref").textValue();
                        }
                    }
                }
                Map resolvedMap = null;
                if (!isCyclicReference) {
                    JsonPointer refPointer = null;
                    refPointer = isPropertyTypeArray ? JsonPointer.of(key, new Object[0]).append(JsonPointer.of(prop, new Object[0])).append(JsonPointer.of("items", new Object[0])) : (isItemsNodeAtTop ? JsonPointer.of("items", new Object[0]).append(JsonPointer.of(key, new Object[0])).append(JsonPointer.of(prop, new Object[0])) : JsonPointer.of(key, new Object[0]).append(JsonPointer.of(prop, new Object[0])));
                    if (!JSON_SCHEMA_OF_KEY.contains(prop) && !node.path(prop).isArray()) {
                        resolvedMap = this.walk(resolvedTree.append(refPointer), schemaVisitor);
                    }
                }
                if (isPropertyTypeArray && resolvedMap != null && refNode != null) {
                    LinkedHashMap<String, Object> itemsMap = resolvedMap;
                    resolvedMap = new LinkedHashMap<String, Object>();
                    Iterator refNodeFields = refNode.fieldNames();
                    while (refNodeFields.hasNext()) {
                        String refNodeFieldProp = (String)refNodeFields.next();
                        if (resolvedMap == null) continue;
                        if ("items".equalsIgnoreCase(refNodeFieldProp)) {
                            resolvedMap.put(refNodeFieldProp, itemsMap);
                            continue;
                        }
                        resolvedMap.put(refNodeFieldProp, (Object)refNode.get(refNodeFieldProp));
                    }
                }
                if (this.includeReferredDefinition.booleanValue() && StringUtils.isNotEmpty((CharSequence)referredDefinition) && resolvedMap != null) {
                    resolvedMap.put("referredDefinition", referredDefinition);
                }
                if (this.mergeTitle.booleanValue() && refNode != null && refNode.has("$ref") && refNode.has("title") && resolvedMap != null) {
                    resolvedMap.put("title", refNode.path("title").asText());
                }
                if (resolvedMap != null) {
                    children.put(prop, resolvedMap);
                }
                if (refName == null) continue;
                this.refs.remove(refName);
            }
            if (key.equals("properties") && schemaNode.has("definitions") || key.equals("definitions")) {
                this.refs.clear();
            }
            if (children.size() <= 0) continue;
            if (isItemsNodeAtTop) {
                LinkedHashMap propMap = new LinkedHashMap();
                propMap.put(key, children);
                schema.put("items", propMap);
                continue;
            }
            schema.put(key, children);
        }
        if (schemaRefName != null) {
            this.refs.remove(schemaRefName);
        }
        return schema;
    }
}