org.openmhealth.reference.domain.Schema.java Source code

Java tutorial

Introduction

Here is the source code for org.openmhealth.reference.domain.Schema.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.domain;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.regex.Pattern;

import name.jenkins.paul.john.concordia.Concordia;
import name.jenkins.paul.john.concordia.exception.ConcordiaException;
import name.jenkins.paul.john.concordia.validator.ValidationController;

import org.openmhealth.reference.exception.OmhException;

import com.fasterxml.jackson.annotation.JacksonInject;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;

/**
 * <p>
 * A schema as defined by the Open mHealth specification.
 * </p>
 * 
 * <p>
 * This class is immutable.
 * </p>
 * 
 * @author John Jenkins
 */
public class Schema implements OmhObject {
    /**
     * The version of this class for serialization purposes.
     */
    private static final long serialVersionUID = 1L;

    /**
     * The pattern to use for validating schema IDs.
     */
    private static final Pattern PATTERN_ID = Pattern.compile("omh(:[a-zA-Z0-9_]+)+");

    /**
     * The JSON key for the ID of a schema.
     */
    public static final String JSON_KEY_ID = "schema_id";
    /**
     * The JSON key for the version of the schema.
     */
    public static final String JSON_KEY_VERSION = "schema_version";
    /**
     * The JSON key for the Concordia schema.
     */
    public static final String JSON_KEY_SCHEMA = "schema";
    /**
     * The JSON key for the {@link ValidationController} that will be used to
     * build the underlying {@link Concordia} object. If not set or not given,
     * the default one, {@link ValidationController#BASIC_CONTROLLER} will be
     * used.
     */
    public static final String JSON_KEY_VALIDATION_CONTROLLER = "validation_controller";

    /**
     * The schema's ID.
     */
    @JsonProperty(JSON_KEY_ID)
    private final String id;
    /**
     * The schema's version.
     */
    @JsonProperty(JSON_KEY_VERSION)
    private final long version;
    /**
     * The actual schema for this {@link Schema} object.
     */
    @JsonProperty(JSON_KEY_SCHEMA)
    private final Concordia schema;

    /**
     * Creates a new schema (registry entry).
     * 
     * @param id
     *        The ID for this schema.
     * 
     * @param version
     *        The version of this schema.
     * 
     * @param schema
     *        The specific schema.
     *        
     * @param controller
     *        The controller used to validate this schema and to validate any
     *        data when using the
     *        {@link #validateData(String, MetaData, JsonNode)} method.
     * 
     * @throws OmhException
     *         A parameter was invalid.
     *
     * @see #validateData(String, MetaData, JsonNode)
     */
    @JsonCreator
    public Schema(@JsonProperty(JSON_KEY_ID) final String id, @JsonProperty(JSON_KEY_VERSION) final long version,
            @JsonProperty(JSON_KEY_SCHEMA) final JsonNode schema,
            @JacksonInject(JSON_KEY_VALIDATION_CONTROLLER) final ValidationController controller)
            throws OmhException {

        // Validate the ID.
        if (id == null) {
            throw new OmhException("The ID is null.");
        } else if (id.trim().length() == 0) {
            throw new OmhException("The ID is empty.");
        } else {
            this.id = validateId(id);
        }

        // Validate the version.
        this.version = validateVersion(version);

        // Make sure the schema is not null.
        if (schema == null) {
            throw new OmhException("The schema is null.");
        }
        try {
            this.schema = new Concordia(new ByteArrayInputStream(schema.toString().getBytes()), controller);
        } catch (IllegalArgumentException e) {
            throw new OmhException("The schema is missing.", e);
        } catch (ConcordiaException e) {
            throw new OmhException("The schema is invalid.", e);
        } catch (IOException e) {
            throw new OmhException("The schema cannot be read.", e);
        }
    }

    /**
     * Returns the unique identifier for this schema.
     * 
     * @return The unique identifier for this schema.
     */
    public String getId() {
        return id;
    }

    /**
     * Returns the version of this schema.
     * 
     * @return The version of this schema.
     */
    public long getVersion() {
        return version;
    }

    /**
     * Returns the schema.
     * 
     * @return The schema.
     */
    public Concordia getSchema() {
        return schema;
    }

    /**
     * Validates some data.
     * 
     * @param owner
     *        The owner of the data that is being validated. This is needed to
     *        build the {@link Data} object.
     * 
     * @param metaData
     *        The meta-data for the data that is being validated. This is
     *        needed to build the {@link Data} object.
     * 
     * @param data
     *        The data to be validated.
     * 
     * @return The validated data as a {@link Data} object.
     * 
     * @throws OmhException
     *         The data was null or invalid.
     */
    public Data validateData(final String owner, final MetaData metaData, final JsonNode data) throws OmhException {

        // Ensure the data is not null.
        if (data == null) {
            throw new OmhException("The data field is null.");
        }

        // Validate the data.
        try {
            schema.validateData(data);
        } catch (ConcordiaException e) {
            throw new OmhException("The data is invalid.", e);
        }

        // Return the result.
        return new Data(owner, this, metaData, data);
    }

    /**
     * Validates that the ID follows our rules.
     * 
     * @param id
     *        The ID to be validated.
     * 
     * @return The validated and, potentially, simplified schema, e.g. trimmed.
     * 
     * @throws OmhException
     *         The ID is invalid.
     */
    public static String validateId(final String id) throws OmhException {
        // Validate that the ID is not null.
        if (id == null) {
            throw new OmhException("The ID is null.");
        }

        // Remove surrounding whitespace.
        String idTrimmed = id.trim();

        // Validate that the ID is not empty or only whitespace.
        if (idTrimmed.length() == 0) {
            throw new OmhException("The ID is empty or only whitespace.");
        }

        // Validate that the trimmed ID matches the pattern.
        if (!PATTERN_ID.matcher(idTrimmed).matches()) {
            throw new OmhException(
                    "The schema ID is invalid. It must be colon " + "deliminated, alphanumeric sections, with or "
                            + "without underscores, where the first section is " + "\"omh\": " + idTrimmed);
        }

        // Return the trimmed ID.
        return idTrimmed;
    }

    /**
     * Validates that the version follows our rules.
     * 
     * @param version
     *        The version to be validated.
     * 
     * @return The version as it was given.
     * 
     * @throws OmhException
     *         The version is invalid.
     */
    public static long validateVersion(final long version) throws OmhException {

        // The version must be positive.
        if (version <= 0) {
            throw new OmhException("The version must be positive.");
        }

        return version;
    }

    /**
     * Validates that the chunk size follows our rules.
     * 
     * @param chunkSize
     *        The chunk size to validate.
     * 
     * @return The chunk size as it was given.
     * 
     * @throws OmhException
     *         The chunk size is invalid.
     */
    public static long validateChunkSize(final long chunkSize) throws OmhException {

        // The chunk size must be positive.
        if (chunkSize <= 0) {
            throw new OmhException("The chunk size must be positive.");
        }

        return chunkSize;
    }
}