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