org.ohmage.request.event.EventReadRequest.java Source code

Java tutorial

Introduction

Here is the source code for org.ohmage.request.event.EventReadRequest.java

Source

/*******************************************************************************
 * Copyright 2012 The Regents of the University of California
 * 
 * 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.ohmage.request.event;

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

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.ohmage.annotator.Annotator.ErrorCode;
import org.ohmage.cache.PreferenceCache;
import org.ohmage.domain.ColumnKey;
import org.ohmage.domain.DataStream;
import org.ohmage.domain.DataStream.MetaData;
import org.ohmage.domain.Location.LocationColumnKey;
import org.ohmage.domain.MobilityPoint;
import org.ohmage.domain.MobilityPoint.MobilityColumnKey;
import org.ohmage.domain.MobilityPoint.SubType;
import org.ohmage.exception.CacheMissException;
import org.ohmage.exception.DomainException;
import org.ohmage.exception.InvalidRequestException;
import org.ohmage.exception.ServiceException;
import org.ohmage.exception.ValidationException;
import org.ohmage.request.InputKeys;
import org.ohmage.request.Request;
import org.ohmage.request.UserRequest.TokenLocation;
import org.ohmage.request.observer.StreamReadRequest;
import org.ohmage.routinesense.RoutineSense;
import org.ohmage.service.MobilityServices;
import org.ohmage.service.UserClassServices;
import org.ohmage.service.UserServices;
import org.ohmage.util.StringUtils;
import org.ohmage.validator.MobilityValidators;
import org.ohmage.validator.UserValidators;

/**
 * Reads the Mobility information about a user during a single day.<br />
 * <br />
 * <table border="1">
 *   <tr>
 *     <td>Parameter Name</td>
 *     <td>Description</td>
 *     <td>Required</td>
 *   </tr>
 *   <tr>
 *     <td>{@value org.ohmage.request.InputKeys#CLIENT}</td>
 *     <td>A string describing the client that is making this request.</td>
 *     <td>true</td>
 *   </tr>
 *   <tr>
 *     <td>{@value org.ohmage.request.InputKeys#DATE}</td>
 *     <td>The date for which the data is desired.</td>
 *     <td>true</td>
 *   </tr>
 *   <tr>
 *     <td>{@value org.ohmage.request.InputKeys#USERNAME}</td>
 *     <td>The username of the user for whom the data is desired. If omitted,
 *       the requesting user is used.</td>
 *     <td>false</td>
 *   </tr>
 *   <tr>
 *     <td>{@value org.ohmage.request.InputKeys#MOBILITY_WITH_SENSOR_DATA}
 *       </td>
 *     <td>A boolean flag indicating whether or not to include sensor data with
 *       each point. This includes things like the accelerometer data and the
 *       WiFi scan results.</td>
 *     <td>false</td>
 *   </tr>
 *   <tr>
 *     <td>{@value org.ohmage.request.InputKeys#COLUMN_LIST}
 *       </td>
 *     <td>A list of the columns to return data. The order in this list will be
 *       reflected in the resulting list. If omitted, the result will be all of
 *       the columns available.</td>
 *     <td>false</td>
 *   </tr>
 * </table>
 * 
 * @author John Jenkins
 */
public class EventReadRequest extends Request {
    private static final Logger LOGGER = Logger.getLogger(EventReadRequest.class);

    private static final Collection<ColumnKey> DEFAULT_COLUMNS;
    static {
        Collection<ColumnKey> columnKeys = new ArrayList<ColumnKey>();

        columnKeys.add(MobilityColumnKey.ID);
        columnKeys.add(MobilityColumnKey.MODE);
        columnKeys.add(MobilityColumnKey.TIME);
        columnKeys.add(MobilityColumnKey.TIMEZONE);
        columnKeys.add(MobilityColumnKey.TIMESTAMP);

        columnKeys.add(LocationColumnKey.STATUS);
        columnKeys.add(LocationColumnKey.LATITUDE);
        columnKeys.add(LocationColumnKey.LONGITUDE);
        columnKeys.add(LocationColumnKey.PROVIDER);
        columnKeys.add(LocationColumnKey.ACCURACY);
        columnKeys.add(LocationColumnKey.TIME);
        columnKeys.add(LocationColumnKey.TIMEZONE);

        DEFAULT_COLUMNS = Collections.unmodifiableCollection(columnKeys);
    }

