001package com.box.sdk;
002
003import java.net.URL;
004import java.util.ArrayList;
005import java.util.List;
006
007import com.eclipsesource.json.JsonObject;
008import com.eclipsesource.json.JsonValue;
009
010/**
011 * The MetadataTemplate class represents the Box metadata template object.
012 * Templates allow the metadata service to provide a multitude of services,
013 * such as pre-defining sets of key:value pairs or schema enforcement on specific fields.
014 *
015 * @see <a href="https://docs.box.com/reference#metadata-templates">Box metadata templates</a>
016 */
017public class MetadataTemplate extends BoxJSONObject {
018
019    /**
020     * @see #getMetadataTemplate(BoxAPIConnection)
021     */
022    private static final URLTemplate METADATA_TEMPLATE_URL_TEMPLATE
023        = new URLTemplate("metadata_templates/%s/%s/schema");
024
025    /**
026     * @see #getEnterpriseMetadataTemplates(String, int, BoxAPIConnection, String...)
027     */
028    private static final URLTemplate ENTERPRISE_METADATA_URL_TEMPLATE = new URLTemplate("metadata_templates/%s");
029
030    /**
031     * Default metadata type to be used in query.
032     */
033    private static final String DEFAULT_METADATA_TYPE = "properties";
034
035    /**
036     * Global metadata scope. Used by default if the metadata type is "properties".
037     */
038    private static final String GLOBAL_METADATA_SCOPE = "global";
039
040    /**
041     * Enterprise metadata scope. Used by default if the metadata type is not "properties".
042     */
043    private static final String ENTERPRISE_METADATA_SCOPE = "enterprise";
044
045    /**
046     * Default number of entries per page.
047     */
048    private static final int DEFAULT_ENTRIES_LIMIT = 100;
049
050    /**
051     * @see #getTemplateKey()
052     */
053    private String templateKey;
054
055    /**
056     * @see #getScope()
057     */
058    private String scope;
059
060    /**
061     * @see #getDisplayName()
062     */
063    private String displayName;
064
065    /**
066     * @see #getIsHidden()
067     */
068    private Boolean isHidden;
069
070    /**
071     * @see #getFields()
072     */
073    private List<Field> fields;
074
075    /**
076     * Constructs an empty metadata template.
077     */
078    public MetadataTemplate() {
079        super();
080    }
081
082    /**
083     * Constructs a metadata template from a JSON string.
084     * @param json the json encoded metadate template.
085     */
086    public MetadataTemplate(String json) {
087        super(json);
088    }
089
090    /**
091     * Constructs a metadate template from a JSON object.
092     * @param jsonObject the json encoded metadate template.
093     */
094    MetadataTemplate(JsonObject jsonObject) {
095        super(jsonObject);
096    }
097
098    /**
099     * Gets the unique template key to identify the metadata template.
100     * @return the unique template key to identify the metadata template.
101     */
102    public String getTemplateKey() {
103        return this.templateKey;
104    }
105
106    /**
107     * Gets the metadata template scope.
108     * @return the metadata template scope.
109     */
110    public String getScope() {
111        return this.scope;
112    }
113
114    /**
115     * Gets the displayed metadata template name.
116     * @return the displayed metadata template name.
117     */
118    public String getDisplayName() {
119        return this.displayName;
120    }
121
122    /**
123     * Gets is the metadata template hidden.
124     * @return is the metadata template hidden.
125     */
126    public Boolean getIsHidden() {
127        return this.isHidden;
128    }
129
130    /**
131     * Gets the iterable with all fields the metadata template contains.
132     * @return the iterable with all fields the metadata template contains.
133     */
134    public List<Field> getFields() {
135        return this.fields;
136    }
137
138    /**
139     * {@inheritDoc}
140     */
141    @Override
142    void parseJSONMember(JsonObject.Member member) {
143        JsonValue value = member.getValue();
144        String memberName = member.getName();
145        if (memberName.equals("templateKey")) {
146            this.templateKey = value.asString();
147        } else if (memberName.equals("scope")) {
148            this.scope = value.asString();
149        } else if (memberName.equals("displayName")) {
150            this.displayName = value.asString();
151        } else if (memberName.equals("hidden")) {
152            this.isHidden = value.asBoolean();
153        } else if (memberName.equals("fields")) {
154            this.fields = new ArrayList<Field>();
155            for (JsonValue field: value.asArray()) {
156                this.fields.add(new Field(field.asObject()));
157            }
158        }
159    }
160
161    /**
162     * Gets the metadata template of properties.
163     * @param api the API connection to be used.
164     * @return the metadata template returned from the server.
165     */
166    public static MetadataTemplate getMetadataTemplate(BoxAPIConnection api) {
167        return getMetadataTemplate(api, DEFAULT_METADATA_TYPE);
168    }
169
170    /**
171     * Gets the metadata template of specified template type.
172     * @param api the API connection to be used.
173     * @param templateName the metadata template type name.
174     * @return the metadata template returned from the server.
175     */
176    public static MetadataTemplate getMetadataTemplate(BoxAPIConnection api, String templateName) {
177        String scope = scopeBasedOnType(templateName);
178        return getMetadataTemplate(api, templateName, scope);
179    }
180
181    /**
182     * Gets the metadata template of specified template type.
183     * @param api the API connection to be used.
184     * @param templateName the metadata template type name.
185     * @param scope the metadata template scope (global or enterprise).
186     * @param fields the fields to retrieve.
187     * @return the metadata template returned from the server.
188     */
189    public static MetadataTemplate getMetadataTemplate(
190            BoxAPIConnection api, String templateName, String scope, String ... fields) {
191        QueryStringBuilder builder = new QueryStringBuilder();
192        if (fields.length > 0) {
193            builder.appendParam("fields", fields);
194        }
195        URL url = METADATA_TEMPLATE_URL_TEMPLATE.buildWithQuery(
196                api.getBaseURL(), builder.toString(), scope, templateName);
197        BoxAPIRequest request = new BoxAPIRequest(api, url, "GET");
198        BoxJSONResponse response = (BoxJSONResponse) request.send();
199        return new MetadataTemplate(response.getJSON());
200    }
201
202    /**
203     * Returns all metadata templates within a user's enterprise.
204     * @param api the API connection to be used.
205     * @param fields the fields to retrieve.
206     * @return the metadata template returned from the server.
207     */
208    public static Iterable<MetadataTemplate> getEnterpriseMetadataTemplates(BoxAPIConnection api, String ... fields) {
209        return getEnterpriseMetadataTemplates(ENTERPRISE_METADATA_SCOPE, api, fields);
210    }
211
212    /**
213     * Returns all metadata templates within a user's scope. Currently only the enterprise scope is supported.
214     * @param scope the scope of the metadata templates.
215     * @param api the API connection to be used.
216     * @param fields the fields to retrieve.
217     * @return the metadata template returned from the server.
218     */
219    public static Iterable<MetadataTemplate> getEnterpriseMetadataTemplates(
220            String scope, BoxAPIConnection api, String ... fields) {
221        return getEnterpriseMetadataTemplates(ENTERPRISE_METADATA_SCOPE, DEFAULT_ENTRIES_LIMIT, api, fields);
222    }
223
224    /**
225     * Returns all metadata templates within a user's scope. Currently only the enterprise scope is supported.
226     * @param scope the scope of the metadata templates.
227     * @param limit maximum number of entries per response.
228     * @param api the API connection to be used.
229     * @param fields the fields to retrieve.
230     * @return the metadata template returned from the server.
231     */
232    public static Iterable<MetadataTemplate> getEnterpriseMetadataTemplates(
233            String scope, int limit, BoxAPIConnection api, String ... fields) {
234        QueryStringBuilder builder = new QueryStringBuilder();
235        if (fields.length > 0) {
236            builder.appendParam("fields", fields);
237        }
238        return new BoxResourceIterable<MetadataTemplate>(
239                api, ENTERPRISE_METADATA_URL_TEMPLATE.buildWithQuery(
240                        api.getBaseURL(), builder.toString(), scope), limit) {
241
242            @Override
243            protected MetadataTemplate factory(JsonObject jsonObject) {
244                return new MetadataTemplate(jsonObject);
245            }
246        };
247    }
248
249    /**
250     * Determines the metadata scope based on type.
251     * @param typeName type of the metadata.
252     * @return scope of the metadata.
253     */
254    private static String scopeBasedOnType(String typeName) {
255        return typeName.equals(DEFAULT_METADATA_TYPE) ? GLOBAL_METADATA_SCOPE : ENTERPRISE_METADATA_SCOPE;
256    }
257
258    /**
259     * Class contains information about the metadata template field.
260     */
261    public class Field extends BoxJSONObject {
262
263        /**
264         * @see #getType()
265         */
266        private String type;
267
268        /**
269         * @see #getKey()
270         */
271        private String key;
272
273        /**
274         * @see #getDisplayName()
275         */
276        private String displayName;
277
278        /**
279         * @see #getIsHidden()
280         */
281        private Boolean isHidden;
282
283        /**
284         * @see #getDescription()
285         */
286        private String description;
287
288        /**
289         * @see #getOptions()
290         */
291        private List<String> options;
292
293        /**
294         * Constructs an empty metadata template.
295         */
296        public Field() {
297            super();
298        }
299
300        /**
301         * Constructs a metadate template field from a JSON string.
302         * @param json the json encoded metadate template field.
303         */
304        public Field(String json) {
305            super(json);
306        }
307
308        /**
309         * Constructs a metadate template field from a JSON object.
310         * @param jsonObject the json encoded metadate template field.
311         */
312        Field(JsonObject jsonObject) {
313            super(jsonObject);
314        }
315
316        /**
317         * Gets the data type of the field's value.
318         * @return the data type of the field's value.
319         */
320        public String getType() {
321            return this.type;
322        }
323
324        /**
325         * Gets the key of the field.
326         * @return the key of the field.
327         */
328        public String getKey() {
329            return this.key;
330        }
331
332        /**
333         * Gets the display name of the field.
334         * @return the display name of the field.
335         */
336        public String getDisplayName() {
337            return this.displayName;
338        }
339
340        /**
341         * Gets is metadata template field hidden.
342         * @return is metadata template field hidden.
343         */
344        public Boolean getIsHidden() {
345            return this.isHidden;
346        }
347
348        /**
349         * Gets the description of the field.
350         * @return the description of the field.
351         */
352        public String getDescription() {
353            return this.description;
354        }
355
356        /**
357         * Gets list of possible options for enum type of the field.
358         * @return list of possible options for enum type of the field.
359         */
360        public List<String> getOptions() {
361            return this.options;
362        }
363
364        /**
365         * {@inheritDoc}
366         */
367        @Override
368        void parseJSONMember(JsonObject.Member member) {
369            JsonValue value = member.getValue();
370            String memberName = member.getName();
371            if (memberName.equals("type")) {
372                this.type = value.asString();
373            } else if (memberName.equals("key")) {
374                this.key = value.asString();
375            } else if (memberName.equals("displayName")) {
376                this.displayName = value.asString();
377            } else if (memberName.equals("hidden")) {
378                this.isHidden = value.asBoolean();
379            } else if (memberName.equals("description")) {
380                this.description = value.asString();
381            } else if (memberName.equals("options")) {
382                this.options = new ArrayList<String>();
383                for (JsonValue key: value.asArray()) {
384                    this.options.add(key.asObject().get("key").asString());
385                }
386            }
387        }
388    }
389
390}