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 final QueryStringBuilder builder = new QueryStringBuilder(); 152 if (name == null || name.trim().isEmpty()) { 153 throw new BoxAPIException("Searching groups by name requires a non NULL or non empty name"); 154 } else { 155 builder.appendParam("name", name); 156 } 157 158 return new Iterable<BoxGroup.Info>() { 159 public Iterator<BoxGroup.Info> iterator() { 160 URL url = GROUPS_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), builder.toString()); 161 return new BoxGroupIterator(api, url); 162 } 163 }; 164 } 165 166 /** 167 * Gets information about this group. 168 * @return info about this group. 169 */ 170 public Info getInfo() { 171 URL url = GROUP_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 172 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 173 BoxJSONResponse response = (BoxJSONResponse) request.send(); 174 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 175 return new Info(responseJSON); 176 } 177 178 /** 179 * Gets information about this group. 180 * @param fields the fields to retrieve. 181 * @return info about this group. 182 */ 183 public Info getInfo(String ... fields) { 184 QueryStringBuilder builder = new QueryStringBuilder(); 185 if (fields.length > 0) { 186 builder.appendParam("fields", fields); 187 } 188 URL url = GROUP_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), builder.toString(), this.getID()); 189 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 190 BoxJSONResponse response = (BoxJSONResponse) request.send(); 191 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 192 return new Info(responseJSON); 193 } 194 195 /** 196 * Gets information about all of the group memberships for this group. 197 * Does not support paging. 198 * @return a collection of information about the group memberships for this group. 199 */ 200 public Collection<BoxGroupMembership.Info> getMemberships() { 201 final BoxAPIConnection api = this.getAPI(); 202 final String groupID = this.getID(); 203 204 Iterable<BoxGroupMembership.Info> iter = new Iterable<BoxGroupMembership.Info>() { 205 public Iterator<BoxGroupMembership.Info> iterator() { 206 URL url = MEMBERSHIPS_URL_TEMPLATE.build(api.getBaseURL(), groupID); 207 return new BoxGroupMembershipIterator(api, url); 208 } 209 }; 210 211 // We need to iterate all results because this method must return a Collection. This logic should be removed in 212 // the next major version, and instead return the Iterable directly. 213 Collection<BoxGroupMembership.Info> memberships = new ArrayList<BoxGroupMembership.Info>(); 214 for (BoxGroupMembership.Info membership : iter) { 215 memberships.add(membership); 216 } 217 return memberships; 218 } 219 220 /** 221 * Gets information about all of the group memberships for this group as iterable with paging support. 222 * @param fields the fields to retrieve. 223 * @return an iterable with information about the group memberships for this group. 224 */ 225 public Iterable<BoxGroupMembership.Info> getAllMemberships(String ... fields) { 226 final QueryStringBuilder builder = new QueryStringBuilder(); 227 if (fields.length > 0) { 228 builder.appendParam("fields", fields); 229 } 230 return new Iterable<BoxGroupMembership.Info>() { 231 public Iterator<BoxGroupMembership.Info> iterator() { 232 URL url = MEMBERSHIPS_URL_TEMPLATE.buildWithQuery( 233 BoxGroup.this.getAPI().getBaseURL(), builder.toString(), BoxGroup.this.getID()); 234 return new BoxGroupMembershipIterator(BoxGroup.this.getAPI(), url); 235 } 236 }; 237 } 238 239 /** 240 * Adds a member to this group with the default role. 241 * @param user the member to be added to this group. 242 * @return info about the new group membership. 243 */ 244 public BoxGroupMembership.Info addMembership(BoxUser user) { 245 return this.addMembership(user, null); 246 } 247 248 /** 249 * Adds a member to this group with the specified role. 250 * @param user the member to be added to this group. 251 * @param role the role of the user in this group. Can be null to assign the default role. 252 * @return info about the new group membership. 253 */ 254 public BoxGroupMembership.Info addMembership(BoxUser user, Role role) { 255 BoxAPIConnection api = this.getAPI(); 256 257 JsonObject requestJSON = new JsonObject(); 258 requestJSON.add("user", new JsonObject().add("id", user.getID())); 259 requestJSON.add("group", new JsonObject().add("id", this.getID())); 260 if (role != null) { 261 requestJSON.add("role", role.toJSONString()); 262 } 263 264 URL url = ADD_MEMBERSHIP_URL_TEMPLATE.build(api.getBaseURL()); 265 BoxJSONRequest request = new BoxJSONRequest(api, url, "POST"); 266 request.setBody(requestJSON.toString()); 267 BoxJSONResponse response = (BoxJSONResponse) request.send(); 268 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 269 270 BoxGroupMembership membership = new BoxGroupMembership(api, responseJSON.get("id").asString()); 271 return membership.new Info(responseJSON); 272 } 273 274 /** 275 * Gets information about all of the collaborations for this group. 276 * @return a collection of information about the collaborations for this group. 277 */ 278 public Collection<BoxCollaboration.Info> getCollaborations() { 279 BoxAPIConnection api = this.getAPI(); 280 URL url = COLLABORATIONS_URL_TEMPLATE.build(api.getBaseURL(), this.getID()); 281 282 BoxAPIRequest request = new BoxAPIRequest(api, url, "GET"); 283 BoxJSONResponse response = (BoxJSONResponse) request.send(); 284 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 285 286 int entriesCount = responseJSON.get("total_count").asInt(); 287 Collection<BoxCollaboration.Info> collaborations = new ArrayList<BoxCollaboration.Info>(entriesCount); 288 JsonArray entries = responseJSON.get("entries").asArray(); 289 for (JsonValue entry : entries) { 290 JsonObject entryObject = entry.asObject(); 291 BoxCollaboration collaboration = new BoxCollaboration(api, entryObject.get("id").asString()); 292 BoxCollaboration.Info info = collaboration.new Info(entryObject); 293 collaborations.add(info); 294 } 295 296 return collaborations; 297 } 298 299 /** 300 * Deletes this group. 301 */ 302 public void delete() { 303 URL url = GROUP_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 304 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 305 BoxAPIResponse response = request.send(); 306 response.disconnect(); 307 } 308 309 /** 310 * Updates the information about this group with any info fields that have been modified locally. 311 * @param info the updated info. 312 */ 313 public void updateInfo(BoxGroup.Info info) { 314 URL url = GROUP_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 315 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 316 request.setBody(info.getPendingChanges()); 317 BoxJSONResponse response = (BoxJSONResponse) request.send(); 318 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 319 info.update(jsonObject); 320 } 321 322 /** 323 * Contains information about a BoxGroup. 324 */ 325 public class Info extends BoxCollaborator.Info { 326 327 /** 328 * @see #getProvenance() 329 */ 330 private String provenance; 331 332 /** 333 * @see #getExternalSyncIdentifier() 334 */ 335 private String externalSyncIdentifier; 336 337 /** 338 * @see #getDescription() 339 */ 340 private String description; 341 342 /** 343 * @see #getInvitabilityLevel() 344 */ 345 private String invitabilityLevel; 346 347 /** 348 * @see #getMemberViewabilityLevel() 349 */ 350 private String memberViewabilityLevel; 351 352 /** 353 * Constructs an empty Info object. 354 */ 355 public Info() { 356 super(); 357 } 358 359 /** 360 * Constructs an Info object by parsing information from a JSON string. 361 * @param json the JSON string to parse. 362 */ 363 public Info(String json) { 364 super(json); 365 } 366 367 /** 368 * Constructs an Info object using an already parsed JSON object. 369 * @param jsonObject the parsed JSON object. 370 */ 371 Info(JsonObject jsonObject) { 372 super(jsonObject); 373 } 374 375 /** 376 * {@inheritDoc} 377 */ 378 @Override 379 public BoxGroup getResource() { 380 return BoxGroup.this; 381 } 382 383 /** 384 * {@inheritDoc} 385 */ 386 @Override 387 protected void parseJSONMember(JsonObject.Member member) { 388 super.parseJSONMember(member); 389 390 String memberName = member.getName(); 391 JsonValue value = member.getValue(); 392 if (memberName.equals("description")) { 393 this.description = value.asString(); 394 } else if (memberName.equals("external_sync_identifier")) { 395 this.externalSyncIdentifier = value.asString(); 396 } else if (memberName.equals("invitability_level")) { 397 this.invitabilityLevel = value.asString(); 398 } else if (memberName.equals("member_viewability_level")) { 399 this.memberViewabilityLevel = value.asString(); 400 } else if (memberName.equals("provenance")) { 401 this.provenance = value.asString(); 402 } 403 } 404 405 /** 406 * Gets the description for the group. 407 * @return the description for the group. 408 */ 409 public String getDescription() { 410 return this.description; 411 } 412 413 /** 414 * Sets the description for the group. 415 * @param description the description for the group. 416 */ 417 public void setDescription(String description) { 418 this.description = description; 419 addPendingChange("description", description); 420 } 421 422 /** 423 * Gets the external_sync_identifier for the group. 424 * @return the external_sync_identifier for the group. 425 */ 426 public String getExternalSyncIdentifier() { 427 return this.externalSyncIdentifier; 428 } 429 430 /** 431 * Sets the external_sync_identifier for the group. 432 * @param externalSyncIdentifier the external_sync_identifier for the group. 433 */ 434 public void setExternalSyncIdentifier(String externalSyncIdentifier) { 435 this.externalSyncIdentifier = externalSyncIdentifier; 436 addPendingChange("external_sync_identifier", externalSyncIdentifier); 437 } 438 439 /** 440 * Gets the invitability_level for the group. 441 * @return the invitability_level for the group. 442 */ 443 public String getInvitabilityLevel() { 444 return this.invitabilityLevel; 445 } 446 447 /** 448 * Sets the invitability_level for the group. 449 * @param invitabilityLevel the invitability_level for the group. 450 */ 451 public void setInvitabilityLevel(String invitabilityLevel) { 452 this.invitabilityLevel = invitabilityLevel; 453 addPendingChange("invitability_level", invitabilityLevel); 454 } 455 456 /** 457 * Gets the member_viewability_level for the group. 458 * @return the member_viewability_level for the group. 459 */ 460 public String getMemberViewabilityLevel() { 461 return this.memberViewabilityLevel; 462 } 463 464 /** 465 * Sets the member_viewability_level for the group. 466 * @param memberViewabilityLevel the member_viewability_level for the group. 467 */ 468 public void setMemberViewabilityLevel(String memberViewabilityLevel) { 469 this.memberViewabilityLevel = memberViewabilityLevel; 470 addPendingChange("member_viewability_level", memberViewabilityLevel); 471 } 472 473 /** 474 * Gets the provenance for the group. 475 * @return the provenance for the group. 476 */ 477 public String getProvenance() { 478 return this.provenance; 479 } 480 481 /** 482 * Sets the provenance for the group. 483 * @param provenance the provenance for the group. 484 */ 485 public void setProvenance(String provenance) { 486 this.provenance = provenance; 487 addPendingChange("provenance", provenance); 488 } 489 } 490}