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