org.openmhealth.reference.request.DataWriteRequest.java Source code

Java tutorial

Introduction

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

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.openmhealth.reference.data.DataSet;
import org.openmhealth.reference.data.Registry;
import org.openmhealth.reference.domain.AuthenticationToken;
import org.openmhealth.reference.domain.Data;
import org.openmhealth.reference.domain.MetaData;
import org.openmhealth.reference.domain.MultiValueResult;
import org.openmhealth.reference.domain.Schema;
import org.openmhealth.reference.domain.User;
import org.openmhealth.reference.exception.InvalidAuthenticationException;
import org.openmhealth.reference.exception.OmhException;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MappingJsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * <p>
 * Stores the given data.
 * </p>
 *
 * @author John Jenkins
 */
public class DataWriteRequest extends Request<Object> {
    /**
     * The JSON factory that is used to create the parser that will be used to
     * parse the data.
     */
    private static final JsonFactory JSON_FACTORY = new MappingJsonFactory();

    /**
     * The authentication token for the requesting user.
     */
    private final AuthenticationToken authToken;
    /**
     * The ID of the schema from which the data was generated.
     */
    private final String schemaId;
    /**
     * The version of the schema from which the data was generated.
     */
    private final long version;
    /**
     * The data to validate and store.
     */
    private final String data;

    /**
     * Creates a request to store some data.
     * 
     * @param authToken
     *        The requesting user's authentication token.
     * 
     * @param schemaId
     *        The ID of the schema which should be used to validate the data.
     * 
     * @param version
     *        The version of the schema which should be used to validate the
     *        data.
     * 
     * @param data
     *        The data to validate and store.
     * 
     * @throws OmhException
     *         A parameter was invalid.
     */
    public DataWriteRequest(final AuthenticationToken authToken, final String schemaId, final long version,
            final String data) throws OmhException {

        if (authToken == null) {
            throw new InvalidAuthenticationException("The authentication token is missing.");
        }
        if (schemaId == null) {
            throw new OmhException("The schema ID is missing.");
        }
        if (data == null) {
            throw new OmhException("The data is missing.");
        }

        this.authToken = authToken;
        this.schemaId = schemaId;
        this.version = version;
        this.data = data;
    }

    /**
     * Validates the data and, if valid, stores it.
     */
    @Override
    public void service() throws OmhException {
        // First, short-circuit if this request has already been serviced.
        if (isServiced()) {
            return;
        } else {
            setServiced();
        }

        // Check to be sure the schema is known.
        MultiValueResult<? extends Schema> schemas = Registry.getInstance().getSchemas(schemaId, version, 0, 1);
        if (schemas.count() == 0) {
            throw new OmhException(
                    "The schema ID, '" + schemaId + "', and version, '" + version + "', pair is unknown.");
        }
        Schema schema = schemas.iterator().next();

        // Get the user that owns this token.
        User requestingUser = authToken.getUser();

        // Parse the data.
        JsonNode dataNode;
        try {
            dataNode = JSON_FACTORY.createJsonParser(data).readValueAs(JsonNode.class);
        } catch (JsonParseException e) {
            throw new OmhException("The data was not well-formed JSON.", e);
        } catch (JsonProcessingException e) {
            throw new OmhException("The data was not well-formed JSON.", e);
        } catch (IOException e) {
            throw new OmhException("The data could not be read.", e);
        }

        // Make sure it is a JSON array.
        if (!(dataNode instanceof ArrayNode)) {
            throw new OmhException("The data was not a JSON array.");
        }
        ArrayNode dataArray = (ArrayNode) dataNode;

        // Get the number of data points.
        int numDataPoints = dataArray.size();

        // Create the result list of data points.
        List<Data> dataPoints = new ArrayList<Data>(numDataPoints);

        // Create a new ObjectMapper that will be used to convert the meta-data
        // node into a MetaData object.
        ObjectMapper mapper = new ObjectMapper();

        // For each element in the array, be sure it is a JSON object that
        // represents a valid data point for this schema.
        for (int i = 0; i < numDataPoints; i++) {
            // Get the current data point.
            JsonNode dataPoint = dataArray.get(i);

            // Validate that it is a JSON object.
            if (!(dataPoint instanceof ObjectNode)) {
                throw new OmhException("A data point was not a JSON object: " + i);
            }
            ObjectNode dataObject = (ObjectNode) dataPoint;

            // Attempt to get the meta-data;
            MetaData metaData = null;
            JsonNode metaDataNode = dataObject.get(Data.JSON_KEY_METADATA);
            if (metaDataNode != null) {
                metaData = mapper.convertValue(metaDataNode, MetaData.class);
            }

            // Attempt to get the schema data.
            JsonNode schemaData = dataObject.get(Data.JSON_KEY_DATA);

            // If the data is missing, fail the request.
            if (schemaData == null) {
                throw new OmhException("A data point's '" + Data.JSON_KEY_DATA + "' field is missing.");
            }

            // Create and add the point to the set of data.
            dataPoints.add(schema.validateData(requestingUser.getUsername(), metaData, schemaData));
        }

        // Store the data.
        DataSet.getInstance().storeData(dataPoints);
    }
}