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