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 BoxItem.Info search results 362 */ 363 public static BoxResourceIterable<BoxItem.Info> executeMetadataQuery(final BoxAPIConnection api, 364 String from, String ancestorFolderId) { 365 return executeMetadataQuery(api, from, null, null, ancestorFolderId, null, null, 100, null, null); 366 } 367 368 /** 369 * Executes a metadata query. 370 * 371 * @param api The API connection to be used 372 * @param from The template used in the query. Must be in the form scope.templateKey 373 * @param ancestorFolderId The folder_id to which to restrain the query 374 * @param fields The fields to retrieve. 375 * @return An iterable of BoxItem.Info search results 376 */ 377 public static BoxResourceIterable<BoxItem.Info> executeMetadataQuery(final BoxAPIConnection api, 378 String from, String ancestorFolderId, String ... fields) { 379 return executeMetadataQuery(api, from, null, null, ancestorFolderId, null, null, 100, null, fields); 380 } 381 382 /** 383 * Executes a metadata query. 384 * 385 * @param api The API connection to be used 386 * @param from The template used in the query. Must be in the form scope.templateKey 387 * @param query The logical expression of the query 388 * @param queryParameters Required if query present. The arguments for the query 389 * @param ancestorFolderId The folder_id to which to restrain the query 390 * @return An iterable of BoxItem.Info search results 391 */ 392 public static BoxResourceIterable<BoxItem.Info> executeMetadataQuery(final BoxAPIConnection api, 393 String from, String query, JsonObject queryParameters, 394 String ancestorFolderId) { 395 return executeMetadataQuery(api, from, query, queryParameters, ancestorFolderId, null, null, 100, null, null); 396 } 397 398 /** 399 * Executes a metadata query. 400 * 401 * @param api The API connection to be used 402 * @param from The template used in the query. Must be in the form scope.templateKey 403 * @param query The logical expression of the query 404 * @param queryParameters Required if query present. The arguments for the query 405 * @param ancestorFolderId The folder_id to which to restrain the query 406 * @param fields The fields to retrieve. 407 * @return An iterable of BoxItem.Info search results 408 */ 409 public static BoxResourceIterable<BoxItem.Info> executeMetadataQuery(final BoxAPIConnection api, 410 String from, String query, JsonObject queryParameters, 411 String ancestorFolderId, String ... fields) { 412 return executeMetadataQuery(api, from, query, queryParameters, ancestorFolderId, null, null, 100, null, fields); 413 } 414 415 /** 416 * Executes a metadata query. 417 * 418 * @param api The API connection to be used 419 * @param from The template used in the query. Must be in the form scope.templateKey 420 * @param query The logical expression of the query 421 * @param queryParameters Required if query present. The arguments for the query 422 * @param ancestorFolderId The folder_id to which to restrain the query 423 * @param indexName The name of the Index to use 424 * @param orderBy The field_key(s) to order on and the corresponding direction(s) 425 * @return An iterable of BoxItem.Info search results 426 */ 427 public static BoxResourceIterable<BoxItem.Info> executeMetadataQuery(final BoxAPIConnection api, 428 String from, String query, JsonObject queryParameters, 429 String ancestorFolderId, String indexName, 430 JsonArray orderBy) { 431 return executeMetadataQuery(api, from, query, queryParameters, ancestorFolderId, indexName, orderBy, 100, 432 null, null); 433 } 434 435 /** 436 * Executes a metadata query. 437 * 438 * @param api The API connection to be used 439 * @param from The template used in the query. Must be in the form scope.templateKey 440 * @param query The logical expression of the query 441 * @param queryParameters Required if query present. The arguments for the query 442 * @param ancestorFolderId The folder_id to which to restrain the query 443 * @param indexName The name of the Index to use 444 * @param orderBy The field_key(s) to order on and the corresponding direction(s) 445 * @param fields The fields to retrieve. 446 * @return An iterable of BoxItem.Info search results 447 */ 448 public static BoxResourceIterable<BoxItem.Info> executeMetadataQuery(final BoxAPIConnection api, 449 String from, String query, JsonObject queryParameters, 450 String ancestorFolderId, String indexName, 451 JsonArray orderBy, String ... fields) { 452 return executeMetadataQuery(api, from, query, queryParameters, ancestorFolderId, indexName, orderBy, 100, 453 null, fields); 454 } 455 456 /** 457 * Executes a metadata query. 458 * 459 * @param api The API connection to be used 460 * @param from The template used in the query. Must be in the form scope.templateKey 461 * @param query The logical expression of the query 462 * @param queryParameters Required if query present. The arguments for the query 463 * @param ancestorFolderId The folder_id to which to restrain the query 464 * @param indexName The name of the Index to use 465 * @param orderBy The field_key(s) to order on and the corresponding direction(s) 466 * @param limit Max results to return for a single request (0-100 inclusive) 467 * @param marker The marker to use for requesting the next page 468 * @param fields The fields to retrieve. 469 * @return An iterable of BoxItem.Info search results 470 */ 471 //CHECKSTYLE:OFF 472 public static BoxResourceIterable<BoxItem.Info> executeMetadataQuery(final BoxAPIConnection api, 473 String from, String query, JsonObject queryParameters, 474 String ancestorFolderId, String indexName, 475 JsonArray orderBy, int limit, String marker, 476 String ... fields) { 477 //CHECKSTYLE:ON 478 JsonObject jsonObject = createMetadataQueryBody(from, query, queryParameters, ancestorFolderId, 479 indexName, orderBy, limit, marker, fields); 480 481 URL url = METADATA_QUERIES_URL_TEMPLATE.build(api.getBaseURL()); 482 return new BoxResourceIterable<BoxItem.Info>(api, url, limit, jsonObject, marker) { 483 484 @Override 485 protected BoxItem.Info factory(JsonObject jsonObject) { 486 String type = jsonObject.get("type").asString(); 487 String id = jsonObject.get("id").asString(); 488 489 BoxItem.Info nextItemInfo; 490 if (type.equals("folder")) { 491 BoxFolder folder = new BoxFolder(api, id); 492 nextItemInfo = folder.new Info(jsonObject); 493 } else if (type.equals("file")) { 494 BoxFile file = new BoxFile(api, id); 495 nextItemInfo = file.new Info(jsonObject); 496 } else if (type.equals("web_link")) { 497 BoxWebLink link = new BoxWebLink(api, id); 498 nextItemInfo = link.new Info(jsonObject); 499 } else { 500 assert false : "Unsupported item type: " + type; 501 throw new BoxAPIException("Unsupported item type: " + type); 502 } 503 504 return nextItemInfo; 505 } 506 }; 507 } 508 509 /** 510 * Create JSON body for metadata query. 511 * 512 * @param from The template used in the query. Must be in the form scope.templateKey 513 * @param query The logical expression of the query 514 * @param queryParameters Required if query present. The arguments for the query 515 * @param ancestorFolderId The folder_id to which to restrain the query 516 * @param indexName The name of the Index to use 517 * @param orderBy The field_key(s) to order on and the corresponding direction(s) 518 * @param limit Max results to return for a single request (0-100 inclusive) 519 * @param marker The marker to use for requesting the next page 520 * @param fields The fields to retrieve. 521 * @return A JSON object that is the body 522 */ 523 private static JsonObject createMetadataQueryBody(String from, String query, JsonObject queryParameters, 524 String ancestorFolderId, String indexName, 525 JsonArray orderBy, int limit, String marker, 526 String ... fields) { 527 JsonObject jsonObject = new JsonObject().add("from", from); 528 if (query != null) { 529 jsonObject.add("query", query); 530 } 531 if (queryParameters != null) { 532 jsonObject.add("query_params", queryParameters); 533 } 534 if (ancestorFolderId != null) { 535 jsonObject.add("ancestor_folder_id", ancestorFolderId); 536 } 537 if (indexName != null) { 538 jsonObject.add("use_index", indexName); 539 } 540 if (orderBy != null) { 541 jsonObject.add("order_by", orderBy); 542 } 543 if (fields != null && fields.length > 0) { 544 JsonArray fieldsBody = new JsonArray(); 545 for (String field : fields) { 546 fieldsBody.add(field); 547 } 548 jsonObject.add("fields", fieldsBody); 549 } 550 jsonObject.add("limit", limit); 551 if (marker != null) { 552 jsonObject.add("marker", marker); 553 } 554 return jsonObject; 555 } 556 557 /** 558 * Gets the JsonObject representation of the Field Operation. 559 * @param fieldOperation represents the template update operation 560 * @return the json object 561 */ 562 private static JsonObject getFieldOperationJsonObject(FieldOperation fieldOperation) { 563 JsonObject jsonObject = new JsonObject(); 564 jsonObject.add("op", fieldOperation.getOp().toString()); 565 566 String fieldKey = fieldOperation.getFieldKey(); 567 if (fieldKey != null) { 568 jsonObject.add("fieldKey", fieldKey); 569 } 570 571 Field field = fieldOperation.getData(); 572 if (field != null) { 573 JsonObject fieldObj = new JsonObject(); 574 575 String type = field.getType(); 576 if (type != null) { 577 fieldObj.add("type", type); 578 } 579 580 String key = field.getKey(); 581 if (key != null) { 582 fieldObj.add("key", key); 583 } 584 585 String displayName = field.getDisplayName(); 586 if (displayName != null) { 587 fieldObj.add("displayName", displayName); 588 } 589 590 String description = field.getDescription(); 591 if (description != null) { 592 fieldObj.add("description", description); 593 } 594 595 Boolean hidden = field.getIsHidden(); 596 if (hidden != null) { 597 fieldObj.add("hidden", hidden); 598 } 599 600 List<String> options = field.getOptions(); 601 if (options != null) { 602 JsonArray array = new JsonArray(); 603 for (String option: options) { 604 JsonObject optionObj = new JsonObject(); 605 optionObj.add("key", option); 606 607 array.add(optionObj); 608 } 609 610 fieldObj.add("options", array); 611 } 612 613 Boolean copyInstanceOnItemCopy = field.getCopyInstanceOnItemCopy(); 614 if (copyInstanceOnItemCopy != null) { 615 fieldObj.add("copyInstanceOnItemCopy", copyInstanceOnItemCopy); 616 } 617 618 jsonObject.add("data", fieldObj); 619 } 620 621 List<String> fieldKeys = fieldOperation.getFieldKeys(); 622 if (fieldKeys != null) { 623 jsonObject.add("fieldKeys", getJsonArray(fieldKeys)); 624 } 625 626 List<String> enumOptionKeys = fieldOperation.getEnumOptionKeys(); 627 if (enumOptionKeys != null) { 628 jsonObject.add("enumOptionKeys", getJsonArray(enumOptionKeys)); 629 } 630 631 String enumOptionKey = fieldOperation.getEnumOptionKey(); 632 if (enumOptionKey != null) { 633 jsonObject.add("enumOptionKey", enumOptionKey); 634 } 635 636 String multiSelectOptionKey = fieldOperation.getMultiSelectOptionKey(); 637 if (multiSelectOptionKey != null) { 638 jsonObject.add("multiSelectOptionKey", multiSelectOptionKey); 639 } 640 641 List<String> multiSelectOptionKeys = fieldOperation.getMultiSelectOptionKeys(); 642 if (multiSelectOptionKeys != null) { 643 jsonObject.add("multiSelectOptionKeys", getJsonArray(multiSelectOptionKeys)); 644 } 645 646 return jsonObject; 647 } 648 649 /** 650 * Gets the Json Array representation of the given list of strings. 651 * @param keys List of strings 652 * @return the JsonArray represents the list of keys 653 */ 654 private static JsonArray getJsonArray(List<String> keys) { 655 JsonArray array = new JsonArray(); 656 for (String key : keys) { 657 array.add(key); 658 } 659 660 return array; 661 } 662 663 /** 664 * Gets the metadata template of properties. 665 * @param api the API connection to be used. 666 * @return the metadata template returned from the server. 667 */ 668 public static MetadataTemplate getMetadataTemplate(BoxAPIConnection api) { 669 return getMetadataTemplate(api, DEFAULT_METADATA_TYPE); 670 } 671 672 /** 673 * Gets the metadata template of specified template type. 674 * @param api the API connection to be used. 675 * @param templateName the metadata template type name. 676 * @return the metadata template returned from the server. 677 */ 678 public static MetadataTemplate getMetadataTemplate(BoxAPIConnection api, String templateName) { 679 String scope = scopeBasedOnType(templateName); 680 return getMetadataTemplate(api, templateName, scope); 681 } 682 683 /** 684 * Gets the metadata template of specified template type. 685 * @param api the API connection to be used. 686 * @param templateName the metadata template type name. 687 * @param scope the metadata template scope (global or enterprise). 688 * @param fields the fields to retrieve. 689 * @return the metadata template returned from the server. 690 */ 691 public static MetadataTemplate getMetadataTemplate( 692 BoxAPIConnection api, String templateName, String scope, String ... fields) { 693 QueryStringBuilder builder = new QueryStringBuilder(); 694 if (fields.length > 0) { 695 builder.appendParam("fields", fields); 696 } 697 URL url = METADATA_TEMPLATE_URL_TEMPLATE.buildAlphaWithQuery( 698 api.getBaseURL(), builder.toString(), scope, templateName); 699 BoxAPIRequest request = new BoxAPIRequest(api, url, "GET"); 700 BoxJSONResponse response = (BoxJSONResponse) request.send(); 701 return new MetadataTemplate(response.getJSON()); 702 } 703 704 /** 705 * Geta the specified metadata template by its ID. 706 * @param api the API connection to be used. 707 * @param templateID the ID of the template to get. 708 * @return the metadata template object. 709 */ 710 public static MetadataTemplate getMetadataTemplateByID(BoxAPIConnection api, String templateID) { 711 712 URL url = METADATA_TEMPLATE_BY_ID_URL_TEMPLATE.buildAlpha(api.getBaseURL(), templateID); 713 BoxAPIRequest request = new BoxAPIRequest(api, url, "GET"); 714 BoxJSONResponse response = (BoxJSONResponse) request.send(); 715 return new MetadataTemplate(response.getJSON()); 716 } 717 718 /** 719 * Returns all metadata templates within a user's enterprise. 720 * @param api the API connection to be used. 721 * @param fields the fields to retrieve. 722 * @return the metadata template returned from the server. 723 */ 724 public static Iterable<MetadataTemplate> getEnterpriseMetadataTemplates(BoxAPIConnection api, String ... fields) { 725 return getEnterpriseMetadataTemplates(ENTERPRISE_METADATA_SCOPE, api, fields); 726 } 727 728 /** 729 * Returns all metadata templates within a user's scope. Currently only the enterprise scope is supported. 730 * @param scope the scope of the metadata templates. 731 * @param api the API connection to be used. 732 * @param fields the fields to retrieve. 733 * @return the metadata template returned from the server. 734 */ 735 public static Iterable<MetadataTemplate> getEnterpriseMetadataTemplates( 736 String scope, BoxAPIConnection api, String ... fields) { 737 return getEnterpriseMetadataTemplates(ENTERPRISE_METADATA_SCOPE, DEFAULT_ENTRIES_LIMIT, api, fields); 738 } 739 740 /** 741 * Returns all metadata templates within a user's scope. Currently only the enterprise scope is supported. 742 * @param scope the scope of the metadata templates. 743 * @param limit maximum number of entries per response. 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, int limit, BoxAPIConnection api, String ... fields) { 750 QueryStringBuilder builder = new QueryStringBuilder(); 751 if (fields.length > 0) { 752 builder.appendParam("fields", fields); 753 } 754 return new BoxResourceIterable<MetadataTemplate>( 755 api, ENTERPRISE_METADATA_URL_TEMPLATE.buildAlphaWithQuery( 756 api.getBaseURL(), builder.toString(), scope), limit) { 757 758 @Override 759 protected MetadataTemplate factory(JsonObject jsonObject) { 760 return new MetadataTemplate(jsonObject); 761 } 762 }; 763 } 764 765 /** 766 * Determines the metadata scope based on type. 767 * @param typeName type of the metadata. 768 * @return scope of the metadata. 769 */ 770 private static String scopeBasedOnType(String typeName) { 771 return typeName.equals(DEFAULT_METADATA_TYPE) ? GLOBAL_METADATA_SCOPE : ENTERPRISE_METADATA_SCOPE; 772 } 773 774 /** 775 * Class contains information about the metadata template field. 776 */ 777 public static class Field extends BoxJSONObject { 778 779 /** 780 * @see #getID() 781 */ 782 private String id; 783 784 /** 785 * @see #getType() 786 */ 787 private String type; 788 789 /** 790 * @see #getKey() 791 */ 792 private String key; 793 794 /** 795 * @see #getDisplayName() 796 */ 797 private String displayName; 798 799 /** 800 * @see #getIsHidden() 801 */ 802 private Boolean isHidden; 803 804 /** 805 * @see #getDescription() 806 */ 807 private String description; 808 809 /** 810 * @see #getOptionsObject() 811 */ 812 private List<Option> options; 813 814 /** 815 * @see #getCopyInstanceOnItemCopy() 816 */ 817 private Boolean copyInstanceOnItemCopy; 818 819 /** 820 * Constructs an empty metadata template. 821 */ 822 public Field() { 823 super(); 824 } 825 826 /** 827 * Constructs a metadate template field from a JSON string. 828 * @param json the json encoded metadate template field. 829 */ 830 public Field(String json) { 831 super(json); 832 } 833 834 /** 835 * Constructs a metadate template field from a JSON object. 836 * @param jsonObject the json encoded metadate template field. 837 */ 838 Field(JsonObject jsonObject) { 839 super(jsonObject); 840 } 841 842 /** 843 * Gets the ID of the template field. 844 * @return the template field ID. 845 */ 846 public String getID() { 847 return this.id; 848 } 849 850 /** 851 * Gets the data type of the field's value. 852 * @return the data type of the field's value. 853 */ 854 public String getType() { 855 return this.type; 856 } 857 858 /** 859 * Sets the data type of the field's value. 860 * @param type the data type of the field's value. 861 */ 862 public void setType(String type) { 863 this.type = type; 864 } 865 866 /** 867 * Gets the key of the field. 868 * @return the key of the field. 869 */ 870 public String getKey() { 871 return this.key; 872 } 873 874 /** 875 * Sets the key of the field. 876 * @param key the key of the field. 877 */ 878 public void setKey(String key) { 879 this.key = key; 880 } 881 882 /** 883 * Gets the display name of the field. 884 * @return the display name of the field. 885 */ 886 public String getDisplayName() { 887 return this.displayName; 888 } 889 890 /** 891 * Sets the display name of the field. 892 * @param displayName the display name of the field. 893 */ 894 public void setDisplayName(String displayName) { 895 this.displayName = displayName; 896 } 897 898 /** 899 * Gets is metadata template field hidden. 900 * @return is metadata template field hidden. 901 */ 902 public Boolean getIsHidden() { 903 return this.isHidden; 904 } 905 906 /** 907 * Sets is metadata template field hidden. 908 * @param isHidden is metadata template field hidden? 909 */ 910 public void setIsHidden(boolean isHidden) { 911 this.isHidden = isHidden; 912 } 913 914 /** 915 * Gets the description of the field. 916 * @return the description of the field. 917 */ 918 public String getDescription() { 919 return this.description; 920 } 921 922 /** 923 * Sets the description of the field. 924 * @param description the description of the field. 925 */ 926 public void setDescription(String description) { 927 this.description = description; 928 } 929 930 /** 931 * Gets list of possible options for enum type of the field. 932 * @return list of possible options for enum type of the field. 933 */ 934 public List<String> getOptions() { 935 if (this.options == null) { 936 return null; 937 } 938 List<String> optionsList = new ArrayList<String>(); 939 for (Option option : this.options) { 940 optionsList.add(option.getKey()); 941 } 942 return optionsList; 943 } 944 945 /** 946 * Gets list of possible options for options type of the field. 947 * @return list of possible options for option type of the field. 948 */ 949 public List<Option> getOptionsObjects() { 950 return this.options; 951 } 952 953 /** 954 * Sets list of possible options for enum type of the field. 955 * @param options list of possible options for enum type of the field. 956 */ 957 public void setOptions(List<String> options) { 958 if (options == null) { 959 this.options = null; 960 } 961 List<Option> optionList = new ArrayList<Option>(); 962 for (String key : options) { 963 JsonObject optionObject = new JsonObject(); 964 optionObject.add("key", key); 965 Option newOption = new Option(optionObject); 966 optionList.add(newOption); 967 } 968 this.options = optionList; 969 } 970 971 /** 972 * Gets whether the copy operation should copy the metadata along with the item. 973 * @return whether the copy operation should copy the metadata along with the item. 974 */ 975 public Boolean getCopyInstanceOnItemCopy() { 976 return this.copyInstanceOnItemCopy; 977 } 978 979 /** 980 * Sets whether the copy operation should copy the metadata along with the item. 981 * @param copyInstanceOnItemCopy whether the copy operation should copy the metadata along with the item. 982 */ 983 public void setCopyInstanceOnItemCopy(Boolean copyInstanceOnItemCopy) { 984 this.copyInstanceOnItemCopy = copyInstanceOnItemCopy; 985 } 986 987 /** 988 * {@inheritDoc} 989 */ 990 @Override 991 void parseJSONMember(JsonObject.Member member) { 992 JsonValue value = member.getValue(); 993 String memberName = member.getName(); 994 if (memberName.equals("type")) { 995 this.type = value.asString(); 996 } else if (memberName.equals("key")) { 997 this.key = value.asString(); 998 } else if (memberName.equals("displayName")) { 999 this.displayName = value.asString(); 1000 } else if (memberName.equals("hidden")) { 1001 this.isHidden = value.asBoolean(); 1002 } else if (memberName.equals("description")) { 1003 this.description = value.asString(); 1004 } else if (memberName.equals("options")) { 1005 this.options = new ArrayList<Option>(); 1006 for (JsonValue option : value.asArray()) { 1007 this.options.add(new Option(option.asObject())); 1008 } 1009 } else if (memberName.equals("id")) { 1010 this.id = value.asString(); 1011 } else if (memberName.equals("copyInstanceOnItemCopy")) { 1012 this.copyInstanceOnItemCopy = value.asBoolean(); 1013 } 1014 } 1015 } 1016 1017 /** 1018 * Class contains information about the metadata template option. 1019 */ 1020 public static class Option extends BoxJSONObject { 1021 /** 1022 * @see #getID() 1023 */ 1024 private String id; 1025 /** 1026 * @see #getKey() 1027 */ 1028 private String key; 1029 /** 1030 * Constructs an empty metadata template. 1031 */ 1032 public Option() { 1033 super(); 1034 } 1035 /** 1036 * Constructs a metadate template option from a JSON string. 1037 * @param json the json encoded metadata template option. 1038 */ 1039 public Option(String json) { 1040 super(json); 1041 } 1042 1043 /** 1044 * Constructs a metadate template option from a JSON object. 1045 * @param jsonObject the json encoded metadate template option. 1046 */ 1047 Option(JsonObject jsonObject) { 1048 super(jsonObject); 1049 } 1050 /** 1051 * Gets the ID of the template field. 1052 * @return the template field ID. 1053 */ 1054 public String getID() { 1055 return this.id; 1056 } 1057 /** 1058 * Gets the key of the field. 1059 * @return the key of the field. 1060 */ 1061 public String getKey() { 1062 return this.key; 1063 } 1064 1065 /** 1066 * {@inheritDoc} 1067 */ 1068 @Override 1069 void parseJSONMember(JsonObject.Member member) { 1070 JsonValue value = member.getValue(); 1071 String memberName = member.getName(); 1072 if (memberName.equals("id")) { 1073 this.id = value.asString(); 1074 } else if (memberName.equals("key")) { 1075 this.key = value.asString(); 1076 } 1077 } 1078 } 1079 1080 /** 1081 * Posssible operations that can be performed in a Metadata template. 1082 * <ul> 1083 * <li>Add an enum option</li> 1084 * <li>Edit an enum option</li> 1085 * <li>Remove an enum option</li> 1086 * <li>Add a field</li> 1087 * <li>Edit a field</li> 1088 * <li>Remove a field</li> 1089 * <li>Edit template</li> 1090 * <li>Reorder the enum option</li> 1091 * <li>Reorder the field list</li> 1092 * </ul> 1093 */ 1094 public static class FieldOperation extends BoxJSONObject { 1095 1096 private Operation op; 1097 private Field data; 1098 private String fieldKey; 1099 private List<String> fieldKeys; 1100 private List<String> enumOptionKeys; 1101 private String enumOptionKey; 1102 private String multiSelectOptionKey; 1103 private List<String> multiSelectOptionKeys; 1104 1105 /** 1106 * Constructs an empty FieldOperation. 1107 */ 1108 public FieldOperation() { 1109 super(); 1110 } 1111 1112 /** 1113 * Constructs a Field operation from a JSON string. 1114 * @param json the json encoded metadate template field. 1115 */ 1116 public FieldOperation(String json) { 1117 super(json); 1118 } 1119 1120 /** 1121 * Constructs a Field operation from a JSON object. 1122 * @param jsonObject the json encoded metadate template field. 1123 */ 1124 FieldOperation(JsonObject jsonObject) { 1125 super(jsonObject); 1126 } 1127 1128 /** 1129 * Gets the operation. 1130 * @return the operation 1131 */ 1132 public Operation getOp() { 1133 return this.op; 1134 } 1135 1136 /** 1137 * Gets the data associated with the operation. 1138 * @return the field object representing the data 1139 */ 1140 public Field getData() { 1141 return this.data; 1142 } 1143 1144 /** 1145 * Gets the field key. 1146 * @return the field key 1147 */ 1148 public String getFieldKey() { 1149 return this.fieldKey; 1150 } 1151 1152 /** 1153 * Gets the list of field keys. 1154 * @return the list of Strings 1155 */ 1156 public List<String> getFieldKeys() { 1157 return this.fieldKeys; 1158 } 1159 1160 /** 1161 * Gets the list of keys of the Enum options. 1162 * @return the list of Strings 1163 */ 1164 public List<String> getEnumOptionKeys() { 1165 return this.enumOptionKeys; 1166 } 1167 1168 /** 1169 * Sets the operation. 1170 * @param op the operation 1171 */ 1172 public void setOp(Operation op) { 1173 this.op = op; 1174 } 1175 1176 /** 1177 * Sets the data. 1178 * @param data the Field object representing the data 1179 */ 1180 public void setData(Field data) { 1181 this.data = data; 1182 } 1183 1184 /** 1185 * Sets the field key. 1186 * @param fieldKey the key of the field 1187 */ 1188 public void setFieldKey(String fieldKey) { 1189 this.fieldKey = fieldKey; 1190 } 1191 1192 /** 1193 * Sets the list of the field keys. 1194 * @param fieldKeys the list of strings 1195 */ 1196 public void setFieldKeys(List<String> fieldKeys) { 1197 this.fieldKeys = fieldKeys; 1198 } 1199 1200 /** 1201 * Sets the list of the enum option keys. 1202 * @param enumOptionKeys the list of Strings 1203 */ 1204 public void setEnumOptionKeys(List<String> enumOptionKeys) { 1205 this.enumOptionKeys = enumOptionKeys; 1206 } 1207 1208 /** 1209 * Gets the enum option key. 1210 * @return the enum option key 1211 */ 1212 public String getEnumOptionKey() { 1213 return this.enumOptionKey; 1214 } 1215 1216 /** 1217 * Sets the enum option key. 1218 * @param enumOptionKey the enum option key 1219 */ 1220 public void setEnumOptionKey(String enumOptionKey) { 1221 this.enumOptionKey = enumOptionKey; 1222 } 1223 1224 /** 1225 * Gets the multi-select option key. 1226 * @return the key. 1227 */ 1228 public String getMultiSelectOptionKey() { 1229 return this.multiSelectOptionKey; 1230 } 1231 1232 /** 1233 * Sets the multi-select option key. 1234 * @param key the key. 1235 */ 1236 public void setMultiSelectOptionKey(String key) { 1237 this.multiSelectOptionKey = key; 1238 } 1239 1240 /** 1241 * Gets the list of multiselect option keys. 1242 * @return the list of keys. 1243 */ 1244 public List<String> getMultiSelectOptionKeys() { 1245 return this.multiSelectOptionKeys; 1246 } 1247 1248 /** 1249 * Sets the multi-select option keys. 1250 * @param keys the list of keys. 1251 */ 1252 public void setMultiSelectOptionKeys(List<String> keys) { 1253 this.multiSelectOptionKeys = keys; 1254 } 1255 1256 /** 1257 * {@inheritDoc} 1258 */ 1259 @Override 1260 void parseJSONMember(JsonObject.Member member) { 1261 JsonValue value = member.getValue(); 1262 String memberName = member.getName(); 1263 if (memberName.equals("op")) { 1264 this.op = Operation.valueOf(value.asString()); 1265 } else if (memberName.equals("data")) { 1266 this.data = new Field(value.asObject()); 1267 } else if (memberName.equals("fieldKey")) { 1268 this.fieldKey = value.asString(); 1269 } else if (memberName.equals("fieldKeys")) { 1270 if (this.fieldKeys == null) { 1271 this.fieldKeys = new ArrayList<String>(); 1272 } else { 1273 this.fieldKeys.clear(); 1274 } 1275 1276 JsonArray array = value.asArray(); 1277 for (JsonValue jsonValue: array) { 1278 this.fieldKeys.add(jsonValue.asString()); 1279 } 1280 } else if (memberName.equals("enumOptionKeys")) { 1281 if (this.enumOptionKeys == null) { 1282 this.enumOptionKeys = new ArrayList<String>(); 1283 } else { 1284 this.enumOptionKeys.clear(); 1285 } 1286 1287 JsonArray array = value.asArray(); 1288 for (JsonValue jsonValue: array) { 1289 this.enumOptionKeys.add(jsonValue.asString()); 1290 } 1291 } else if (memberName.equals("enumOptionKey")) { 1292 this.enumOptionKey = value.asString(); 1293 } else if (memberName.equals("multiSelectOptionKey")) { 1294 this.multiSelectOptionKey = value.asString(); 1295 } else if (memberName.equals("multiSelectOptionKeys")) { 1296 this.multiSelectOptionKeys = new ArrayList<String>(); 1297 for (JsonValue key : value.asArray()) { 1298 this.multiSelectOptionKeys.add(key.asString()); 1299 } 1300 } 1301 } 1302 } 1303 1304 /** 1305 * Possible template operations. 1306 */ 1307 public enum Operation { 1308 1309 /** 1310 * Adds an enum option at the end of the enum option list for the specified field. 1311 */ 1312 addEnumOption, 1313 1314 /** 1315 * Edits the enum option. 1316 */ 1317 editEnumOption, 1318 1319 /** 1320 * Removes the specified enum option from the specified enum field. 1321 */ 1322 removeEnumOption, 1323 1324 /** 1325 * Adds a field at the end of the field list for the template. 1326 */ 1327 addField, 1328 1329 /** 1330 * Edits any number of the base properties of a field: displayName, hidden, description. 1331 */ 1332 editField, 1333 1334 /** 1335 * Removes the specified field from the template. 1336 */ 1337 removeField, 1338 1339 /** 1340 * Edits any number of the base properties of a template: displayName, hidden. 1341 */ 1342 editTemplate, 1343 1344 /** 1345 * Reorders the enum option list to match the requested enum option list. 1346 */ 1347 reorderEnumOptions, 1348 1349 /** 1350 * Reorders the field list to match the requested field list. 1351 */ 1352 reorderFields, 1353 1354 /** 1355 * Adds a new option to a multiselect field. 1356 */ 1357 addMultiSelectOption, 1358 1359 /** 1360 * Edits an existing option in a multiselect field. 1361 */ 1362 editMultiSelectOption, 1363 1364 /** 1365 * Removes an option from a multiselect field. 1366 */ 1367 removeMultiSelectOption, 1368 1369 /** 1370 * Changes the display order of options in a multiselect field. 1371 */ 1372 reorderMultiSelectOptions 1373 } 1374}