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, 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 */ 272 public BoxGroupMembership.Info addMembership(BoxUser user, Role role) { 273 return this.addMembership(user, role, null); 274 } 275 276 /** 277 * Adds a member to this group with the specified role. 278 * @param user the member to be added to this group. 279 * @param role the role of the user in this group. Can be null to assign the default role. 280 * @param configurablePermissions the configurable permission of the user as a group admin. 281 * Can be null to give all group admin permissions. 282 * @return info about the new group membership. 283 */ 284 public BoxGroupMembership.Info addMembership(BoxUser user, Role role, 285 Map<BoxGroupMembership.Permission, Boolean> configurablePermissions) { 286 BoxAPIConnection api = this.getAPI(); 287 288 JsonObject requestJSON = new JsonObject(); 289 requestJSON.add("user", new JsonObject().add("id", user.getID())); 290 requestJSON.add("group", new JsonObject().add("id", this.getID())); 291 if (role != null) { 292 requestJSON.add("role", role.toJSONString()); 293 } 294 295 if (configurablePermissions != null) { 296 JsonObject configurablePermissionJson = new JsonObject(); 297 for (Permission attrKey : configurablePermissions.keySet()) { 298 configurablePermissionJson.set(attrKey.toJSONValue(), configurablePermissions.get(attrKey)); 299 } 300 requestJSON.add("configurable_permissions", configurablePermissionJson); 301 } 302 303 URL url = ADD_MEMBERSHIP_URL_TEMPLATE.build(api.getBaseURL()); 304 BoxJSONRequest request = new BoxJSONRequest(api, url, "POST"); 305 request.setBody(requestJSON.toString()); 306 BoxJSONResponse response = (BoxJSONResponse) request.send(); 307 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 308 309 BoxGroupMembership membership = new BoxGroupMembership(api, responseJSON.get("id").asString()); 310 return membership.new Info(responseJSON); 311 } 312 313 /** 314 * Gets information about all of the collaborations for this group. 315 * @return a collection of information about the collaborations for this group. 316 */ 317 public Collection<BoxCollaboration.Info> getCollaborations() { 318 BoxAPIConnection api = this.getAPI(); 319 URL url = COLLABORATIONS_URL_TEMPLATE.build(api.getBaseURL(), this.getID()); 320 321 BoxAPIRequest request = new BoxAPIRequest(api, url, "GET"); 322 BoxJSONResponse response = (BoxJSONResponse) request.send(); 323 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 324 325 int entriesCount = responseJSON.get("total_count").asInt(); 326 Collection<BoxCollaboration.Info> collaborations = new ArrayList<BoxCollaboration.Info>(entriesCount); 327 JsonArray entries = responseJSON.get("entries").asArray(); 328 for (JsonValue entry : entries) { 329 JsonObject entryObject = entry.asObject(); 330 BoxCollaboration collaboration = new BoxCollaboration(api, entryObject.get("id").asString()); 331 BoxCollaboration.Info info = collaboration.new Info(entryObject); 332 collaborations.add(info); 333 } 334 335 return collaborations; 336 } 337 338 /** 339 * Gets information about all of the collaborations for this group. 340 * @param fields the optional fields to retrieve. 341 * @return An iterable of BoxCollaboration.Info instances associated with the item. 342 */ 343 public Iterable<BoxCollaboration.Info> getAllCollaborations(String... fields) { 344 final BoxAPIConnection api = this.getAPI(); 345 final QueryStringBuilder builder = new QueryStringBuilder(); 346 if (fields.length > 0) { 347 builder.appendParam("fields", fields); 348 } 349 return new Iterable<BoxCollaboration.Info>() { 350 public Iterator<BoxCollaboration.Info> iterator() { 351 URL url = COLLABORATIONS_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), builder.toString(), 352 BoxGroup.this.getID()); 353 return new BoxCollaborationIterator(api, url); 354 } 355 }; 356 } 357 358 /** 359 * Deletes this group. 360 */ 361 public void delete() { 362 URL url = GROUP_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 363 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 364 BoxAPIResponse response = request.send(); 365 response.disconnect(); 366 } 367 368 /** 369 * Updates the information about this group with any info fields that have been modified locally. 370 * @param info the updated info. 371 */ 372 public void updateInfo(BoxGroup.Info info) { 373 URL url = GROUP_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 374 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 375 request.setBody(info.getPendingChanges()); 376 BoxJSONResponse response = (BoxJSONResponse) request.send(); 377 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 378 info.update(jsonObject); 379 } 380 381 /** 382 * Contains information about a BoxGroup. 383 */ 384 public class Info extends BoxCollaborator.Info { 385 386 /** 387 * @see #getProvenance() 388 */ 389 private String provenance; 390 391 /** 392 * @see #getExternalSyncIdentifier() 393 */ 394 private String externalSyncIdentifier; 395 396 /** 397 * @see #getDescription() 398 */ 399 private String description; 400 401 /** 402 * @see #getInvitabilityLevel() 403 */ 404 private String invitabilityLevel; 405 406 /** 407 * @see #getMemberViewabilityLevel() 408 */ 409 private String memberViewabilityLevel; 410 411 /** 412 * Constructs an empty Info object. 413 */ 414 public Info() { 415 super(); 416 } 417 418 /** 419 * Constructs an Info object by parsing information from a JSON string. 420 * @param json the JSON string to parse. 421 */ 422 public Info(String json) { 423 super(json); 424 } 425 426 /** 427 * Constructs an Info object using an already parsed JSON object. 428 * @param jsonObject the parsed JSON object. 429 */ 430 Info(JsonObject jsonObject) { 431 super(jsonObject); 432 } 433 434 /** 435 * {@inheritDoc} 436 */ 437 @Override 438 public BoxGroup getResource() { 439 return BoxGroup.this; 440 } 441 442 /** 443 * {@inheritDoc} 444 */ 445 @Override 446 protected void parseJSONMember(JsonObject.Member member) { 447 super.parseJSONMember(member); 448 449 String memberName = member.getName(); 450 JsonValue value = member.getValue(); 451 try { 452 if (memberName.equals("description")) { 453 this.description = value.asString(); 454 } else if (memberName.equals("external_sync_identifier")) { 455 this.externalSyncIdentifier = value.asString(); 456 } else if (memberName.equals("invitability_level")) { 457 this.invitabilityLevel = value.asString(); 458 } else if (memberName.equals("member_viewability_level")) { 459 this.memberViewabilityLevel = value.asString(); 460 } else if (memberName.equals("provenance")) { 461 this.provenance = value.asString(); 462 } 463 } catch (Exception e) { 464 throw new BoxDeserializationException(memberName, value.toString(), e); 465 } 466 } 467 468 /** 469 * Gets the description for the group. 470 * @return the description for the group. 471 */ 472 public String getDescription() { 473 return this.description; 474 } 475 476 /** 477 * Sets the description for the group. 478 * @param description the description for the group. 479 */ 480 public void setDescription(String description) { 481 this.description = description; 482 addPendingChange("description", description); 483 } 484 485 /** 486 * Gets the external_sync_identifier for the group. 487 * @return the external_sync_identifier for the group. 488 */ 489 public String getExternalSyncIdentifier() { 490 return this.externalSyncIdentifier; 491 } 492 493 /** 494 * Sets the external_sync_identifier for the group. 495 * @param externalSyncIdentifier the external_sync_identifier for the group. 496 */ 497 public void setExternalSyncIdentifier(String externalSyncIdentifier) { 498 this.externalSyncIdentifier = externalSyncIdentifier; 499 addPendingChange("external_sync_identifier", externalSyncIdentifier); 500 } 501 502 /** 503 * Gets the invitability_level for the group. 504 * @return the invitability_level for the group. 505 */ 506 public String getInvitabilityLevel() { 507 return this.invitabilityLevel; 508 } 509 510 /** 511 * Sets the invitability_level for the group. 512 * @param invitabilityLevel the invitability_level for the group. 513 */ 514 public void setInvitabilityLevel(String invitabilityLevel) { 515 this.invitabilityLevel = invitabilityLevel; 516 addPendingChange("invitability_level", invitabilityLevel); 517 } 518 519 /** 520 * Gets the member_viewability_level for the group. 521 * @return the member_viewability_level for the group. 522 */ 523 public String getMemberViewabilityLevel() { 524 return this.memberViewabilityLevel; 525 } 526 527 /** 528 * Sets the member_viewability_level for the group. 529 * @param memberViewabilityLevel the member_viewability_level for the group. 530 */ 531 public void setMemberViewabilityLevel(String memberViewabilityLevel) { 532 this.memberViewabilityLevel = memberViewabilityLevel; 533 addPendingChange("member_viewability_level", memberViewabilityLevel); 534 } 535 536 /** 537 * Gets the provenance for the group. 538 * @return the provenance for the group. 539 */ 540 public String getProvenance() { 541 return this.provenance; 542 } 543 544 /** 545 * Sets the provenance for the group. 546 * @param provenance the provenance for the group. 547 */ 548 public void setProvenance(String provenance) { 549 this.provenance = provenance; 550 addPendingChange("provenance", provenance); 551 } 552 } 553}