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

org.everit.json.schema.ObjectSchemaValidatingVisitor Maven / Gradle / Ivy

Go to download

Implementation of the JSON Schema Core Draft v4 specification built with the org.json API

There is a newer version: 1.14.4
Show newest version
package org.everit.json.schema;

import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
import static org.everit.json.schema.loader.OrgJsonUtil.getNames;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.everit.json.schema.regexp.Regexp;
import org.json.JSONObject;

class ObjectSchemaValidatingVisitor extends Visitor {

    private final Object subject;

    private JSONObject objSubject;

    private ObjectSchema schema;

    private int objectSize;

    private final ValidatingVisitor owner;

    public ObjectSchemaValidatingVisitor(Object subject, ValidatingVisitor owner) {
        this.subject = requireNonNull(subject, "subject cannot be null");
        this.owner = requireNonNull(owner, "owner cannot be null");
    }

    @Override void visitObjectSchema(ObjectSchema objectSchema) {
        if (owner.passesTypeCheck(JSONObject.class, objectSchema.requiresObject(), objectSchema.isNullable())) {
            objSubject = (JSONObject) subject;
            objectSize = objSubject.length();
            this.schema = objectSchema;
            Object failureState = owner.getFailureState();
            Set objSubjectKeys = null;
            if (objectSchema.hasDefaultProperty()) {
                objSubjectKeys = new HashSet<>(objSubject.keySet());
            }
            super.visitObjectSchema(objectSchema);
            if (owner.isFailureStateChanged(failureState) && objectSchema.hasDefaultProperty()) {
                objSubject.keySet().retainAll(objSubjectKeys);
            }
        }
    }

    @Override void visitRequiredPropertyName(String requiredPropName) {
        if (!objSubject.has(requiredPropName)) {
            owner.failure(format("required key [%s] not found", requiredPropName), "required");
        }
    }

    @Override void visitPropertyNameSchema(Schema propertyNameSchema) {
        if (propertyNameSchema != null) {
            String[] names = getNames(objSubject);
            if (names == null || names.length == 0) {
                return;
            }
            for (String name : names) {
                ValidationException failure = owner.getFailureOfSchema(propertyNameSchema, name);
                if (failure != null) {
                    owner.failure(failure.prepend(name));
                }
            }
        }
    }

    @Override void visitMinProperties(Integer minProperties) {
        if (minProperties != null && objectSize < minProperties.intValue()) {
            owner.failure(format("minimum size: [%d], found: [%d]", minProperties, objectSize), "minProperties");
        }
    }

    @Override void visitMaxProperties(Integer maxProperties) {
        if (maxProperties != null && objectSize > maxProperties.intValue()) {
            owner.failure(format("maximum size: [%d], found: [%d]", maxProperties, objectSize), "maxProperties");
        }
    }

    @Override void visitPropertyDependencies(String ifPresent, Set allMustBePresent) {
        if (objSubject.has(ifPresent)) {
            for (String mustBePresent : allMustBePresent) {
                if (!objSubject.has(mustBePresent)) {
                    owner.failure(format("property [%s] is required", mustBePresent), "dependencies");
                }
            }
        }
    }

    @Override void visitAdditionalProperties(boolean permitsAdditionalProperties) {
        if (!permitsAdditionalProperties) {
            List additionalProperties = getAdditionalProperties();
            if (null == additionalProperties || additionalProperties.isEmpty()) {
                return;
            }
            for (String additionalProperty : additionalProperties) {
                owner.failure(format("extraneous key [%s] is not permitted", additionalProperty), "additionalProperties");
            }
        }
    }

    @Override void visitSchemaOfAdditionalProperties(Schema schemaOfAdditionalProperties) {
        if (schemaOfAdditionalProperties != null) {
            List additionalPropNames = getAdditionalProperties();
            for (String propName : additionalPropNames) {
                Object propVal = objSubject.get(propName);
                ValidationException failure = owner.getFailureOfSchema(schemaOfAdditionalProperties, propVal);
                if (failure != null) {
                    owner.failure(failure.prepend(propName, schema));
                }
            }
        }
    }

    private List getAdditionalProperties() {
        String[] names = getNames(objSubject);
        if (names == null) {
            return new ArrayList<>();
        } else {
            List namesList = new ArrayList<>();
            for (String name : names) {
                if (!schema.getPropertySchemas().containsKey(name) && !matchesAnyPattern(name)) {
                    namesList.add(name);
                }
            }
            return namesList;
        }
    }

    private boolean matchesAnyPattern(String key) {
        for (Regexp pattern : schema.getRegexpPatternProperties().keySet()) {
            if (!pattern.patternMatchingFailure(key).isPresent()) {
                return true;
            }
        }
        return false;
    }

    @Override void visitPatternPropertySchema(Regexp propertyNamePattern, Schema schema) {
        String[] propNames = getNames(objSubject);
        if (propNames == null || propNames.length == 0) {
            return;
        }
        for (String propName : propNames) {
            if (!propertyNamePattern.patternMatchingFailure(propName).isPresent()) {
                ValidationException failure = owner.getFailureOfSchema(schema, objSubject.get(propName));
                if (failure != null) {
                    owner.failure(failure.prepend(propName));
                }
            }
        }
    }

    @Override void visitSchemaDependency(String propName, Schema schema) {
        if (objSubject.has(propName)) {
            ValidationException failure = owner.getFailureOfSchema(schema, objSubject);
            if (failure != null) {
                owner.failure(failure);
            }
        }
    }

    @Override void visitPropertySchema(String properyName, Schema schema) {
        if (objSubject.has(properyName)) {
            ValidationException failure = owner.getFailureOfSchema(schema, objSubject.get(properyName));
            if (failure != null) {
                owner.failure(failure.prepend(properyName));
            }
        } else if (schema.hasDefaultValue()) {
            objSubject.put(properyName, schema.getDefaultValue());
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy