001package com.box.sdk;
002
003import com.eclipsesource.json.Json;
004import com.eclipsesource.json.JsonObject;
005import com.eclipsesource.json.JsonValue;
006import java.net.URL;
007import java.util.ArrayList;
008import java.util.List;
009
010/**
011 * Represents a Sign Template used in the Box Sign API.
012 *
013 * @see <a href="https://developer.box.com/reference/resources/sign-templates/">Box Sign
014 *     Templates</a>
015 *     <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link
016 *     BoxAPIException} (unchecked meaning that the compiler won't force you to handle it) if an
017 *     error occurs. If you wish to implement custom error handling for errors related to the Box
018 *     REST API, you should capture this exception explicitly.
019 */
020@BoxResourceType("sign_template")
021public class BoxSignTemplate extends BoxResource {
022
023  /** The URL template for Sign Templates. */
024  public static final URLTemplate SIGN_TEMPLATES_URL_TEMPLATE = new URLTemplate("sign_templates");
025
026  /** The URL template for Sign Templates operations with a given ID. */
027  public static final URLTemplate SIGN_TEMPLATE_URL_TEMPLATE = new URLTemplate("sign_templates/%s");
028
029  /** The default limit of entries per response. */
030  public static final int DEFAULT_LIMIT = 100;
031
032  /**
033   * Constructs a BoxSignTemplate for a resource with a given ID.
034   *
035   * @param api the API connection to be used by the resource.
036   * @param id the ID of the resource.
037   */
038  public BoxSignTemplate(BoxAPIConnection api, String id) {
039    super(api, id);
040  }
041
042  /**
043   * Return all Sign Templates.
044   *
045   * @param api the API connection to be used by the resource.
046   * @return an iterable with all Sign Templates.
047   */
048  public static Iterable<BoxSignTemplate.Info> getAll(BoxAPIConnection api) {
049    return getAll(api, DEFAULT_LIMIT);
050  }
051
052  /**
053   * Return all Sign Templates.
054   *
055   * @param api the API connection to be used by the resource.
056   * @param limit the limit of entries per response.
057   * @return an iterable with all Sign Templates.
058   */
059  public static Iterable<BoxSignTemplate.Info> getAll(BoxAPIConnection api, int limit) {
060    QueryStringBuilder builder = new QueryStringBuilder();
061    URL url = SIGN_TEMPLATES_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), builder.toString());
062    return new BoxResourceIterable<BoxSignTemplate.Info>(api, url, limit) {
063
064      @Override
065      protected BoxSignTemplate.Info factory(JsonObject jsonObject) {
066        BoxSignTemplate template = new BoxSignTemplate(api, jsonObject.get("id").asString());
067        return template.new Info(jsonObject);
068      }
069    };
070  }
071
072  /**
073   * Return information about this Sign Template.
074   *
075   * @return information about this Sign Template.
076   */
077  public BoxSignTemplate.Info getInfo() {
078    URL url = SIGN_TEMPLATE_URL_TEMPLATE.buildAlpha(this.getAPI().getBaseURL(), this.getID());
079    BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
080    try (BoxJSONResponse response = (BoxJSONResponse) request.send()) {
081      JsonObject jsonObject = Json.parse(response.getJSON()).asObject();
082      return new Info(jsonObject);
083    }
084  }
085
086  /** Contains information about a BoxSignTemplate. */
087  public class Info extends BoxResource.Info {
088
089    private BoxSignTemplateAdditionalInfo additionalInfo;
090    private boolean areEmailSettingsLocked;
091    private boolean areFieldsLocked;
092    private boolean areOptionsLocked;
093    private boolean areFilesLocked;
094    private boolean areRecipientsLocked;
095    private BoxSignTemplateCustomBranding customBranding;
096    private Integer daysValid;
097    private String emailMessage;
098    private String emailSubject;
099    private String name;
100    private BoxFolder.Info parentFolder;
101    private BoxSignTemplateReadySignLink readySignLink;
102    private List<BoxSignTemplateSigner> signers;
103    private List<BoxFile.Info> sourceFiles;
104
105    /** Constructs an empty Info object. */
106    public Info() {
107      super();
108    }
109
110    /**
111     * Constructs an Info object with the provided JSON string.
112     *
113     * @param json the JSON string representing the Sign Template.
114     */
115    public Info(String json) {
116      super(json);
117    }
118
119    /**
120     * Constructs an Info object with the provided JSON object.
121     *
122     * @param jsonObject the JSON object representing the Sign Template.
123     */
124    Info(JsonObject jsonObject) {
125      super(jsonObject);
126    }
127
128    /** {@inheritDoc} */
129    @Override
130    public BoxSignTemplate getResource() {
131      return BoxSignTemplate.this;
132    }
133
134    /**
135     * Gets the additional information about this Sign Template.
136     *
137     * @return the additional information about this Sign Template.
138     */
139    public BoxSignTemplateAdditionalInfo getAdditionalInfo() {
140      return this.additionalInfo;
141    }
142
143    /**
144     * Gets whether the templates email settings are editable or not.
145     *
146     * @return true if the email settings are locked; otherwise false.
147     */
148    public boolean getAreEmailSettingsLocked() {
149      return this.areEmailSettingsLocked;
150    }
151
152    /**
153     * Gets whether the templates input fields are editable or not. This includes deleting or
154     * renaming template files.
155     *
156     * @return true if the fields are locked; otherwise false.
157     */
158    public boolean getAreFieldsLocked() {
159      return this.areFieldsLocked;
160    }
161
162    /**
163     * Gets weather the templates input options are editable or not.
164     *
165     * @return true if the options are editable; otherwise false.
166     */
167    public boolean getAreOptionsLocked() {
168      return this.areOptionsLocked;
169    }
170
171    /**
172     * Gets whether the template document options are editable or not, for example renaming the
173     * document.
174     *
175     * @return true if the files are locked; otherwise false.
176     */
177    public boolean getAreFilesLocked() {
178      return this.areFilesLocked;
179    }
180
181    /**
182     * Gets whether the template signers are editable or not.
183     *
184     * @return true if the recipients are locked; otherwise false.
185     */
186    public boolean getAreRecipientsLocked() {
187      return this.areRecipientsLocked;
188    }
189
190    /**
191     * Gets the custom branding applied to notifications and signature requests.
192     *
193     * @return the custom branding for this Sign Template.
194     */
195    public BoxSignTemplateCustomBranding getCustomBranding() {
196      return this.customBranding;
197    }
198
199    /**
200     * Gets the number of days after which the created signature request will automatically expire
201     * if not completed. By default, we do not apply any expiration date on signature requests, and
202     * the signature request does not expire.
203     *
204     * @return the number of days the template is valid for.
205     */
206    public Integer getDaysValid() {
207      return this.daysValid;
208    }
209
210    /**
211     * Gets the email message that will be sent to all signers.
212     *
213     * @return the email message for this Sign Template.
214     */
215    public String getEmailMessage() {
216      return this.emailMessage;
217    }
218
219    /**
220     * Gets the email subject that will be sent to all signers.
221     *
222     * @return the email subject for this Sign Template.
223     */
224    public String getEmailSubject() {
225      return this.emailSubject;
226    }
227
228    /**
229     * Gets the name of this Sign Template.
230     *
231     * @return the name of this Sign Template.
232     */
233    public String getName() {
234      return this.name;
235    }
236
237    /**
238     * Gets the parent folder of this Sign Template.
239     *
240     * @return the parent folder of this Sign Template.
241     */
242    public BoxFolder.Info getParentFolder() {
243      return this.parentFolder;
244    }
245
246    /**
247     * Gets the ready sign link for this Sign Template.
248     *
249     * @return the ready sign link for this Sign Template.
250     */
251    public BoxSignTemplateReadySignLink getReadySignLink() {
252      return this.readySignLink;
253    }
254
255    /**
256     * Gets the signers for this Sign Template.
257     *
258     * @return the signers for this Sign Template.
259     */
260    public List<BoxSignTemplateSigner> getSigners() {
261      return this.signers;
262    }
263
264    /**
265     * Gets the source files for this Sign Template.
266     *
267     * @return the source files for this Sign Template.
268     */
269    public List<BoxFile.Info> getSourceFiles() {
270      return this.sourceFiles;
271    }
272
273    /** {@inheritDoc} */
274    @Override
275    void parseJSONMember(JsonObject.Member member) {
276      super.parseJSONMember(member);
277      String memberName = member.getName();
278      JsonValue value = member.getValue();
279      try {
280        switch (memberName) {
281          case "additional_info":
282            this.additionalInfo = this.parseAdditionalInfo(value.asObject());
283            break;
284          case "are_email_settings_locked":
285            this.areEmailSettingsLocked = value.asBoolean();
286            break;
287          case "are_fields_locked":
288            this.areFieldsLocked = value.asBoolean();
289            break;
290          case "are_options_locked":
291            this.areOptionsLocked = value.asBoolean();
292            break;
293          case "are_files_locked":
294            this.areFilesLocked = value.asBoolean();
295            break;
296          case "are_recipients_locked":
297            this.areRecipientsLocked = value.asBoolean();
298            break;
299          case "custom_branding":
300            this.customBranding = this.parseCustomBranding(value.asObject());
301            break;
302          case "days_valid":
303            this.daysValid = value.asInt();
304            break;
305          case "email_message":
306            this.emailMessage = value.asString();
307            break;
308          case "email_subject":
309            this.emailSubject = value.asString();
310            break;
311          case "name":
312            this.name = value.asString();
313            break;
314          case "parent_folder":
315            JsonObject parentFolderJSON = value.asObject();
316            String parentFolderID = parentFolderJSON.get("id").asString();
317            BoxFolder parentFolder = new BoxFolder(getAPI(), parentFolderID);
318            this.parentFolder = parentFolder.new Info(parentFolderJSON);
319            break;
320          case "ready_sign_link":
321            this.readySignLink = this.parseReadySignLink(value.asObject());
322            break;
323          case "signers":
324            this.signers = this.parseSigners(value.asArray());
325            break;
326          case "source_files":
327            this.sourceFiles = this.parseSourceFiles(value.asArray());
328            break;
329          default:
330        }
331      } catch (Exception e) {
332        throw new BoxDeserializationException(memberName, value.toString(), e);
333      }
334    }
335
336    private BoxSignTemplateAdditionalInfo parseAdditionalInfo(JsonValue additionalInfoJSON) {
337      List<String> nonEditableFields = new ArrayList<String>();
338      for (JsonValue fieldJSON : additionalInfoJSON.asObject().get("non_editable").asArray()) {
339        nonEditableFields.add(fieldJSON.asString());
340      }
341      BoxSignTemplateAdditionalInfoRequired required =
342          this.parseAdditionalInfoRequired(
343              additionalInfoJSON.asObject().get("required").asObject());
344      return new BoxSignTemplateAdditionalInfo(nonEditableFields, required);
345    }
346
347    private BoxSignTemplateAdditionalInfoRequired parseAdditionalInfoRequired(
348        JsonObject requiredJSON) {
349      List<List<String>> signers = new ArrayList<List<String>>();
350      for (JsonValue signerJSON : requiredJSON.get("signers").asArray()) {
351        List<String> signer = new ArrayList<String>();
352        for (JsonValue fieldJSON : signerJSON.asArray()) {
353          signer.add(fieldJSON.asString());
354        }
355        signers.add(signer);
356      }
357      return new BoxSignTemplateAdditionalInfoRequired(signers);
358    }
359
360    private List<BoxFile.Info> parseSourceFiles(JsonValue filesArray) {
361      List<BoxFile.Info> files = new ArrayList<BoxFile.Info>();
362      for (JsonValue fileJSON : filesArray.asArray()) {
363        JsonObject fileObj = fileJSON.asObject();
364        String fileID = fileObj.get("id").asString();
365        BoxFile file = new BoxFile(getAPI(), fileID);
366        files.add(file.new Info(fileObj));
367      }
368      return files;
369    }
370
371    private List<BoxSignTemplateSigner> parseSigners(JsonValue signersArray) {
372      List<BoxSignTemplateSigner> signers = new ArrayList<BoxSignTemplateSigner>();
373      for (JsonValue signerJSON : signersArray.asArray()) {
374        JsonObject signerObj = signerJSON.asObject();
375        signers.add(new BoxSignTemplateSigner(signerObj, getAPI()));
376      }
377      return signers;
378    }
379
380    private BoxSignTemplateCustomBranding parseCustomBranding(JsonObject customBrandingJSON) {
381      String brandingColor = customBrandingJSON.get("branding_color").asString();
382      String companyName = customBrandingJSON.get("company_name").asString();
383      String emailFooterText = customBrandingJSON.get("email_footer_text").asString();
384      String logoUri = customBrandingJSON.get("logo_uri").asString();
385      return new BoxSignTemplateCustomBranding(
386          brandingColor, companyName, emailFooterText, logoUri);
387    }
388
389    private BoxSignTemplateReadySignLink parseReadySignLink(JsonObject readySignLinkJSON) {
390      String folderID = readySignLinkJSON.get("folder_id").asString();
391      String instructions = readySignLinkJSON.get("instructions").asString();
392      boolean isActive = readySignLinkJSON.get("is_active").asBoolean();
393      boolean isNofiticationDisabled =
394          readySignLinkJSON.get("is_notification_disabled").asBoolean();
395      String name = readySignLinkJSON.get("name").asString();
396      String url = readySignLinkJSON.get("url").asString();
397      return new BoxSignTemplateReadySignLink(
398          folderID, instructions, isActive, isNofiticationDisabled, name, url);
399    }
400  }
401}