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