    private final String username;
    private final DateTime startDate;

    private final StreamReadRequest regularReadRequest;
    private final StreamReadRequest extendedReadRequest;

    private final Collection<ColumnKey> columns;
    private final List<MobilityPoint> points;

    /**
     * Creates an Event read request.
     * 
     * @param httpRequest The HttpServletRequest with the parameters for this
     *                  request.
     * 
     * @throws InvalidRequestException Thrown if the parameters cannot be 
     *                            parsed.
     * 
     * @throws IOException There was an error reading from the request.
     */
    public EventReadRequest(HttpServletRequest httpRequest) throws IOException, InvalidRequestException {
        super(httpRequest, null);

        LOGGER.info("Creating an Event read request.");

        String tUsername = null;
        DateTime tStartDate = null;

        StreamReadRequest tRegularReadRequest = null;
        StreamReadRequest tExtendedReadRequest = null;

        Collection<ColumnKey> tColumns = null;

        if (!isFailed()) {
            try {
                String[] t;
                getParameters().keySet().size();
                t = getParameterValues(InputKeys.DATE);
                if (t.length == 0) {
                    throw new ValidationException(ErrorCode.SERVER_INVALID_DATE,
                            "The date value is missing: " + InputKeys.DATE);
                } else if (t.length == 1) {
                    tStartDate = MobilityValidators.validateDate(t[0]);

                    if (tStartDate == null) {
                        throw new ValidationException(ErrorCode.SERVER_INVALID_DATE,
                                "The date value is missing: " + InputKeys.DATE);
                    } else {
                        tStartDate = new DateTime(tStartDate.getYear(), tStartDate.getMonthOfYear(),
                                tStartDate.getDayOfMonth(), 0, 0, DateTimeZone.UTC);
                    }
                } else {
                    throw new ValidationException(ErrorCode.SERVER_INVALID_DATE,
                            "Multiple date values were given: " + InputKeys.DATE);
                }

                //            tColumns = null;
                //            
                //                     
                //            t = getParameterValues(InputKeys.MOBILITY_WITH_SENSOR_DATA);
                //            if(t.length > 1) {
                //               throw new ValidationException(
                //                     ErrorCode.MOBILITY_INVALID_INCLUDE_SENSOR_DATA_VALUE, 
                //                     "Multiple \"include sensor data\" values to query were given: " + 
                //                           InputKeys.MOBILITY_WITH_SENSOR_DATA);
                //            }
                //            else if(t.length == 1) {
                //               if(MobilityValidators.validateIncludeSensorDataValue(t[0])) {
                //                  tColumns = MobilityColumnKey.ALL_COLUMNS;
                //               }
                //            }
                //            
                //            t = getParameterValues(InputKeys.COLUMN_LIST);
                //            if(t.length > 1) {
                //               throw new ValidationException(
                //                     ErrorCode.MOBILITY_INVALID_COLUMN_LIST,
                //                     "Multiple column lists were given: " +
                //                           InputKeys.COLUMN_LIST);
                //            }
                //            else if(t.length == 1) {
                //               if(! StringUtils.isEmptyOrWhitespaceOnly(t[0])) {
                //                  if(tColumns == null) {
                //                     tColumns = 
                //                        MobilityValidators.validateColumns(
                //                              t[0],
                //                              true);
                //                  }
                //                  else {
                //                     throw new ValidationException(
                //                           ErrorCode.MOBILITY_INVALID_COLUMN_LIST,
                //                           "Both '" +
                //                              InputKeys.MOBILITY_WITH_SENSOR_DATA +
                //                              "' and '" +
                //                              InputKeys.COLUMN_LIST +
                //                              "' were present. Only one may be present.");
                //                  }
                //               }
                //            }
                //            if(tColumns == null) {
                //               tColumns = DEFAULT_COLUMNS;
                //            }

                // Get the user.
                t = getParameterValues(InputKeys.USERNAME);
                if (t.length > 1) {
                    throw new ValidationException(ErrorCode.USER_INVALID_USERNAME,
                            "Multiple usernames to query were given: " + InputKeys.USERNAME);
                } else if (t.length == 1) {
                    tUsername = UserValidators.validateUsername(t[0]);
                }

                // TODO forget all that stream nonsense, just call .NET from here

                // Always get all of the columns.
                try {
                    tRegularReadRequest = new StreamReadRequest(httpRequest, getParameterMap(), false,
                            TokenLocation.EITHER, false, tUsername, "edu.ucla.cens.Mobility", null, "regular",
                            2012050700, tStartDate.minusMinutes(10), tStartDate.plusDays(1), null, true, null,
                            null);

                    tExtendedReadRequest = new StreamReadRequest(httpRequest, getParameterMap(), false,
                            TokenLocation.EITHER, false, tUsername, "edu.ucla.cens.Mobility", null, "extended",
                            2012050700, tStartDate.minusMinutes(10), tStartDate.plusDays(1), null, true, null,
                            null);
                } catch (IllegalArgumentException e) {
                    throw new ValidationException("There was an error creating the request.", e);
                }
            } catch (ValidationException e) {
                e.failRequest(this);
                e.logException(LOGGER);
            }
        }

        username = tUsername;
        startDate = tStartDate;

        regularReadRequest = tRegularReadRequest;
        extendedReadRequest = tExtendedReadRequest;

        columns = tColumns;
        points = new ArrayList<MobilityPoint>();
    }

