/*******************************************************************************
* 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.data.mongodb;
import org.mongojack.DBCursor;
import org.mongojack.DBQuery;
import org.mongojack.DBQuery.Query;
import org.mongojack.JacksonDBCollection;
import org.mongojack.internal.MongoJackModule;
import org.openmhealth.reference.data.UserBin;
import org.openmhealth.reference.domain.Schema;
import org.openmhealth.reference.domain.User;
import org.openmhealth.reference.domain.mongodb.MongoUser;
import org.openmhealth.reference.exception.OmhException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.MongoException;
import com.mongodb.QueryBuilder;
/**
* <p>
* The MongoDB implementation of the interface to the database-backed
* collection of users.
* </p>
*
* @author John Jenkins
*/
public class MongoUserBin extends UserBin {
/**
* The object mapper that should be used to parse {@link Schema}s.
*/
private static final ObjectMapper JSON_MAPPER;
static {
// Create the object mapper.
ObjectMapper mapper = new ObjectMapper();
// Create the FilterProvider.
SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.setFailOnUnknownId(false);
mapper.setFilters(filterProvider);
// Finally, we must configure the mapper to work with the MongoJack
// configuration.
JSON_MAPPER = MongoJackModule.configure(mapper);
}
/**
* Default constructor that creates any tables and indexes if necessary.
*/
protected MongoUserBin() {
// Get the collection to add indexes to.
DBCollection collection =
MongoDao.getInstance().getDb().getCollection(DB_NAME);
// Ensure that there is an index on the username.
collection
.ensureIndex(
new BasicDBObject(User.JSON_KEY_USERNAME, 1),
DB_NAME + "_" + User.JSON_KEY_USERNAME + "_unique",
true);
// Ensure that there is an index on the username.
collection
.ensureIndex(
new BasicDBObject(User.JSON_KEY_REGISTRATION_KEY, 1),
DB_NAME + "_" + User.JSON_KEY_REGISTRATION_KEY,
false);
}
/*
* (non-Javadoc)
* @see org.openmhealth.reference.data.UserBin#createUser(org.openmhealth.reference.domain.User)
*/
@Override
public void createUser(final User user) throws OmhException {
// Validate the input.
if(user == null) {
throw new OmhException("The user is null.");
}
// Get the user collection.
JacksonDBCollection<User, Object> collection =
JacksonDBCollection
.wrap(
MongoDao.getInstance()
.getDb()
.getCollection(DB_NAME),
User.class,
Object.class,
JSON_MAPPER);
// Save the user.
try {
collection.insert(user);
}
catch(MongoException.DuplicateKey e) {
throw
new OmhException(
"A user with that username already exists.",
e);
}
}
/*
* (non-Javadoc)
* @see org.openmhealth.reference.data.UserBin#getUser(java.lang.String)
*/
@Override
public User getUser(final String username) throws OmhException {
// Validate the parameter.
if(username == null) {
throw new OmhException("The username is null.");
}
// Get the authentication token collection.
JacksonDBCollection<MongoUser, Object> collection =
JacksonDBCollection
.wrap(
MongoDao.getInstance()
.getDb()
.getCollection(DB_NAME),
MongoUser.class,
Object.class,
JSON_MAPPER);
// Build the query.
QueryBuilder queryBuilder = QueryBuilder.start();
// Add the authentication token to the query
queryBuilder.and(MongoUser.JSON_KEY_USERNAME).is(username);
// Execute query.
DBCursor<MongoUser> result = collection.find(queryBuilder.get());
// If multiple authentication tokens were returned, that is a violation
// of the system.
if(result.count() > 1) {
throw
new OmhException(
"Multiple users exist with the same username: " +
username);
}
// If no tokens were returned, then return null.
if(result.count() == 0) {
return null;
}
else {
return result.next();
}
}
/*
* (non-Javadoc)
* @see org.openmhealth.reference.data.UserBin#getUserFormRegistration(java.lang.String)
*/
@Override
public User getUserFromRegistrationId(
final String registrationId)
throws OmhException {
// Validate the parameter.
if(registrationId == null) {
throw new OmhException("The registration ID is null.");
}
// Get the authentication token collection.
JacksonDBCollection<MongoUser, Object> collection =
JacksonDBCollection
.wrap(
MongoDao.getInstance()
.getDb()
.getCollection(DB_NAME),
MongoUser.class,
Object.class,
JSON_MAPPER);
// Build the query.
QueryBuilder queryBuilder = QueryBuilder.start();
// Add the authentication token to the query
queryBuilder
.and(MongoUser.JSON_KEY_REGISTRATION_KEY)
.is(registrationId);
// Execute query.
DBCursor<MongoUser> result = collection.find(queryBuilder.get());
// If multiple authentication tokens were returned, that is a violation
// of the system.
if(result.count() > 1) {
throw
new OmhException(
"Multiple users exist with the same registration ID: " +
registrationId);
}
// If no tokens were returned, then return null.
if(result.count() == 0) {
return null;
}
else {
return result.next();
}
}
/*
* (non-Javadoc)
* @see org.openmhealth.reference.data.UserBin#updateUser(org.openmhealth.reference.domain.User)
*/
@Override
public void updateUser(final User user) throws OmhException {
// Validate the input.
if(user == null) {
throw new OmhException("The user is null.");
}
// Get the user collection.
JacksonDBCollection<User, Object> collection =
JacksonDBCollection
.wrap(
MongoDao.getInstance()
.getDb()
.getCollection(DB_NAME),
User.class,
Object.class,
JSON_MAPPER);
// Ensure that we are only updating the user with the same user-name.
Query query = DBQuery.is(User.JSON_KEY_USERNAME, user.getUsername());
// Save the user.
try {
collection.update(query, user);
}
catch(MongoException e) {
throw new OmhException("An internal error occurred.", e);
}
}
}