|
|
|
@ -5,11 +5,10 @@ import android.content.Context;
|
|
|
|
|
import com.google.api.client.extensions.android.http.AndroidHttp;
|
|
|
|
|
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
|
|
|
|
import com.google.api.client.http.HttpResponseException;
|
|
|
|
|
import com.google.api.client.json.GenericJson;
|
|
|
|
|
import com.google.api.client.json.gson.GsonFactory;
|
|
|
|
|
import com.google.api.services.tasks.Tasks;
|
|
|
|
|
import com.google.api.services.tasks.Tasks.TasksOperations.Insert;
|
|
|
|
|
import com.google.api.services.tasks.Tasks.TasksOperations.List;
|
|
|
|
|
import com.google.api.services.tasks.Tasks.TasksOperations.Move;
|
|
|
|
|
import com.google.api.services.tasks.TasksRequest;
|
|
|
|
|
import com.google.api.services.tasks.model.Task;
|
|
|
|
|
import com.google.api.services.tasks.model.TaskList;
|
|
|
|
|
import com.google.api.services.tasks.model.TaskLists;
|
|
|
|
@ -25,8 +24,8 @@ import java.io.IOException;
|
|
|
|
|
/**
|
|
|
|
|
* Wrapper around the official Google Tasks API to simplify common operations. In the case
|
|
|
|
|
* of an exception, each request is tried twice in case of a timeout.
|
|
|
|
|
* @author Sam Bosley
|
|
|
|
|
*
|
|
|
|
|
* @author Sam Bosley
|
|
|
|
|
*/
|
|
|
|
|
public class GtasksInvoker {
|
|
|
|
|
|
|
|
|
@ -56,9 +55,8 @@ public class GtasksInvoker {
|
|
|
|
|
//If we get a 401 or 403, try revalidating the auth token before bailing
|
|
|
|
|
private synchronized void handleException(IOException e) throws IOException {
|
|
|
|
|
if (e instanceof HttpResponseException) {
|
|
|
|
|
HttpResponseException h = (HttpResponseException)e;
|
|
|
|
|
HttpResponseException h = (HttpResponseException) e;
|
|
|
|
|
int statusCode = h.getStatusCode();
|
|
|
|
|
log.error(statusCode + ": " + h.getStatusMessage(), e);
|
|
|
|
|
if (statusCode == 401 || statusCode == 403) {
|
|
|
|
|
token = gtasksTokenValidator.validateAuthToken(ContextManager.getContext(), token);
|
|
|
|
|
if (token != null) {
|
|
|
|
@ -66,6 +64,8 @@ public class GtasksInvoker {
|
|
|
|
|
}
|
|
|
|
|
} else if (statusCode == 400 || statusCode == 500) {
|
|
|
|
|
throw h;
|
|
|
|
|
} else {
|
|
|
|
|
log.error(statusCode + ": " + h.getStatusMessage(), e);
|
|
|
|
|
}
|
|
|
|
|
// 503 errors are generally either 1) quota limit reached or 2) problems on Google's end
|
|
|
|
|
} else {
|
|
|
|
@ -73,177 +73,110 @@ public class GtasksInvoker {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void log(String method, Object result) {
|
|
|
|
|
System.err.println("QUERY: " + method + ", RESULT: " + result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A simple service query that will throw an exception if anything goes wrong.
|
|
|
|
|
* Useful for checking if token needs revalidating or if there are network problems--
|
|
|
|
|
* no exception means all is well
|
|
|
|
|
*
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public void ping() throws IOException {
|
|
|
|
|
service.tasklists().get("@default")
|
|
|
|
|
.setOauthToken(token)
|
|
|
|
|
service.tasklists()
|
|
|
|
|
.get("@default")
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public TaskLists allGtaskLists() throws IOException {
|
|
|
|
|
TaskLists toReturn = null;
|
|
|
|
|
try {
|
|
|
|
|
toReturn = service
|
|
|
|
|
return execute(service
|
|
|
|
|
.tasklists()
|
|
|
|
|
.list()
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
handleException(e);
|
|
|
|
|
toReturn = service.tasklists().list()
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} finally {
|
|
|
|
|
log("All gtasks lists", toReturn);
|
|
|
|
|
}
|
|
|
|
|
return toReturn;
|
|
|
|
|
.list());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public TaskList getGtaskList(String id) throws IOException {
|
|
|
|
|
TaskList toReturn = null;
|
|
|
|
|
try {
|
|
|
|
|
toReturn = service.tasklists().get(id)
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
handleException(e);
|
|
|
|
|
toReturn = service.tasklists().get(id)
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} finally {
|
|
|
|
|
log("Get gtask list, id: " + id, toReturn);
|
|
|
|
|
}
|
|
|
|
|
return toReturn;
|
|
|
|
|
return execute(service
|
|
|
|
|
.tasklists()
|
|
|
|
|
.get(id));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public TaskList createGtaskList(String title) throws IOException {
|
|
|
|
|
TaskList newList = new TaskList();
|
|
|
|
|
newList.setTitle(title);
|
|
|
|
|
TaskList toReturn = null;
|
|
|
|
|
try {
|
|
|
|
|
toReturn = service.tasklists().insert(newList)
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
handleException(e);
|
|
|
|
|
toReturn = service.tasklists().insert(newList)
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} finally {
|
|
|
|
|
log("Create gtask list, title: " + title, toReturn);
|
|
|
|
|
}
|
|
|
|
|
return toReturn;
|
|
|
|
|
return execute(service
|
|
|
|
|
.tasklists()
|
|
|
|
|
.insert(newList));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public com.google.api.services.tasks.model.Tasks getAllGtasksFromListId(String listId, boolean includeDeleted, boolean includeHidden, long lastSyncDate) throws IOException {
|
|
|
|
|
com.google.api.services.tasks.model.Tasks toReturn = null;
|
|
|
|
|
List request = service.tasks().list(listId);
|
|
|
|
|
request.setShowDeleted(includeDeleted);
|
|
|
|
|
request.setShowHidden(includeHidden);
|
|
|
|
|
request.setUpdatedMin(GtasksApiUtilities.unixTimeToGtasksCompletionTime(lastSyncDate).toStringRfc3339());
|
|
|
|
|
try {
|
|
|
|
|
toReturn = request
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
handleException(e);
|
|
|
|
|
toReturn = request
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} finally {
|
|
|
|
|
log("Get all tasks, list: " + listId + ", include deleted: " + includeDeleted, toReturn);
|
|
|
|
|
}
|
|
|
|
|
return toReturn;
|
|
|
|
|
return execute(service
|
|
|
|
|
.tasks()
|
|
|
|
|
.list(listId)
|
|
|
|
|
.setShowDeleted(includeDeleted)
|
|
|
|
|
.setShowHidden(includeHidden)
|
|
|
|
|
.setUpdatedMin(GtasksApiUtilities.unixTimeToGtasksCompletionTime(lastSyncDate).toStringRfc3339()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Task createGtask(String listId, Task task, String parent, String priorSiblingId) throws IOException {
|
|
|
|
|
Insert insertOp = service.tasks().insert(listId, task);
|
|
|
|
|
insertOp.setParent(parent);
|
|
|
|
|
insertOp.setPrevious(priorSiblingId);
|
|
|
|
|
|
|
|
|
|
Task toReturn = null;
|
|
|
|
|
try {
|
|
|
|
|
toReturn = insertOp
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
handleException(e);
|
|
|
|
|
toReturn = insertOp
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} finally {
|
|
|
|
|
log("Creating gtask, title: " + task.getTitle(), toReturn);
|
|
|
|
|
}
|
|
|
|
|
return toReturn;
|
|
|
|
|
return execute(service
|
|
|
|
|
.tasks()
|
|
|
|
|
.insert(listId, task)
|
|
|
|
|
.setParent(parent)
|
|
|
|
|
.setPrevious(priorSiblingId));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void updateGtask(String listId, Task task) throws IOException {
|
|
|
|
|
Task toReturn = null;
|
|
|
|
|
try {
|
|
|
|
|
toReturn = service
|
|
|
|
|
.tasks()
|
|
|
|
|
.update(listId, task.getId(), task)
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
handleException(e);
|
|
|
|
|
toReturn = service
|
|
|
|
|
execute(service
|
|
|
|
|
.tasks()
|
|
|
|
|
.update(listId, task.getId(), task)
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} finally {
|
|
|
|
|
log("Update gtask, title: " + task.getTitle(), toReturn);
|
|
|
|
|
}
|
|
|
|
|
.update(listId, task.getId(), task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Task moveGtask(String listId, String taskId, String parentId, String previousId) throws IOException {
|
|
|
|
|
Move move = service.tasks().move(listId, taskId);
|
|
|
|
|
move.setParent(parentId);
|
|
|
|
|
move.setPrevious(previousId);
|
|
|
|
|
return execute(service
|
|
|
|
|
.tasks()
|
|
|
|
|
.move(listId, taskId)
|
|
|
|
|
.setParent(parentId)
|
|
|
|
|
.setPrevious(previousId));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void deleteGtask(String listId, String taskId) throws IOException {
|
|
|
|
|
execute(service
|
|
|
|
|
.tasks()
|
|
|
|
|
.delete(listId, taskId));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Task toReturn = null;
|
|
|
|
|
private <T> T execute(TasksRequest<T> request) throws IOException {
|
|
|
|
|
String caller = getCaller();
|
|
|
|
|
log.debug("{} request: {}", caller, request);
|
|
|
|
|
T response;
|
|
|
|
|
try {
|
|
|
|
|
toReturn = move
|
|
|
|
|
response = request
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
handleException(e);
|
|
|
|
|
toReturn = move
|
|
|
|
|
response = request
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} finally {
|
|
|
|
|
log("Move task " + taskId + "to parent: " + parentId + ", prior sibling: " + previousId, toReturn);
|
|
|
|
|
}
|
|
|
|
|
return toReturn;
|
|
|
|
|
log.debug("{} response: {}", caller, prettyPrint(response));
|
|
|
|
|
return response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void deleteGtask(String listId, String taskId) throws IOException {
|
|
|
|
|
private <T> Object prettyPrint(T object) throws IOException {
|
|
|
|
|
if (log.isDebugEnabled() && object instanceof GenericJson) {
|
|
|
|
|
return ((GenericJson) object).toPrettyString();
|
|
|
|
|
}
|
|
|
|
|
return object;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String getCaller() {
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
try {
|
|
|
|
|
service
|
|
|
|
|
.tasks()
|
|
|
|
|
.delete(listId, taskId)
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
handleException(e);
|
|
|
|
|
service
|
|
|
|
|
.tasks()
|
|
|
|
|
.delete(listId, taskId)
|
|
|
|
|
.setKey(key)
|
|
|
|
|
.execute();
|
|
|
|
|
} finally {
|
|
|
|
|
log("Delete task, id: " + taskId, null);
|
|
|
|
|
return Thread.currentThread().getStackTrace()[4].getMethodName();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error(e.getMessage(), e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|