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