Search in sources :

Example 1 with Triple

use of org.opendatakit.briefcase.reused.Triple in project briefcase by opendatakit.

the class PushToCentral method push.

/**
 * Pushes a form completely, sending the form file, form attachments,
 * submission files and their attachments to the Aggregate server.
 * <p>
 * It won't push a form and form attachments if it's already
 * present in the server.
 */
@SuppressWarnings("checkstyle:Indentation")
public Job<Void> push(FormStatus form) {
    PushToCentralTracker tracker = new PushToCentralTracker(form, onEventCallback);
    Job<Void> startTrackingJob = Job.run(runnerStatus -> tracker.trackStart());
    // Verify that the form is not encrypted
    Path formFile = form.getFormFile(briefcaseDir);
    try {
        if (FormDefinition.from(formFile).isFileEncryptedForm())
            return startTrackingJob.thenRun(rs -> {
                tracker.trackEncryptedForm();
                tracker.trackEnd();
            });
    } catch (RuntimeException e) {
        return startTrackingJob.thenRun(rs -> {
            tracker.trackCannotDetermineEncryption(e);
            tracker.trackEnd();
        });
    }
    FormMetadataPort formMetadataPort = FileSystemFormMetadataAdapter.at(briefcaseDir);
    return startTrackingJob.thenSupply(rs -> getMissingFormVersions(form, rs, tracker, formMetadataPort)).thenAccept(((rs, missingFormVersions) -> {
        String localFormVersion = form.getVersion().orElse("");
        boolean sendLocal = missingFormVersions.remove(localFormVersion);
        // First send a request to create the form. It doesn't matter what version is sent because it will be replaced
        // below. Will fail if a published form already exists with this id but then missing versions can still be added.
        createForm(form.getFormFile(briefcaseDir), rs, tracker);
        // Send all of the obsolete versions first so that we can send corresponding submissions. Skip attachments
        // because those versions won't be used by clients.
        missingFormVersions.stream().sorted().forEach(version -> {
            pushFormDraft(form.getFormFile(briefcaseDir), form.getFormId(), version, rs, tracker);
            publishDraft(form.getFormId(), version, rs, tracker);
        });
        if (sendLocal) {
            boolean formSent = pushFormDraft(formFile, form.getFormId(), localFormVersion, rs, tracker);
            if (formSent) {
                List<Path> formAttachments = getFormAttachments(form);
                AtomicInteger attachmentSeq = new AtomicInteger(1);
                int totalAttachments = formAttachments.size();
                formAttachments.forEach(attachment -> pushFormAttachment(form.getFormId(), attachment, rs, tracker, attachmentSeq.getAndIncrement(), totalAttachments));
                publishDraft(form.getFormId(), localFormVersion, rs, tracker);
            }
        }
    })).thenSupply(__ -> getSubmissions(form)).thenAccept((rs, submissions) -> {
        AtomicInteger submissionNumber = new AtomicInteger(1);
        int totalSubmissions = submissions.size();
        if (submissions.isEmpty())
            tracker.trackNoSubmissions();
        // We might not have had access to submission versions because e.g. submissions were manually added to the
        // Briefcase folder or were imported in <=v1.17 when submission versions weren't saved.
        Set<String> seenVersions = new HashSet<>();
        submissions.parallelStream().map(submission -> {
            XmlElement root = XmlElement.from(new String(readAllBytes(submission)));
            SubmissionMetaData metaData = new SubmissionMetaData(root);
            metaData.getVersion().ifPresent(seenVersions::add);
            return Triple.of(submission, submissionNumber.getAndIncrement(), metaData.getInstanceId());
        }).peek(triple -> {
            if (!triple.get3().isPresent())
                tracker.trackNoInstanceId(triple.get2(), totalSubmissions);
        }).filter(triple -> triple.get3().isPresent()).forEach(triple -> {
            Path submission = triple.get1();
            int currentSubmissionNumber = triple.get2();
            String instanceId = triple.get3().get();
            boolean submissionSent = pushSubmission(form.getFormId(), submission, rs, tracker, currentSubmissionNumber, totalSubmissions);
            if (submissionSent) {
                List<Path> submissionAttachments = getSubmissionAttachments(submission);
                AtomicInteger attachmentSeq = new AtomicInteger(1);
                int totalAttachments = submissionAttachments.size();
                submissionAttachments.parallelStream().forEach(attachment -> pushSubmissionAttachment(form.getFormId(), instanceId, attachment, rs, tracker, currentSubmissionNumber, totalSubmissions, attachmentSeq.getAndIncrement(), totalAttachments));
            }
        });
        formMetadataPort.execute(updateSubmissionVersions(FormKey.from(form), briefcaseDir, form.getFormDir(briefcaseDir), seenVersions));
        tracker.trackEnd();
    }).thenRun(rs -> EventBus.publish(new PushEvent.Success(form)));
}
Also used : Path(java.nio.file.Path) FormDefinition(org.opendatakit.briefcase.export.FormDefinition) FileSystemFormMetadataAdapter(org.opendatakit.briefcase.model.form.FileSystemFormMetadataAdapter) UncheckedFiles(org.opendatakit.briefcase.reused.UncheckedFiles) Response(org.opendatakit.briefcase.reused.http.response.Response) SubmissionMetaData(org.opendatakit.briefcase.export.SubmissionMetaData) HashSet(java.util.HashSet) FormMetadataPort(org.opendatakit.briefcase.model.form.FormMetadataPort) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) UncheckedFiles.readAllBytes(org.opendatakit.briefcase.reused.UncheckedFiles.readAllBytes) EventBus(org.bushe.swing.event.EventBus) UncheckedFiles.list(org.opendatakit.briefcase.reused.UncheckedFiles.list) Path(java.nio.file.Path) FormKey(org.opendatakit.briefcase.model.form.FormKey) FormMetadataQueries.submissionVersionsOf(org.opendatakit.briefcase.model.form.FormMetadataQueries.submissionVersionsOf) FormStatus(org.opendatakit.briefcase.model.FormStatus) FormStatusEvent(org.opendatakit.briefcase.model.FormStatusEvent) CentralServer(org.opendatakit.briefcase.reused.transfer.CentralServer) Files(java.nio.file.Files) Collections.emptyList(java.util.Collections.emptyList) Set(java.util.Set) RunnerStatus(org.opendatakit.briefcase.reused.job.RunnerStatus) Http(org.opendatakit.briefcase.reused.http.Http) UncheckedFiles.exists(org.opendatakit.briefcase.reused.UncheckedFiles.exists) FormMetadataCommands.updateSubmissionVersions(org.opendatakit.briefcase.model.form.FormMetadataCommands.updateSubmissionVersions) Consumer(java.util.function.Consumer) Collectors.toList(java.util.stream.Collectors.toList) List(java.util.List) PushEvent(org.opendatakit.briefcase.push.PushEvent) Triple(org.opendatakit.briefcase.reused.Triple) Job(org.opendatakit.briefcase.reused.job.Job) Collections(java.util.Collections) InputStream(java.io.InputStream) XmlElement(org.opendatakit.briefcase.export.XmlElement) SubmissionMetaData(org.opendatakit.briefcase.export.SubmissionMetaData) HashSet(java.util.HashSet) Set(java.util.Set) FormMetadataPort(org.opendatakit.briefcase.model.form.FormMetadataPort) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) XmlElement(org.opendatakit.briefcase.export.XmlElement) Collections.emptyList(java.util.Collections.emptyList) Collectors.toList(java.util.stream.Collectors.toList) List(java.util.List)