    /**
     * Services the request.
     */
    @Override
    public void service() {
        // If any of the sub-requests have failed, then return.
        if (regularReadRequest.isFailed() || extendedReadRequest.isFailed()) {
            return;
        }

        LOGGER.info("Servicing the Event read request.");

        try {
            if ((username != null) && (!username.equals(regularReadRequest.getUser().getUsername()))) {
                try {
                    LOGGER.info("Checking if the user is an admin.");
                    UserServices.instance().verifyUserIsAdmin(regularReadRequest.getUser().getUsername());
                } catch (ServiceException notAdmin) {
                    LOGGER.info("The user is not an admin.");

                    LOGGER.info("Checking if reading Mobility points about another user is even allowed.");
                    boolean isPlausible;
                    try {
                        isPlausible = StringUtils.decodeBoolean(PreferenceCache.instance().lookup(
                                PreferenceCache.KEY_PRIVILEGED_USER_IN_CLASS_CAN_VIEW_MOBILITY_FOR_EVERYONE_IN_CLASS));
                    } catch (CacheMissException e) {
                        throw new ServiceException(e);
                    }

                    if (isPlausible) {
                        LOGGER.info("Checking if the requester is allowed to read Mobility points about the user.");
                        UserClassServices.instance().userIsPrivilegedInAnotherUserClass(
                                regularReadRequest.getUser().getUsername(), username);
                    } else {
                        throw new ServiceException(ErrorCode.MOBILITY_INSUFFICIENT_PERMISSIONS,
                                "A user is not allowed to query Mobility information about another user.");
                    }
                }
            }
            LOGGER.info("Serviced the Event read request.");
            // Service the read requests.
            //         regularReadRequest.service();
            //         if(regularReadRequest.isFailed()) {
            //            return;
            //         }
            //         extendedReadRequest.service();
            //         if(extendedReadRequest.isFailed()) {
            //            return;
            //         }
            //         
            //         LOGGER.info("Aggregating the resulting points.");
            //         Collection<DataStream> regularResults = 
            //            regularReadRequest.getResults();
            //         for(DataStream dataStream : regularResults) {
            //            MetaData metaData = dataStream.getMetaData();
            //            if(metaData == null) {
            //               LOGGER.info("A Mobility point is missing meta-data.");
            //               continue;
            //            }
            //            
            //            DateTime timestamp = metaData.getTimestamp();
            //            if(timestamp == null) {
            //               LOGGER.info(
            //                  "A Mobility point is missing a timestamp: " +
            //                     metaData.getId());
            //               continue;
            //            }
            //            
            //            try {
            //               points.add(
            //                  new MobilityPoint(
            //                     dataStream, 
            //                     SubType.MODE_ONLY,
            //                     MobilityPoint.PrivacyState.PRIVATE));
            //            }
            //            catch(DomainException e) {
            //               throw new ServiceException(
            //                  "One of the points was invalid.",
            //                  e);
            //            }
            //         }
            //
            //         Collection<DataStream> extendedResults = 
            //            extendedReadRequest.getResults();
            //         for(DataStream dataStream : extendedResults) {
            //            MetaData metaData = dataStream.getMetaData();
            //            if(metaData == null) {
            //               LOGGER.info("A Mobility point is missing meta-data.");
            //               continue;
            //            }
            //            
            //            DateTime timestamp = metaData.getTimestamp();
            //            if(timestamp == null) {
            //               LOGGER.info(
            //                  "A Mobility point is missing a timestamp: " +
            //                     metaData.getId());
            //               continue;
            //            }
            //            
            //            try {
            //               points.add(
            //                  new MobilityPoint(
            //                     dataStream, 
            //                     SubType.SENSOR_DATA,
            //                     MobilityPoint.PrivacyState.PRIVATE));
            //            }
            //            catch(DomainException e) {
            //               throw new ServiceException(
            //                  "One of the points was invalid.",
            //                  e);
            //            }
            //         }
            //         
            //         LOGGER.info("Sorting the aggregated points.");
            //         Collections.sort(points);
            //         
            //         // Run them through the classifier.
            //         LOGGER.info("Classifying the points.");
            //         MobilityServices.instance().classifyData(
            //            regularReadRequest.getUser().getUsername(),
            //            points);
        } catch (ServiceException e) {
            e.failRequest(this);
            e.logException(LOGGER);
        }
    }

