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