001package com.box.sdk;
002
003import static java.lang.String.format;
004
005import com.box.sdk.internal.utils.JsonUtils;
006import com.eclipsesource.json.JsonObject;
007import com.eclipsesource.json.JsonValue;
008import java.util.ArrayList;
009import java.util.Date;
010import java.util.List;
011
012/**
013 * Represents a signer in BoxSignRequest.
014 */
015public class BoxSignRequestSigner extends BoxJSONObject {
016    private String email;
017    private BoxSignRequestSignerRole role;
018    private Boolean isInPerson;
019    private Integer order;
020    private String embedUrlExternalUserId;
021    private Boolean hasViewedEmail;
022    private Boolean hasViewedDocument;
023    private BoxSignerDecision signerDecision;
024    private List<BoxSignerInput> inputs;
025    private String embedUrl;
026    private String redirectUrl;
027    private String declinedRedirectUrl;
028    private String iframeableEmedUrl;
029    private String signerGroupId;
030    private Boolean loginRequired;
031    private String password;
032    private Boolean suppressNotifications;
033    private String verificationPhoneNumber;
034    private BoxAPIConnection api;
035
036    /**
037     * Constructs a BoxSignRequestSigner with an email.
038     *
039     * @param email of signer.
040     */
041    public BoxSignRequestSigner(String email) {
042        this.email = email;
043    }
044
045    /**
046     * Construct a BoxSignRequestSigner.
047     *
048     * @param jsonObject the parsed JSON object.
049     * @param api        the API connection to be used to fetch interacted item
050     */
051    public BoxSignRequestSigner(JsonObject jsonObject, BoxAPIConnection api) {
052        super(jsonObject);
053        this.api = api;
054    }
055
056    /**
057     * Gets the email address of the signer.
058     *
059     * @return email address of the signer.
060     */
061    public String getEmail() {
062        return this.email;
063    }
064
065    /**
066     * Sets the email address of the signer.
067     *
068     * @param email address of the signer.
069     * @return this BoxSignRequestSigner object for chaining.
070     */
071    public BoxSignRequestSigner setEmail(String email) {
072        this.email = email;
073        return this;
074    }
075
076    /**
077     * Gets the role of the signer.
078     *
079     * @return role of the signer.
080     */
081    public BoxSignRequestSignerRole getRole() {
082        return this.role;
083    }
084
085    /**
086     * Sets the role of the signer. If role is not set it's FinalCopyReader by default.
087     *
088     * @param role of the signer.
089     * @return this BoxSignRequestSigner object for chaining.
090     */
091    public BoxSignRequestSigner setRole(BoxSignRequestSignerRole role) {
092        this.role = role;
093        return this;
094    }
095
096    /**
097     * Gets the flag that when used in combination with an embed url on the sender. After the sender signs,
098     * they will be redirected to the next InPerson signer.
099     *
100     * @return true if is in person signer, otherwise false.
101     */
102    public boolean getIsInPerson() {
103        return this.isInPerson;
104    }
105
106    /**
107     * Gets the order of signer.
108     *
109     * @return order of signer.
110     */
111    public int getOrder() {
112        return this.order;
113    }
114
115    /**
116     * Sets the order of signer.
117     *
118     * @param order of signer.
119     * @return this BoxSignRequestSigner object for chaining.
120     */
121    public BoxSignRequestSigner setOrder(Integer order) {
122        this.order = order;
123        return this;
124    }
125
126    /**
127     * Gets the user id for this signer in external application responsible
128     * for authentication when accessing the embed url.
129     *
130     * @return embed url external user id.
131     */
132    public String getEmbedUrlExternalUserId() {
133        return this.embedUrlExternalUserId;
134    }
135
136    /**
137     * Sets the user id for this signer in external application responsible
138     * for authentication when accessing the embed url.
139     *
140     * @param embedUrlExternalUserId for this signer in external application responsible
141     *                               for authentication when accessing the embed url.
142     * @return this BoxSignRequestSigner object for chaining.
143     */
144    public BoxSignRequestSigner setEmbedUrlExternalUserId(String embedUrlExternalUserId) {
145        this.embedUrlExternalUserId = embedUrlExternalUserId;
146        return this;
147    }
148
149    /**
150     * Gets the flag indicating if signer has viewed the sign request email.
151     *
152     * @return true if the signer has viewed the sign request email, otherwise false.
153     */
154    public boolean getHasViewedEmail() {
155        return this.hasViewedEmail;
156    }
157
158    /**
159     * Gets the flag indicating if signer has viewed the document.
160     *
161     * @return true if the signer has viewed the document, otherwise false.
162     */
163    public boolean getHasViewedDocument() {
164        return this.hasViewedDocument;
165    }
166
167    /**
168     * Gets the final decision made by signer.
169     *
170     * @return final decision made by signer.
171     */
172    public BoxSignerDecision getSignerDecision() {
173        return this.signerDecision;
174    }
175
176    /**
177     * Gets the inputs created by a signer on a sign request.
178     *
179     * @return list of inputs created by a signer on a sign request.
180     */
181    public List<BoxSignerInput> getInputs() {
182        return this.inputs;
183    }
184
185    /**
186     * Gets the url to direct signer to for signing.
187     *
188     * @return url to direct signer to for signing.
189     */
190    public String getEmbedUrl() {
191        return this.embedUrl;
192    }
193
194    /**
195     * Gets the flag that is used in combination with an embed url for a the sender. After the sender signs,
196     * they will be redirected to the next InPerson signer.
197     *
198     * @return true if is in person signer, otherwise false.
199     */
200    public Boolean getInPerson() {
201        return this.isInPerson;
202    }
203
204    /**
205     * Sets the flag that is used in combination with an embed url for a the sender. After the sender signs,
206     * they will be redirected to the next InPerson signer.
207     *
208     * @param isInPerson flag.
209     * @return this BoxSignRequestSigner object for chaining.
210     */
211    public BoxSignRequestSigner setInPerson(Boolean isInPerson) {
212        this.isInPerson = isInPerson;
213        return this;
214    }
215
216    /**
217     * Gets the redirect url for the signer.
218     *
219     * @return redirect url for the signer.
220     */
221    public String getRedirectUrl() {
222        return this.redirectUrl;
223    }
224
225    /**
226     * Sets the redirect url for the signer.
227     *
228     * @param redirectUrl for the signer.
229     * @return this BoxSignRequestSigner object for chaining.
230     */
231    public BoxSignRequestSigner setRedirectUrl(String redirectUrl) {
232        this.redirectUrl = redirectUrl;
233        return this;
234    }
235
236    /**
237     * Gets the declined redirect url for the signer.
238     *
239     * @return declined redirect url for the signer.
240     */
241    public String getDeclinedRedirectUrl() {
242        return this.declinedRedirectUrl;
243    }
244
245    /**
246     * Sets the declined redirect url for the signer.
247     *
248     * @param declinedRedirectUrl for the signer.
249     * @return this BoxSignRequestSigner object for chaining.
250     */
251    public BoxSignRequestSigner setDeclinedRedirectUrl(String declinedRedirectUrl) {
252        this.declinedRedirectUrl = declinedRedirectUrl;
253        return this;
254    }
255
256    /**
257     * Gets the URL designed for signing documents within an HTML iframe tag.
258     * It will be returned in the response only if the embedUrlExternalUserId parameter was passed
259     * in the create sign request call.
260     *
261     * @return url for signing documents within an HTML iframe tag.
262     */
263    public String getIframeableEmedUrl() {
264        return this.iframeableEmedUrl;
265    }
266
267    /**
268     * Sets the URL designed for signing documents within an HTML iframe tag.
269     * It will be returned in the response only if the embedUrlExternalUserId parameter was passed
270     * in the create sign request call.
271     *
272     * @param iframeableEmedUrl url for signing documents within an HTML iframe tag.
273     * @return this BoxSignRequestSigner object for chaining.
274     */
275    public BoxSignRequestSigner setIframeableEmedUrl(String iframeableEmedUrl) {
276        this.iframeableEmedUrl = iframeableEmedUrl;
277        return this;
278    }
279
280    /**
281     * Gets the signer group id. It is sufficient for only one signer from the group to sign the document.
282     *
283     * @return id of the group to which the sign request will be sent.
284     */
285    public String getSignerGroupId() {
286        return this.signerGroupId;
287    }
288
289    /**
290     * Sets the group id. If specified, signers sharing the same group ID will be assigned to the same input.
291     * The group ID can be any string value, but it must be consistent across all signers.
292     * It is sufficient for only one signer from the group to sign the document.
293     *
294     * @param signerGroupId id of the group to which the sign request will be sent
295     * @return this BoxSignRequestSigner object for chaining.
296     */
297    public BoxSignRequestSigner setSignerGroupId(String signerGroupId) {
298        this.signerGroupId = signerGroupId;
299        return this;
300    }
301
302    /**
303     * If set to true, signer will need to login to a Box account before signing the request.
304     * If the signer does not have an existing account, they will have an option to create a free Box account.
305     *
306     * @return true if login is required for the signer, otherwise false.
307     */
308    public Boolean getLoginRequired() {
309        return this.loginRequired;
310    }
311
312    /**
313     * If set to true, signer will need to login to a Box account before signing the request.
314     * If the signer does not have an existing account, they will have an option to create a free Box account.
315     *
316     * @param loginRequired indicates if login is required for the signer.
317     * @return this BoxSignRequestSigner object for chaining.
318     */
319    public BoxSignRequestSigner setLoginRequired(Boolean loginRequired) {
320        this.loginRequired = loginRequired;
321        return this;
322    }
323
324    /**
325     * If set, the signer is required to enter the password before they are able to sign a document.
326     * This field is write only.
327     *
328     * @return password required for the signer to access the sign request.
329     */
330    public String getPassword() {
331        return this.password;
332    }
333
334    /**
335     * Sets the password required for the signer to access the sign request.
336     *
337     * @param password required for the signer to access the sign request.
338     * @return this BoxSignRequestSigner object for chaining.
339     */
340    public BoxSignRequestSigner setPassword(String password) {
341        this.password = password;
342        return this;
343    }
344
345    /**
346     * Gets the flag that suppresses email notifications for the signer.
347     *
348     * @return true if email notifications are suppressed for the signer, otherwise false.
349     */
350    public Boolean getSuppressNotifications() {
351        return this.suppressNotifications;
352    }
353
354    /**
355     * Sets the flag that suppresses email notifications for the signer.
356     *
357     * @param suppressNotifications indicates if email notifications are suppressed for the signer.
358     * @return this BoxSignRequestSigner object for chaining.
359     */
360    public BoxSignRequestSigner setSuppressNotifications(Boolean suppressNotifications) {
361        this.suppressNotifications = suppressNotifications;
362        return this;
363    }
364
365    /**
366     * Gets the phone number used for verification.
367     * If set, this phone number is be used to verify the signer via two factor authentication
368     * before they are able to sign the document.
369     *
370     * @return phone number used for verification.
371     */
372    public String getVerificationPhoneNumber() {
373        return this.verificationPhoneNumber;
374    }
375
376    /**
377     * Sets the phone number used for verification.
378     * If set, this phone number is be used to verify the signer via two factor authentication
379     * before they are able to sign the document.
380     *
381     * @param verificationPhoneNumber phone number used for verification.
382     * @return this BoxSignRequestSigner object for chaining.
383     */
384    public BoxSignRequestSigner setVerificationPhoneNumber(String verificationPhoneNumber) {
385        this.verificationPhoneNumber = verificationPhoneNumber;
386        return this;
387    }
388
389    /**
390     * {@inheritDoc}
391     */
392    @Override
393    void parseJSONMember(JsonObject.Member member) {
394        JsonValue value = member.getValue();
395        String memberName = member.getName();
396        try {
397            switch (memberName) {
398                case "email":
399                    this.email = value.asString();
400                    break;
401                case "role":
402                    this.role = BoxSignRequestSignerRole.fromJSONString(value.asString());
403                    break;
404                case "is_in_person":
405                    this.isInPerson = value.asBoolean();
406                    break;
407                case "order":
408                    this.order = value.asInt();
409                    break;
410                case "embed_url_external_user_id":
411                    this.embedUrlExternalUserId = value.asString();
412                    break;
413                case "has_viewed_email":
414                    this.hasViewedEmail = value.asBoolean();
415                    break;
416                case "has_viewed_document":
417                    this.hasViewedDocument = value.asBoolean();
418                    break;
419                case "signer_decision":
420                    JsonObject signerDecisionJSON = value.asObject();
421                    this.signerDecision = new BoxSignerDecision(signerDecisionJSON);
422                    break;
423                case "inputs":
424                    List<BoxSignerInput> inputs = new ArrayList<>();
425                    for (JsonValue inputJSON : value.asArray()) {
426                        BoxSignerInput input = new BoxSignerInput(inputJSON.asObject());
427                        inputs.add(input);
428                    }
429                    this.inputs = inputs;
430                    break;
431                case "embed_url":
432                    this.embedUrl = value.asString();
433                    break;
434                case "redirect_url":
435                    this.redirectUrl = value.asString();
436                    break;
437                case "declined_redirect_url":
438                    this.declinedRedirectUrl = value.asString();
439                    break;
440                case "iframeable_embed_url":
441                    this.iframeableEmedUrl = value.asString();
442                    break;
443                case "signer_group_id":
444                    this.signerGroupId = value.asString();
445                    break;
446                case "login_required":
447                    this.loginRequired = value.asBoolean();
448                    break;
449                case "suppress_notifications":
450                    this.suppressNotifications = value.asBoolean();
451                    break;
452                case "verification_phone_number":
453                    this.verificationPhoneNumber = value.asString();
454                default:
455                    return;
456            }
457        } catch (Exception e) {
458            throw new BoxDeserializationException(memberName, value.toString(), e);
459        }
460    }
461
462    /**
463     * Gets a JSON object representing this class.
464     *
465     * @return the JSON object representing this class.
466     */
467    public JsonObject getJSONObject() {
468        JsonObject jsonObj = new JsonObject();
469        JsonUtils.addIfNotNull(jsonObj, "email", this.email);
470        JsonUtils.addIfNotNull(jsonObj, "role", this.role);
471        JsonUtils.addIfNotNull(jsonObj, "is_in_person", this.isInPerson);
472        JsonUtils.addIfNotNull(jsonObj, "order", this.order);
473        JsonUtils.addIfNotNull(jsonObj, "embed_url_external_user_id", this.embedUrlExternalUserId);
474        JsonUtils.addIfNotNull(jsonObj, "redirect_url", this.redirectUrl);
475        JsonUtils.addIfNotNull(jsonObj, "declined_redirect_url", this.declinedRedirectUrl);
476        JsonUtils.addIfNotNull(jsonObj, "signer_group_id", this.signerGroupId);
477        JsonUtils.addIfNotNull(jsonObj, "login_required", this.loginRequired);
478        JsonUtils.addIfNotNull(jsonObj, "password", this.password);
479        JsonUtils.addIfNotNull(jsonObj, "suppress_notifications", this.suppressNotifications);
480        JsonUtils.addIfNotNull(jsonObj, "verification_phone_number", this.verificationPhoneNumber);
481        return jsonObj;
482    }
483
484    /**
485     * Type of decision made by signer.
486     */
487    public enum BoxSignRequestSignerDecisionType {
488
489        /**
490         * Signed decision.
491         */
492        Signed("signed"),
493
494        /**
495         * Declined decision.
496         */
497        Declined("declined");
498
499        private final String jsonValue;
500
501        BoxSignRequestSignerDecisionType(String jsonValue) {
502            this.jsonValue = jsonValue;
503        }
504
505        static BoxSignRequestSignerDecisionType fromJSONString(String jsonValue) {
506            if ("signed".equals(jsonValue)) {
507                return Signed;
508            } else if ("declined".equals(jsonValue)) {
509                return Declined;
510            }
511            throw new IllegalArgumentException(
512                "The provided JSON value isn't a valid " + "BoxSignRequestSignerDecisionType.");
513        }
514    }
515
516    /**
517     * Represents a type of input.
518     */
519    public enum BoxSignRequestInputType {
520
521        /**
522         * Signature input.
523         */
524        Signature("signature"),
525
526        /**
527         * Text input.
528         */
529        Text("text"),
530
531        /**
532         * Checkbox input.
533         */
534        Checkbox("checkbox"),
535
536        /**
537         * Date input.
538         */
539        Date("date");
540
541        private final String jsonValue;
542
543        BoxSignRequestInputType(String jsonValue) {
544            this.jsonValue = jsonValue;
545        }
546
547        static BoxSignRequestInputType fromJSONString(String jsonValue) {
548            if ("signature".equals(jsonValue)) {
549                return Signature;
550            } else if ("text".equals(jsonValue)) {
551                return Text;
552            } else if ("checkbox".equals(jsonValue)) {
553                return Checkbox;
554            } else if ("date".equals(jsonValue)) {
555                return Date;
556            }
557            throw new IllegalArgumentException("The provided JSON value isn't a valid " + "BoxSignRequestInputType.");
558        }
559    }
560
561    /**
562     * Represents a content type of input.
563     */
564    public enum BoxSignRequestInputContentType {
565        /**
566         * Initial content type
567         */
568        Initial("initial"),
569        /**
570         * Stamp content type
571         */
572        Stamp("stamp"),
573        /**
574         * Signature content type
575         */
576        Signature("signature"),
577        /**
578         * Company content type
579         */
580        Company("company"),
581        /**
582         * Title content type
583         */
584        Title("title"),
585        /**
586         * Email content type
587         */
588        Email("email"),
589        /**
590         * Full name content type
591         */
592        FullName("full_name"),
593        /**
594         * First name content type
595         */
596        FirstName("first_name"),
597        /**
598         * Last name content type
599         */
600        LastName("last_name"),
601        /**
602         * Text content type
603         */
604        Text("text"),
605        /**
606         * Date content type
607         */
608        Date("date"),
609        /**
610         * Checkbox content type
611         */
612        Checkbox("checkbox");
613
614        private final String jsonValue;
615
616        BoxSignRequestInputContentType(String jsonValue) {
617            this.jsonValue = jsonValue;
618        }
619
620        static BoxSignRequestInputContentType fromJSONString(String jsonValue) {
621            switch (jsonValue) {
622                case "initial":
623                    return Initial;
624                case "stamp":
625                    return Stamp;
626                case "signature":
627                    return Signature;
628                case "company":
629                    return Company;
630                case "title":
631                    return Title;
632                case "email":
633                    return Email;
634                case "full_name":
635                    return FullName;
636                case "first_name":
637                    return FirstName;
638                case "last_name":
639                    return LastName;
640                case "text":
641                    return Text;
642                case "date":
643                    return Date;
644                case "checkbox":
645                    return Checkbox;
646                default:
647                    throw new IllegalArgumentException(
648                        format("The provided JSON value '%s' isn't a valid BoxSignRequestInputContentType.", jsonValue)
649                    );
650            }
651        }
652    }
653
654    /**
655     * Represents a final decision made by signer (type and time the decision was made).
656     */
657    public class BoxSignerDecision extends BoxJSONObject {
658        private BoxSignRequestSignerDecisionType type;
659        private Date finalizedAt;
660        private String additionalInfo;
661
662        /**
663         * Constructs a BoxSignerDecision object using an already parsed JSON object.
664         *
665         * @param jsonObject the parsed JSON object.
666         */
667        public BoxSignerDecision(JsonObject jsonObject) {
668            super(jsonObject);
669        }
670
671        /**
672         * Gets the type of decision made by signer.
673         *
674         * @return type of decision made by signer.
675         */
676        public BoxSignRequestSignerDecisionType getType() {
677            return this.type;
678        }
679
680        /**
681         * Gets the date/time that the decision was made.
682         *
683         * @return date/time that the decision was made.
684         */
685        public Date getFinalizedAt() {
686            return this.finalizedAt;
687        }
688
689        /**
690         * Gets the additional info about the decision, such as the decline reason from the signer.
691         *
692         * @return additional information about the decision.
693         */
694        public String getAdditionalInfo() {
695            return this.additionalInfo;
696        }
697
698        /**
699         * {@inheritDoc}
700         */
701        @Override
702        void parseJSONMember(JsonObject.Member member) {
703            JsonValue value = member.getValue();
704            String memberName = member.getName();
705            try {
706                if (memberName.equals("type")) {
707                    this.type = BoxSignRequestSignerDecisionType.fromJSONString(value.asString());
708                } else if (memberName.equals("finalized_at")) {
709                    this.finalizedAt = BoxDateFormat.parse(value.asString());
710                } else if (memberName.equals("additional_info")) {
711                    this.additionalInfo = value.asString();
712                }
713            } catch (Exception e) {
714                throw new BoxDeserializationException(memberName, value.toString(), e);
715            }
716        }
717    }
718
719    /**
720     * Represents an input created by a signer on a sign request.
721     */
722    public class BoxSignerInput extends BoxJSONObject {
723        private String documentTagId;
724        private String textValue;
725        private boolean checkboxValue;
726        private BoxSignRequestInputContentType contentType;
727        private Date dateValue;
728        private BoxSignRequestInputType type;
729        private int pageIndex;
730
731        /**
732         * Constructs a BoxSignerInput object using an already parsed JSON object.
733         *
734         * @param jsonObject the parsed JSON object.
735         */
736        public BoxSignerInput(JsonObject jsonObject) {
737            super(jsonObject);
738        }
739
740        /**
741         * Gets the reference of the id of a particular tag added to the content
742         * of the files being used to create the sign request.
743         *
744         * @return document tag id.
745         */
746        public String getDocumentTagId() {
747            return this.documentTagId;
748        }
749
750        /**
751         * Gets the text prefill value.
752         *
753         * @return text prefill value.
754         */
755        public String getTextValue() {
756            return this.textValue;
757        }
758
759        /**
760         * Gets the checkbox prefill value.
761         *
762         * @return checkbox prefill value.
763         */
764        public boolean getIsCheckboxValue() {
765            return this.checkboxValue;
766        }
767
768        /**
769         * Gets the content type of the input.
770         *
771         * @return content type of the input.
772         */
773        public BoxSignRequestInputContentType getContentType() {
774            return this.contentType;
775        }
776
777        /**
778         * Gets the date prefill value.
779         *
780         * @return date prefill value.
781         */
782        public Date getDateValue() {
783            return this.dateValue;
784        }
785
786        /**
787         * Gets the type of input.
788         *
789         * @return type of input.
790         */
791        public BoxSignRequestInputType getType() {
792            return this.type;
793        }
794
795        /**
796         * Gets the index of page that input is on.
797         *
798         * @return index of page that input is on.
799         */
800        public int getPageIndex() {
801            return this.pageIndex;
802        }
803
804        /**
805         * {@inheritDoc}
806         */
807        @Override
808        void parseJSONMember(JsonObject.Member member) {
809            JsonValue value = member.getValue();
810            String memberName = member.getName();
811            try {
812                switch (memberName) {
813                    case "documentTagId":
814                        this.documentTagId = value.asString();
815                        break;
816                    case "text_value":
817                        this.textValue = value.asString();
818                        break;
819                    case "checkbox_value":
820                        this.checkboxValue = value.asBoolean();
821                        break;
822                    case "content_type":
823                        this.contentType = BoxSignRequestInputContentType.fromJSONString(value.asString());
824                        break;
825                    case "date_value":
826                        this.dateValue = BoxDateFormat.parseDateOnly(value.asString());
827                        break;
828                    case "type":
829                        this.type = BoxSignRequestInputType.fromJSONString(value.asString());
830                        break;
831                    case "page_index":
832                        this.pageIndex = value.asInt();
833                        break;
834                    default:
835                        return;
836                }
837            } catch (Exception e) {
838                throw new BoxDeserializationException(memberName, value.toString(), e);
839            }
840        }
841    }
842}
843
844