001package com.box.sdk;
002
003import com.eclipsesource.json.Json;
004import com.eclipsesource.json.JsonArray;
005import com.eclipsesource.json.JsonObject;
006import com.eclipsesource.json.JsonValue;
007import java.net.URL;
008import java.util.ArrayList;
009import java.util.Date;
010import java.util.List;
011
012/**
013 * Represents a Sign Request used by Box Sign.
014 * Sign Requests are used to request e-signatures on documents from signers.
015 * A Sign Request can refer to one or more Box Files and can be sent to one or more Box Sign Request Signers.
016 *
017 * @see <a href="https://developer.box.com/reference/resources/sign-requests/">Box Sign Request</a>
018 *
019 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked
020 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error
021 * handling for errors related to the Box REST API, you should capture this exception explicitly.</p>
022 */
023@BoxResourceType("sign_request")
024public class BoxSignRequest extends BoxResource {
025
026    /**
027     * The URL template used for operation Sign Request operations.
028     */
029    public static final URLTemplate SIGN_REQUESTS_URL_TEMPLATE = new URLTemplate("sign_requests");
030
031    /**
032     * The URL template used for Sign Request operations with a given ID.
033     */
034    public static final URLTemplate SIGN_REQUEST_URL_TEMPLATE = new URLTemplate("sign_requests/%s");
035
036    /**
037     * The URL template used to cancel an existing Sign Request.
038     */
039    public static final URLTemplate SIGN_REQUEST_CANCEL_URL_TEMPLATE = new URLTemplate("sign_requests/%s/cancel");
040
041    /**
042     * The URL template used to resend an existing Sign Request.
043     */
044    public static final URLTemplate SIGN_REQUEST_RESEND_URL_TEMPLATE = new URLTemplate("sign_requests/%s/resend");
045
046    /**
047     * The default limit of entries per response.
048     */
049    private static final int DEFAULT_LIMIT = 100;
050
051    /**
052     * Constructs a BoxResource for a resource with a given ID.
053     *
054     * @param api the API connection to be used by the resource.
055     * @param id  the ID of the resource.
056     */
057    public BoxSignRequest(BoxAPIConnection api, String id) {
058        super(api, id);
059    }
060
061    /**
062     * Used to create a new sign request using existing BoxFile.Info models.
063     *
064     * @param api            the API connection to be used by the created user.
065     * @param sourceFiles    the list of BoxFile.Info files to create a signing document from.
066     * @param signers        the list of signers for this sign request.
067     * @param parentFolderId the id of the destination folder to place sign request specific data in.
068     * @param optionalParams the optional parameters.
069     * @return the created sign request's info.
070     */
071    public static BoxSignRequest.Info createSignRequestFromFiles(BoxAPIConnection api,
072                                                                 List<BoxFile.Info> sourceFiles,
073                                                                 List<BoxSignRequestSigner> signers,
074                                                                 String parentFolderId,
075                                                                 BoxSignRequestCreateParams optionalParams) {
076        return createSignRequest(api, toBoxSignRequestFiles(sourceFiles), signers, parentFolderId, optionalParams);
077    }
078
079    /**
080     * Used to create a new sign request using BoxFile.Info models.
081     *
082     * @param api            the API connection to be used by the created user.
083     * @param sourceFiles    the list of BoxFile.Info files to create a signing document from.
084     * @param signers        the list of signers for this sign request.
085     * @param parentFolderId the id of the destination folder to place sign request specific data in.
086     * @return the created sign request's info.
087     */
088    public static BoxSignRequest.Info createSignRequestFromFiles(BoxAPIConnection api,
089                                                                 List<BoxFile.Info> sourceFiles,
090                                                                 List<BoxSignRequestSigner> signers,
091                                                                 String parentFolderId) {
092
093        return createSignRequest(api, toBoxSignRequestFiles(sourceFiles), signers, parentFolderId, null);
094    }
095
096    /**
097     * Used to create a new sign request.
098     *
099     * @param api            the API connection to be used by the created user.
100     * @param sourceFiles    the list of files to a signing document from.
101     * @param signers        the list of signers for this sign request.
102     * @param parentFolderId the id of the destination folder to place sign request specific data in.
103     * @return the created sign request's info.
104     */
105    public static BoxSignRequest.Info createSignRequest(BoxAPIConnection api, List<BoxSignRequestFile> sourceFiles,
106                                                        List<BoxSignRequestSigner> signers, String parentFolderId) {
107        return createSignRequest(api, sourceFiles, signers, parentFolderId, null);
108    }
109
110    /**
111     * Used to create a new sign request with optional parameters.
112     *
113     * @param api            the API connection to be used by the created user.
114     * @param signers        the list of signers for this sign request.
115     * @param sourceFiles    the list of files to a signing document from.
116     * @param parentFolderId the id of the destination folder to place sign request specific data in.
117     * @param optionalParams the optional parameters.
118     * @return the created sign request's info.
119     */
120    public static BoxSignRequest.Info createSignRequest(BoxAPIConnection api, List<BoxSignRequestFile> sourceFiles,
121                                                        List<BoxSignRequestSigner> signers, String parentFolderId,
122                                                        BoxSignRequestCreateParams optionalParams) {
123
124        JsonObject requestJSON = new JsonObject();
125
126        JsonArray sourceFilesJSON = new JsonArray();
127        for (BoxSignRequestFile sourceFile : sourceFiles) {
128            sourceFilesJSON.add(sourceFile.getJSONObject());
129        }
130        requestJSON.add("source_files", sourceFilesJSON);
131
132        JsonArray signersJSON = new JsonArray();
133        for (BoxSignRequestSigner signer : signers) {
134            signersJSON.add(signer.getJSONObject());
135        }
136        requestJSON.add("signers", signersJSON);
137
138        JsonObject parentFolderJSON = new JsonObject();
139        parentFolderJSON.add("id", parentFolderId);
140        parentFolderJSON.add("type", "folder");
141        requestJSON.add("parent_folder", parentFolderJSON);
142
143        if (optionalParams != null) {
144            optionalParams.appendParamsAsJson(requestJSON);
145        }
146
147        URL url = SIGN_REQUESTS_URL_TEMPLATE.build(api.getBaseURL());
148        BoxJSONRequest request = new BoxJSONRequest(api, url, "POST");
149        request.setBody(requestJSON.toString());
150        try (BoxJSONResponse response = request.send()) {
151            JsonObject responseJSON = Json.parse(response.getJSON()).asObject();
152            BoxSignRequest signRequest = new BoxSignRequest(api, responseJSON.get("id").asString());
153            return signRequest.new Info(responseJSON);
154        }
155    }
156
157    /**
158     * Returns all the sign requests.
159     *
160     * @param api    the API connection to be used by the resource.
161     * @param fields the fields to retrieve.
162     * @return an iterable with all the sign requests.
163     */
164    public static Iterable<BoxSignRequest.Info> getAll(final BoxAPIConnection api, String... fields) {
165        return getAll(api, DEFAULT_LIMIT, fields);
166    }
167
168    /**
169     * Returns all the sign requests.
170     *
171     * @param api    the API connection to be used by the resource.
172     * @param limit  the limit of items per single response. The default value is 100.
173     * @param fields the fields to retrieve.
174     * @return an iterable with all the sign requests.
175     */
176    public static Iterable<BoxSignRequest.Info> getAll(final BoxAPIConnection api, int limit, String... fields) {
177        QueryStringBuilder queryString = new QueryStringBuilder();
178        if (fields.length > 0) {
179            queryString.appendParam("fields", fields);
180        }
181        URL url = SIGN_REQUESTS_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), queryString.toString());
182        return new BoxResourceIterable<BoxSignRequest.Info>(api, url, limit) {
183
184            @Override
185            protected BoxSignRequest.Info factory(JsonObject jsonObject) {
186                BoxSignRequest signRequest = new BoxSignRequest(api, jsonObject.get("id").asString());
187                return signRequest.new Info(jsonObject);
188            }
189
190        };
191    }
192
193    private static List<BoxSignRequestFile> toBoxSignRequestFiles(List<BoxFile.Info> sourceFiles) {
194        List<BoxSignRequestFile> files = new ArrayList<>();
195        for (BoxFile.Info sourceFile : sourceFiles) {
196            BoxSignRequestFile file = BoxSignRequestFile.fromFile(sourceFile);
197            files.add(file);
198        }
199
200        return files;
201    }
202
203    /**
204     * Returns information about this sign request.
205     *
206     * @param fields the fields to retrieve.
207     * @return information about this sign request.
208     */
209    public BoxSignRequest.Info getInfo(String... fields) {
210        QueryStringBuilder builder = new QueryStringBuilder();
211        if (fields.length > 0) {
212            builder.appendParam("fields", fields);
213        }
214        URL url = SIGN_REQUEST_URL_TEMPLATE.buildAlphaWithQuery(
215            this.getAPI().getBaseURL(), builder.toString(), this.getID());
216        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "GET");
217        try (BoxJSONResponse response = request.send()) {
218            JsonObject responseJSON = Json.parse(response.getJSON()).asObject();
219            return new BoxSignRequest.Info(responseJSON);
220        }
221    }
222
223    /**
224     * Cancels a sign request if it has not yet been signed or declined.
225     * Any outstanding signers will no longer be able to sign the document.
226     *
227     * @return the cancelled sign request's info.
228     */
229    public BoxSignRequest.Info cancel() {
230        URL url = SIGN_REQUEST_CANCEL_URL_TEMPLATE.buildAlphaWithQuery(getAPI().getBaseURL(), "", this.getID());
231        BoxJSONRequest request = new BoxJSONRequest(getAPI(), url, "POST");
232        try (BoxJSONResponse response = request.send()) {
233            JsonObject responseJSON = Json.parse(response.getJSON()).asObject();
234            return new BoxSignRequest.Info(responseJSON);
235        }
236    }
237
238    /**
239     * Attempts to resend a Sign Request to all signers that have not signed yet.
240     * There is a 10 minute cooling-off period between each resend request.
241     * If you make a resend call during the cooling-off period, a BoxAPIException will be thrown.
242     */
243    public void resend() {
244        URL url = SIGN_REQUEST_RESEND_URL_TEMPLATE.buildAlphaWithQuery(getAPI().getBaseURL(), "", this.getID());
245        BoxAPIRequest request = new BoxAPIRequest(getAPI(), url, "POST");
246        request.send().close();
247    }
248
249    /**
250     * Represents a status of the sign request.
251     */
252    public enum BoxSignRequestStatus {
253
254        /**
255         * Converting status.
256         */
257        Converting("converting"),
258
259        /**
260         * Created status.
261         */
262        Created("created"),
263
264        /**
265         * Sent status.
266         */
267        Sent("sent"),
268
269        /**
270         * Viewed status.
271         */
272        Viewed("viewed"),
273
274        /**
275         * Signed status.
276         */
277        Signed("signed"),
278
279        /**
280         * Cancelled status.
281         */
282        Cancelled("cancelled"),
283
284        /**
285         * Declined status.
286         */
287        Declined("declined"),
288
289        /**
290         * Error converting status.
291         */
292        ErrorConverting("error_converting"),
293
294        /**
295         * Error sending status.
296         */
297        ErrorSending("error_sending"),
298
299        /**
300         * Expired status.
301         */
302        Expired("expired"),
303
304        /**
305         * Finalizing status.
306         */
307        Finalizing("finalizing"),
308
309        /**
310         * Error finalizing status.
311         */
312        ErrorFinalizing("error_finalizing");
313
314        private final String jsonValue;
315
316        BoxSignRequestStatus(String jsonValue) {
317            this.jsonValue = jsonValue;
318        }
319
320        static BoxSignRequestStatus fromJSONString(String jsonValue) {
321            switch (jsonValue) {
322                case "converting":
323                    return Converting;
324                case "created":
325                    return Created;
326                case "sent":
327                    return Sent;
328                case "viewed":
329                    return Viewed;
330                case "signed":
331                    return Signed;
332                case "cancelled":
333                    return Cancelled;
334                case "declined":
335                    return Declined;
336                case "error_converting":
337                    return ErrorConverting;
338                case "error_sending":
339                    return ErrorSending;
340                case "expired":
341                    return Expired;
342                case "finalizing":
343                    return Finalizing;
344                case "error_finalizing":
345                    return ErrorFinalizing;
346                default:
347            }
348            throw new IllegalArgumentException("The provided JSON value isn't a valid BoxSignRequestStatus value.");
349        }
350    }
351
352    /**
353     * Contains information about the Sign Request.
354     */
355    public class Info extends BoxResource.Info {
356
357        private boolean isDocumentPreparationNeeded;
358        private boolean areTextSignaturesEnabled;
359        private boolean areDatesEnabled;
360        private BoxSignRequestSignatureColor signatureColor;
361        private String emailSubject;
362        private String emailMessage;
363        private boolean areRemindersEnabled;
364        private List<BoxFile.Info> sourceFiles;
365        private BoxFolder.Info parentFolder;
366        private List<BoxSignRequestSigner> signers;
367        private String name;
368        private List<BoxSignRequestPrefillTag> prefillTags;
369        private Integer daysValid;
370        private String externalId;
371        private String prepareUrl;
372        private BoxFile.Info signingLog;
373        private BoxSignRequestStatus status;
374        private BoxSignRequestSignFiles signFiles;
375        private Date autoExpireAt;
376        private String redirectUrl;
377        private String declinedRedirectUrl;
378        private String templateId;
379
380        /**
381         * Constructs an empty Info object.
382         */
383        public Info() {
384            super();
385        }
386
387        /**
388         * Constructs an Info object by parsing information from a JSON string.
389         *
390         * @param json the JSON string to parse.
391         */
392        public Info(String json) {
393            super(json);
394        }
395
396        /**
397         * Constructs an Info object using an already parsed JSON object.
398         *
399         * @param jsonObject the parsed JSON object.
400         */
401        Info(JsonObject jsonObject) {
402            super(jsonObject);
403        }
404
405        /**
406         * Indicates if the sender should receive a prepare_url in the response to complete document preparation via UI.
407         *
408         * @return true if document preparation is needed, otherwise false.
409         */
410        public boolean getIsDocumentPreparationNeeded() {
411            return this.isDocumentPreparationNeeded;
412        }
413
414        /**
415         * Gets the flag indicating if usage of signatures generated by typing (text) is enabled.
416         *
417         * @return true if text signatures are enabled, otherwise false.
418         */
419        public boolean getAreTextSignaturesEnabled() {
420            return this.areTextSignaturesEnabled;
421        }
422
423        /**
424         * Gets the flag indicating if ability for signer to add dates is enabled.
425         *
426         * @return true if ability for signer to add dates is enabled, otherwise false.
427         */
428        public boolean getAreDatesEnabled() {
429            return this.areDatesEnabled;
430        }
431
432        /**
433         * Gets the forced, specific color for the signature.
434         *
435         * @return signature color (blue, black, red).
436         */
437        public BoxSignRequestSignatureColor getSignatureColor() {
438            return this.signatureColor;
439        }
440
441        /**
442         * Gets the subject of the sign request email.
443         *
444         * @return subject of the sign request email.
445         */
446        public String getEmailSubject() {
447            return this.emailSubject;
448        }
449
450        /**
451         * Gets the message to include in the sign request email.
452         *
453         * @return message of sign request email.
454         */
455        public String getEmailMessage() {
456            return this.emailMessage;
457        }
458
459        /**
460         * Gets the flag indicating if sending reminders for signers to sign a document on day 3, 8, 13 and 18
461         * (or less if the document has been digitally signed already) is enabled.
462         *
463         * @return true if reminders are enabled, otherwise false.
464         */
465        public boolean getAreRemindersEnabled() {
466            return this.areRemindersEnabled;
467        }
468
469        /**
470         * Gets the list of files to create a signing document from.
471         *
472         * @return list of files to create a signing document from.
473         */
474        public List<BoxFile.Info> getSourceFiles() {
475            return this.sourceFiles;
476        }
477
478        /**
479         * Gets the destination folder to place sign request specific data in (copy of source files, signing log etc.).
480         *
481         * @return destination folder to place sign request specific data in.
482         */
483        public BoxFolder.Info getParentFolder() {
484            return this.parentFolder;
485        }
486
487        /**
488         * Gets the list of signers for this sign request.
489         *
490         * @return list of signers for this sign request.
491         */
492        public List<BoxSignRequestSigner> getSigners() {
493            return this.signers;
494        }
495
496        /**
497         * Gets the name of this sign request.
498         *
499         * @return name of this sign request.
500         */
501        public String getName() {
502            return this.name;
503        }
504
505        /**
506         * Gets the list of prefill tags.
507         *
508         * @return list of prefill tags.
509         */
510        public List<BoxSignRequestPrefillTag> getPrefillTags() {
511            return this.prefillTags;
512        }
513
514        /**
515         * Gets the number of days after which this request will automatically expire if not completed.
516         *
517         * @return number of days after which this request will automatically expire if not completed.
518         */
519        public Integer getDaysValid() {
520            return this.daysValid;
521        }
522
523        /**
524         * Gets the reference id in an external system that this sign request is related to.
525         *
526         * @return external id.
527         */
528        public String getExternalId() {
529            return this.externalId;
530        }
531
532        /**
533         * Gets the URL that can be used by the sign request sender to prepare the document through the UI.
534         *
535         * @return prepare url.
536         */
537        public String getPrepareUrl() {
538            return this.prepareUrl;
539        }
540
541        /**
542         * Gets the reference to a file that will hold a log of all signer activity for this request.
543         *
544         * @return signing log.
545         */
546        public BoxFile.Info getSigningLog() {
547            return this.signingLog;
548        }
549
550        /**
551         * Gets the status of the sign request.
552         *
553         * @return sign request's status.
554         */
555        public BoxSignRequestStatus getStatus() {
556            return this.status;
557        }
558
559        /**
560         * List of files that will be signed, which are copies of the original source files.
561         * A new version of these files are created as signers sign and can be downloaded
562         * at any point in the signing process.
563         *
564         * @return sign files.
565         */
566        public BoxSignRequestSignFiles getSignFiles() {
567            return this.signFiles;
568        }
569
570        /**
571         * Uses days_valid to calculate the date and time that
572         * the sign request will expire, if unsigned.
573         *
574         * @return auto expires at date.
575         */
576        public Date getAutoExpireAt() {
577            return this.autoExpireAt;
578        }
579
580        /**
581         * Gets the URL that will be redirected to after the signer completes the sign request.
582         *
583         * @return redirect url.
584         */
585        public String getRedirectUrl() {
586            return this.redirectUrl;
587        }
588
589        /**
590         * Gets the URL that will be redirected to after the signer declines the sign request.
591         *
592         * @return declined redirect url.
593         */
594        public String getDeclinedRedirectUrl() {
595            return this.declinedRedirectUrl;
596        }
597
598        /**
599         * Gets the id of the template that was used to create this sign request.
600         *
601         * @return sign template id.
602         */
603        public String getTemplateId() {
604            return this.templateId;
605        }
606
607        /**
608         * {@inheritDoc}
609         */
610        @Override
611        public BoxSignRequest getResource() {
612            return BoxSignRequest.this;
613        }
614
615        /**
616         * {@inheritDoc}
617         */
618        @Override
619        void parseJSONMember(JsonObject.Member member) {
620            super.parseJSONMember(member);
621            String memberName = member.getName();
622            JsonValue value = member.getValue();
623            try {
624                switch (memberName) {
625                    case "is_document_preparation_needed":
626                        this.isDocumentPreparationNeeded = value.asBoolean();
627                        break;
628                    case "are_text_signatures_enabled":
629                        this.areTextSignaturesEnabled = value.asBoolean();
630                        break;
631                    case "are_dates_enabled":
632                        this.areDatesEnabled = value.asBoolean();
633                        break;
634                    case "signature_color":
635                        this.signatureColor = BoxSignRequestSignatureColor.fromJSONString(value.asString());
636                        break;
637                    case "email_subject":
638                        this.emailSubject = value.asString();
639                        break;
640                    case "email_message":
641                        this.emailMessage = value.asString();
642                        break;
643                    case "are_reminders_enabled":
644                        this.areRemindersEnabled = value.asBoolean();
645                        break;
646                    case "signers":
647                        List<BoxSignRequestSigner> signers = new ArrayList<>();
648                        for (JsonValue signerJSON : value.asArray()) {
649                            BoxSignRequestSigner signer = new BoxSignRequestSigner(signerJSON.asObject(), getAPI());
650                            signers.add(signer);
651                        }
652                        this.signers = signers;
653                        break;
654                    case "source_files":
655                        this.sourceFiles = this.getFiles(value.asArray());
656                        break;
657                    case "parent_folder":
658                        JsonObject folderJSON = value.asObject();
659                        String folderID = folderJSON.get("id").asString();
660                        BoxFolder folder = new BoxFolder(getAPI(), folderID);
661                        this.parentFolder = folder.new Info(folderJSON);
662                        break;
663                    case "name":
664                        this.name = value.asString();
665                        break;
666                    case "prefill_tags":
667                        List<BoxSignRequestPrefillTag> prefillTags = new ArrayList<>();
668                        for (JsonValue prefillTagJSON : value.asArray()) {
669                            BoxSignRequestPrefillTag prefillTag =
670                                new BoxSignRequestPrefillTag(prefillTagJSON.asObject());
671                            prefillTags.add(prefillTag);
672                        }
673                        this.prefillTags = prefillTags;
674                        break;
675                    case "days_valid":
676                        this.daysValid = value.asInt();
677                        break;
678                    case "external_id":
679                        this.externalId = value.asString();
680                        break;
681                    case "prepare_url":
682                        this.prepareUrl = value.asString();
683                        break;
684                    case "signing_log":
685                        JsonObject signingLogJSON = value.asObject();
686                        String fileID = signingLogJSON.get("id").asString();
687                        BoxFile file = new BoxFile(getAPI(), fileID);
688                        this.signingLog = file.new Info(signingLogJSON);
689                        break;
690                    case "status":
691                        this.status = BoxSignRequestStatus.fromJSONString(value.asString());
692                        break;
693                    case "sign_files":
694                        JsonObject signFilesJSON = value.asObject();
695                        JsonValue filesArray = signFilesJSON.get("files");
696                        List<BoxFile.Info> signFiles = this.getFiles(filesArray);
697                        boolean isReadyForDownload = signFilesJSON.get("is_ready_for_download").asBoolean();
698                        this.signFiles = new BoxSignRequestSignFiles(signFiles, isReadyForDownload);
699                        break;
700                    case "auto_expire_at":
701                        this.autoExpireAt = BoxDateFormat.parse(value.asString());
702                        break;
703                    case "redirect_url":
704                        this.redirectUrl = value.asString();
705                        break;
706                    case "declined_redirect_url":
707                        this.declinedRedirectUrl = value.asString();
708                        break;
709                    case "template_id":
710                        this.templateId = value.asString();
711                        break;
712                    default:
713                }
714            } catch (Exception e) {
715                throw new BoxDeserializationException(memberName, value.toString(), e);
716            }
717        }
718
719        private List<BoxFile.Info> getFiles(JsonValue filesArray) {
720            List<BoxFile.Info> files = new ArrayList<>();
721            for (JsonValue fileJSON : filesArray.asArray()) {
722                String fileID = fileJSON.asObject().get("id").asString();
723                BoxFile file = new BoxFile(getAPI(), fileID);
724                files.add(file.new Info(fileJSON.asObject()));
725            }
726            return files;
727        }
728
729        /**
730         * List of files that will be signed, which are copies of the original source files.
731         * A new version of these files are created as signers sign and can be downloaded
732         * at any point in the signing process.
733         */
734        public class BoxSignRequestSignFiles {
735            private final List<BoxFile.Info> files;
736            private final boolean isReadyToDownload;
737
738            /**
739             * Constructs a BoxSignRequestSignFiles.
740             *
741             * @param files             list that signing events will occur on.
742             * @param isReadyToDownload indicating whether a change to the document is processing.
743             */
744            public BoxSignRequestSignFiles(List<BoxFile.Info> files, boolean isReadyToDownload) {
745                this.files = files;
746                this.isReadyToDownload = isReadyToDownload;
747            }
748
749            /**
750             * Gets the list of files that signing events will occur on - these are copies of the original source files.
751             *
752             * @return list of files.
753             */
754            public List<BoxFile.Info> getFiles() {
755                return this.files;
756            }
757
758            /**
759             * Gets the flag indicating whether a change to the document is processing and the PDF may be out of date.
760             * It is recommended to wait until processing has finished before downloading the PDF.
761             * Webhooks are not sent until processing has been completed.
762             *
763             * @return true if files are ready to download, otherwise false.
764             */
765            public boolean getIsReadyToDownload() {
766                return this.isReadyToDownload;
767            }
768        }
769    }
770}