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