package gettasky.storage.mongodb;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.bson.types.ObjectId;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import gettasky.domain.Task;
import gettasky.storage.StorageException;
import gettasky.storage.TaskStorage;
/*
* Task storage using MongoDB.
*/
public class MongoTaskStorage implements TaskStorage
{
private static final String TASK_COLLECTION_NAME = "tasks";
/**
* Return whether the task collection is empty.
* (MongoDB will create an empty task collection if there wasn't one previously.)
*/
@Override
public boolean isEmpty() throws StorageException
{
return getTaskCollection().count() == 0;
}
/**
* If the given task has no id, add it to the database.
* If it had an id, update it in the database.
*/
@Override
public void save(Task task) throws StorageException
{
BasicDBObject doc = new BasicDBObject();
doc.put("description", task.getDescription());
doc.put("priority", task.getPriority().getNumericValue());
doc.put("tags", task.getTags());
doc.put("is completed", task.isCompleted());
if (task.getId() != null)
{
doc.put("_id", new ObjectId(task.getId()));
}
// Upsert. That is, update if it exists in the database already;
// insert it if it does not exist in the database.
getTaskCollection().save(doc);
}
/**
* Delete all completed tasks.
*/
@Override
public void deleteCompletedTasks() throws StorageException
{
BasicDBObject query = new BasicDBObject();
query.put("is completed", true);
getTaskCollection().remove(query);
}
/**
* Return all the tasks in the database.
*/
@Override
public Task[] findAllTasks() throws StorageException
{
return tasksFromCursor(getTaskCollection().find());
}
/**
* Return the tasks that have the given tag.
*
* @param tag The tag to search on.
*/
@Override
public Task[] findTasksWithTag(String tag) throws StorageException
{
BasicDBObject query = new BasicDBObject();
query.put("tags", tag);
return tasksFromCursor(getTaskCollection().find(query));
}
/**
* Return all the tags used in tasks in the database.
*
* @return All tags without duplicates.
*/
@Override
public String[] findAllTags() throws StorageException
{
DBObject keys = new BasicDBObject();
keys.put("tags", 1);
DBCursor cursor = getTaskCollection().find(new BasicDBObject(), keys);
Map<String, String> tagMap = new TreeMap<String, String>();
for (DBObject doc : cursor)
{
BasicDBList tags = (BasicDBList) doc.get("tags");
for (Object obj : tags)
{
String tag = (String) obj;
tagMap.put(tag, tag);
}
}
cursor.close();
return tagMap.values().toArray(new String[tagMap.size()]);
}
/**
* Return the task collection. MongoDB will create it if it doesn't exist.
*/
private DBCollection getTaskCollection() throws StorageException
{
return ConnectionFactory.getConnection().getCollection(TASK_COLLECTION_NAME);
}
/**
* The given cursor is the result of a search returning tasks in document form.
* Return the tasks in domain form.
*
* @param cursor The cursor resulting from a search returning tasks.
*
* @return The tasks matching the search represented by the cursor.
*/
private Task[] tasksFromCursor(DBCursor cursor)
{
List<Task> tasks = new ArrayList<Task>();
for (DBObject doc : cursor)
{
tasks.add(taskFromDocument(doc));
}
cursor.close(); // dunno whether this is needed
return tasks.toArray(new Task[tasks.size()]);
}
/**
* Return a task mapped from the given MongoDB document.
*/
private static Task taskFromDocument(DBObject taskDoc)
{
Task task = new Task((String) taskDoc.get("description"));
Integer priorityInteger = (Integer) taskDoc.get("priority");
int priorityInt = priorityInteger.intValue();
task.setPriority(Task.Priority.valueOf(priorityInt));
Boolean isCompletedObject = (Boolean) taskDoc.get("is completed");
task.setCompleted(isCompletedObject.booleanValue());
BasicDBList tags = (BasicDBList) taskDoc.get("tags");
for (Object obj : tags)
{
String tag = (String) obj;
task.addTag(tag);
}
ObjectId id = (ObjectId) taskDoc.get("_id");
task.setId(id.toString());
return task;
}
}