/*******************************************************************************
* 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.util.HashMap;
import java.util.List;
import java.util.Map;
import org.openmhealth.reference.data.DataSet;
import org.openmhealth.reference.data.Registry;
import org.openmhealth.reference.domain.AuthenticationToken;
import org.openmhealth.reference.domain.AuthorizationToken;
import org.openmhealth.reference.domain.ColumnList;
import org.openmhealth.reference.domain.Data;
import org.openmhealth.reference.domain.MultiValueResult;
import org.openmhealth.reference.exception.InvalidAuthenticationException;
import org.openmhealth.reference.exception.InvalidAuthorizationException;
import org.openmhealth.reference.exception.NoSuchSchemaException;
import org.openmhealth.reference.exception.OmhException;
import org.openmhealth.reference.servlet.Version1;
/**
* <p>
* Retrieves data based on the given parameters.
* </p>
*
* @author John Jenkins
*/
public class DataReadRequest extends ListRequest<Data> {
/**
* The authentication token for the requesting user.
*/
private final AuthenticationToken authenticationToken;
/**
* The authorization token for the requesting third-party.
*/
private final AuthorizationToken authorizationToken;
/**
* 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 identifier for the user to which the data should belong.
*/
private final String owner;
/**
* The list of columns to select from the data.
*/
private final ColumnList columnList;
/**
* Creates a request for data.
*
* @param authenticationToken The requesting user's authentication token.
*
* @param authorizationToken The third-party's authorization token.
*
* @param schemaId The ID of the schema from which the data was generated.
*
* @param version The version of the schema from which the data was
* generated.
*
* @param owner Defines whose data should be read.
*
* @param columnList The list of columns in the data to return.
*
* @param numToSkip The number of data points to skip.
*
* @param numToReturn The number of data points to return.
*
* @throws OmhException A parameter was invalid.
*/
public DataReadRequest(
final AuthenticationToken authenticationToken,
final AuthorizationToken authorizationToken,
final String schemaId,
final long version,
final String owner,
final List<String> columnList,
final Long numToSkip,
final Long numToReturn)
throws OmhException {
super(numToSkip, numToReturn);
if(authenticationToken == null) {
throw
new InvalidAuthenticationException(
"No authentication token was provided.");
}
if(schemaId == null) {
throw new OmhException("The schema ID is missing.");
}
this.authenticationToken = authenticationToken;
this.authorizationToken = authorizationToken;
this.schemaId = schemaId;
this.version = version;
this.columnList = new ColumnList(columnList);
if(owner == null) {
this.owner = authenticationToken.getUsername();
}
else {
this.owner = owner;
}
}
/**
* Authenticates the user, authorizes the request if it was for data that
* belongs to a different user, and retrieves the applicable data.
*/
@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.
if(
Registry
.getInstance()
.getSchemas(schemaId, version, 0, 1).count() == 0) {
throw
new NoSuchSchemaException(
"The schema ID, '" +
schemaId +
"', and version, '" +
version +
"', pair is unknown.");
}
// If the owner value is not the same as the requesting user, validate
// that the authorization token grants them access.
if(! authenticationToken.getUsername().equals(owner)) {
// Ensure that the given authorization token grants access to the
// given schema.
if(
! authorizationToken
.getAuthorizationCode()
.getScopes()
.contains(schemaId)) {
throw
new InvalidAuthorizationException(
"The authorization token does not grant access to " +
"the given schema: " +
schemaId);
}
// Ensure that the given authorization token grants access to the
// user in question.
if(
! authorizationToken
.getAuthorizationCodeVerification()
.getOwnerUsername()
.equals(owner)) {
throw
new InvalidAuthorizationException(
"The authorization token does not grant access to " +
"the given user's data: " +
owner);
}
}
// Get the data.
MultiValueResult<Data> result =
DataSet
.getInstance()
.getData(
owner,
schemaId,
version,
columnList,
getNumToSkip(),
getNumToReturn());
// Set the meta-data.
Map<String, Object> metaData = new HashMap<String, Object>();
metaData.put(METADATA_KEY_COUNT, result.count());
setMetaData(metaData);
// Set the data.
setData(result);
}
/*
* (non-Javadoc)
* @see org.openmhealth.reference.request.ListRequest#getPreviousNextParameters()
*/
@Override
public Map<String, String> getPreviousNextParameters() {
// Create the result map.
Map<String, String> result = new HashMap<String, String>();
// Add the owner if it's not the requesting user.
if(! authenticationToken.getUsername().equals(owner)) {
result.put(Version1.PARAM_OWNER, owner);
}
// Add the columns if they were given.
if((columnList != null) && (columnList.size() > 0)) {
result.put(Version1.PARAM_COLUMN_LIST, columnList.toString());
}
// Return the map.
return result;
}
}