001package com.box.sdk;
002
003import com.eclipsesource.json.Json;
004import com.eclipsesource.json.JsonObject;
005import com.eclipsesource.json.JsonValue;
006import java.net.URL;
007import java.util.ArrayList;
008import java.util.List;
009
010
011/**
012 * Represents a Sign Template used in the Box Sign API.
013 *
014 * @see <a href="https://developer.box.com/reference/resources/sign-templates/">Box Sign Templates</a>
015 *
016 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked
017 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error
018 * handling for errors related to the Box REST API, you should capture this exception explicitly.</p>
019 */
020@BoxResourceType("sign_template")
021public class BoxSignTemplate extends BoxResource {
022
023    /**
024     * The URL template for Sign Templates.
025     */
026    public static final URLTemplate SIGN_TEMPLATES_URL_TEMPLATE = new URLTemplate("sign_templates");
027
028    /**
029     * The URL template for Sign Templates operations with a given ID.
030     */
031    public static final URLTemplate SIGN_TEMPLATE_URL_TEMPLATE = new URLTemplate("sign_templates/%s");
032
033    /**
034     * The default limit of entries per response.
035     */
036    public static final int DEFAULT_LIMIT = 100;
037
038    /**
039     * Constructs a BoxSignTemplate for a resource with a given ID.
040     *
041     * @param api the API connection to be used by the resource.
042     * @param id  the ID of the resource.
043     */
044    public BoxSignTemplate(BoxAPIConnection api, String id) {
045        super(api, id);
046    }
047
048    /**
049     * Return all Sign Templates.
050     *
051     * @param api the API connection to be used by the resource.
052     * @return an iterable with all Sign Templates.
053     */
054    public static Iterable<BoxSignTemplate.Info> getAll(BoxAPIConnection api) {
055        return getAll(api, DEFAULT_LIMIT);
056    }
057
058    /**
059     * Return all Sign Templates.
060     *
061     * @param api   the API connection to be used by the resource.
062     * @param limit the limit of entries per response.
063     * @return an iterable with all Sign Templates.
064     */
065    public static Iterable<BoxSignTemplate.Info> getAll(BoxAPIConnection api, int limit) {
066        QueryStringBuilder builder = new QueryStringBuilder();
067        URL url = SIGN_TEMPLATES_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), builder.toString());
068        return new BoxResourceIterable<BoxSignTemplate.Info>(api, url, limit) {
069
070            @Override
071            protected BoxSignTemplate.Info factory(JsonObject jsonObject) {
072                BoxSignTemplate template = new BoxSignTemplate(api, jsonObject.get("id").asString());
073                return template.new Info(jsonObject);
074            }
075        };
076
077    }
078
079    /**
080     * Return information about this Sign Template.
081     *
082     * @return information about this Sign Template.
083     */
084    public BoxSignTemplate.Info getInfo() {
085        URL url = SIGN_TEMPLATE_URL_TEMPLATE.buildAlpha(this.getAPI().getBaseURL(), this.getID());
086        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
087        try (BoxJSONResponse response = (BoxJSONResponse) request.send()) {
088            JsonObject jsonObject = Json.parse(response.getJSON()).asObject();
089            return new Info(jsonObject);
090        }
091    }
092
093    /**
094     * Contains information about a BoxSignTemplate.
095     */
096    public class Info extends BoxResource.Info {
097
098        private BoxSignTemplateAdditionalInfo additionalInfo;
099        private boolean areEmailSettingsLocked;
100        private boolean areFieldsLocked;
101        private boolean areOptionsLocked;
102        private boolean areFilesLocked;
103        private boolean areRecipientsLocked;
104        private BoxSignTemplateCustomBranding customBranding;
105        private Integer daysValid;
106        private String emailMessage;
107        private String emailSubject;
108        private String name;
109        private BoxFolder.Info parentFolder;
110        private BoxSignTemplateReadySignLink readySignLink;
111        private List<BoxSignRequestSigner> signers;
112        private List<BoxFile.Info> sourceFiles;
113
114        /**
115         * Constructs an empty Info object.
116         */
117        public Info() {
118            super();
119        }
120
121        /**
122         * Constructs an Info object with the provided JSON string.
123         *
124         * @param json the JSON string representing the Sign Template.
125         */
126        public Info(String json) {
127            super(json);
128        }
129
130        /**
131         * Constructs an Info object with the provided JSON object.
132         *
133         * @param jsonObject the JSON object representing the Sign Template.
134         */
135        Info(JsonObject jsonObject) {
136            super(jsonObject);
137        }
138
139        /**
140         * {@inheritDoc}
141         */
142        @Override
143        public BoxSignTemplate getResource() {
144            return BoxSignTemplate.this;
145        }
146
147        /**
148         * Gets the additional information about this Sign Template.
149         *
150         * @return the additional information about this Sign Template.
151         */
152        public BoxSignTemplateAdditionalInfo getAdditionalInfo() {
153            return this.additionalInfo;
154        }
155
156        /**
157         * Gets whether the templates email settings are editable or not.
158         *
159         * @return true if the email settings are locked; otherwise false.
160         */
161        public boolean getAreEmailSettingsLocked() {
162            return this.areEmailSettingsLocked;
163        }
164
165        /**
166         * Gets whether the templates input fields are editable or not.
167         * This includes deleting or renaming template files.
168         *
169         * @return true if the fields are locked; otherwise false.
170         */
171        public boolean getAreFieldsLocked() {
172            return this.areFieldsLocked;
173        }
174
175        /**
176         * Gets weather the templates input options are editable or not.
177         *
178         * @return true if the options are editable; otherwise false.
179         */
180        public boolean getAreOptionsLocked() {
181            return this.areOptionsLocked;
182        }
183
184        /**
185         * Gets whether the template document options are editable or not,
186         * for example renaming the document.
187         *
188         * @return true if the files are locked; otherwise false.
189         */
190        public boolean getAreFilesLocked() {
191            return this.areFilesLocked;
192        }
193
194        /**
195         * Gets whether the template signers are editable or not.
196         *
197         * @return true if the recipients are locked; otherwise false.
198         */
199        public boolean getAreRecipientsLocked() {
200            return this.areRecipientsLocked;
201        }
202
203        /**
204         * Gets the custom branding applied to notifications and signature requests.
205         *
206         * @return the custom branding for this Sign Template.
207         */
208        public BoxSignTemplateCustomBranding getCustomBranding() {
209            return this.customBranding;
210        }
211
212        /**
213         * Gets the number of days after which the created signature request
214         * will automatically expire if not completed.
215         * By default, we do not apply any expiration date on signature requests,
216         * and the signature request does not expire.
217         *
218         * @return the number of days the template is valid for.
219         */
220        public Integer getDaysValid() {
221            return this.daysValid;
222        }
223
224        /**
225         * Gets the email message that will be sent to all signers.
226         *
227         * @return the email message for this Sign Template.
228         */
229        public String getEmailMessage() {
230            return this.emailMessage;
231        }
232
233        /**
234         * Gets the email subject that will be sent to all signers.
235         *
236         * @return the email subject for this Sign Template.
237         */
238        public String getEmailSubject() {
239            return this.emailSubject;
240        }
241
242        /**
243         * Gets the name of this Sign Template.
244         *
245         * @return the name of this Sign Template.
246         */
247        public String getName() {
248            return this.name;
249        }
250
251        /**
252         * Gets the parent folder of this Sign Template.
253         *
254         * @return the parent folder of this Sign Template.
255         */
256        public BoxFolder.Info getParentFolder() {
257            return this.parentFolder;
258        }
259
260        /**
261         * Gets the ready sign link for this Sign Template.
262         *
263         * @return the ready sign link for this Sign Template.
264         */
265        public BoxSignTemplateReadySignLink getReadySignLink() {
266            return this.readySignLink;
267        }
268
269        /**
270         * Gets the signers for this Sign Template.
271         *
272         * @return the signers for this Sign Template.
273         */
274        public List<BoxSignRequestSigner> getSigners() {
275            return this.signers;
276        }
277
278        /**
279         * Gets the source files for this Sign Template.
280         *
281         * @return the source files for this Sign Template.
282         */
283        public List<BoxFile.Info> getSourceFiles() {
284            return this.sourceFiles;
285        }
286
287        /**
288         * {@inheritDoc}
289         */
290        @Override
291        void parseJSONMember(JsonObject.Member member) {
292            super.parseJSONMember(member);
293            String memberName = member.getName();
294            JsonValue value = member.getValue();
295            try {
296                switch (memberName) {
297                    case "additional_info":
298                        this.additionalInfo = this.parseAdditionalInfo(value.asObject());
299                        break;
300                    case "are_email_settings_locked":
301                        this.areEmailSettingsLocked = value.asBoolean();
302                        break;
303                    case "are_fields_locked":
304                        this.areFieldsLocked = value.asBoolean();
305                        break;
306                    case "are_options_locked":
307                        this.areOptionsLocked = value.asBoolean();
308                        break;
309                    case "are_files_locked":
310                        this.areFilesLocked = value.asBoolean();
311                        break;
312                    case "are_recipients_locked":
313                        this.areRecipientsLocked = value.asBoolean();
314                        break;
315                    case "custom_branding":
316                        this.customBranding = this.parseCustomBranding(value.asObject());
317                        break;
318                    case "days_valid":
319                        this.daysValid = value.asInt();
320                        break;
321                    case "email_message":
322                        this.emailMessage = value.asString();
323                        break;
324                    case "email_subject":
325                        this.emailSubject = value.asString();
326                        break;
327                    case "name":
328                        this.name = value.asString();
329                        break;
330                    case "parent_folder":
331                        JsonObject parentFolderJSON = value.asObject();
332                        String parentFolderID = parentFolderJSON.get("id").asString();
333                        BoxFolder parentFolder = new BoxFolder(getAPI(), parentFolderID);
334                        this.parentFolder = parentFolder.new Info(parentFolderJSON);
335                        break;
336                    case "ready_sign_link":
337                        this.readySignLink = this.parseReadySignLink(value.asObject());
338                        break;
339                    case "signers":
340                        this.signers = this.parseSigners(value.asArray());
341                        break;
342                    case "source_files":
343                        this.sourceFiles = this.parseSourceFiles(value.asArray());
344                        break;
345                    default:
346                }
347            } catch (Exception e) {
348                throw new BoxDeserializationException(memberName, value.toString(), e);
349            }
350        }
351
352        private BoxSignTemplateAdditionalInfo parseAdditionalInfo(JsonValue additionalInfoJSON) {
353            List<String> nonEditableFields = new ArrayList<String>();
354            for (JsonValue fieldJSON : additionalInfoJSON.asObject().get("non_editable").asArray()) {
355                nonEditableFields.add(fieldJSON.asString());
356            }
357            BoxSignTemplateAdditionalInfoRequired required = this.parseAdditionalInfoRequired(
358                additionalInfoJSON.asObject().get("required").asObject()
359            );
360            return new BoxSignTemplateAdditionalInfo(nonEditableFields, required);
361        }
362
363        private BoxSignTemplateAdditionalInfoRequired parseAdditionalInfoRequired(JsonObject requiredJSON) {
364            List<List<String>> signers = new ArrayList<List<String>>();
365            for (JsonValue signerJSON : requiredJSON.get("signers").asArray()) {
366                List<String> signer = new ArrayList<String>();
367                for (JsonValue fieldJSON : signerJSON.asArray()) {
368                    signer.add(fieldJSON.asString());
369                }
370                signers.add(signer);
371            }
372            return new BoxSignTemplateAdditionalInfoRequired(signers);
373        }
374
375        private List<BoxFile.Info> parseSourceFiles(JsonValue filesArray) {
376            List<BoxFile.Info> files = new ArrayList<BoxFile.Info>();
377            for (JsonValue fileJSON : filesArray.asArray()) {
378                JsonObject fileObj = fileJSON.asObject();
379                String fileID = fileObj.get("id").asString();
380                BoxFile file = new BoxFile(getAPI(), fileID);
381                files.add(file.new Info(fileObj));
382            }
383            return files;
384        }
385
386        private List<BoxSignRequestSigner> parseSigners(JsonValue signersArray) {
387            List<BoxSignRequestSigner> signers = new ArrayList<BoxSignRequestSigner>();
388            for (JsonValue signerJSON : signersArray.asArray()) {
389                JsonObject signerObj = signerJSON.asObject();
390                signers.add(new BoxSignRequestSigner(signerObj, getAPI()));
391            }
392            return signers;
393        }
394
395        private BoxSignTemplateCustomBranding parseCustomBranding(JsonObject customBrandingJSON) {
396            String brandingColor = customBrandingJSON.get("branding_color").asString();
397            String companyName = customBrandingJSON.get("company_name").asString();
398            String emailFooterText = customBrandingJSON.get("email_footer_text").asString();
399            String logoUri = customBrandingJSON.get("logo_uri").asString();
400            return new BoxSignTemplateCustomBranding(brandingColor, companyName, emailFooterText, logoUri);
401        }
402
403        private BoxSignTemplateReadySignLink parseReadySignLink(JsonObject readySignLinkJSON) {
404            String folderID = readySignLinkJSON.get("folder_id").asString();
405            String instructions = readySignLinkJSON.get("instructions").asString();
406            boolean isActive = readySignLinkJSON.get("is_active").asBoolean();
407            boolean isNofiticationDisabled = readySignLinkJSON.get("is_notification_disabled").asBoolean();
408            String name = readySignLinkJSON.get("name").asString();
409            String url = readySignLinkJSON.get("url").asString();
410            return new BoxSignTemplateReadySignLink(folderID, instructions, isActive,
411                isNofiticationDisabled, name, url);
412        }
413
414        /**
415         * Box Sign Template additional information on which fields are required
416         * and which fields are not editable.
417         */
418        public class BoxSignTemplateAdditionalInfo {
419            private final List<String> nonEditable;
420            private final BoxSignTemplateAdditionalInfoRequired required;
421
422            public BoxSignTemplateAdditionalInfo(List<String> nonEditable,
423                                                 BoxSignTemplateAdditionalInfoRequired required) {
424                this.nonEditable = nonEditable;
425                this.required = required;
426            }
427
428            /**
429             * Get non-editable fields.
430             *
431             * @return list of non-editable fields.\
432             */
433            public List<String> getNonEditable() {
434                return this.nonEditable;
435            }
436
437            /**
438             * Gets the required fields.
439             *
440             * @return the required fields.
441             */
442            public BoxSignTemplateAdditionalInfoRequired getRequired() {
443                return this.required;
444            }
445        }
446
447        /**
448         * Box Sign Template additional information on which fields are required.
449         */
450        public class BoxSignTemplateAdditionalInfoRequired {
451            private final List<List<String>> signers;
452
453            /**
454             * Constructs a BoxSignTemplateAdditionalInfoRequired object with the provided list of signers.
455             */
456            public BoxSignTemplateAdditionalInfoRequired(List<List<String>> signers) {
457                this.signers = signers;
458            }
459
460            /**
461             * Gets the required signer fields.
462             *
463             * @return the required signer fields.
464             */
465            public List<List<String>> getSigners() {
466                return this.signers;
467            }
468        }
469
470        /**
471         * Custom branding applied to notifications and signature requests.
472         */
473        public class BoxSignTemplateCustomBranding {
474            private final String brandingColor;
475            private final String companyName;
476            private final String emailFooterText;
477            private final String logoUri;
478
479            /**
480             * Constructs a BoxSignTemplateCustomBranding object with the provided information.
481             *
482             * @param brandingColor   the branding color.
483             * @param companyName     the company name.
484             * @param emailFooterText the email footer text.
485             * @param logoUri         the logo URI.
486             */
487            public BoxSignTemplateCustomBranding(String brandingColor, String companyName, String emailFooterText,
488                                                 String logoUri) {
489                this.brandingColor = brandingColor;
490                this.companyName = companyName;
491                this.emailFooterText = emailFooterText;
492                this.logoUri = logoUri;
493            }
494
495            /**
496             * Gets the branding color.
497             *
498             * @return the branding color.
499             */
500            public String getBrandingColor() {
501                return this.brandingColor;
502            }
503
504            /**
505             * Gets the company name.
506             *
507             * @return the company name.
508             */
509            public String getCompanyName() {
510                return this.companyName;
511            }
512
513            /**
514             * Gets the email footer text.
515             *
516             * @return the email footer text.
517             */
518            public String getEmailFooterText() {
519                return this.emailFooterText;
520            }
521
522            /**
523             * Gets the logo URI.
524             *
525             * @return the logo URI.
526             */
527            public String getLogoUri() {
528                return this.logoUri;
529            }
530        }
531
532        /**
533         * Box's ready-sign link feature enables you to create a link to a signature request that you've created from a template.
534         * Use this link when you want to post a signature request on a public form — such as an email,
535         * social media post, or web page — without knowing who the signers will be.
536         * Note: The ready-sign link feature is limited to Enterprise Plus customers and not available to Box Verified Enterprises.
537         */
538        public class BoxSignTemplateReadySignLink {
539            private final String folderID;
540            private final String instructions;
541            private final boolean isActive;
542            private final boolean isNofiticationDisabled;
543            private final String name;
544            private final String url;
545
546            /**
547             * Constructs a BoxSignTemplateReadySignLink object with the provided information.
548             *
549             * @param folderID               the folder ID.
550             * @param instructions           the instructions.
551             * @param isActive               whether the link is active or not.
552             * @param isNofiticationDisabled whether the notification is disabled or not.
553             * @param name                   the name.
554             * @param url                    the URL.
555             */
556            public BoxSignTemplateReadySignLink(String folderID, String instructions, boolean isActive,
557                                                boolean isNofiticationDisabled, String name, String url) {
558                this.folderID = folderID;
559                this.instructions = instructions;
560                this.isActive = isActive;
561                this.isNofiticationDisabled = isNofiticationDisabled;
562                this.name = name;
563                this.url = url;
564            }
565
566            /**
567             * Gets the folder ID.
568             *
569             * @return the folder ID.
570             */
571            public String getFolderID() {
572                return this.folderID;
573            }
574
575            /**
576             * Gets the instructions.
577             *
578             * @return the instructions.
579             */
580            public String getInstructions() {
581                return this.instructions;
582            }
583
584            /**
585             * Gets whether the link is active or not.
586             *
587             * @return true if the link is active; otherwise false.
588             */
589            public boolean getIsActive() {
590                return this.isActive;
591            }
592
593            /**
594             * Gets whether the notification is disabled or not.
595             *
596             * @return true if the notification is disabled; otherwise false.
597             */
598            public boolean getIsNofiticationDisabled() {
599                return this.isNofiticationDisabled;
600            }
601
602            /**
603             * Gets the name of the ready-sign link.
604             *
605             * @return the name.
606             */
607            public String getName() {
608                return this.name;
609            }
610
611            /**
612             * Gets the URL of the ready-sign link.
613             *
614             * @return the URL.
615             */
616            public String getUrl() {
617                return this.url;
618            }
619        }
620    }
621}