Example 2 with Triple

use of org.opendatakit.briefcase.reused.Triple in project briefcase by opendatakit.

the class PullFromAggregate method pull.

/**
 * Pulls a form completely, writing the form file, form attachments,
 * submission files and their attachments to the local filesystem
 * under the Briefcase Storage directory.
 * <p>
 * A {@link Cursor} can be provided to define the starting point to
 * download the form's submissions.
 * <p>
 * Returns a Job that will produce a pull operation result.
 */
public Job<Void> pull(FormStatus form, Optional<Cursor> lastCursor) {
    FormKey key = FormKey.from(form);
    PullFromAggregateTracker tracker = new PullFromAggregateTracker(form, onEventCallback);
    // Download the form and attachments, and get the submissions list
    return run(rs -> tracker.trackStart()).thenSupply(rs -> downloadForm(form, rs, tracker)).thenAccept((rs, formXml) -> {
        if (formXml == null)
            return;
        List<AggregateAttachment> attachments = getFormAttachments(form, rs, tracker);
        int totalAttachments = attachments.size();
        AtomicInteger attachmentNumber = new AtomicInteger(1);
        attachments.parallelStream().forEach(attachment -> downloadFormAttachment(form, attachment, rs, tracker, attachmentNumber.getAndIncrement(), totalAttachments));
        List<InstanceIdBatch> instanceIdBatches = getSubmissionIds(form, lastCursor.orElse(Cursor.empty()), rs, tracker);
        // Build the submission key generator with the form's XML contents
        SubmissionKeyGenerator subKeyGen = SubmissionKeyGenerator.from(formXml);
        // Extract all the instance IDs from all the batches and download each instance
        List<String> ids = instanceIdBatches.stream().flatMap(batch -> batch.getInstanceIds().stream()).collect(toList());
        int totalSubmissions = ids.size();
        AtomicInteger submissionNumber = new AtomicInteger(1);
        Set<String> submissionVersions = new HashSet<>();
        if (ids.isEmpty())
            tracker.trackNoSubmissions();
        withDb(form.getFormDir(briefcaseDir), db -> {
            // We need to collect to be able to create a parallel stream again
            ids.parallelStream().map(instanceId -> Triple.of(submissionNumber.getAndIncrement(), instanceId, db.hasRecordedInstance(instanceId) == null)).peek(triple -> {
                if (!triple.get3())
                    tracker.trackSubmissionAlreadyDownloaded(triple.get1(), totalSubmissions);
            }).filter(Triple::get3).map(triple -> Pair.of(triple.get1(), downloadSubmission(form, triple.get2(), subKeyGen, rs, tracker, triple.get1(), totalSubmissions))).filter(p -> p.getRight() != null).forEach(pair -> {
                int currentSubmissionNumber = pair.getLeft();
                DownloadedSubmission submission = pair.getRight();
                submission.getFormVersion().ifPresent(submissionVersions::add);
                List<AggregateAttachment> submissionAttachments = submission.getAttachments();
                AtomicInteger submissionAttachmentNumber = new AtomicInteger(1);
                int totalSubmissionAttachments = submissionAttachments.size();
                submissionAttachments.parallelStream().forEach(attachment -> downloadSubmissionAttachment(form, submission, attachment, rs, tracker, currentSubmissionNumber, totalSubmissions, submissionAttachmentNumber.getAndIncrement(), totalSubmissionAttachments));
                if (!rs.isCancelled()) {
                    db.putRecordedInstanceDirectory(submission.getInstanceId(), form.getSubmissionDir(briefcaseDir, submission.getInstanceId()).toFile());
                }
            });
        });
        tracker.trackEnd();
        Cursor newCursor = getLastCursor(instanceIdBatches).orElse(Cursor.empty());
        formMetadataPort.execute(updateAsPulled(key, newCursor, briefcaseDir, form.getFormDir(briefcaseDir), submissionVersions));
        EventBus.publish(PullEvent.Success.of(form, server));
    });
}
Also used : Job.run(org.opendatakit.briefcase.reused.job.Job.run) TRUNCATE_EXISTING(java.nio.file.StandardOpenOption.TRUNCATE_EXISTING) URL(java.net.URL) Response(org.opendatakit.briefcase.reused.http.response.Response) RequestBuilder(org.opendatakit.briefcase.reused.http.RequestBuilder) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) FormMetadataPort(org.opendatakit.briefcase.model.form.FormMetadataPort) PullEvent(org.opendatakit.briefcase.pull.PullEvent) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) EventBus(org.bushe.swing.event.EventBus) AggregateServer(org.opendatakit.briefcase.reused.transfer.AggregateServer) Pair(org.opendatakit.briefcase.reused.Pair) DatabaseUtils.withDb(org.opendatakit.briefcase.util.DatabaseUtils.withDb) Path(java.nio.file.Path) FormKey(org.opendatakit.briefcase.model.form.FormKey) RemoteFormDefinition(org.opendatakit.briefcase.model.RemoteFormDefinition) BinaryOperator.maxBy(java.util.function.BinaryOperator.maxBy) OptionalProduct(org.opendatakit.briefcase.reused.OptionalProduct) FormStatus(org.opendatakit.briefcase.model.FormStatus) FormStatusEvent(org.opendatakit.briefcase.model.FormStatusEvent) Request(org.opendatakit.briefcase.reused.http.Request) Collections.emptyList(java.util.Collections.emptyList) Set(java.util.Set) RunnerStatus(org.opendatakit.briefcase.reused.job.RunnerStatus) FormMetadataCommands.updateAsPulled(org.opendatakit.briefcase.model.form.FormMetadataCommands.updateAsPulled) Http(org.opendatakit.briefcase.reused.http.Http) UncheckedFiles.createDirectories(org.opendatakit.briefcase.reused.UncheckedFiles.createDirectories) Consumer(java.util.function.Consumer) Collectors.toList(java.util.stream.Collectors.toList) List(java.util.List) UncheckedFiles.write(org.opendatakit.briefcase.reused.UncheckedFiles.write) CREATE(java.nio.file.StandardOpenOption.CREATE) Triple(org.opendatakit.briefcase.reused.Triple) Optional(java.util.Optional) Job(org.opendatakit.briefcase.reused.job.Job) Collections(java.util.Collections) RequestBuilder.get(org.opendatakit.briefcase.reused.http.RequestBuilder.get) XmlElement(org.opendatakit.briefcase.export.XmlElement) FormKey(org.opendatakit.briefcase.model.form.FormKey) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) HashSet(java.util.HashSet)

Aggregations

Path (java.nio.file.Path)2 Collections (java.util.Collections)2 Collections.emptyList (java.util.Collections.emptyList)2 HashSet (java.util.HashSet)2 List (java.util.List)2 Set (java.util.Set)2 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)2 Consumer (java.util.function.Consumer)2 Collectors.toList (java.util.stream.Collectors.toList)2 EventBus (org.bushe.swing.event.EventBus)2 XmlElement (org.opendatakit.briefcase.export.XmlElement)2 FormStatus (org.opendatakit.briefcase.model.FormStatus)2 FormStatusEvent (org.opendatakit.briefcase.model.FormStatusEvent)2 FormKey (org.opendatakit.briefcase.model.form.FormKey)2 FormMetadataPort (org.opendatakit.briefcase.model.form.FormMetadataPort)2 Triple (org.opendatakit.briefcase.reused.Triple)2 Http (org.opendatakit.briefcase.reused.http.Http)2 Response (org.opendatakit.briefcase.reused.http.response.Response)2 Job (org.opendatakit.briefcase.reused.job.Job)2 RunnerStatus (org.opendatakit.briefcase.reused.job.RunnerStatus)2