    /**
     * Responds to the request.
     */
    @Override
    public void respond(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
        LOGGER.info("Responding to the Event read request.");

        if (isFailed()) {
            super.respond(httpRequest, httpResponse, null);
        } else if (regularReadRequest.isFailed()) {
            regularReadRequest.respond(httpRequest, httpResponse);
        } else if (extendedReadRequest.isFailed()) {
            extendedReadRequest.respond(httpRequest, httpResponse);
        }

        JSONObject resultObject = new JSONObject();
        try {
            //         JSONArray resultArray = new JSONArray();
            //         long startDateMillis = startDate.getMillis();
            //         for(MobilityPoint mobilityPoint : points) {
            //            if((mobilityPoint.getTime() + mobilityPoint.getTimezone().getOffset(mobilityPoint.getTime()))>= startDateMillis) {
            //               resultArray.put(mobilityPoint.toJson(true, columns));
            //            }
            //         }
            //         resultObject.put(JSON_KEY_DATA, resultArray);
            String eventJSON = RoutineSense.getDayEvents(username, startDate);
            resultObject.put(JSON_KEY_DATA, new JSONObject(eventJSON));
        } catch (JSONException e) {
            LOGGER.error("Error creating the JSONObject.", e);
            setFailed();
        }
        //      catch(DomainException e) {
        //         LOGGER.error("Error creating the JSONObject.", e);
        //         setFailed();
        //      }

        super.respond(httpRequest, httpResponse, resultObject);
    }
}