/* * Copyright 2009 Google Inc. * * 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 com.google.appengine.demos.taskengine.server; import com.google.appengine.api.users.User; import com.google.appengine.api.users.UserService; import com.google.appengine.api.users.UserServiceFactory; import com.google.appengine.demos.taskengine.client.TasksApi; import com.google.appengine.demos.taskengine.shared.Task; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import java.util.HashMap; import java.util.List; import javax.jdo.JDOHelper; import javax.jdo.PersistenceManager; import javax.jdo.PersistenceManagerFactory; import javax.jdo.Query; import javax.jdo.Transaction; /** * Implementation of Tasks API. */ @SuppressWarnings("serial") public class TasksApiImpl extends RemoteServiceServlet implements TasksApi { private final PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory("transactions-optional"); public String deleteTasks(String[] tasksToDelete) { UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); String lastTaskDeletedId = null; String email = null; if (user != null) { email = user.getEmail(); PersistenceManager pm = pmf.getPersistenceManager(); List<Task> tasks = getPersistedTasksForUser(email, pm); // AppEngine datastore does not allow multiple conditional operators. So // we need to select all tasks for this user and then do our own hash // join. HashMap<String, Task> managedTaskHash = new HashMap<String, Task>(); for (int i = 0; i < tasks.size(); i++) { Task task = tasks.get(i); managedTaskHash.put(task.getId(), task); } // Delete the tasks we need to delete. for (int i = 0; i < tasksToDelete.length; i++) { String idOfTaskToDelete = tasksToDelete[i]; Object toDelete = managedTaskHash.get(idOfTaskToDelete); if (toDelete != null) { pm.deletePersistent(toDelete); // We want to return at least one non-null String Id as a weak // indication that the deletes happened. lastTaskDeletedId = idOfTaskToDelete; } } pm.close(); } return lastTaskDeletedId; } public String getLoginUrl() { UserService userService = UserServiceFactory.getUserService(); return userService.createLoginURL(getAppUrl()); } public Task[] getTaskList() { UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); String email = null; if (user != null) { email = user.getEmail(); PersistenceManager pm = pmf.getPersistenceManager(); List<Task> detachedTasks = null; List<Task> persistedTasks = getPersistedTasksForUser(email, pm); detachedTasks = (List<Task>) pm.detachCopyAll(persistedTasks); pm.close(); // This pattern is not the cleanest. But so that we don't have to create // another GWT serializable wrapper type, we reuse the TaskData type and // simply special case the first entry in the returned array to have // meta data about the logged in user. Task metaTask = new Task(); metaTask.setEmail(email); metaTask.setDetails(userService.createLogoutURL( userService.createLoginURL(getAppUrl()))); detachedTasks.add(0, metaTask); return detachedTasks.toArray(new Task[0]); } else { return null; } } public String persistTask(Task task) { UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); String email = null; if (user != null) { email = user.getEmail(); task.setEmail(email); if (task.getId() == null) { // We are adding a new Task to the data store return persistNewTask(task); } else { // We need to update an existing record return updateExistingTask(task); } } // User not logged in return null; } private String getAppUrl() { String servletUrl = getThreadLocalRequest().getRequestURL().toString(); String resourcePath = getThreadLocalRequest().getRequestURI(); return servletUrl.replace(resourcePath, ""); } @SuppressWarnings("unchecked") private List<Task> getPersistedTasksForUser(String email, PersistenceManager pm) { Query q = pm.newQuery(Task.class, "email == email_address"); q.declareParameters("java.lang.String email_address"); List<Task> persistedTasks = (List<Task>) q.execute(email); return persistedTasks; } private String persistNewTask(Task newTask) { PersistenceManager pm = pmf.getPersistenceManager(); pm.makePersistent(newTask); pm.close(); return newTask.getId(); } private String updateExistingTask(Task existingTask) { String taskId = null; PersistenceManager pm = pmf.getPersistenceManager(); Transaction tx = pm.currentTransaction(); try { tx.begin(); Task managedTask = (Task) pm.getObjectById(Task.class, existingTask.getId()); if (managedTask != null) { managedTask.setEmail(existingTask.getEmail()); managedTask.setTitle(existingTask.getTitle()); managedTask.setDetails(existingTask.getDetails()); managedTask.setFinished(existingTask.isFinished()); managedTask.setLabelPriority(existingTask.getLabelPriority()); taskId = managedTask.getId(); } tx.commit(); } catch (Exception e) { if (tx.isActive()) { tx.rollback(); } } finally { pm.close(); } return taskId; } }