org.openmhealth.reference.concordia.EnumValidator.java Source code

Java tutorial

Introduction

Here is the source code for org.openmhealth.reference.concordia.EnumValidator.java

Source

/*******************************************************************************
 * Copyright 2013 Open mHealth
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package org.openmhealth.reference.concordia;

import java.util.Iterator;
import java.util.List;

import name.jenkins.paul.john.concordia.exception.ConcordiaException;
import name.jenkins.paul.john.concordia.schema.StringSchema;
import name.jenkins.paul.john.concordia.validator.DataValidator;
import name.jenkins.paul.john.concordia.validator.SchemaValidator;
import name.jenkins.paul.john.concordia.validator.ValidationController;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.NullNode;

/**
 * <p>
 * A type and data validator for enums within string schemas.
 * </p>
 *
 * @author John Jenkins
 */
public class EnumValidator implements SchemaValidator<StringSchema>, DataValidator<StringSchema> {

    /**
     * The schema field name for string schemas that may be present and, if so,
     * must be an array of strings that are valid values for this data.
     */
    public static final String ENUM_SCHEMA_FIELD = "allowed_values";

    /**
     * Verifies that if {@link #ENUM_SCHEMA_FIELD} exists, it is an array of
     * strings.
     * 
     * @param schema
     *        The {@link StringSchema} to validate.
     * 
     * @param controller
     *        The controller to use in the event that a sub-schema existed and
     *        needed to be validated as well.
     */
    @Override
    public void validate(final StringSchema schema, final ValidationController controller)
            throws ConcordiaException {

        // Attempt to get the enum definition.
        Object enumField = schema.getAdditionalFields().get(ENUM_SCHEMA_FIELD);

        // If the definition exists, validate it.
        if (enumField != null) {
            // It must be a JSON array.
            if (enumField instanceof List) {
                // Iterate through the elements.
                Iterator<?> enumFieldIter = ((List<?>) enumField).iterator();

                // Each element must be a string.
                while (enumFieldIter.hasNext()) {
                    if (!(enumFieldIter.next() instanceof String)) {
                        throw new ConcordiaException(
                                "An " + ENUM_SCHEMA_FIELD + " entry is not a string: " + enumField.toString());
                    }
                }
            }
            // It is not a JSON array.
            else {
                throw new ConcordiaException(
                        "The " + ENUM_SCHEMA_FIELD + " field list must be a JSON array: " + enumField.toString());
            }
        }
    }

    /**
     * Verifies that any data point for this schema is one of the required enum
     * values.
     * 
     * @param schema
     *        The schema to reference when validating the data.
     * 
     * @param data
     *        The data to validate.
     * 
     * @param controller
     *        The controller to use in the event that there is sub-data that
     *        also needed to be validated.
     */
    @Override
    public void validate(final StringSchema schema, final JsonNode data, final ValidationController controller)
            throws ConcordiaException {

        // If the data is null, we can ignore it because that value shouldn't
        // be in our list. Null will be caught by our default, required
        // validation, which will only allow this if the schema defines this
        // field as optional.
        if ((data == null) || (data instanceof NullNode)) {
            return;
        }

        // Get the value of this node.
        // We can also safely assume that this will return us a non-null value
        // as our default, required validation would have first run to ensure
        // that it is a TextNode.
        String value = data.textValue();

        // Attempt to get the enum definition.
        Object enumField = schema.getAdditionalFields().get(ENUM_SCHEMA_FIELD);

        // If the definition exists, validate it.
        if (enumField != null) {
            // We can safely cast here, because our validation above took care
            // of this for us.
            @SuppressWarnings("unchecked")
            List<String> enumFieldIter = (List<String>) enumField;

            // Check each of our allowed values against the given value.
            if (!enumFieldIter.contains(value)) {
                // If one was not found, throw an exception.
                throw new ConcordiaException("The value, '" + value + "', is not in our list of acceptable values: "
                        + enumField.toString());
            }
        }
    }
}