package com.instructure.canvasapi.api; import android.content.Context; import com.instructure.canvasapi.model.Assignment; import com.instructure.canvasapi.model.CanvasContext; import com.instructure.canvasapi.model.ToDo; import com.instructure.canvasapi.utilities.APIHelpers; import com.instructure.canvasapi.utilities.CanvasCallback; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import retrofit.Callback; import retrofit.client.Response; import retrofit.http.DELETE; import retrofit.http.GET; import retrofit.http.Path; /** * * Copyright (c) 2014 Instructure. All rights reserved. */ public class ToDoAPI extends BuildInterfaceAPI { interface ToDosInterface { @GET("/users/self/todo") void getUserTodos(Callback<ToDo[]> callback); @GET("/{context_id}/todo") void getCourseTodos(@Path("context_id") long context_id, Callback<ToDo[]> callback); @DELETE("/{path}") void dismissTodo(@Path(value = "path", encode = false)String path, CanvasCallback<Response>responseCallback); ///////////////////////////////////////////////////////////////////////////// // Synchronous ///////////////////////////////////////////////////////////////////////////// @GET("/{context_id}/todo") ToDo[] getCourseTodos(@Path("context_id") long courseID); @GET("/users/self/todo") ToDo[] getUserTodos(); } ///////////////////////////////////////////////////////////////////////// // API Calls ///////////////////////////////////////////////////////////////////////// public static void getUserTodos(CanvasCallback<ToDo[]> callback) { if (APIHelpers.paramIsNull(callback)) { return; } buildCacheInterface(ToDosInterface.class, callback, null).getUserTodos(callback); buildInterface(ToDosInterface.class, callback, null).getUserTodos(callback); } public static void getCourseTodos(CanvasContext canvasContext, CanvasCallback<ToDo[]> callback) { if (APIHelpers.paramIsNull(callback, canvasContext)) { return; } buildCacheInterface(ToDosInterface.class, callback, canvasContext).getCourseTodos(canvasContext.getId(), callback); buildInterface(ToDosInterface.class, callback, canvasContext).getCourseTodos(canvasContext.getId(), callback); } public static void getTodos(CanvasContext canvasContext, final CanvasCallback<ToDo[]> callback) { if (APIHelpers.paramIsNull(callback, canvasContext)) { return; } if (canvasContext.getType() == CanvasContext.Type.USER) { getUserTodos(callback); } else { getCourseTodos(canvasContext, callback); } } public static void dismissTodo(Context context, ToDo toDo, CanvasCallback<Response> callback) { if (APIHelpers.paramIsNull(callback, toDo)) return; String path = APIHelpers.removeDomainFromUrl(toDo.getIgnore()); buildInterface(ToDosInterface.class, callback, null).dismissTodo(path, callback); } ///////////////////////////////////////////////////////////////////////////// // Helper Methods ///////////////////////////////////////////////////////////////////////////// public static ArrayList<ToDo> mergeToDoUpcoming(ArrayList<ToDo> todos, ArrayList<ToDo> upcomingEvents) { if (todos == null && upcomingEvents == null) { return null; } if (todos == null) { todos = new ArrayList<ToDo>(); } if (upcomingEvents == null) { upcomingEvents = new ArrayList<ToDo>(); } //Add all Assignment ids from TODO HashMap<Long, Boolean> assignmentIds = new HashMap<Long, Boolean>(); for (ToDo toDo : todos) { if (toDo.getAssignment() != null) { assignmentIds.put(toDo.getAssignment().getId(), true); } } //If the hashmap contains any assignment ids from Upcoming, it's a duplicate Iterator<ToDo> iterator = upcomingEvents.iterator(); while (iterator.hasNext()) { ToDo current = iterator.next(); Assignment assignment = current.getScheduleItem().getAssignment(); if (assignment != null && assignmentIds.containsKey(assignment.getId())) { //We already have it in ToDo so remove the item. iterator.remove(); } } int todoIndex = 0; int upcomingIndex = 0; ArrayList<ToDo> merged = new ArrayList<ToDo>(); while (todoIndex < todos.size() || upcomingIndex < upcomingEvents.size()) { //We only have upcoming left. if (todoIndex >= todos.size()) { List<ToDo> subset = upcomingEvents.subList(upcomingIndex, upcomingEvents.size()); for (ToDo upcomming : subset) { merged.add(upcomming); } return merged; } //We only have todo left. if (upcomingIndex >= upcomingEvents.size()) { List<ToDo> subset = todos.subList(todoIndex, todos.size()); for (ToDo td : subset) { merged.add(td); } return merged; } //We need to determine which one comes sooner. Date toDoDate; if (todos.get(todoIndex).getAssignment() == null) { toDoDate = null; } else { toDoDate = todos.get(todoIndex).getAssignment().getDueDate(); } Date upcomingDate = upcomingEvents.get(upcomingIndex).getScheduleItem().getStartDate(); //handle null cases first if (toDoDate == null) { merged.add(upcomingEvents.get(upcomingIndex)); upcomingIndex++; } else if (upcomingDate == null) { merged.add(todos.get(todoIndex)); todoIndex++; } else if (toDoDate.before(upcomingDate)) { merged.add(todos.get(todoIndex)); todoIndex++; } else { merged.add(upcomingEvents.get(upcomingIndex)); upcomingIndex++; } } //Should never get here. return merged; } ///////////////////////////////////////////////////////////////////////////// // Synchronous // // If Retrofit is unable to parse (no network for example) Synchronous calls // will throw a nullPointer exception. All synchronous calls need to be in a // try catch block. ///////////////////////////////////////////////////////////////////////////// public static ToDo[] getTodosSynchronous(Context context, CanvasContext canvasContext) { if(context == null || canvasContext == null) { return null; } if (canvasContext.getType() == CanvasContext.Type.USER) { return getUserTodosSynchronous(context); } else { return getCourseTodosSynchronous(context, canvasContext); } } public static ToDo[] getUserTodosSynchronous(Context context) { if(context == null){ return null; } //If not able to parse (no network for example), this will crash. Handle that case. try { return buildInterface(ToDosInterface.class, context).getUserTodos(); } catch (Exception E){ return null; } } public static ToDo[] getCourseTodosSynchronous(Context context, CanvasContext canvasContext) { if(context == null || canvasContext == null) { return null; } //If not able to parse (no network for example), this will crash. Handle that case. try { return buildInterface(ToDosInterface.class, context, canvasContext).getCourseTodos(canvasContext.getId()); } catch (Exception E){ return null; } } }