001package com.box.sdk; 002 003import java.net.URL; 004import java.util.ArrayList; 005import java.util.Collection; 006import java.util.Iterator; 007import java.util.Map; 008 009import com.box.sdk.BoxGroupMembership.Permission; 010import com.box.sdk.BoxGroupMembership.Role; 011import com.eclipsesource.json.JsonArray; 012import com.eclipsesource.json.JsonObject; 013import com.eclipsesource.json.JsonValue; 014 015/** 016 * Represents a set of Box users. 017 * 018 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked 019 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error 020 * handling for errors related to the Box REST API, you should capture this exception explicitly.</p> 021 */ 022@BoxResourceType("group") 023public class BoxGroup extends BoxCollaborator { 024 025 /** 026 * @see #getAllGroups(BoxAPIConnection, String...) 027 */ 028 public static final URLTemplate GROUPS_URL_TEMPLATE = new URLTemplate("groups"); 029 030 /** 031 * @see #getInfo() 032 */ 033 public static final URLTemplate GROUP_URL_TEMPLATE = new URLTemplate("groups/%s"); 034 035 /** 036 * @see #getMemberships() 037 */ 038 public static final URLTemplate MEMBERSHIPS_URL_TEMPLATE = new URLTemplate("groups/%s/memberships"); 039 040 /** 041 * @see #addMembership(BoxUser) 042 */ 043 public static final URLTemplate ADD_MEMBERSHIP_URL_TEMPLATE = new URLTemplate("group_memberships"); 044 045 /** 046 * @see #getCollaborations() 047 */ 048 public static final URLTemplate COLLABORATIONS_URL_TEMPLATE = new URLTemplate("groups/%s/collaborations"); 049 050 /** 051 * Constructs a BoxGroup for a group with a given ID. 052 * @param api the API connection to be used by the group. 053 * @param id the ID of the group. 054 */ 055 public BoxGroup(BoxAPIConnection api, String id) { 056 super(api, id); 057 } 058 059 /** 060 * Creates a new group with a specified name. 061 * @param api the API connection to be used by the group. 062 * @param name the name of the new group. 063 * @return info about the created group. 064 */ 065 public static BoxGroup.Info createGroup(BoxAPIConnection api, String name) { 066 return createGroup(api, name, null, null, null, null, null); 067 } 068 069 /** 070 * Creates a new group with a specified name. 071 * @param api the API connection to be used by the group. 072 * @param name the name of the new group. 073 * @param provenance the provenance of the new group 074 * @param externalSyncIdentifier the external_sync_identifier of the new group 075 * @param description the description of the new group 076 * @param invitabilityLevel the invitibility_level of the new group 077 * @param memberViewabilityLevel the member_viewability_level of the new group 078 * @return info about the created group. 079 */ 080 public static BoxGroup.Info createGroup(BoxAPIConnection api, String name, String provenance, 081 String externalSyncIdentifier, String description, 082 String invitabilityLevel, String memberViewabilityLevel) { 083 JsonObject requestJSON = new JsonObject(); 084 requestJSON.add("name", name); 085 086 if (provenance != null) { 087 requestJSON.add("provenance", provenance); 088 } 089 if (externalSyncIdentifier != null) { 090 requestJSON.add("external_sync_identifier", externalSyncIdentifier); 091 } 092 if (description != null) { 093 requestJSON.add("description", description); 094 } 095 if (invitabilityLevel != null) { 096 requestJSON.add("invitability_level", invitabilityLevel); 097 } 098 if (memberViewabilityLevel != null) { 099 requestJSON.add("member_viewability_level", memberViewabilityLevel); 100 } 101 102 URL url = GROUPS_URL_TEMPLATE.build(api.getBaseURL()); 103 BoxJSONRequest request = new BoxJSONRequest(api, url, "POST"); 104 request.setBody(requestJSON.toString()); 105 BoxJSONResponse response = (BoxJSONResponse) request.send(); 106 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 107 108 BoxGroup group = new BoxGroup(api, responseJSON.get("id").asString()); 109 return group.new Info(responseJSON); 110 } 111 112 /** 113 * Gets an iterable of all the groups in the enterprise. 114 * @param api the API connection to be used when retrieving the groups. 115 * @return an iterable containing info about all the groups. 116 */ 117 public static Iterable<BoxGroup.Info> getAllGroups(final BoxAPIConnection api) { 118 return new Iterable<BoxGroup.Info>() { 119 public Iterator<BoxGroup.Info> iterator() { 120 URL url = GROUPS_URL_TEMPLATE.build(api.getBaseURL()); 121 return new BoxGroupIterator(api, url); 122 } 123 }; 124 } 125 126 /** 127 * Gets an iterable of all the groups in the enterprise. 128 * @param api the API connection to be used when retrieving the groups. 129 * @param fields the fields to retrieve. 130 * @return an iterable containing info about all the groups. 131 */ 132 public static Iterable<BoxGroup.Info> getAllGroups(final BoxAPIConnection api, String ... fields) { 133 final QueryStringBuilder builder = new QueryStringBuilder(); 134 if (fields.length > 0) { 135 builder.appendParam("fields", fields); 136 } 137 return new Iterable<BoxGroup.Info>() { 138 public Iterator<BoxGroup.Info> iterator() { 139 URL url = GROUPS_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), builder.toString()); 140 return new BoxGroupIterator(api, url); 141 } 142 }; 143 } 144 145 /** 146 * Gets an iterable of all the groups in the enterprise that are starting with the given name string. 147 * @param api the API connection to be used when retrieving the groups. 148 * @param name the name prefix of the groups. If the groups need to searched by full name that has spaces, 149 * then the parameter string should have been wrapped with "". 150 * @return an iterable containing info about all the groups. 151 */ 152 public static Iterable<BoxGroup.Info> getAllGroupsByName(final BoxAPIConnection api, String name) { 153 return getAllGroupsByName(api, name, null); 154 } 155 156 /** 157 * Gets an iterable of all the groups in the enterprise that are starting with the given name string. 158 * @param api the API connection to be used when retrieving the groups. 159 * @param name the name prefix of the groups. If the groups need to searched by full name that has spaces, 160 * then the parameter string should have been wrapped with "". 161 * @param fields the fields to retrieve. 162 * @return an iterable containing info about all the groups. 163 */ 164 public static Iterable<BoxGroup.Info> getAllGroupsByName(final BoxAPIConnection api, String name, 165 String... fields) { 166 final QueryStringBuilder builder = new QueryStringBuilder(); 167 if (name == null || name.trim().isEmpty()) { 168 throw new BoxAPIException("Searching groups by name requires a non NULL or non empty name"); 169 } else { 170 builder.appendParam("filter_term", name); 171 if (fields != null && fields.length > 0) { 172 builder.appendParam("fields", fields); 173 } 174 } 175 176 return new Iterable<BoxGroup.Info>() { 177 public Iterator<BoxGroup.Info> iterator() { 178 URL url = GROUPS_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), builder.toString()); 179 return new BoxGroupIterator(api, url); 180 } 181 }; 182 } 183 184 /** 185 * Gets information about this group. 186 * @return info about this group. 187 */ 188 public Info getInfo() { 189 URL url = GROUP_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 190 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 191 BoxJSONResponse response = (BoxJSONResponse) request.send(); 192 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 193 return new Info(responseJSON); 194 } 195 196 /** 197 * Gets information about this group. 198 * @param fields the fields to retrieve. 199 * @return info about this group. 200 */ 201 public Info getInfo(String ... fields) { 202 QueryStringBuilder builder = new QueryStringBuilder(); 203 if (fields.length > 0) { 204 builder.appendParam("fields", fields); 205 } 206 URL url = GROUP_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), builder.toString(), this.getID()); 207 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 208 BoxJSONResponse response = (BoxJSONResponse) request.send(); 209 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 210 return new Info(responseJSON); 211 } 212 213 /** 214 * Gets information about all of the group memberships for this group. 215 * Does not support paging. 216 * @return a collection of information about the group memberships for this group. 217 */ 218 public Collection<BoxGroupMembership.Info> getMemberships() { 219 final BoxAPIConnection api = this.getAPI(); 220 final String groupID = this.getID(); 221 222 Iterable<BoxGroupMembership.Info> iter = new Iterable<BoxGroupMembership.Info>() { 223 public Iterator<BoxGroupMembership.Info> iterator() { 224 URL url = MEMBERSHIPS_URL_TEMPLATE.build(api.getBaseURL(), groupID); 225 return new BoxGroupMembershipIterator(api, url); 226 } 227 }; 228 229 // We need to iterate all results because this method must return a Collection. This logic should be removed in 230 // the next major version, and instead return the Iterable directly. 231 Collection<BoxGroupMembership.Info> memberships = new ArrayList<BoxGroupMembership.Info>(); 232 for (BoxGroupMembership.Info membership : iter) { 233 memberships.add(membership); 234 } 235 return memberships; 236 } 237 238 /** 239 * Gets information about all of the group memberships for this group as iterable with paging support. 240 * @param fields the fields to retrieve. 241 * @return an iterable with information about the group memberships for this group. 242 */ 243 public Iterable<BoxGroupMembership.Info> getAllMemberships(String ... fields) { 244 final QueryStringBuilder builder = new QueryStringBuilder(); 245 if (fields.length > 0) { 246 builder.appendParam("fields", fields); 247 } 248 return new Iterable<BoxGroupMembership.Info>() { 249 public Iterator<BoxGroupMembership.Info> iterator() { 250 URL url = MEMBERSHIPS_URL_TEMPLATE.buildWithQuery( 251 BoxGroup.this.getAPI().getBaseURL(), builder.toString(), BoxGroup.this.getID()); 252 return new BoxGroupMembershipIterator(BoxGroup.this.getAPI(), url); 253 } 254 }; 255 } 256 257 /** 258 * Adds a member to this group with the default role. 259 * @param user the member to be added to this group. 260 * @return info about the new group membership. 261 */ 262 public BoxGroupMembership.Info addMembership(BoxUser user) { 263 return this.addMembership(user, (Role) null, null); 264 } 265 266 /** 267 * Adds a member to this group with the specified role. 268 * @param user the member to be added to this group. 269 * @param role the role of the user in this group. Can be null to assign the default role. 270 * @return info about the new group membership. 271 * @deprecated use addMembership(BoxUser user, BoxGroupMembership.GroupRole role) instead. 272 */ 273 @Deprecated 274 public BoxGroupMembership.Info addMembership(BoxUser user, Role role) { 275 return this.addMembership(user, role, null); 276 } 277 278 /** 279 * Adds a member to this group with the specified role. 280 * @param user the member to be added to this group. 281 * @param role the role of the user in this group. Can be null to assign the default role. 282 * @return info about the new group membership. 283 */ 284 public BoxGroupMembership.Info addMembership(BoxUser user, BoxGroupMembership.GroupRole role) { 285 return this.addMembership(user, role, null); 286 } 287 288 /** 289 * Adds a member to this group with the specified role. 290 * @param user the member to be added to this group. 291 * @param role the role of the user in this group. Can be null to assign the default role. 292 * @param configurablePermissions the configurable permission of the user as a group admin. 293 * Can be null to give all group admin permissions. 294 * @return info about the new group membership. 295 * @deprecated use {@code addMembership(BoxUser user, GroupRole role, 296 * Map<BoxGroupMembership.Permission, Boolean> configurablePermissions)} instead. 297 */ 298 @Deprecated 299 public BoxGroupMembership.Info addMembership(BoxUser user, Role role, 300 Map<BoxGroupMembership.Permission, Boolean> configurablePermissions) { 301 BoxAPIConnection api = this.getAPI(); 302 303 JsonObject requestJSON = new JsonObject(); 304 requestJSON.add("user", new JsonObject().add("id", user.getID())); 305 requestJSON.add("group", new JsonObject().add("id", this.getID())); 306 if (role != null) { 307 requestJSON.add("role", role.toJSONString()); 308 } 309 310 if (configurablePermissions != null) { 311 JsonObject configurablePermissionJson = new JsonObject(); 312 for (Permission attrKey : configurablePermissions.keySet()) { 313 configurablePermissionJson.set(attrKey.toJSONValue(), configurablePermissions.get(attrKey)); 314 } 315 requestJSON.add("configurable_permissions", configurablePermissionJson); 316 } 317 318 URL url = ADD_MEMBERSHIP_URL_TEMPLATE.build(api.getBaseURL()); 319 BoxJSONRequest request = new BoxJSONRequest(api, url, "POST"); 320 request.setBody(requestJSON.toString()); 321 BoxJSONResponse response = (BoxJSONResponse) request.send(); 322 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 323 324 BoxGroupMembership membership = new BoxGroupMembership(api, responseJSON.get("id").asString()); 325 return membership.new Info(responseJSON); 326 } 327 328 /** 329 * Adds a member to this group with the specified role. 330 * @param user the member to be added to this group. 331 * @param role the role of the user in this group. Can be null to assign the default role. 332 * @param configurablePermissions the configurable permission of the user as a group admin. 333 * Can be null to give all group admin permissions. 334 * @return info about the new group membership. 335 */ 336 public BoxGroupMembership.Info addMembership(BoxUser user, BoxGroupMembership.GroupRole role, 337 Map<BoxGroupMembership.Permission, Boolean> configurablePermissions) { 338 BoxAPIConnection api = this.getAPI(); 339 340 JsonObject requestJSON = new JsonObject(); 341 requestJSON.add("user", new JsonObject().add("id", user.getID())); 342 requestJSON.add("group", new JsonObject().add("id", this.getID())); 343 if (role != null) { 344 requestJSON.add("role", role.toJSONString()); 345 } 346 347 if (configurablePermissions != null) { 348 JsonObject configurablePermissionJson = new JsonObject(); 349 for (Permission attrKey : configurablePermissions.keySet()) { 350 configurablePermissionJson.set(attrKey.toJSONValue(), configurablePermissions.get(attrKey)); 351 } 352 requestJSON.add("configurable_permissions", configurablePermissionJson); 353 } 354 355 URL url = ADD_MEMBERSHIP_URL_TEMPLATE.build(api.getBaseURL()); 356 BoxJSONRequest request = new BoxJSONRequest(api, url, "POST"); 357 request.setBody(requestJSON.toString()); 358 BoxJSONResponse response = (BoxJSONResponse) request.send(); 359 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 360 361 BoxGroupMembership membership = new BoxGroupMembership(api, responseJSON.get("id").asString()); 362 return membership.new Info(responseJSON); 363 } 364 365 /** 366 * Gets information about all of the collaborations for this group. 367 * @return a collection of information about the collaborations for this group. 368 */ 369 public Collection<BoxCollaboration.Info> getCollaborations() { 370 BoxAPIConnection api = this.getAPI(); 371 URL url = COLLABORATIONS_URL_TEMPLATE.build(api.getBaseURL(), this.getID()); 372 373 BoxAPIRequest request = new BoxAPIRequest(api, url, "GET"); 374 BoxJSONResponse response = (BoxJSONResponse) request.send(); 375 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 376 377 int entriesCount = responseJSON.get("total_count").asInt(); 378 Collection<BoxCollaboration.Info> collaborations = new ArrayList<BoxCollaboration.Info>(entriesCount); 379 JsonArray entries = responseJSON.get("entries").asArray(); 380 for (JsonValue entry : entries) { 381 JsonObject entryObject = entry.asObject(); 382 BoxCollaboration collaboration = new BoxCollaboration(api, entryObject.get("id").asString()); 383 BoxCollaboration.Info info = collaboration.new Info(entryObject); 384 collaborations.add(info); 385 } 386 387 return collaborations; 388 } 389 390 /** 391 * Gets information about all of the collaborations for this group. 392 * @param fields the optional fields to retrieve. 393 * @return An iterable of BoxCollaboration.Info instances associated with the item. 394 */ 395 public Iterable<BoxCollaboration.Info> getAllCollaborations(String... fields) { 396 final BoxAPIConnection api = this.getAPI(); 397 final QueryStringBuilder builder = new QueryStringBuilder(); 398 if (fields.length > 0) { 399 builder.appendParam("fields", fields); 400 } 401 return new Iterable<BoxCollaboration.Info>() { 402 public Iterator<BoxCollaboration.Info> iterator() { 403 URL url = COLLABORATIONS_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), builder.toString(), 404 BoxGroup.this.getID()); 405 return new BoxCollaborationIterator(api, url); 406 } 407 }; 408 } 409 410 /** 411 * Deletes this group. 412 */ 413 public void delete() { 414 URL url = GROUP_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 415 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 416 BoxAPIResponse response = request.send(); 417 response.disconnect(); 418 } 419 420 /** 421 * Updates the information about this group with any info fields that have been modified locally. 422 * @param info the updated info. 423 */ 424 public void updateInfo(BoxGroup.Info info) { 425 URL url = GROUP_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 426 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 427 request.setBody(info.getPendingChanges()); 428 BoxJSONResponse response = (BoxJSONResponse) request.send(); 429 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 430 info.update(jsonObject); 431 } 432 433 /** 434 * Contains information about a BoxGroup. 435 */ 436 public class Info extends BoxCollaborator.Info { 437 438 /** 439 * @see #getProvenance() 440 */ 441 private String provenance; 442 443 /** 444 * @see #getExternalSyncIdentifier() 445 */ 446 private String externalSyncIdentifier; 447 448 /** 449 * @see #getDescription() 450 */ 451 private String description; 452 453 /** 454 * @see #getInvitabilityLevel() 455 */ 456 private String invitabilityLevel; 457 458 /** 459 * @see #getMemberViewabilityLevel() 460 */ 461 private String memberViewabilityLevel; 462 463 /** 464 * Constructs an empty Info object. 465 */ 466 public Info() { 467 super(); 468 } 469 470 /** 471 * Constructs an Info object by parsing information from a JSON string. 472 * @param json the JSON string to parse. 473 */ 474 public Info(String json) { 475 super(json); 476 } 477 478 /** 479 * Constructs an Info object using an already parsed JSON object. 480 * @param jsonObject the parsed JSON object. 481 */ 482 Info(JsonObject jsonObject) { 483 super(jsonObject); 484 } 485 486 /** 487 * {@inheritDoc} 488 */ 489 @Override 490 public BoxGroup getResource() { 491 return BoxGroup.this; 492 } 493 494 /** 495 * {@inheritDoc} 496 */ 497 @Override 498 protected void parseJSONMember(JsonObject.Member member) { 499 super.parseJSONMember(member); 500 501 String memberName = member.getName(); 502 JsonValue value = member.getValue(); 503 try { 504 if (memberName.equals("description")) { 505 this.description = value.asString(); 506 } else if (memberName.equals("external_sync_identifier")) { 507 this.externalSyncIdentifier = value.asString(); 508 } else if (memberName.equals("invitability_level")) { 509 this.invitabilityLevel = value.asString(); 510 } else if (memberName.equals("member_viewability_level")) { 511 this.memberViewabilityLevel = value.asString(); 512 } else if (memberName.equals("provenance")) { 513 this.provenance = value.asString(); 514 } 515 } catch (Exception e) { 516 throw new BoxDeserializationException(memberName, value.toString(), e); 517 } 518 } 519 520 /** 521 * Gets the description for the group. 522 * @return the description for the group. 523 */ 524 public String getDescription() { 525 return this.description; 526 } 527 528 /** 529 * Sets the description for the group. 530 * @param description the description for the group. 531 */ 532 public void setDescription(String description) { 533 this.description = description; 534 addPendingChange("description", description); 535 } 536 537 /** 538 * Gets the external_sync_identifier for the group. 539 * @return the external_sync_identifier for the group. 540 */ 541 public String getExternalSyncIdentifier() { 542 return this.externalSyncIdentifier; 543 } 544 545 /** 546 * Sets the external_sync_identifier for the group. 547 * @param externalSyncIdentifier the external_sync_identifier for the group. 548 */ 549 public void setExternalSyncIdentifier(String externalSyncIdentifier) { 550 this.externalSyncIdentifier = externalSyncIdentifier; 551 addPendingChange("external_sync_identifier", externalSyncIdentifier); 552 } 553 554 /** 555 * Gets the invitability_level for the group. 556 * @return the invitability_level for the group. 557 */ 558 public String getInvitabilityLevel() { 559 return this.invitabilityLevel; 560 } 561 562 /** 563 * Sets the invitability_level for the group. 564 * @param invitabilityLevel the invitability_level for the group. 565 */ 566 public void setInvitabilityLevel(String invitabilityLevel) { 567 this.invitabilityLevel = invitabilityLevel; 568 addPendingChange("invitability_level", invitabilityLevel); 569 } 570 571 /** 572 * Gets the member_viewability_level for the group. 573 * @return the member_viewability_level for the group. 574 */ 575 public String getMemberViewabilityLevel() { 576 return this.memberViewabilityLevel; 577 } 578 579 /** 580 * Sets the member_viewability_level for the group. 581 * @param memberViewabilityLevel the member_viewability_level for the group. 582 */ 583 public void setMemberViewabilityLevel(String memberViewabilityLevel) { 584 this.memberViewabilityLevel = memberViewabilityLevel; 585 addPendingChange("member_viewability_level", memberViewabilityLevel); 586 } 587 588 /** 589 * Gets the provenance for the group. 590 * @return the provenance for the group. 591 */ 592 public String getProvenance() { 593 return this.provenance; 594 } 595 596 /** 597 * Sets the provenance for the group. 598 * @param provenance the provenance for the group. 599 */ 600 public void setProvenance(String provenance) { 601 this.provenance = provenance; 602 addPendingChange("provenance", provenance); 603 } 604 } 605}