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}