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     * Default metadata type to be used in query.
044     */
045    private static final String DEFAULT_METADATA_TYPE = "properties";
046
047    /**
048     * Global metadata scope. Used by default if the metadata type is "properties".
049     */
050    private static final String GLOBAL_METADATA_SCOPE = "global";
051
052    /**
053     * Enterprise metadata scope. Used by default if the metadata type is not "properties".
054     */
055    private static final String ENTERPRISE_METADATA_SCOPE = "enterprise";
056
057    /**
058     * Default number of entries per page.
059     */
060    private static final int DEFAULT_ENTRIES_LIMIT = 100;
061
062    /**
063     * @see #getID()
064     */
065    private String id;
066
067    /**
068     * @see #getTemplateKey()
069     */
070    private String templateKey;
071
072    /**
073     * @see #getScope()
074     */
075    private String scope;
076
077    /**
078     * @see #getDisplayName()
079     */
080    private String displayName;
081
082    /**
083     * @see #getIsHidden()
084     */
085    private Boolean isHidden;
086
087    /**
088     * @see #getFields()
089     */
090    private List<Field> fields;
091
092    /**
093     * Constructs an empty metadata template.
094     */
095    public MetadataTemplate() {
096        super();
097    }
098
099    /**
100     * Constructs a metadata template from a JSON string.
101     * @param json the json encoded metadate template.
102     */
103    public MetadataTemplate(String json) {
104        super(json);
105    }
106
107    /**
108     * Constructs a metadate template from a JSON object.
109     * @param jsonObject the json encoded metadate template.
110     */
111    MetadataTemplate(JsonObject jsonObject) {
112        super(jsonObject);
113    }
114
115    /**
116     * Gets the ID of the template.
117     * @return the template ID.
118     */
119    public String getID() {
120        return this.id;
121    }
122
123    /**
124     * Gets the unique template key to identify the metadata template.
125     * @return the unique template key to identify the metadata template.
126     */
127    public String getTemplateKey() {
128        return this.templateKey;
129    }
130
131    /**
132     * Gets the metadata template scope.
133     * @return the metadata template scope.
134     */
135    public String getScope() {
136        return this.scope;
137    }
138
139    /**
140     * Gets the displayed metadata template name.
141     * @return the displayed metadata template name.
142     */
143    public String getDisplayName() {
144        return this.displayName;
145    }
146
147    /**
148     * Gets is the metadata template hidden.
149     * @return is the metadata template hidden.
150     */
151    public Boolean getIsHidden() {
152        return this.isHidden;
153    }
154
155    /**
156     * Gets the iterable with all fields the metadata template contains.
157     * @return the iterable with all fields the metadata template contains.
158     */
159    public List<Field> getFields() {
160        return this.fields;
161    }
162
163    /**
164     * {@inheritDoc}
165     */
166    @Override
167    void parseJSONMember(JsonObject.Member member) {
168        JsonValue value = member.getValue();
169        String memberName = member.getName();
170        if (memberName.equals("templateKey")) {
171            this.templateKey = value.asString();
172        } else if (memberName.equals("scope")) {
173            this.scope = value.asString();
174        } else if (memberName.equals("displayName")) {
175            this.displayName = value.asString();
176        } else if (memberName.equals("hidden")) {
177            this.isHidden = value.asBoolean();
178        } else if (memberName.equals("fields")) {
179            this.fields = new ArrayList<Field>();
180            for (JsonValue field: value.asArray()) {
181                this.fields.add(new Field(field.asObject()));
182            }
183        } else if (memberName.equals("id")) {
184            this.id = value.asString();
185        }
186    }
187
188    /**
189     * Creates new metadata template.
190     * @param api the API connection to be used.
191     * @param scope the scope of the object.
192     * @param templateKey a unique identifier for the template.
193     * @param displayName the display name of the field.
194     * @param hidden whether this template is hidden in the UI.
195     * @param fields the ordered set of fields for the template
196     * @return the metadata template returned from the server.
197     */
198    public static MetadataTemplate createMetadataTemplate(BoxAPIConnection api, String scope, String templateKey,
199            String displayName, boolean hidden, List<Field> fields) {
200
201        JsonObject jsonObject = new JsonObject();
202        jsonObject.add("scope", scope);
203        jsonObject.add("displayName", displayName);
204        jsonObject.add("hidden", hidden);
205
206        if (templateKey != null) {
207            jsonObject.add("templateKey", templateKey);
208        }
209
210        JsonArray fieldsArray = new JsonArray();
211        if (fields != null && !fields.isEmpty()) {
212            for (Field field : fields) {
213                JsonObject fieldObj = getFieldJsonObject(field);
214
215                fieldsArray.add(fieldObj);
216            }
217
218            jsonObject.add("fields", fieldsArray);
219        }
220
221        URL url = METADATA_TEMPLATE_SCHEMA_URL_TEMPLATE.build(api.getBaseURL());
222        BoxJSONRequest request = new BoxJSONRequest(api, url, "POST");
223        request.setBody(jsonObject.toString());
224
225        BoxJSONResponse response = (BoxJSONResponse) request.send();
226        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
227
228        return new MetadataTemplate(responseJSON);
229    }
230
231    /**
232     * Gets the JsonObject representation of the given field object.
233     * @param field represents a template field
234     * @return the json object
235     */
236    private static JsonObject getFieldJsonObject(Field field) {
237        JsonObject fieldObj = new JsonObject();
238        fieldObj.add("type", field.getType());
239        fieldObj.add("key", field.getKey());
240        fieldObj.add("displayName", field.getDisplayName());
241
242        String fieldDesc = field.getDescription();
243        if (fieldDesc != null) {
244            fieldObj.add("description", field.getDescription());
245        }
246
247        Boolean fieldIsHidden = field.getIsHidden();
248        if (fieldIsHidden != null) {
249            fieldObj.add("hidden", field.getIsHidden());
250        }
251
252        JsonArray array = new JsonArray();
253        List<String> options = field.getOptions();
254        if (options != null && !options.isEmpty()) {
255            for (String option : options) {
256                JsonObject optionObj = new JsonObject();
257                optionObj.add("key", option);
258
259                array.add(optionObj);
260            }
261            fieldObj.add("options", array);
262        }
263
264        return fieldObj;
265    }
266
267    /**
268     * Updates the schema of an existing metadata template.
269     *
270     * @param api the API connection to be used
271     * @param scope the scope of the object
272     * @param template Unique identifier of the template
273     * @param fieldOperations the fields that needs to be updated / added in the template
274     * @return the updated metadata template
275     */
276    public static MetadataTemplate updateMetadataTemplate(BoxAPIConnection api, String scope, String template,
277            List<FieldOperation> fieldOperations) {
278
279        JsonArray array = new JsonArray();
280
281        for (FieldOperation fieldOperation : fieldOperations) {
282            JsonObject jsonObject = getFieldOperationJsonObject(fieldOperation);
283            array.add(jsonObject);
284        }
285
286        QueryStringBuilder builder = new QueryStringBuilder();
287        URL url = METADATA_TEMPLATE_URL_TEMPLATE.build(api.getBaseURL(), scope, template);
288        BoxJSONRequest request = new BoxJSONRequest(api, url, "PUT");
289        request.setBody(array.toString());
290
291        BoxJSONResponse response = (BoxJSONResponse) request.send();
292        JsonObject responseJson = JsonObject.readFrom(response.getJSON());
293
294        return new MetadataTemplate(responseJson);
295    }
296
297    /**
298     * Deletes the schema of an existing metadata template.
299     *
300     * @param api the API connection to be used
301     * @param scope the scope of the object
302     * @param template Unique identifier of the template
303     */
304    public static void deleteMetadataTemplate(BoxAPIConnection api, String scope, String template) {
305
306        URL url = METADATA_TEMPLATE_URL_TEMPLATE.build(api.getBaseURL(), scope, template);
307        BoxJSONRequest request = new BoxJSONRequest(api, url, "DELETE");
308
309        request.send();
310    }
311
312    /**
313     * Gets the JsonObject representation of the Field Operation.
314     * @param fieldOperation represents the template update operation
315     * @return the json object
316     */
317    private static JsonObject getFieldOperationJsonObject(FieldOperation fieldOperation) {
318        JsonObject jsonObject = new JsonObject();
319        jsonObject.add("op", fieldOperation.getOp().toString());
320
321        String fieldKey = fieldOperation.getFieldKey();
322        if (fieldKey != null) {
323            jsonObject.add("fieldKey", fieldKey);
324        }
325
326        Field field = fieldOperation.getData();
327        if (field != null) {
328            JsonObject fieldObj = new JsonObject();
329
330            String type = field.getType();
331            if (type != null) {
332                fieldObj.add("type", type);
333            }
334
335            String key = field.getKey();
336            if (key != null) {
337                fieldObj.add("key", key);
338            }
339
340            String displayName = field.getDisplayName();
341            if (displayName != null) {
342                fieldObj.add("displayName", displayName);
343            }
344
345            String description = field.getDescription();
346            if (description != null) {
347                fieldObj.add("description", description);
348            }
349
350            Boolean hidden = field.getIsHidden();
351            if (hidden != null) {
352                fieldObj.add("hidden", hidden);
353            }
354
355            List<String> options = field.getOptions();
356            if (options != null) {
357                JsonArray array = new JsonArray();
358                for (String option: options) {
359                    JsonObject optionObj = new JsonObject();
360                    optionObj.add("key", option);
361
362                    array.add(optionObj);
363                }
364
365                fieldObj.add("options", array);
366            }
367
368            jsonObject.add("data", fieldObj);
369        }
370
371        List<String> fieldKeys = fieldOperation.getFieldKeys();
372        if (fieldKeys != null) {
373            jsonObject.add("fieldKeys", getJsonArray(fieldKeys));
374        }
375
376        List<String> enumOptionKeys = fieldOperation.getEnumOptionKeys();
377        if (enumOptionKeys != null) {
378            jsonObject.add("enumOptionKeys", getJsonArray(enumOptionKeys));
379        }
380
381        String enumOptionKey = fieldOperation.getEnumOptionKey();
382        if (enumOptionKey != null) {
383            jsonObject.add("enumOptionKey", enumOptionKey);
384        }
385        return jsonObject;
386    }
387
388    /**
389     * Gets the Json Array representation of the given list of strings.
390     * @param keys List of strings
391     * @return the JsonArray represents the list of keys
392     */
393    private static JsonArray getJsonArray(List<String> keys) {
394        JsonArray array = new JsonArray();
395        for (String key : keys) {
396            array.add(key);
397        }
398
399        return array;
400    }
401
402    /**
403     * Gets the metadata template of properties.
404     * @param api the API connection to be used.
405     * @return the metadata template returned from the server.
406     */
407    public static MetadataTemplate getMetadataTemplate(BoxAPIConnection api) {
408        return getMetadataTemplate(api, DEFAULT_METADATA_TYPE);
409    }
410
411    /**
412     * Gets the metadata template of specified template type.
413     * @param api the API connection to be used.
414     * @param templateName the metadata template type name.
415     * @return the metadata template returned from the server.
416     */
417    public static MetadataTemplate getMetadataTemplate(BoxAPIConnection api, String templateName) {
418        String scope = scopeBasedOnType(templateName);
419        return getMetadataTemplate(api, templateName, scope);
420    }
421
422    /**
423     * Gets the metadata template of specified template type.
424     * @param api the API connection to be used.
425     * @param templateName the metadata template type name.
426     * @param scope the metadata template scope (global or enterprise).
427     * @param fields the fields to retrieve.
428     * @return the metadata template returned from the server.
429     */
430    public static MetadataTemplate getMetadataTemplate(
431            BoxAPIConnection api, String templateName, String scope, String ... fields) {
432        QueryStringBuilder builder = new QueryStringBuilder();
433        if (fields.length > 0) {
434            builder.appendParam("fields", fields);
435        }
436        URL url = METADATA_TEMPLATE_URL_TEMPLATE.buildWithQuery(
437                api.getBaseURL(), builder.toString(), scope, templateName);
438        BoxAPIRequest request = new BoxAPIRequest(api, url, "GET");
439        BoxJSONResponse response = (BoxJSONResponse) request.send();
440        return new MetadataTemplate(response.getJSON());
441    }
442
443    /**
444     * Geta the specified metadata template by its ID.
445     * @param api the API connection to be used.
446     * @param templateID the ID of the template to get.
447     * @return the metadata template object.
448     */
449    public static MetadataTemplate getMetadataTemplateByID(BoxAPIConnection api, String templateID) {
450
451        URL url = METADATA_TEMPLATE_BY_ID_URL_TEMPLATE.build(api.getBaseURL(), templateID);
452        BoxAPIRequest request = new BoxAPIRequest(api, url, "GET");
453        BoxJSONResponse response = (BoxJSONResponse) request.send();
454        return new MetadataTemplate(response.getJSON());
455    }
456
457    /**
458     * Returns all metadata templates within a user's enterprise.
459     * @param api the API connection to be used.
460     * @param fields the fields to retrieve.
461     * @return the metadata template returned from the server.
462     */
463    public static Iterable<MetadataTemplate> getEnterpriseMetadataTemplates(BoxAPIConnection api, String ... fields) {
464        return getEnterpriseMetadataTemplates(ENTERPRISE_METADATA_SCOPE, api, fields);
465    }
466
467    /**
468     * Returns all metadata templates within a user's scope. Currently only the enterprise scope is supported.
469     * @param scope the scope of the metadata templates.
470     * @param api the API connection to be used.
471     * @param fields the fields to retrieve.
472     * @return the metadata template returned from the server.
473     */
474    public static Iterable<MetadataTemplate> getEnterpriseMetadataTemplates(
475            String scope, BoxAPIConnection api, String ... fields) {
476        return getEnterpriseMetadataTemplates(ENTERPRISE_METADATA_SCOPE, DEFAULT_ENTRIES_LIMIT, api, fields);
477    }
478
479    /**
480     * Returns all metadata templates within a user's scope. Currently only the enterprise scope is supported.
481     * @param scope the scope of the metadata templates.
482     * @param limit maximum number of entries per response.
483     * @param api the API connection to be used.
484     * @param fields the fields to retrieve.
485     * @return the metadata template returned from the server.
486     */
487    public static Iterable<MetadataTemplate> getEnterpriseMetadataTemplates(
488            String scope, int limit, BoxAPIConnection api, String ... fields) {
489        QueryStringBuilder builder = new QueryStringBuilder();
490        if (fields.length > 0) {
491            builder.appendParam("fields", fields);
492        }
493        return new BoxResourceIterable<MetadataTemplate>(
494                api, ENTERPRISE_METADATA_URL_TEMPLATE.buildWithQuery(
495                        api.getBaseURL(), builder.toString(), scope), limit) {
496
497            @Override
498            protected MetadataTemplate factory(JsonObject jsonObject) {
499                return new MetadataTemplate(jsonObject);
500            }
501        };
502    }
503
504    /**
505     * Determines the metadata scope based on type.
506     * @param typeName type of the metadata.
507     * @return scope of the metadata.
508     */
509    private static String scopeBasedOnType(String typeName) {
510        return typeName.equals(DEFAULT_METADATA_TYPE) ? GLOBAL_METADATA_SCOPE : ENTERPRISE_METADATA_SCOPE;
511    }
512
513    /**
514     * Class contains information about the metadata template field.
515     */
516    public static class Field extends BoxJSONObject {
517
518        /**
519         * @see #getID()
520         */
521        private String id;
522
523        /**
524         * @see #getType()
525         */
526        private String type;
527
528        /**
529         * @see #getKey()
530         */
531        private String key;
532
533        /**
534         * @see #getDisplayName()
535         */
536        private String displayName;
537
538        /**
539         * @see #getIsHidden()
540         */
541        private Boolean isHidden;
542
543        /**
544         * @see #getDescription()
545         */
546        private String description;
547
548        /**
549         * @see #getOptions()
550         */
551        private List<String> options;
552
553        /**
554         * Constructs an empty metadata template.
555         */
556        public Field() {
557            super();
558        }
559
560        /**
561         * Constructs a metadate template field from a JSON string.
562         * @param json the json encoded metadate template field.
563         */
564        public Field(String json) {
565            super(json);
566        }
567
568        /**
569         * Constructs a metadate template field from a JSON object.
570         * @param jsonObject the json encoded metadate template field.
571         */
572        Field(JsonObject jsonObject) {
573            super(jsonObject);
574        }
575
576        /**
577         * Gets the ID of the template field.
578         * @return the template field ID.
579         */
580        public String getID() {
581            return this.id;
582        }
583
584        /**
585         * Gets the data type of the field's value.
586         * @return the data type of the field's value.
587         */
588        public String getType() {
589            return this.type;
590        }
591
592        /**
593         * Sets the data type of the field's value.
594         * @param type the data type of the field's value.
595         */
596        public void setType(String type) {
597            this.type = type;
598        }
599
600        /**
601         * Gets the key of the field.
602         * @return the key of the field.
603         */
604        public String getKey() {
605            return this.key;
606        }
607
608        /**
609         * Sets the key of the field.
610         * @param key the key of the field.
611         */
612        public void setKey(String key) {
613            this.key = key;
614        }
615
616        /**
617         * Gets the display name of the field.
618         * @return the display name of the field.
619         */
620        public String getDisplayName() {
621            return this.displayName;
622        }
623
624        /**
625         * Sets the display name of the field.
626         * @param displayName the display name of the field.
627         */
628        public void setDisplayName(String displayName) {
629            this.displayName = displayName;
630        }
631
632        /**
633         * Gets is metadata template field hidden.
634         * @return is metadata template field hidden.
635         */
636        public Boolean getIsHidden() {
637            return this.isHidden;
638        }
639
640        /**
641         * Sets is metadata template field hidden.
642         * @param isHidden is metadata template field hidden?
643         */
644        public void setIsHidden(boolean isHidden) {
645            this.isHidden = isHidden;
646        }
647
648        /**
649         * Gets the description of the field.
650         * @return the description of the field.
651         */
652        public String getDescription() {
653            return this.description;
654        }
655
656        /**
657         * Sets the description of the field.
658         * @param description the description of the field.
659         */
660        public void setDescription(String description) {
661            this.description = description;
662        }
663
664        /**
665         * Gets list of possible options for enum type of the field.
666         * @return list of possible options for enum type of the field.
667         */
668        public List<String> getOptions() {
669            return this.options;
670        }
671
672        /**
673         * Sets list of possible options for enum type of the field.
674         * @param options list of possible options for enum type of the field.
675         */
676        public void setOptions(List<String> options) {
677            this.options = options;
678        }
679
680        /**
681         * {@inheritDoc}
682         */
683        @Override
684        void parseJSONMember(JsonObject.Member member) {
685            JsonValue value = member.getValue();
686            String memberName = member.getName();
687            if (memberName.equals("type")) {
688                this.type = value.asString();
689            } else if (memberName.equals("key")) {
690                this.key = value.asString();
691            } else if (memberName.equals("displayName")) {
692                this.displayName = value.asString();
693            } else if (memberName.equals("hidden")) {
694                this.isHidden = value.asBoolean();
695            } else if (memberName.equals("description")) {
696                this.description = value.asString();
697            } else if (memberName.equals("options")) {
698                this.options = new ArrayList<String>();
699                for (JsonValue key: value.asArray()) {
700                    this.options.add(key.asObject().get("key").asString());
701                }
702            } else if (memberName.equals("id")) {
703                this.id = value.asString();
704            }
705        }
706    }
707
708    /**
709     * Posssible operations that can be performed in a Metadata template.
710     *  <ul>
711     *      <li>Add an enum option</li>
712     *      <li>Edit an enum option</li>
713     *      <li>Remove an enum option</li>
714     *      <li>Add a field</li>
715     *      <li>Edit a field</li>
716     *      <li>Remove a field</li>
717     *      <li>Edit template</li>
718     *      <li>Reorder the enum option</li>
719     *      <li>Reorder the field list</li>
720     *  </ul>
721     */
722    public static class FieldOperation extends BoxJSONObject {
723
724        private Operation op;
725        private Field data;
726        private String fieldKey;
727        private List<String> fieldKeys;
728        private List<String> enumOptionKeys;
729        private String enumOptionKey;
730
731        /**
732         * Constructs an empty FieldOperation.
733         */
734        public FieldOperation() {
735            super();
736        }
737
738        /**
739         * Constructs a Field operation from a JSON string.
740         * @param json the json encoded metadate template field.
741         */
742        public FieldOperation(String json) {
743            super(json);
744        }
745
746        /**
747         * Constructs a Field operation from a JSON object.
748         * @param jsonObject the json encoded metadate template field.
749         */
750        FieldOperation(JsonObject jsonObject) {
751            super(jsonObject);
752        }
753
754        /**
755         * Gets the operation.
756         * @return the operation
757         */
758        public Operation getOp() {
759            return this.op;
760        }
761
762        /**
763         * Gets the data associated with the operation.
764         * @return the field object representing the data
765         */
766        public Field getData() {
767            return this.data;
768        }
769
770        /**
771         * Gets the field key.
772         * @return the field key
773         */
774        public String getFieldKey() {
775            return this.fieldKey;
776        }
777
778        /**
779         * Gets the list of field keys.
780         * @return the list of Strings
781         */
782        public List<String> getFieldKeys() {
783            return this.fieldKeys;
784        }
785
786        /**
787         * Gets the list of keys of the Enum options.
788         * @return the list of Strings
789         */
790        public List<String> getEnumOptionKeys() {
791            return this.enumOptionKeys;
792        }
793
794        /**
795         * Sets the operation.
796         * @param op the operation
797         */
798        public void setOp(Operation op) {
799            this.op = op;
800        }
801
802        /**
803         * Sets the data.
804         * @param data the Field object representing the data
805         */
806        public void setData(Field data) {
807            this.data = data;
808        }
809
810        /**
811         * Sets the field key.
812         * @param fieldKey the key of the field
813         */
814        public void setFieldKey(String fieldKey) {
815            this.fieldKey = fieldKey;
816        }
817
818        /**
819         * Sets the list of the field keys.
820         * @param fieldKeys the list of strings
821         */
822        public void setFieldKeys(List<String> fieldKeys) {
823            this.fieldKeys = fieldKeys;
824        }
825
826        /**
827         * Sets the list of the enum option keys.
828         * @param enumOptionKeys the list of Strings
829         */
830        public void setEnumOptionKeys(List<String> enumOptionKeys) {
831            this.enumOptionKeys = enumOptionKeys;
832        }
833
834        /**
835         * Gets the enum option key.
836         * @return the enum option key
837         */
838        public String getEnumOptionKey() {
839            return this.enumOptionKey;
840        }
841
842        /**
843         * Sets the enum option key.
844         * @param enumOptionKey the enum option key
845         */
846        public void setEnumOptionKey(String enumOptionKey) {
847            this.enumOptionKey = enumOptionKey;
848        }
849
850        /**
851         * {@inheritDoc}
852         */
853        @Override
854        void parseJSONMember(JsonObject.Member member) {
855            JsonValue value = member.getValue();
856            String memberName = member.getName();
857            if (memberName.equals("op")) {
858                this.op = Operation.valueOf(value.asString());
859            } else if (memberName.equals("data")) {
860                this.data = new Field(value.asObject());
861            } else if (memberName.equals("fieldKey")) {
862                this.fieldKey = value.asString();
863            } else if (memberName.equals("fieldKeys")) {
864                if (this.fieldKeys == null) {
865                    this.fieldKeys = new ArrayList<String>();
866                } else {
867                    this.fieldKeys.clear();
868                }
869
870                JsonArray array = value.asArray();
871                for (JsonValue jsonValue: array) {
872                    this.fieldKeys.add(jsonValue.asString());
873                }
874            } else if (memberName.equals("enumOptionKeys")) {
875                if (this.enumOptionKeys == null) {
876                    this.enumOptionKeys = new ArrayList<String>();
877                } else {
878                    this.enumOptionKeys.clear();
879                }
880
881                JsonArray array = value.asArray();
882                for (JsonValue jsonValue: array) {
883                    this.enumOptionKeys.add(jsonValue.asString());
884                }
885            } else if (memberName.equals("enumOptionKey")) {
886                this.enumOptionKey = value.asString();
887            }
888        }
889    }
890
891    /**
892     * Possible template operations.
893     */
894    public enum Operation {
895
896        /**
897         * Adds an enum option at the end of the enum option list for the specified field.
898         */
899        addEnumOption,
900
901        /**
902         * Edits the enum option.
903         */
904        editEnumOption,
905
906        /**
907         * Removes the specified enum option from the specified enum field.
908         */
909        removeEnumOption,
910
911        /**
912         * Adds a field at the end of the field list for the template.
913         */
914        addField,
915
916        /**
917         * Edits any number of the base properties of a field: displayName, hidden, description.
918         */
919        editField,
920
921        /**
922         * Removes the specified field from the template.
923         */
924        removeField,
925
926        /**
927         * Edits any number of the base properties of a template: displayName, hidden.
928         */
929        editTemplate,
930
931        /**
932         * Reorders the enum option list to match the requested enum option list.
933         */
934        reorderEnumOptions,
935
936        /**
937         * Reorders the field list to match the requested field list.
938         */
939        reorderFields
940    }
941}