001package com.box.sdk; 002 003import java.net.URL; 004import java.util.ArrayList; 005import java.util.List; 006 007import com.eclipsesource.json.JsonArray; 008import com.eclipsesource.json.JsonObject; 009import com.eclipsesource.json.JsonValue; 010 011/** 012 * The MetadataTemplate class represents the Box metadata template object. 013 * Templates allow the metadata service to provide a multitude of services, 014 * such as pre-defining sets of key:value pairs or schema enforcement on specific fields. 015 * 016 * @see <a href="https://developer.box.com/reference/resources/metadata-templates/">Box metadata templates</a> 017 */ 018public class MetadataTemplate extends BoxJSONObject { 019 020 /** 021 * @see #getMetadataTemplate(BoxAPIConnection) 022 */ 023 public static final URLTemplate METADATA_TEMPLATE_URL_TEMPLATE 024 = new URLTemplate("metadata_templates/%s/%s/schema"); 025 026 /** 027 * @see #getMetadataTemplateByID(BoxAPIConnection, String) 028 */ 029 public static final URLTemplate METADATA_TEMPLATE_BY_ID_URL_TEMPLATE = new URLTemplate("metadata_templates/%s"); 030 031 /** 032 * @see #createMetadataTemplate(BoxAPIConnection, String, String, String, boolean, List) 033 */ 034 public static final URLTemplate METADATA_TEMPLATE_SCHEMA_URL_TEMPLATE 035 = new URLTemplate("metadata_templates/schema"); 036 037 /** 038 * @see #getEnterpriseMetadataTemplates(String, int, BoxAPIConnection, String...) 039 */ 040 public static final URLTemplate ENTERPRISE_METADATA_URL_TEMPLATE = new URLTemplate("metadata_templates/%s"); 041 042 /** 043 * 044 */ 045 private static final URLTemplate METADATA_QUERIES_URL_TEMPLATE = new URLTemplate("metadata_queries/execute_read"); 046 047 /** 048 * Default metadata type to be used in query. 049 */ 050 private static final String DEFAULT_METADATA_TYPE = "properties"; 051 052 /** 053 * Global metadata scope. Used by default if the metadata type is "properties". 054 */ 055 private static final String GLOBAL_METADATA_SCOPE = "global"; 056 057 /** 058 * Enterprise metadata scope. Used by default if the metadata type is not "properties". 059 */ 060 private static final String ENTERPRISE_METADATA_SCOPE = "enterprise"; 061 062 /** 063 * Default number of entries per page. 064 */ 065 private static final int DEFAULT_ENTRIES_LIMIT = 100; 066 067 /** 068 * @see #getID() 069 */ 070 private String id; 071 072 /** 073 * @see #getTemplateKey() 074 */ 075 private String templateKey; 076 077 /** 078 * @see #getScope() 079 */ 080 private String scope; 081 082 /** 083 * @see #getDisplayName() 084 */ 085 private String displayName; 086 087 /** 088 * @see #getIsHidden() 089 */ 090 private Boolean isHidden; 091 092 /** 093 * @see #getFields() 094 */ 095 private List<Field> fields; 096 097 /** 098 * @see #getCopyInstanceOnItemCopy() 099 */ 100 private Boolean copyInstanceOnItemCopy; 101 102 /** 103 * Constructs an empty metadata template. 104 */ 105 public MetadataTemplate() { 106 super(); 107 } 108 109 /** 110 * Constructs a metadata template from a JSON string. 111 * @param json the json encoded metadate template. 112 */ 113 public MetadataTemplate(String json) { 114 super(json); 115 } 116 117 /** 118 * Constructs a metadate template from a JSON object. 119 * @param jsonObject the json encoded metadate template. 120 */ 121 MetadataTemplate(JsonObject jsonObject) { 122 super(jsonObject); 123 } 124 125 /** 126 * Gets the ID of the template. 127 * @return the template ID. 128 */ 129 public String getID() { 130 return this.id; 131 } 132 133 /** 134 * Gets the unique template key to identify the metadata template. 135 * @return the unique template key to identify the metadata template. 136 */ 137 public String getTemplateKey() { 138 return this.templateKey; 139 } 140 141 /** 142 * Gets the metadata template scope. 143 * @return the metadata template scope. 144 */ 145 public String getScope() { 146 return this.scope; 147 } 148 149 /** 150 * Gets the displayed metadata template name. 151 * @return the displayed metadata template name. 152 */ 153 public String getDisplayName() { 154 return this.displayName; 155 } 156 157 /** 158 * Gets is the metadata template hidden. 159 * @return is the metadata template hidden. 160 */ 161 public Boolean getIsHidden() { 162 return this.isHidden; 163 } 164 165 /** 166 * Gets the iterable with all fields the metadata template contains. 167 * @return the iterable with all fields the metadata template contains. 168 */ 169 public List<Field> getFields() { 170 return this.fields; 171 } 172 173 /** 174 * Gets whether the copy operation should copy the metadata along with the item. 175 * @return whether the copy operation should copy the metadata along with the item. 176 */ 177 public Boolean getCopyInstanceOnItemCopy() { 178 return this.copyInstanceOnItemCopy; 179 } 180 181 /** 182 * {@inheritDoc} 183 */ 184 @Override 185 void parseJSONMember(JsonObject.Member member) { 186 JsonValue value = member.getValue(); 187 String memberName = member.getName(); 188 if (memberName.equals("templateKey")) { 189 this.templateKey = value.asString(); 190 } else if (memberName.equals("scope")) { 191 this.scope = value.asString(); 192 } else if (memberName.equals("displayName")) { 193 this.displayName = value.asString(); 194 } else if (memberName.equals("hidden")) { 195 this.isHidden = value.asBoolean(); 196 } else if (memberName.equals("fields")) { 197 this.fields = new ArrayList<Field>(); 198 for (JsonValue field: value.asArray()) { 199 this.fields.add(new Field(field.asObject())); 200 } 201 } else if (memberName.equals("id")) { 202 this.id = value.asString(); 203 } else if (memberName.equals("copyInstanceOnItemCopy")) { 204 this.copyInstanceOnItemCopy = value.asBoolean(); 205 } 206 } 207 208 /** 209 * Creates new metadata template. 210 * @param api the API connection to be used. 211 * @param scope the scope of the object. 212 * @param templateKey a unique identifier for the template. 213 * @param displayName the display name of the field. 214 * @param hidden whether this template is hidden in the UI. 215 * @param fields the ordered set of fields for the template 216 * @return the metadata template returned from the server. 217 */ 218 public static MetadataTemplate createMetadataTemplate(BoxAPIConnection api, String scope, String templateKey, 219 String displayName, boolean hidden, List<Field> fields) { 220 return createMetadataTemplate(api, scope, templateKey, displayName, hidden, fields, null); 221 } 222 223 /** 224 * Creates new metadata template. 225 * @param api the API connection to be used. 226 * @param scope the scope of the object. 227 * @param templateKey a unique identifier for the template. 228 * @param displayName the display name of the field. 229 * @param hidden whether this template is hidden in the UI. 230 * @param fields the ordered set of fields for the template 231 * @param copyInstanceOnItemCopy determines whether the copy operation should copy the metadata along with the item. 232 * @return the metadata template returned from the server. 233 */ 234 public static MetadataTemplate createMetadataTemplate(BoxAPIConnection api, String scope, String templateKey, 235 String displayName, Boolean hidden, List<Field> fields, Boolean copyInstanceOnItemCopy) { 236 237 JsonObject jsonObject = new JsonObject(); 238 jsonObject.add("scope", scope); 239 jsonObject.add("displayName", displayName); 240 241 if (hidden != null) { 242 jsonObject.add("hidden", hidden); 243 } 244 245 if (copyInstanceOnItemCopy != null) { 246 jsonObject.add("copyInstanceOnItemCopy", copyInstanceOnItemCopy); 247 } 248 249 if (templateKey != null) { 250 jsonObject.add("templateKey", templateKey); 251 } 252 253 JsonArray fieldsArray = new JsonArray(); 254 if (fields != null && !fields.isEmpty()) { 255 for (Field field : fields) { 256 JsonObject fieldObj = getFieldJsonObject(field); 257 258 fieldsArray.add(fieldObj); 259 } 260 261 jsonObject.add("fields", fieldsArray); 262 } 263 264 URL url = METADATA_TEMPLATE_SCHEMA_URL_TEMPLATE.build(api.getBaseURL()); 265 BoxJSONRequest request = new BoxJSONRequest(api, url, "POST"); 266 request.setBody(jsonObject.toString()); 267 268 BoxJSONResponse response = (BoxJSONResponse) request.send(); 269 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 270 271 return new MetadataTemplate(responseJSON); 272 } 273 274 /** 275 * Gets the JsonObject representation of the given field object. 276 * @param field represents a template field 277 * @return the json object 278 */ 279 private static JsonObject getFieldJsonObject(Field field) { 280 JsonObject fieldObj = new JsonObject(); 281 fieldObj.add("type", field.getType()); 282 fieldObj.add("key", field.getKey()); 283 fieldObj.add("displayName", field.getDisplayName()); 284 285 String fieldDesc = field.getDescription(); 286 if (fieldDesc != null) { 287 fieldObj.add("description", field.getDescription()); 288 } 289 290 Boolean fieldIsHidden = field.getIsHidden(); 291 if (fieldIsHidden != null) { 292 fieldObj.add("hidden", field.getIsHidden()); 293 } 294 295 JsonArray array = new JsonArray(); 296 List<String> options = field.getOptions(); 297 if (options != null && !options.isEmpty()) { 298 for (String option : options) { 299 JsonObject optionObj = new JsonObject(); 300 optionObj.add("key", option); 301 302 array.add(optionObj); 303 } 304 fieldObj.add("options", array); 305 } 306 307 return fieldObj; 308 } 309 310 /** 311 * Updates the schema of an existing metadata template. 312 * 313 * @param api the API connection to be used 314 * @param scope the scope of the object 315 * @param template Unique identifier of the template 316 * @param fieldOperations the fields that needs to be updated / added in the template 317 * @return the updated metadata template 318 */ 319 public static MetadataTemplate updateMetadataTemplate(BoxAPIConnection api, String scope, String template, 320 List<FieldOperation> fieldOperations) { 321 322 JsonArray array = new JsonArray(); 323 324 for (FieldOperation fieldOperation : fieldOperations) { 325 JsonObject jsonObject = getFieldOperationJsonObject(fieldOperation); 326 array.add(jsonObject); 327 } 328 329 QueryStringBuilder builder = new QueryStringBuilder(); 330 URL url = METADATA_TEMPLATE_URL_TEMPLATE.buildAlpha(api.getBaseURL(), scope, template); 331 BoxJSONRequest request = new BoxJSONRequest(api, url, "PUT"); 332 request.setBody(array.toString()); 333 334 BoxJSONResponse response = (BoxJSONResponse) request.send(); 335 JsonObject responseJson = JsonObject.readFrom(response.getJSON()); 336 337 return new MetadataTemplate(responseJson); 338 } 339 340 /** 341 * Deletes the schema of an existing metadata template. 342 * 343 * @param api the API connection to be used 344 * @param scope the scope of the object 345 * @param template Unique identifier of the template 346 */ 347 public static void deleteMetadataTemplate(BoxAPIConnection api, String scope, String template) { 348 349 URL url = METADATA_TEMPLATE_URL_TEMPLATE.buildAlpha(api.getBaseURL(), scope, template); 350 BoxJSONRequest request = new BoxJSONRequest(api, url, "DELETE"); 351 352 request.send(); 353 } 354 355 /** 356 * Executes a metadata query. 357 * 358 * @param api The API connection to be used 359 * @param from The template used in the query. Must be in the form scope.templateKey 360 * @param ancestorFolderId The folder_id to which to restrain the query 361 * @return An iterable of BoxMetadataQueryItem search results 362 * @deprecated use executeMetadataQuery() that returns BoxItem.Info instead. 363 */ 364 @Deprecated 365 public static BoxResourceIterable<BoxMetadataQueryItem> executeMetadataQuery(final BoxAPIConnection api, 366 String from, String ancestorFolderId) { 367 return executeMetadataQuery(api, from, null, null, ancestorFolderId, null, null, 100, null); 368 } 369 370 /** 371 * Executes a metadata query. 372 * 373 * @param api The API connection to be used 374 * @param from The template used in the query. Must be in the form scope.templateKey 375 * @param ancestorFolderId The folder_id to which to restrain the query 376 * @param fields The fields to retrieve. 377 * @return An iterable of BoxItem.Info search results 378 */ 379 public static BoxResourceIterable<BoxItem.Info> executeMetadataQuery(final BoxAPIConnection api, 380 String from, String ancestorFolderId, String ... fields) { 381 return executeMetadataQuery(api, from, null, null, ancestorFolderId, null, null, 100, null, fields); 382 } 383 384 /** 385 * Executes a metadata query. 386 * 387 * @param api The API connection to be used 388 * @param from The template used in the query. Must be in the form scope.templateKey 389 * @param query The logical expression of the query 390 * @param queryParameters Required if query present. The arguments for the query 391 * @param ancestorFolderId The folder_id to which to restrain the query 392 * @return An iterable of BoxMetadataQueryItem search results 393 * @deprecated use executeMetadataQuery() that returns BoxItem.Info instead. 394 */ 395 @Deprecated 396 public static BoxResourceIterable<BoxMetadataQueryItem> executeMetadataQuery(final BoxAPIConnection api, 397 String from, String query, JsonObject queryParameters, 398 String ancestorFolderId) { 399 return executeMetadataQuery(api, from, query, queryParameters, ancestorFolderId, null, null, 100, null); 400 } 401 402 /** 403 * Executes a metadata query. 404 * 405 * @param api The API connection to be used 406 * @param from The template used in the query. Must be in the form scope.templateKey 407 * @param query The logical expression of the query 408 * @param queryParameters Required if query present. The arguments for the query 409 * @param ancestorFolderId The folder_id to which to restrain the query 410 * @param fields The fields to retrieve. 411 * @return An iterable of BoxItem.Info search results 412 */ 413 public static BoxResourceIterable<BoxItem.Info> executeMetadataQuery(final BoxAPIConnection api, 414 String from, String query, JsonObject queryParameters, 415 String ancestorFolderId, String ... fields) { 416 return executeMetadataQuery(api, from, query, queryParameters, ancestorFolderId, null, null, 100, null, fields); 417 } 418 419 /** 420 * Executes a metadata query. 421 * 422 * @param api The API connection to be used 423 * @param from The template used in the query. Must be in the form scope.templateKey 424 * @param query The logical expression of the query 425 * @param queryParameters Required if query present. The arguments for the query 426 * @param ancestorFolderId The folder_id to which to restrain the query 427 * @param indexName The name of the Index to use 428 * @param orderBy The field_key(s) to order on and the corresponding direction(s) 429 * @return An iterable of BoxMetadataQueryItem search results 430 * @deprecated use executeMetadataQuery() that returns BoxItem.Info instead. 431 */ 432 @Deprecated 433 public static BoxResourceIterable<BoxMetadataQueryItem> executeMetadataQuery(final BoxAPIConnection api, 434 String from, String query, JsonObject queryParameters, 435 String ancestorFolderId, String indexName, 436 JsonArray orderBy) { 437 return executeMetadataQuery(api, from, query, queryParameters, ancestorFolderId, indexName, orderBy, 100, null); 438 } 439 440 /** 441 * Executes a metadata query. 442 * 443 * @param api The API connection to be used 444 * @param from The template used in the query. Must be in the form scope.templateKey 445 * @param query The logical expression of the query 446 * @param queryParameters Required if query present. The arguments for the query 447 * @param ancestorFolderId The folder_id to which to restrain the query 448 * @param indexName The name of the Index to use 449 * @param orderBy The field_key(s) to order on and the corresponding direction(s) 450 * @param fields The fields to retrieve. 451 * @return An iterable of BoxItem.Info search results 452 */ 453 public static BoxResourceIterable<BoxItem.Info> executeMetadataQuery(final BoxAPIConnection api, 454 String from, String query, JsonObject queryParameters, 455 String ancestorFolderId, String indexName, 456 JsonArray orderBy, String ... fields) { 457 return executeMetadataQuery(api, from, query, queryParameters, ancestorFolderId, indexName, orderBy, 100, 458 null, fields); 459 } 460 461 /** 462 * Executes a metadata query. 463 * 464 * @param api The API connection to be used 465 * @param from The template used in the query. Must be in the form scope.templateKey 466 * @param query The logical expression of the query 467 * @param queryParameters Required if query present. The arguments for the query 468 * @param ancestorFolderId The folder_id to which to restrain the query 469 * @param indexName The name of the Index to use 470 * @param orderBy The field_key(s) to order on and the corresponding direction(s) 471 * @param limit Max results to return for a single request (0-100 inclusive) 472 * @param marker The marker to use for requesting the next page 473 * @return An iterable of BoxMetadataQueryItem search results 474 * @deprecated use executeMetadataQuery() that returns BoxItem.Info instead. 475 */ 476 @Deprecated 477 public static BoxResourceIterable<BoxMetadataQueryItem> executeMetadataQuery(final BoxAPIConnection api, 478 String from, String query, JsonObject queryParameters, 479 String ancestorFolderId, String indexName, 480 JsonArray orderBy, int limit, String marker) { 481 JsonObject jsonObject = createMetadataQueryBody(from, query, queryParameters, ancestorFolderId, 482 indexName, orderBy, limit, marker); 483 484 URL url = METADATA_QUERIES_URL_TEMPLATE.build(api.getBaseURL()); 485 return new BoxResourceIterable<BoxMetadataQueryItem>(api, url, limit, jsonObject, marker) { 486 487 @Override 488 protected BoxMetadataQueryItem factory(JsonObject jsonObject) { 489 return new BoxMetadataQueryItem(jsonObject, api); 490 } 491 }; 492 } 493 494 /** 495 * Executes a metadata query. 496 * 497 * @param api The API connection to be used 498 * @param from The template used in the query. Must be in the form scope.templateKey 499 * @param query The logical expression of the query 500 * @param queryParameters Required if query present. The arguments for the query 501 * @param ancestorFolderId The folder_id to which to restrain the query 502 * @param indexName The name of the Index to use 503 * @param orderBy The field_key(s) to order on and the corresponding direction(s) 504 * @param limit Max results to return for a single request (0-100 inclusive) 505 * @param marker The marker to use for requesting the next page 506 * @param fields The fields to retrieve. 507 * @return An iterable of BoxItem.Info search results 508 */ 509 //CHECKSTYLE:OFF 510 public static BoxResourceIterable<BoxItem.Info> executeMetadataQuery(final BoxAPIConnection api, 511 String from, String query, JsonObject queryParameters, 512 String ancestorFolderId, String indexName, 513 JsonArray orderBy, int limit, String marker, 514 String ... fields) { 515 //CHECKSTYLE:ON 516 JsonObject jsonObject = createMetadataQueryBody(from, query, queryParameters, ancestorFolderId, 517 indexName, orderBy, limit, marker, fields); 518 519 URL url = METADATA_QUERIES_URL_TEMPLATE.build(api.getBaseURL()); 520 return new BoxResourceIterable<BoxItem.Info>(api, url, limit, jsonObject, marker) { 521 522 @Override 523 protected BoxItem.Info factory(JsonObject jsonObject) { 524 String type = jsonObject.get("type").asString(); 525 String id = jsonObject.get("id").asString(); 526 527 BoxItem.Info nextItemInfo; 528 if (type.equals("folder")) { 529 BoxFolder folder = new BoxFolder(api, id); 530 nextItemInfo = folder.new Info(jsonObject); 531 } else if (type.equals("file")) { 532 BoxFile file = new BoxFile(api, id); 533 nextItemInfo = file.new Info(jsonObject); 534 } else if (type.equals("web_link")) { 535 BoxWebLink link = new BoxWebLink(api, id); 536 nextItemInfo = link.new Info(jsonObject); 537 } else { 538 assert false : "Unsupported item type: " + type; 539 throw new BoxAPIException("Unsupported item type: " + type); 540 } 541 542 return nextItemInfo; 543 } 544 }; 545 } 546 547 /** 548 * Create JSON body for metadata query. 549 * 550 * @param from The template used in the query. Must be in the form scope.templateKey 551 * @param query The logical expression of the query 552 * @param queryParameters Required if query present. The arguments for the query 553 * @param ancestorFolderId The folder_id to which to restrain the query 554 * @param indexName The name of the Index to use 555 * @param orderBy The field_key(s) to order on and the corresponding direction(s) 556 * @param limit Max results to return for a single request (0-100 inclusive) 557 * @param marker The marker to use for requesting the next page 558 * @param fields The fields to retrieve. 559 * @return A JSON object that is the body 560 */ 561 private static JsonObject createMetadataQueryBody(String from, String query, JsonObject queryParameters, 562 String ancestorFolderId, String indexName, 563 JsonArray orderBy, int limit, String marker, 564 String ... fields) { 565 JsonObject jsonObject = new JsonObject().add("from", from); 566 if (query != null) { 567 jsonObject.add("query", query); 568 } 569 if (queryParameters != null) { 570 jsonObject.add("query_params", queryParameters); 571 } 572 if (ancestorFolderId != null) { 573 jsonObject.add("ancestor_folder_id", ancestorFolderId); 574 } 575 if (indexName != null) { 576 jsonObject.add("use_index", indexName); 577 } 578 if (orderBy != null) { 579 jsonObject.add("order_by", orderBy); 580 } 581 if (fields != null && fields.length > 0) { 582 JsonArray fieldsBody = new JsonArray(); 583 for (String field : fields) { 584 fieldsBody.add(field); 585 } 586 jsonObject.add("fields", fieldsBody); 587 } 588 jsonObject.add("limit", limit); 589 if (marker != null) { 590 jsonObject.add("marker", marker); 591 } 592 return jsonObject; 593 } 594 595 /** 596 * Gets the JsonObject representation of the Field Operation. 597 * @param fieldOperation represents the template update operation 598 * @return the json object 599 */ 600 private static JsonObject getFieldOperationJsonObject(FieldOperation fieldOperation) { 601 JsonObject jsonObject = new JsonObject(); 602 jsonObject.add("op", fieldOperation.getOp().toString()); 603 604 String fieldKey = fieldOperation.getFieldKey(); 605 if (fieldKey != null) { 606 jsonObject.add("fieldKey", fieldKey); 607 } 608 609 Field field = fieldOperation.getData(); 610 if (field != null) { 611 JsonObject fieldObj = new JsonObject(); 612 613 String type = field.getType(); 614 if (type != null) { 615 fieldObj.add("type", type); 616 } 617 618 String key = field.getKey(); 619 if (key != null) { 620 fieldObj.add("key", key); 621 } 622 623 String displayName = field.getDisplayName(); 624 if (displayName != null) { 625 fieldObj.add("displayName", displayName); 626 } 627 628 String description = field.getDescription(); 629 if (description != null) { 630 fieldObj.add("description", description); 631 } 632 633 Boolean hidden = field.getIsHidden(); 634 if (hidden != null) { 635 fieldObj.add("hidden", hidden); 636 } 637 638 List<String> options = field.getOptions(); 639 if (options != null) { 640 JsonArray array = new JsonArray(); 641 for (String option: options) { 642 JsonObject optionObj = new JsonObject(); 643 optionObj.add("key", option); 644 645 array.add(optionObj); 646 } 647 648 fieldObj.add("options", array); 649 } 650 651 Boolean copyInstanceOnItemCopy = field.getCopyInstanceOnItemCopy(); 652 if (copyInstanceOnItemCopy != null) { 653 fieldObj.add("copyInstanceOnItemCopy", copyInstanceOnItemCopy); 654 } 655 656 jsonObject.add("data", fieldObj); 657 } 658 659 List<String> fieldKeys = fieldOperation.getFieldKeys(); 660 if (fieldKeys != null) { 661 jsonObject.add("fieldKeys", getJsonArray(fieldKeys)); 662 } 663 664 List<String> enumOptionKeys = fieldOperation.getEnumOptionKeys(); 665 if (enumOptionKeys != null) { 666 jsonObject.add("enumOptionKeys", getJsonArray(enumOptionKeys)); 667 } 668 669 String enumOptionKey = fieldOperation.getEnumOptionKey(); 670 if (enumOptionKey != null) { 671 jsonObject.add("enumOptionKey", enumOptionKey); 672 } 673 674 String multiSelectOptionKey = fieldOperation.getMultiSelectOptionKey(); 675 if (multiSelectOptionKey != null) { 676 jsonObject.add("multiSelectOptionKey", multiSelectOptionKey); 677 } 678 679 List<String> multiSelectOptionKeys = fieldOperation.getMultiSelectOptionKeys(); 680 if (multiSelectOptionKeys != null) { 681 jsonObject.add("multiSelectOptionKeys", getJsonArray(multiSelectOptionKeys)); 682 } 683 684 return jsonObject; 685 } 686 687 /** 688 * Gets the Json Array representation of the given list of strings. 689 * @param keys List of strings 690 * @return the JsonArray represents the list of keys 691 */ 692 private static JsonArray getJsonArray(List<String> keys) { 693 JsonArray array = new JsonArray(); 694 for (String key : keys) { 695 array.add(key); 696 } 697 698 return array; 699 } 700 701 /** 702 * Gets the metadata template of properties. 703 * @param api the API connection to be used. 704 * @return the metadata template returned from the server. 705 */ 706 public static MetadataTemplate getMetadataTemplate(BoxAPIConnection api) { 707 return getMetadataTemplate(api, DEFAULT_METADATA_TYPE); 708 } 709 710 /** 711 * Gets the metadata template of specified template type. 712 * @param api the API connection to be used. 713 * @param templateName the metadata template type name. 714 * @return the metadata template returned from the server. 715 */ 716 public static MetadataTemplate getMetadataTemplate(BoxAPIConnection api, String templateName) { 717 String scope = scopeBasedOnType(templateName); 718 return getMetadataTemplate(api, templateName, scope); 719 } 720 721 /** 722 * Gets the metadata template of specified template type. 723 * @param api the API connection to be used. 724 * @param templateName the metadata template type name. 725 * @param scope the metadata template scope (global or enterprise). 726 * @param fields the fields to retrieve. 727 * @return the metadata template returned from the server. 728 */ 729 public static MetadataTemplate getMetadataTemplate( 730 BoxAPIConnection api, String templateName, String scope, String ... fields) { 731 QueryStringBuilder builder = new QueryStringBuilder(); 732 if (fields.length > 0) { 733 builder.appendParam("fields", fields); 734 } 735 URL url = METADATA_TEMPLATE_URL_TEMPLATE.buildAlphaWithQuery( 736 api.getBaseURL(), builder.toString(), scope, templateName); 737 BoxAPIRequest request = new BoxAPIRequest(api, url, "GET"); 738 BoxJSONResponse response = (BoxJSONResponse) request.send(); 739 return new MetadataTemplate(response.getJSON()); 740 } 741 742 /** 743 * Geta the specified metadata template by its ID. 744 * @param api the API connection to be used. 745 * @param templateID the ID of the template to get. 746 * @return the metadata template object. 747 */ 748 public static MetadataTemplate getMetadataTemplateByID(BoxAPIConnection api, String templateID) { 749 750 URL url = METADATA_TEMPLATE_BY_ID_URL_TEMPLATE.buildAlpha(api.getBaseURL(), templateID); 751 BoxAPIRequest request = new BoxAPIRequest(api, url, "GET"); 752 BoxJSONResponse response = (BoxJSONResponse) request.send(); 753 return new MetadataTemplate(response.getJSON()); 754 } 755 756 /** 757 * Returns all metadata templates within a user's enterprise. 758 * @param api the API connection to be used. 759 * @param fields the fields to retrieve. 760 * @return the metadata template returned from the server. 761 */ 762 public static Iterable<MetadataTemplate> getEnterpriseMetadataTemplates(BoxAPIConnection api, String ... fields) { 763 return getEnterpriseMetadataTemplates(ENTERPRISE_METADATA_SCOPE, api, fields); 764 } 765 766 /** 767 * Returns all metadata templates within a user's scope. Currently only the enterprise scope is supported. 768 * @param scope the scope of the metadata templates. 769 * @param api the API connection to be used. 770 * @param fields the fields to retrieve. 771 * @return the metadata template returned from the server. 772 */ 773 public static Iterable<MetadataTemplate> getEnterpriseMetadataTemplates( 774 String scope, BoxAPIConnection api, String ... fields) { 775 return getEnterpriseMetadataTemplates(ENTERPRISE_METADATA_SCOPE, DEFAULT_ENTRIES_LIMIT, api, fields); 776 } 777 778 /** 779 * Returns all metadata templates within a user's scope. Currently only the enterprise scope is supported. 780 * @param scope the scope of the metadata templates. 781 * @param limit maximum number of entries per response. 782 * @param api the API connection to be used. 783 * @param fields the fields to retrieve. 784 * @return the metadata template returned from the server. 785 */ 786 public static Iterable<MetadataTemplate> getEnterpriseMetadataTemplates( 787 String scope, int limit, BoxAPIConnection api, String ... fields) { 788 QueryStringBuilder builder = new QueryStringBuilder(); 789 if (fields.length > 0) { 790 builder.appendParam("fields", fields); 791 } 792 return new BoxResourceIterable<MetadataTemplate>( 793 api, ENTERPRISE_METADATA_URL_TEMPLATE.buildAlphaWithQuery( 794 api.getBaseURL(), builder.toString(), scope), limit) { 795 796 @Override 797 protected MetadataTemplate factory(JsonObject jsonObject) { 798 return new MetadataTemplate(jsonObject); 799 } 800 }; 801 } 802 803 /** 804 * Determines the metadata scope based on type. 805 * @param typeName type of the metadata. 806 * @return scope of the metadata. 807 */ 808 private static String scopeBasedOnType(String typeName) { 809 return typeName.equals(DEFAULT_METADATA_TYPE) ? GLOBAL_METADATA_SCOPE : ENTERPRISE_METADATA_SCOPE; 810 } 811 812 /** 813 * Class contains information about the metadata template field. 814 */ 815 public static class Field extends BoxJSONObject { 816 817 /** 818 * @see #getID() 819 */ 820 private String id; 821 822 /** 823 * @see #getType() 824 */ 825 private String type; 826 827 /** 828 * @see #getKey() 829 */ 830 private String key; 831 832 /** 833 * @see #getDisplayName() 834 */ 835 private String displayName; 836 837 /** 838 * @see #getIsHidden() 839 */ 840 private Boolean isHidden; 841 842 /** 843 * @see #getDescription() 844 */ 845 private String description; 846 847 /** 848 * @see #getOptionsObject() 849 */ 850 private List<Option> options; 851 852 /** 853 * @see #getCopyInstanceOnItemCopy() 854 */ 855 private Boolean copyInstanceOnItemCopy; 856 857 /** 858 * Constructs an empty metadata template. 859 */ 860 public Field() { 861 super(); 862 } 863 864 /** 865 * Constructs a metadate template field from a JSON string. 866 * @param json the json encoded metadate template field. 867 */ 868 public Field(String json) { 869 super(json); 870 } 871 872 /** 873 * Constructs a metadate template field from a JSON object. 874 * @param jsonObject the json encoded metadate template field. 875 */ 876 Field(JsonObject jsonObject) { 877 super(jsonObject); 878 } 879 880 /** 881 * Gets the ID of the template field. 882 * @return the template field ID. 883 */ 884 public String getID() { 885 return this.id; 886 } 887 888 /** 889 * Gets the data type of the field's value. 890 * @return the data type of the field's value. 891 */ 892 public String getType() { 893 return this.type; 894 } 895 896 /** 897 * Sets the data type of the field's value. 898 * @param type the data type of the field's value. 899 */ 900 public void setType(String type) { 901 this.type = type; 902 } 903 904 /** 905 * Gets the key of the field. 906 * @return the key of the field. 907 */ 908 public String getKey() { 909 return this.key; 910 } 911 912 /** 913 * Sets the key of the field. 914 * @param key the key of the field. 915 */ 916 public void setKey(String key) { 917 this.key = key; 918 } 919 920 /** 921 * Gets the display name of the field. 922 * @return the display name of the field. 923 */ 924 public String getDisplayName() { 925 return this.displayName; 926 } 927 928 /** 929 * Sets the display name of the field. 930 * @param displayName the display name of the field. 931 */ 932 public void setDisplayName(String displayName) { 933 this.displayName = displayName; 934 } 935 936 /** 937 * Gets is metadata template field hidden. 938 * @return is metadata template field hidden. 939 */ 940 public Boolean getIsHidden() { 941 return this.isHidden; 942 } 943 944 /** 945 * Sets is metadata template field hidden. 946 * @param isHidden is metadata template field hidden? 947 */ 948 public void setIsHidden(boolean isHidden) { 949 this.isHidden = isHidden; 950 } 951 952 /** 953 * Gets the description of the field. 954 * @return the description of the field. 955 */ 956 public String getDescription() { 957 return this.description; 958 } 959 960 /** 961 * Sets the description of the field. 962 * @param description the description of the field. 963 */ 964 public void setDescription(String description) { 965 this.description = description; 966 } 967 968 /** 969 * Gets list of possible options for enum type of the field. 970 * @return list of possible options for enum type of the field. 971 */ 972 public List<String> getOptions() { 973 if (this.options == null) { 974 return null; 975 } 976 List<String> optionsList = new ArrayList<String>(); 977 for (Option option : this.options) { 978 optionsList.add(option.getKey()); 979 } 980 return optionsList; 981 } 982 983 /** 984 * Gets list of possible options for options type of the field. 985 * @return list of possible options for option type of the field. 986 */ 987 public List<Option> getOptionsObjects() { 988 return this.options; 989 } 990 991 /** 992 * Sets list of possible options for enum type of the field. 993 * @param options list of possible options for enum type of the field. 994 */ 995 public void setOptions(List<String> options) { 996 if (options == null) { 997 this.options = null; 998 } 999 List<Option> optionList = new ArrayList<Option>(); 1000 for (String key : options) { 1001 JsonObject optionObject = new JsonObject(); 1002 optionObject.add("key", key); 1003 Option newOption = new Option(optionObject); 1004 optionList.add(newOption); 1005 } 1006 this.options = optionList; 1007 } 1008 1009 /** 1010 * Gets whether the copy operation should copy the metadata along with the item. 1011 * @return whether the copy operation should copy the metadata along with the item. 1012 */ 1013 public Boolean getCopyInstanceOnItemCopy() { 1014 return this.copyInstanceOnItemCopy; 1015 } 1016 1017 /** 1018 * Sets whether the copy operation should copy the metadata along with the item. 1019 * @param copyInstanceOnItemCopy whether the copy operation should copy the metadata along with the item. 1020 */ 1021 public void setCopyInstanceOnItemCopy(Boolean copyInstanceOnItemCopy) { 1022 this.copyInstanceOnItemCopy = copyInstanceOnItemCopy; 1023 } 1024 1025 /** 1026 * {@inheritDoc} 1027 */ 1028 @Override 1029 void parseJSONMember(JsonObject.Member member) { 1030 JsonValue value = member.getValue(); 1031 String memberName = member.getName(); 1032 if (memberName.equals("type")) { 1033 this.type = value.asString(); 1034 } else if (memberName.equals("key")) { 1035 this.key = value.asString(); 1036 } else if (memberName.equals("displayName")) { 1037 this.displayName = value.asString(); 1038 } else if (memberName.equals("hidden")) { 1039 this.isHidden = value.asBoolean(); 1040 } else if (memberName.equals("description")) { 1041 this.description = value.asString(); 1042 } else if (memberName.equals("options")) { 1043 this.options = new ArrayList<Option>(); 1044 for (JsonValue option : value.asArray()) { 1045 this.options.add(new Option(option.asObject())); 1046 } 1047 } else if (memberName.equals("id")) { 1048 this.id = value.asString(); 1049 } else if (memberName.equals("copyInstanceOnItemCopy")) { 1050 this.copyInstanceOnItemCopy = value.asBoolean(); 1051 } 1052 } 1053 } 1054 1055 /** 1056 * Class contains information about the metadata template option. 1057 */ 1058 public static class Option extends BoxJSONObject { 1059 /** 1060 * @see #getID() 1061 */ 1062 private String id; 1063 /** 1064 * @see #getKey() 1065 */ 1066 private String key; 1067 /** 1068 * Constructs an empty metadata template. 1069 */ 1070 public Option() { 1071 super(); 1072 } 1073 /** 1074 * Constructs a metadate template option from a JSON string. 1075 * @param json the json encoded metadata template option. 1076 */ 1077 public Option(String json) { 1078 super(json); 1079 } 1080 1081 /** 1082 * Constructs a metadate template option from a JSON object. 1083 * @param jsonObject the json encoded metadate template option. 1084 */ 1085 Option(JsonObject jsonObject) { 1086 super(jsonObject); 1087 } 1088 /** 1089 * Gets the ID of the template field. 1090 * @return the template field ID. 1091 */ 1092 public String getID() { 1093 return this.id; 1094 } 1095 /** 1096 * Gets the key of the field. 1097 * @return the key of the field. 1098 */ 1099 public String getKey() { 1100 return this.key; 1101 } 1102 1103 /** 1104 * {@inheritDoc} 1105 */ 1106 @Override 1107 void parseJSONMember(JsonObject.Member member) { 1108 JsonValue value = member.getValue(); 1109 String memberName = member.getName(); 1110 if (memberName.equals("id")) { 1111 this.id = value.asString(); 1112 } else if (memberName.equals("key")) { 1113 this.key = value.asString(); 1114 } 1115 } 1116 } 1117 1118 /** 1119 * Posssible operations that can be performed in a Metadata template. 1120 * <ul> 1121 * <li>Add an enum option</li> 1122 * <li>Edit an enum option</li> 1123 * <li>Remove an enum option</li> 1124 * <li>Add a field</li> 1125 * <li>Edit a field</li> 1126 * <li>Remove a field</li> 1127 * <li>Edit template</li> 1128 * <li>Reorder the enum option</li> 1129 * <li>Reorder the field list</li> 1130 * </ul> 1131 */ 1132 public static class FieldOperation extends BoxJSONObject { 1133 1134 private Operation op; 1135 private Field data; 1136 private String fieldKey; 1137 private List<String> fieldKeys; 1138 private List<String> enumOptionKeys; 1139 private String enumOptionKey; 1140 private String multiSelectOptionKey; 1141 private List<String> multiSelectOptionKeys; 1142 1143 /** 1144 * Constructs an empty FieldOperation. 1145 */ 1146 public FieldOperation() { 1147 super(); 1148 } 1149 1150 /** 1151 * Constructs a Field operation from a JSON string. 1152 * @param json the json encoded metadate template field. 1153 */ 1154 public FieldOperation(String json) { 1155 super(json); 1156 } 1157 1158 /** 1159 * Constructs a Field operation from a JSON object. 1160 * @param jsonObject the json encoded metadate template field. 1161 */ 1162 FieldOperation(JsonObject jsonObject) { 1163 super(jsonObject); 1164 } 1165 1166 /** 1167 * Gets the operation. 1168 * @return the operation 1169 */ 1170 public Operation getOp() { 1171 return this.op; 1172 } 1173 1174 /** 1175 * Gets the data associated with the operation. 1176 * @return the field object representing the data 1177 */ 1178 public Field getData() { 1179 return this.data; 1180 } 1181 1182 /** 1183 * Gets the field key. 1184 * @return the field key 1185 */ 1186 public String getFieldKey() { 1187 return this.fieldKey; 1188 } 1189 1190 /** 1191 * Gets the list of field keys. 1192 * @return the list of Strings 1193 */ 1194 public List<String> getFieldKeys() { 1195 return this.fieldKeys; 1196 } 1197 1198 /** 1199 * Gets the list of keys of the Enum options. 1200 * @return the list of Strings 1201 */ 1202 public List<String> getEnumOptionKeys() { 1203 return this.enumOptionKeys; 1204 } 1205 1206 /** 1207 * Sets the operation. 1208 * @param op the operation 1209 */ 1210 public void setOp(Operation op) { 1211 this.op = op; 1212 } 1213 1214 /** 1215 * Sets the data. 1216 * @param data the Field object representing the data 1217 */ 1218 public void setData(Field data) { 1219 this.data = data; 1220 } 1221 1222 /** 1223 * Sets the field key. 1224 * @param fieldKey the key of the field 1225 */ 1226 public void setFieldKey(String fieldKey) { 1227 this.fieldKey = fieldKey; 1228 } 1229 1230 /** 1231 * Sets the list of the field keys. 1232 * @param fieldKeys the list of strings 1233 */ 1234 public void setFieldKeys(List<String> fieldKeys) { 1235 this.fieldKeys = fieldKeys; 1236 } 1237 1238 /** 1239 * Sets the list of the enum option keys. 1240 * @param enumOptionKeys the list of Strings 1241 */ 1242 public void setEnumOptionKeys(List<String> enumOptionKeys) { 1243 this.enumOptionKeys = enumOptionKeys; 1244 } 1245 1246 /** 1247 * Gets the enum option key. 1248 * @return the enum option key 1249 */ 1250 public String getEnumOptionKey() { 1251 return this.enumOptionKey; 1252 } 1253 1254 /** 1255 * Sets the enum option key. 1256 * @param enumOptionKey the enum option key 1257 */ 1258 public void setEnumOptionKey(String enumOptionKey) { 1259 this.enumOptionKey = enumOptionKey; 1260 } 1261 1262 /** 1263 * Gets the multi-select option key. 1264 * @return the key. 1265 */ 1266 public String getMultiSelectOptionKey() { 1267 return this.multiSelectOptionKey; 1268 } 1269 1270 /** 1271 * Sets the multi-select option key. 1272 * @param key the key. 1273 */ 1274 public void setMultiSelectOptionKey(String key) { 1275 this.multiSelectOptionKey = key; 1276 } 1277 1278 /** 1279 * Gets the list of multiselect option keys. 1280 * @return the list of keys. 1281 */ 1282 public List<String> getMultiSelectOptionKeys() { 1283 return this.multiSelectOptionKeys; 1284 } 1285 1286 /** 1287 * Sets the multi-select option keys. 1288 * @param keys the list of keys. 1289 */ 1290 public void setMultiSelectOptionKeys(List<String> keys) { 1291 this.multiSelectOptionKeys = keys; 1292 } 1293 1294 /** 1295 * {@inheritDoc} 1296 */ 1297 @Override 1298 void parseJSONMember(JsonObject.Member member) { 1299 JsonValue value = member.getValue(); 1300 String memberName = member.getName(); 1301 if (memberName.equals("op")) { 1302 this.op = Operation.valueOf(value.asString()); 1303 } else if (memberName.equals("data")) { 1304 this.data = new Field(value.asObject()); 1305 } else if (memberName.equals("fieldKey")) { 1306 this.fieldKey = value.asString(); 1307 } else if (memberName.equals("fieldKeys")) { 1308 if (this.fieldKeys == null) { 1309 this.fieldKeys = new ArrayList<String>(); 1310 } else { 1311 this.fieldKeys.clear(); 1312 } 1313 1314 JsonArray array = value.asArray(); 1315 for (JsonValue jsonValue: array) { 1316 this.fieldKeys.add(jsonValue.asString()); 1317 } 1318 } else if (memberName.equals("enumOptionKeys")) { 1319 if (this.enumOptionKeys == null) { 1320 this.enumOptionKeys = new ArrayList<String>(); 1321 } else { 1322 this.enumOptionKeys.clear(); 1323 } 1324 1325 JsonArray array = value.asArray(); 1326 for (JsonValue jsonValue: array) { 1327 this.enumOptionKeys.add(jsonValue.asString()); 1328 } 1329 } else if (memberName.equals("enumOptionKey")) { 1330 this.enumOptionKey = value.asString(); 1331 } else if (memberName.equals("multiSelectOptionKey")) { 1332 this.multiSelectOptionKey = value.asString(); 1333 } else if (memberName.equals("multiSelectOptionKeys")) { 1334 this.multiSelectOptionKeys = new ArrayList<String>(); 1335 for (JsonValue key : value.asArray()) { 1336 this.multiSelectOptionKeys.add(key.asString()); 1337 } 1338 } 1339 } 1340 } 1341 1342 /** 1343 * Possible template operations. 1344 */ 1345 public enum Operation { 1346 1347 /** 1348 * Adds an enum option at the end of the enum option list for the specified field. 1349 */ 1350 addEnumOption, 1351 1352 /** 1353 * Edits the enum option. 1354 */ 1355 editEnumOption, 1356 1357 /** 1358 * Removes the specified enum option from the specified enum field. 1359 */ 1360 removeEnumOption, 1361 1362 /** 1363 * Adds a field at the end of the field list for the template. 1364 */ 1365 addField, 1366 1367 /** 1368 * Edits any number of the base properties of a field: displayName, hidden, description. 1369 */ 1370 editField, 1371 1372 /** 1373 * Removes the specified field from the template. 1374 */ 1375 removeField, 1376 1377 /** 1378 * Edits any number of the base properties of a template: displayName, hidden. 1379 */ 1380 editTemplate, 1381 1382 /** 1383 * Reorders the enum option list to match the requested enum option list. 1384 */ 1385 reorderEnumOptions, 1386 1387 /** 1388 * Reorders the field list to match the requested field list. 1389 */ 1390 reorderFields, 1391 1392 /** 1393 * Adds a new option to a multiselect field. 1394 */ 1395 addMultiSelectOption, 1396 1397 /** 1398 * Edits an existing option in a multiselect field. 1399 */ 1400 editMultiSelectOption, 1401 1402 /** 1403 * Removes an option from a multiselect field. 1404 */ 1405 removeMultiSelectOption, 1406 1407 /** 1408 * Changes the display order of options in a multiselect field. 1409 */ 1410 reorderMultiSelectOptions 1411 } 1412}