001package com.box.sdk; 002 003import java.net.URL; 004import java.text.ParseException; 005import java.util.ArrayList; 006import java.util.Date; 007import java.util.Iterator; 008import java.util.List; 009 010import com.eclipsesource.json.JsonArray; 011import com.eclipsesource.json.JsonObject; 012import com.eclipsesource.json.JsonValue; 013 014/** 015 * Represents a task on Box. Tasks can have a due date and can be assigned to a specific user. 016 */ 017@BoxResourceType("task") 018public class BoxTask extends BoxResource { 019 020 /** 021 * Task URL Template. 022 */ 023 public static final URLTemplate TASK_URL_TEMPLATE = new URLTemplate("tasks/%s"); 024 /** 025 * Get Assignments URL Template. 026 */ 027 public static final URLTemplate GET_ASSIGNMENTS_URL_TEMPLATE = new URLTemplate("tasks/%s/assignments"); 028 /** 029 * Add Task Assignment URL Template. 030 */ 031 public static final URLTemplate ADD_TASK_ASSIGNMENT_URL_TEMPLATE = new URLTemplate("task_assignments"); 032 033 /** 034 * Constructs a BoxTask for a task with a given ID. 035 * @param api the API connection to be used by the task. 036 * @param id the ID of the task. 037 */ 038 public BoxTask(BoxAPIConnection api, String id) { 039 super(api, id); 040 } 041 042 /** 043 * Deletes this task. 044 */ 045 public void delete() { 046 URL url = TASK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 047 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 048 BoxAPIResponse response = request.send(); 049 response.disconnect(); 050 } 051 052 /** 053 * Adds a new assignment to this task. 054 * @param assignTo the user to assign the assignment to. 055 * @return information about the newly added task assignment. 056 */ 057 public BoxTaskAssignment.Info addAssignment(BoxUser assignTo) { 058 JsonObject taskJSON = new JsonObject(); 059 taskJSON.add("type", "task"); 060 taskJSON.add("id", this.getID()); 061 062 JsonObject assignToJSON = new JsonObject(); 063 assignToJSON.add("id", assignTo.getID()); 064 065 JsonObject requestJSON = new JsonObject(); 066 requestJSON.add("task", taskJSON); 067 requestJSON.add("assign_to", assignToJSON); 068 069 URL url = ADD_TASK_ASSIGNMENT_URL_TEMPLATE.build(this.getAPI().getBaseURL()); 070 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 071 request.setBody(requestJSON.toString()); 072 BoxJSONResponse response = (BoxJSONResponse) request.send(); 073 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 074 075 BoxTaskAssignment addedAssignment = new BoxTaskAssignment(this.getAPI(), responseJSON.get("id").asString()); 076 return addedAssignment.new Info(responseJSON); 077 } 078 079 /** 080 * Adds a new assignment to this task using user's login as identifier. 081 * @param assignToLogin the login of user to assign the task to. 082 * @return information about the newly added task assignment. 083 */ 084 public BoxTaskAssignment.Info addAssignmentByLogin(String assignToLogin) { 085 JsonObject taskJSON = new JsonObject(); 086 taskJSON.add("type", "task"); 087 taskJSON.add("id", this.getID()); 088 089 JsonObject assignToJSON = new JsonObject(); 090 assignToJSON.add("login", assignToLogin); 091 092 JsonObject requestJSON = new JsonObject(); 093 requestJSON.add("task", taskJSON); 094 requestJSON.add("assign_to", assignToJSON); 095 096 URL url = ADD_TASK_ASSIGNMENT_URL_TEMPLATE.build(this.getAPI().getBaseURL()); 097 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 098 request.setBody(requestJSON.toString()); 099 BoxJSONResponse response = (BoxJSONResponse) request.send(); 100 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 101 102 BoxTaskAssignment addedAssignment = new BoxTaskAssignment(this.getAPI(), responseJSON.get("id").asString()); 103 return addedAssignment.new Info(responseJSON); 104 } 105 106 /** 107 * Gets any assignments for this task. 108 * @return a list of assignments for this task. 109 */ 110 public List<BoxTaskAssignment.Info> getAssignments() { 111 URL url = GET_ASSIGNMENTS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 112 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 113 BoxJSONResponse response = (BoxJSONResponse) request.send(); 114 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 115 116 int totalCount = responseJSON.get("total_count").asInt(); 117 List<BoxTaskAssignment.Info> assignments = new ArrayList<BoxTaskAssignment.Info>(totalCount); 118 JsonArray entries = responseJSON.get("entries").asArray(); 119 for (JsonValue value : entries) { 120 JsonObject assignmentJSON = value.asObject(); 121 BoxTaskAssignment assignment = new BoxTaskAssignment(this.getAPI(), assignmentJSON.get("id").asString()); 122 BoxTaskAssignment.Info info = assignment.new Info(assignmentJSON); 123 assignments.add(info); 124 } 125 126 return assignments; 127 } 128 129 /** 130 * Gets an iterable of all the assignments of this task. 131 * @param fields the fields to retrieve. 132 * @return an iterable containing info about all the assignments. 133 */ 134 public Iterable<BoxTaskAssignment.Info> getAllAssignments(String ... fields) { 135 final QueryStringBuilder builder = new QueryStringBuilder(); 136 if (fields.length > 0) { 137 builder.appendParam("fields", fields); 138 } 139 return new Iterable<BoxTaskAssignment.Info>() { 140 public Iterator<BoxTaskAssignment.Info> iterator() { 141 URL url = GET_ASSIGNMENTS_URL_TEMPLATE.buildWithQuery( 142 BoxTask.this.getAPI().getBaseURL(), builder.toString(), BoxTask.this.getID()); 143 return new BoxTaskAssignmentIterator(BoxTask.this.getAPI(), url); 144 } 145 }; 146 } 147 148 /** 149 * Gets information about this task. 150 * @return info about this task. 151 */ 152 public Info getInfo() { 153 URL url = TASK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 154 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 155 BoxJSONResponse response = (BoxJSONResponse) request.send(); 156 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 157 return new Info(responseJSON); 158 } 159 160 /** 161 * Gets information about this task. 162 * @param fields the fields to retrieve. 163 * @return info about this task. 164 */ 165 public Info getInfo(String... fields) { 166 QueryStringBuilder builder = new QueryStringBuilder(); 167 if (fields.length > 0) { 168 builder.appendParam("fields", fields); 169 } 170 URL url = TASK_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), builder.toString(), this.getID()); 171 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 172 BoxJSONResponse response = (BoxJSONResponse) request.send(); 173 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 174 return new Info(responseJSON); 175 } 176 177 /** 178 * Updates the information about this task with any info fields that have been modified locally. 179 * 180 * <p>The only fields that will be updated are the ones that have been modified locally. For example, the following 181 * code won't update any information (or even send a network request) since none of the info's fields were 182 * changed:</p> 183 * 184 * <pre>BoxTask task = new BoxTask(api, id); 185 *BoxTask.Info info = task.getInfo(); 186 *task.updateInfo(info);</pre> 187 * 188 * @param info the updated info. 189 */ 190 public void updateInfo(BoxTask.Info info) { 191 URL url = TASK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 192 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 193 request.setBody(info.getPendingChanges()); 194 BoxJSONResponse response = (BoxJSONResponse) request.send(); 195 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 196 info.update(jsonObject); 197 } 198 199 /** 200 * Contains information about a BoxTask. 201 */ 202 public class Info extends BoxResource.Info { 203 private BoxFile.Info item; 204 private Date dueAt; 205 private String action; 206 private String message; 207 private List<BoxTaskAssignment.Info> taskAssignments; 208 private boolean completed; 209 private BoxUser.Info createdBy; 210 private Date createdAt; 211 212 /** 213 * Constructs an empty Info object. 214 */ 215 public Info() { 216 super(); 217 } 218 219 /** 220 * Constructs an Info object by parsing information from a JSON string. 221 * @param json the JSON string to parse. 222 */ 223 public Info(String json) { 224 super(json); 225 } 226 227 /** 228 * Constructs an Info object using an already parsed JSON object. 229 * @param jsonObject the parsed JSON object. 230 */ 231 Info(JsonObject jsonObject) { 232 super(jsonObject); 233 } 234 235 @Override 236 public BoxTask getResource() { 237 return BoxTask.this; 238 } 239 240 /** 241 * Gets the file associated with this task. 242 * @return the file associated with this task. 243 */ 244 public BoxFile.Info getItem() { 245 return this.item; 246 } 247 248 /** 249 * Gets the date at which this task is due. 250 * @return the date at which this task is due. 251 */ 252 public Date getDueAt() { 253 return this.dueAt; 254 } 255 256 /** 257 * Sets the task's due date. 258 * @param dueAt the task's due date. 259 */ 260 public void setDueAt(Date dueAt) { 261 this.dueAt = dueAt; 262 this.addPendingChange("due_at", BoxDateFormat.format(dueAt)); 263 } 264 265 /** 266 * @deprecated 267 * Please use getTaskType() 268 * 269 * Gets the action the task assignee will be prompted to do. 270 * @return the action the task assignee will be prompted to do. 271 */ 272 @Deprecated 273 public Action getAction() { 274 return Action.REVIEW; 275 } 276 277 /** 278 * Gets the action the task assignee will be prompted to do. 279 * @return the action the task assignee will be prompted to do. 280 */ 281 public String getTaskType() { 282 return this.action; 283 } 284 285 /** 286 * Gets the message that will be included with this task. 287 * @return the message that will be included with this task. 288 */ 289 public String getMessage() { 290 return this.message; 291 } 292 293 /** 294 * Sets the task's message. 295 * @param message the task's new message. 296 */ 297 public void setMessage(String message) { 298 this.message = message; 299 this.addPendingChange("message", message); 300 } 301 302 /** 303 * Gets the collection of task assignments associated with this task. 304 * @return the collection of task assignments associated with this task. 305 */ 306 public List<BoxTaskAssignment.Info> getTaskAssignments() { 307 return this.taskAssignments; 308 } 309 310 /** 311 * Gets whether or not this task has been completed. 312 * @return whether or not this task has been completed. 313 */ 314 public boolean isCompleted() { 315 return this.completed; 316 } 317 318 /** 319 * Gets the user who created this task. 320 * @return the user who created this task. 321 */ 322 public BoxUser.Info getCreatedBy() { 323 return this.createdBy; 324 } 325 326 /** 327 * Gets when this task was created. 328 * @return when this task was created. 329 */ 330 public Date getCreatedAt() { 331 return this.createdAt; 332 } 333 334 @Override 335 void parseJSONMember(JsonObject.Member member) { 336 super.parseJSONMember(member); 337 338 String memberName = member.getName(); 339 JsonValue value = member.getValue(); 340 try { 341 if (memberName.equals("item")) { 342 JsonObject itemJSON = value.asObject(); 343 String itemID = itemJSON.get("id").asString(); 344 BoxFile file = new BoxFile(getAPI(), itemID); 345 this.item = file.new Info(itemJSON); 346 } else if (memberName.equals("due_at")) { 347 this.dueAt = BoxDateFormat.parse(value.asString()); 348 } else if (memberName.equals("action")) { 349 this.action = value.asString(); 350 } else if (memberName.equals("message")) { 351 this.message = value.asString(); 352 } else if (memberName.equals("task_assignment_collection")) { 353 this.taskAssignments = this.parseTaskAssignmentCollection(value.asObject()); 354 } else if (memberName.equals("is_completed")) { 355 this.completed = value.asBoolean(); 356 } else if (memberName.equals("created_by")) { 357 JsonObject userJSON = value.asObject(); 358 String userID = userJSON.get("id").asString(); 359 BoxUser user = new BoxUser(getAPI(), userID); 360 this.createdBy = user.new Info(userJSON); 361 } else if (memberName.equals("created_at")) { 362 this.createdAt = BoxDateFormat.parse(value.asString()); 363 } 364 365 } catch (ParseException e) { 366 assert false : "A ParseException indicates a bug in the SDK."; 367 } 368 } 369 370 private List<BoxTaskAssignment.Info> parseTaskAssignmentCollection(JsonObject jsonObject) { 371 int count = jsonObject.get("total_count").asInt(); 372 List<BoxTaskAssignment.Info> taskAssignmentCollection = new ArrayList<BoxTaskAssignment.Info>(count); 373 JsonArray entries = jsonObject.get("entries").asArray(); 374 for (JsonValue value : entries) { 375 JsonObject entry = value.asObject(); 376 String id = entry.get("id").asString(); 377 BoxTaskAssignment assignment = new BoxTaskAssignment(getAPI(), id); 378 taskAssignmentCollection.add(assignment.new Info(entry)); 379 } 380 381 return taskAssignmentCollection; 382 } 383 } 384 385 /** 386 * Enumerates the possible actions that a task can have. 387 */ 388 public enum Action { 389 /** 390 * The task must be reviewed. 391 */ 392 REVIEW ("review"); 393 394 private final String jsonValue; 395 396 private Action(String jsonValue) { 397 this.jsonValue = jsonValue; 398 } 399 400 static Action fromJSONString(String jsonValue) { 401 if (jsonValue.equals("review")) { 402 return REVIEW; 403 } else { 404 throw new IllegalArgumentException("The provided JSON value isn't a valid Action."); 405 } 406 } 407 408 String toJSONString() { 409 return this.jsonValue; 410 } 411 } 412}