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