001package com.box.sdk; 002 003import java.net.URL; 004import java.text.ParseException; 005import java.util.ArrayList; 006import java.util.Collection; 007import java.util.Date; 008 009import com.eclipsesource.json.JsonArray; 010import com.eclipsesource.json.JsonObject; 011import com.eclipsesource.json.JsonValue; 012 013/** 014 * Represents a collaboration between a user and another user or group. Collaborations are Box's equivalent of access 015 * control lists. They can be used to set and apply permissions for users or groups to folders. 016 */ 017public class BoxCollaboration extends BoxResource { 018 private static final URLTemplate COLLABORATIONS_URL_TEMPLATE = new URLTemplate("collaborations"); 019 private static final URLTemplate PENDING_COLLABORATIONS_URL = new URLTemplate("collaborations?status=pending"); 020 private static final URLTemplate COLLABORATION_URL_TEMPLATE = new URLTemplate("collaborations/%s"); 021 022 /** 023 * Constructs a BoxCollaboration for a collaboration with a given ID. 024 * @param api the API connection to be used by the collaboration. 025 * @param id the ID of the collaboration. 026 */ 027 public BoxCollaboration(BoxAPIConnection api, String id) { 028 super(api, id); 029 } 030 031 /** 032 * Gets all pending collaboration invites for the current user. 033 * @param api the API connection to use. 034 * @return a collection of pending collaboration infos. 035 */ 036 public static Collection<Info> getPendingCollaborations(BoxAPIConnection api) { 037 URL url = PENDING_COLLABORATIONS_URL.build(api.getBaseURL()); 038 039 BoxAPIRequest request = new BoxAPIRequest(api, url, "GET"); 040 BoxJSONResponse response = (BoxJSONResponse) request.send(); 041 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 042 043 int entriesCount = responseJSON.get("total_count").asInt(); 044 Collection<BoxCollaboration.Info> collaborations = new ArrayList<BoxCollaboration.Info>(entriesCount); 045 JsonArray entries = responseJSON.get("entries").asArray(); 046 for (JsonValue entry : entries) { 047 JsonObject entryObject = entry.asObject(); 048 BoxCollaboration collaboration = new BoxCollaboration(api, entryObject.get("id").asString()); 049 BoxCollaboration.Info info = collaboration.new Info(entryObject); 050 collaborations.add(info); 051 } 052 053 return collaborations; 054 } 055 056 /** 057 * Gets information about this collaboration. 058 * @return info about this collaboration. 059 */ 060 public Info getInfo() { 061 BoxAPIConnection api = this.getAPI(); 062 URL url = COLLABORATIONS_URL_TEMPLATE.build(api.getBaseURL()); 063 064 BoxAPIRequest request = new BoxAPIRequest(api, url, "GET"); 065 BoxJSONResponse response = (BoxJSONResponse) request.send(); 066 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 067 return new Info(jsonObject); 068 } 069 070 /** 071 * Updates the information about this collaboration with any info fields that have been modified locally. 072 * @param info the updated info. 073 */ 074 public void updateInfo(Info info) { 075 BoxAPIConnection api = this.getAPI(); 076 URL url = COLLABORATION_URL_TEMPLATE.build(api.getBaseURL(), this.getID()); 077 078 BoxJSONRequest request = new BoxJSONRequest(api, url, "PUT"); 079 request.setBody(info.getPendingChanges()); 080 BoxJSONResponse response = (BoxJSONResponse) request.send(); 081 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 082 info.update(jsonObject); 083 } 084 085 /** 086 * Deletes this collaboration. 087 */ 088 public void delete() { 089 BoxAPIConnection api = this.getAPI(); 090 URL url = COLLABORATION_URL_TEMPLATE.build(api.getBaseURL(), this.getID()); 091 092 BoxAPIRequest request = new BoxAPIRequest(api, url, "DELETE"); 093 BoxAPIResponse response = request.send(); 094 response.disconnect(); 095 } 096 097 /** 098 * Contains information about a BoxCollaboration. 099 */ 100 public class Info extends BoxResource.Info { 101 private BoxUser.Info createdBy; 102 private Date createdAt; 103 private Date modifiedAt; 104 private Date expiresAt; 105 private Status status; 106 private BoxCollaborator.Info accessibleBy; 107 private Role role; 108 private Date acknowledgedAt; 109 private BoxFolder.Info item; 110 111 /** 112 * Constructs an empty Info object. 113 */ 114 public Info() { 115 super(); 116 } 117 118 /** 119 * Constructs an Info object by parsing information from a JSON string. 120 * @param json the JSON string to parse. 121 */ 122 public Info(String json) { 123 super(json); 124 } 125 126 Info(JsonObject jsonObject) { 127 super(jsonObject); 128 } 129 130 /** 131 * Gets the user who created the collaboration. 132 * @return the user who created the collaboration. 133 */ 134 public BoxUser.Info getCreatedBy() { 135 return this.createdBy; 136 } 137 138 /** 139 * Gets the time the collaboration was created. 140 * @return the time the collaboration was created. 141 */ 142 public Date getCreatedAt() { 143 return this.createdAt; 144 } 145 146 /** 147 * Gets the time the collaboration was last modified. 148 * @return the time the collaboration was last modified. 149 */ 150 public Date getModifiedAt() { 151 return this.modifiedAt; 152 } 153 154 /** 155 * Gets the time the collaboration will expire. 156 * @return the time the collaboration will expire. 157 */ 158 public Date getExpiresAt() { 159 return this.expiresAt; 160 } 161 162 /** 163 * Gets the status of the collaboration. 164 * @return the status of the collaboration. 165 */ 166 public Status getStatus() { 167 return this.status; 168 } 169 170 /** 171 * Sets the status of the collaboration in order to accept or reject the collaboration if it's pending. 172 * @param status the new status of the collaboration. 173 */ 174 public void setStatus(Status status) { 175 this.status = status; 176 this.addPendingChange("status", status.name().toLowerCase()); 177 } 178 179 /** 180 * Gets the collaborator who this collaboration applies to. 181 * @return the collaborator who this collaboration applies to. 182 */ 183 public BoxCollaborator.Info getAccessibleBy() { 184 return this.accessibleBy; 185 } 186 187 /** 188 * Gets the level of access the collaborator has. 189 * @return the level of access the collaborator has. 190 */ 191 public Role getRole() { 192 return this.role; 193 } 194 195 /** 196 * Sets the level of access the collaborator has. 197 * @param role the new level of access to give the collaborator. 198 */ 199 public void setRole(Role role) { 200 this.role = role; 201 this.addPendingChange("role", role.toJSONString()); 202 } 203 204 /** 205 * Gets the time the collaboration's status was changed. 206 * @return the time the collaboration's status was changed. 207 */ 208 public Date getAcknowledgedAt() { 209 return this.acknowledgedAt; 210 } 211 212 /** 213 * Gets the folder the collaboration is related to. 214 * @return the folder the collaboration is related to. 215 */ 216 public BoxFolder.Info getItem() { 217 return this.item; 218 } 219 220 @Override 221 public BoxCollaboration getResource() { 222 return BoxCollaboration.this; 223 } 224 225 @Override 226 protected void parseJSONMember(JsonObject.Member member) { 227 super.parseJSONMember(member); 228 229 String memberName = member.getName(); 230 JsonValue value = member.getValue(); 231 try { 232 switch (memberName) { 233 case "created_by": 234 JsonObject userJSON = value.asObject(); 235 if (this.createdBy == null) { 236 String userID = userJSON.get("id").asString(); 237 BoxUser user = new BoxUser(getAPI(), userID); 238 this.createdBy = user.new Info(userJSON); 239 } else { 240 this.createdBy.update(userJSON); 241 } 242 break; 243 case "created_at": 244 this.createdAt = BoxDateFormat.parse(value.asString()); 245 break; 246 case "modified_at": 247 this.modifiedAt = BoxDateFormat.parse(value.asString()); 248 break; 249 case "expires_at": 250 this.expiresAt = BoxDateFormat.parse(value.asString()); 251 break; 252 case "status": 253 String statusString = value.asString().toUpperCase(); 254 this.status = Status.valueOf(statusString); 255 break; 256 case "accessible_by": 257 userJSON = value.asObject(); 258 if (this.accessibleBy == null) { 259 String userID = userJSON.get("id").asString(); 260 BoxUser user = new BoxUser(getAPI(), userID); 261 BoxUser.Info userInfo = user.new Info(userJSON); 262 this.accessibleBy = userInfo; 263 } else { 264 this.accessibleBy.update(userJSON); 265 } 266 break; 267 case "role": 268 this.role = Role.fromJSONString(value.asString()); 269 break; 270 case "acknowledged_at": 271 this.acknowledgedAt = BoxDateFormat.parse(value.asString()); 272 break; 273 case "item": 274 JsonObject folderJSON = value.asObject(); 275 if (this.item == null) { 276 String folderID = folderJSON.get("id").asString(); 277 BoxFolder folder = new BoxFolder(getAPI(), folderID); 278 this.item = folder.new Info(folderJSON); 279 } else { 280 this.item.update(folderJSON); 281 } 282 break; 283 default: 284 break; 285 } 286 } catch (ParseException e) { 287 assert false : "A ParseException indicates a bug in the SDK."; 288 } 289 } 290 } 291 292 /** 293 * Enumerates the possible statuses that a collaboration can have. 294 */ 295 public enum Status { 296 /** 297 * The collaboration has been accepted. 298 */ 299 ACCEPTED, 300 301 /** 302 * The collaboration is waiting to be accepted or rejected. 303 */ 304 PENDING, 305 306 /** 307 * The collaboration has been rejected. 308 */ 309 REJECTED; 310 } 311 312 /** 313 * Enumerates the possible access levels that a collaborator can have. 314 */ 315 public enum Role { 316 /** 317 * An Editor has full read/write access to a folder. Once invited to a folder, they will be able to view, 318 * download, upload, edit, delete, copy, move, rename, generate shared links, make comments, assign tasks, 319 * create tags, and invite/remove collaborators. They will not be able to delete or move root level folders. 320 */ 321 EDITOR ("editor"), 322 323 /** 324 * The viewer role has full read access to a folder. Once invited to a folder, they will be able to preview, 325 * download, make comments, and generate shared links. They will not be able to add tags, invite new 326 * collaborators, upload, edit, or delete items in the folder. 327 */ 328 VIEWER ("viewer"), 329 330 /** 331 * The previewer role has limited read access to a folder. They will only be able to preview the items in the 332 * folder using the integrated content viewer. They will not be able to share, upload, edit, or delete any 333 * content. This role is only available to enterprise accounts. 334 */ 335 PREVIEWER ("previewer"), 336 337 /** 338 * The uploader has limited write access to a folder. They will only be able to upload and see the names of the 339 * items in a folder. They will not able to download or view any content. This role is only available to 340 * enterprise accounts. 341 */ 342 UPLOADER ("uploader"), 343 344 /** 345 * The previewer-uploader role is a combination of previewer and uploader. A user with this access level will be 346 * able to preview files using the integrated content viewer as well as upload items into the folder. They will 347 * not be able to download, edit, or share, items in the folder. This role is only available to enterprise 348 * accounts. 349 */ 350 PREVIEWER_UPLOADER ("previewer uploader"), 351 352 /** 353 * The viewer-uploader role is a combination of viewer and uploader. A viewer-uploader has full read access to a 354 * folder and limited write access. They are able to preview, download, add comments, generate shared links, and 355 * upload content to the folder. They will not be able to add tags, invite new collaborators, edit, or delete 356 * items in the folder. This role is only available to enterprise accounts. 357 */ 358 VIEWER_UPLOADER ("viewer uploader"), 359 360 /** 361 * The co-owner role has all of the functional read/write access that an editor does. This permission level has 362 * the added ability of being able to manage users in the folder. A co-owner can add new collaborators, change 363 * access levels of existing collaborators, and remove collaborators. However, they will not be able to 364 * manipulate the owner of the folder or transfer ownership to another user. This role is only available to 365 * enterprise accounts. 366 */ 367 CO_OWNER ("co-owner"), 368 369 /** 370 * The owner role has all of the functional capabilities of a co-owner. However, they will be able to manipulate 371 * the owner of the folder or transfer ownership to another user. This role is only available to enterprise 372 * accounts. 373 */ 374 OWNER ("owner"); 375 376 private final String jsonValue; 377 378 private Role(String jsonValue) { 379 this.jsonValue = jsonValue; 380 } 381 382 static Role fromJSONString(String jsonValue) { 383 switch (jsonValue) { 384 case "editor": 385 return EDITOR; 386 case "viewer": 387 return VIEWER; 388 case "previewer": 389 return PREVIEWER; 390 case "uploader": 391 return UPLOADER; 392 case "previewer uploader": 393 return PREVIEWER_UPLOADER; 394 case "viewer uploader": 395 return VIEWER_UPLOADER; 396 case "co-owner": 397 return CO_OWNER; 398 case "owner": 399 return OWNER; 400 default: 401 throw new IllegalArgumentException("The provided JSON value isn't a valid Role."); 402 } 403 } 404 405 String toJSONString() { 406 return this.jsonValue; 407 } 408 } 409}