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