001package com.box.sdk; 002 003import java.net.URL; 004import java.util.ArrayList; 005import java.util.Date; 006import java.util.Iterator; 007import java.util.List; 008 009import com.eclipsesource.json.JsonArray; 010import com.eclipsesource.json.JsonObject; 011import com.eclipsesource.json.JsonValue; 012 013/** 014 * Represents a task on Box. Tasks can have a due date and can be assigned to a specific user. 015 */ 016@BoxResourceType("task") 017public class BoxTask extends BoxResource { 018 019 /** 020 * Task URL Template. 021 */ 022 public static final URLTemplate TASK_URL_TEMPLATE = new URLTemplate("tasks/%s"); 023 /** 024 * Get Assignments URL Template. 025 */ 026 public static final URLTemplate GET_ASSIGNMENTS_URL_TEMPLATE = new URLTemplate("tasks/%s/assignments"); 027 /** 028 * Add Task Assignment URL Template. 029 */ 030 public static final URLTemplate ADD_TASK_ASSIGNMENT_URL_TEMPLATE = new URLTemplate("task_assignments"); 031 032 /** 033 * Constructs a BoxTask for a task with a given ID. 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 * @param assignTo the user to assign the assignment to. 054 * @return information about the newly added task assignment. 055 */ 056 public BoxTaskAssignment.Info addAssignment(BoxUser assignTo) { 057 JsonObject taskJSON = new JsonObject(); 058 taskJSON.add("type", "task"); 059 taskJSON.add("id", this.getID()); 060 061 JsonObject assignToJSON = new JsonObject(); 062 assignToJSON.add("id", assignTo.getID()); 063 064 JsonObject requestJSON = new JsonObject(); 065 requestJSON.add("task", taskJSON); 066 requestJSON.add("assign_to", assignToJSON); 067 068 URL url = ADD_TASK_ASSIGNMENT_URL_TEMPLATE.build(this.getAPI().getBaseURL()); 069 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 070 request.setBody(requestJSON.toString()); 071 BoxJSONResponse response = (BoxJSONResponse) request.send(); 072 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 073 074 BoxTaskAssignment addedAssignment = new BoxTaskAssignment(this.getAPI(), responseJSON.get("id").asString()); 075 return addedAssignment.new Info(responseJSON); 076 } 077 078 /** 079 * Adds a new assignment to this task using user's login as identifier. 080 * @param assignToLogin the login of user to assign the task to. 081 * @return information about the newly added task assignment. 082 */ 083 public BoxTaskAssignment.Info addAssignmentByLogin(String assignToLogin) { 084 JsonObject taskJSON = new JsonObject(); 085 taskJSON.add("type", "task"); 086 taskJSON.add("id", this.getID()); 087 088 JsonObject assignToJSON = new JsonObject(); 089 assignToJSON.add("login", assignToLogin); 090 091 JsonObject requestJSON = new JsonObject(); 092 requestJSON.add("task", taskJSON); 093 requestJSON.add("assign_to", assignToJSON); 094 095 URL url = ADD_TASK_ASSIGNMENT_URL_TEMPLATE.build(this.getAPI().getBaseURL()); 096 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 097 request.setBody(requestJSON.toString()); 098 BoxJSONResponse response = (BoxJSONResponse) request.send(); 099 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 100 101 BoxTaskAssignment addedAssignment = new BoxTaskAssignment(this.getAPI(), responseJSON.get("id").asString()); 102 return addedAssignment.new Info(responseJSON); 103 } 104 105 /** 106 * Gets any assignments for this task. 107 * @return a list of assignments for this task. 108 */ 109 public List<BoxTaskAssignment.Info> getAssignments() { 110 URL url = GET_ASSIGNMENTS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 111 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 112 BoxJSONResponse response = (BoxJSONResponse) request.send(); 113 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 114 115 int totalCount = responseJSON.get("total_count").asInt(); 116 List<BoxTaskAssignment.Info> assignments = new ArrayList<BoxTaskAssignment.Info>(totalCount); 117 JsonArray entries = responseJSON.get("entries").asArray(); 118 for (JsonValue value : entries) { 119 JsonObject assignmentJSON = value.asObject(); 120 BoxTaskAssignment assignment = new BoxTaskAssignment(this.getAPI(), assignmentJSON.get("id").asString()); 121 BoxTaskAssignment.Info info = assignment.new Info(assignmentJSON); 122 assignments.add(info); 123 } 124 125 return assignments; 126 } 127 128 /** 129 * Gets an iterable of all the assignments of this task. 130 * @param fields the fields to retrieve. 131 * @return an iterable containing info about all the assignments. 132 */ 133 public Iterable<BoxTaskAssignment.Info> getAllAssignments(String ... fields) { 134 final QueryStringBuilder builder = new QueryStringBuilder(); 135 if (fields.length > 0) { 136 builder.appendParam("fields", fields); 137 } 138 return new Iterable<BoxTaskAssignment.Info>() { 139 public Iterator<BoxTaskAssignment.Info> iterator() { 140 URL url = GET_ASSIGNMENTS_URL_TEMPLATE.buildWithQuery( 141 BoxTask.this.getAPI().getBaseURL(), builder.toString(), BoxTask.this.getID()); 142 return new BoxTaskAssignmentIterator(BoxTask.this.getAPI(), url); 143 } 144 }; 145 } 146 147 /** 148 * Gets information about this task. 149 * @return info about this task. 150 */ 151 public Info getInfo() { 152 URL url = TASK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 153 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 154 BoxJSONResponse response = (BoxJSONResponse) request.send(); 155 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 156 return new Info(responseJSON); 157 } 158 159 /** 160 * Gets information about this task. 161 * @param fields the fields to retrieve. 162 * @return info about this task. 163 */ 164 public Info getInfo(String... fields) { 165 QueryStringBuilder builder = new QueryStringBuilder(); 166 if (fields.length > 0) { 167 builder.appendParam("fields", fields); 168 } 169 URL url = TASK_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), builder.toString(), this.getID()); 170 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 171 BoxJSONResponse response = (BoxJSONResponse) request.send(); 172 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 173 return new Info(responseJSON); 174 } 175 176 /** 177 * Updates the information about this task with any info fields that have been modified locally. 178 * 179 * <p>The only fields that will be updated are the ones that have been modified locally. For example, the following 180 * code won't update any information (or even send a network request) since none of the info's fields were 181 * changed:</p> 182 * 183 * <pre>BoxTask task = new BoxTask(api, id); 184 *BoxTask.Info info = task.getInfo(); 185 *task.updateInfo(info);</pre> 186 * 187 * @param info the updated info. 188 */ 189 public void updateInfo(BoxTask.Info info) { 190 URL url = TASK_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 191 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 192 request.setBody(info.getPendingChanges()); 193 BoxJSONResponse response = (BoxJSONResponse) request.send(); 194 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 195 info.update(jsonObject); 196 } 197 198 /** 199 * Contains information about a BoxTask. 200 */ 201 public class Info extends BoxResource.Info { 202 private BoxFile.Info item; 203 private Date dueAt; 204 private String action; 205 private String completionRule; 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 * Returns the completion rule for the task. 287 * @return the task completion rule. 288 */ 289 public String getCompletionRule() { 290 return this.completionRule; 291 } 292 293 /** 294 * Sets the task's completion rule. 295 * @param completionRule the new completion rule. 296 */ 297 public void setCompletionRule(CompletionRule completionRule) { 298 this.completionRule = completionRule.toJSONString(); 299 this.addPendingChange("completion_rule", completionRule.toJSONString()); 300 } 301 302 /** 303 * Gets the message that will be included with this task. 304 * @return the message that will be included with this task. 305 */ 306 public String getMessage() { 307 return this.message; 308 } 309 310 /** 311 * Sets the task's message. 312 * @param message the task's new message. 313 */ 314 public void setMessage(String message) { 315 this.message = message; 316 this.addPendingChange("message", message); 317 } 318 319 /** 320 * Gets the collection of task assignments associated with this task. 321 * @return the collection of task assignments associated with this task. 322 */ 323 public List<BoxTaskAssignment.Info> getTaskAssignments() { 324 return this.taskAssignments; 325 } 326 327 /** 328 * Gets whether or not this task has been completed. 329 * @return whether or not this task has been completed. 330 */ 331 public boolean isCompleted() { 332 return this.completed; 333 } 334 335 /** 336 * Gets the user who created this task. 337 * @return the user who created this task. 338 */ 339 public BoxUser.Info getCreatedBy() { 340 return this.createdBy; 341 } 342 343 /** 344 * Gets when this task was created. 345 * @return when this task was created. 346 */ 347 public Date getCreatedAt() { 348 return this.createdAt; 349 } 350 351 @Override 352 void parseJSONMember(JsonObject.Member member) { 353 super.parseJSONMember(member); 354 355 String memberName = member.getName(); 356 JsonValue value = member.getValue(); 357 try { 358 if (memberName.equals("item")) { 359 JsonObject itemJSON = value.asObject(); 360 String itemID = itemJSON.get("id").asString(); 361 BoxFile file = new BoxFile(getAPI(), itemID); 362 this.item = file.new Info(itemJSON); 363 } else if (memberName.equals("due_at")) { 364 this.dueAt = BoxDateFormat.parse(value.asString()); 365 } else if (memberName.equals("action")) { 366 this.action = value.asString(); 367 } else if (memberName.equals("completion_rule")) { 368 this.completionRule = value.asString(); 369 } else if (memberName.equals("message")) { 370 this.message = value.asString(); 371 } else if (memberName.equals("task_assignment_collection")) { 372 this.taskAssignments = this.parseTaskAssignmentCollection(value.asObject()); 373 } else if (memberName.equals("is_completed")) { 374 this.completed = value.asBoolean(); 375 } else if (memberName.equals("created_by")) { 376 JsonObject userJSON = value.asObject(); 377 String userID = userJSON.get("id").asString(); 378 BoxUser user = new BoxUser(getAPI(), userID); 379 this.createdBy = user.new Info(userJSON); 380 } else if (memberName.equals("created_at")) { 381 this.createdAt = BoxDateFormat.parse(value.asString()); 382 } 383 384 } catch (Exception e) { 385 throw new BoxDeserializationException(memberName, value.toString(), e); 386 } 387 } 388 389 private List<BoxTaskAssignment.Info> parseTaskAssignmentCollection(JsonObject jsonObject) { 390 int count = jsonObject.get("total_count").asInt(); 391 List<BoxTaskAssignment.Info> taskAssignmentCollection = new ArrayList<BoxTaskAssignment.Info>(count); 392 JsonArray entries = jsonObject.get("entries").asArray(); 393 for (JsonValue value : entries) { 394 JsonObject entry = value.asObject(); 395 String id = entry.get("id").asString(); 396 BoxTaskAssignment assignment = new BoxTaskAssignment(getAPI(), id); 397 taskAssignmentCollection.add(assignment.new Info(entry)); 398 } 399 400 return taskAssignmentCollection; 401 } 402 } 403 404 /** 405 * Enumerates the possible actions that a task can have. 406 */ 407 public enum Action { 408 /** 409 * The task must be reviewed. 410 */ 411 REVIEW ("review"), 412 413 /** 414 * The task must be completed. 415 */ 416 COMPLETE ("complete"); 417 418 private final String jsonValue; 419 420 private Action(String jsonValue) { 421 this.jsonValue = jsonValue; 422 } 423 424 static Action fromJSONString(String jsonValue) { 425 if (jsonValue.equals("review")) { 426 return REVIEW; 427 } else if (jsonValue.equals("complete")) { 428 return COMPLETE; 429 } else { 430 throw new IllegalArgumentException("The provided JSON value isn't a valid Action."); 431 } 432 } 433 434 String toJSONString() { 435 return this.jsonValue; 436 } 437 } 438 439 /** 440 * Enumerates the possible completion rules for a task. 441 */ 442 public enum CompletionRule { 443 444 /** 445 * The task must be completed by all assignees. 446 */ 447 ALL_ASSIGNEES ("all_assignees"), 448 449 /** 450 * The task must be completed by at least one assignee. 451 */ 452 ANY_ASSIGNEE ("any_assignee"); 453 454 private final String jsonValue; 455 456 private CompletionRule(String jsonValue) { 457 this.jsonValue = jsonValue; 458 } 459 460 String toJSONString() { 461 return this.jsonValue; 462 } 463 } 464}