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