Search in sources :

Example 1 with Pair

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

the class PullFromCentral 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.
 */
public Job<Void> pull(FormStatus form) {
    FormKey key = FormKey.from(form);
    PullFromCentralTracker tracker = new PullFromCentralTracker(form, onEventCallback);
    return run(rs -> tracker.trackStart()).thenRun(allOf(supply(runnerStatus -> getSubmissionIds(form, token, runnerStatus, tracker)), run(runnerStatus -> {
        downloadForm(form, token, runnerStatus, tracker);
        List<CentralAttachment> attachments = getFormAttachments(form, token, runnerStatus, tracker);
        int totalAttachments = attachments.size();
        AtomicInteger attachmentNumber = new AtomicInteger(1);
        attachments.parallelStream().forEach(attachment -> downloadFormAttachment(form, attachment, token, runnerStatus, tracker, attachmentNumber.getAndIncrement(), totalAttachments));
    }))).thenAccept((runnerStatus, pair) -> withDb(form.getFormDir(briefcaseDir), db -> {
        List<String> submissions = pair.getLeft();
        int totalSubmissions = submissions.size();
        AtomicInteger submissionNumber = new AtomicInteger(1);
        Set<String> submissionVersions = new HashSet<>();
        if (submissions.isEmpty())
            tracker.trackNoSubmissions();
        submissions.stream().map(instanceId -> Pair.of(submissionNumber.getAndIncrement(), instanceId)).forEach(submissionNumberId -> {
            int currentSubmissionNumber = submissionNumberId.getLeft();
            String instanceId = submissionNumberId.getRight();
            boolean inDb = db.hasRecordedInstance(instanceId) != null;
            Path downloadedSubmissionPath = form.getSubmissionFile(briefcaseDir, instanceId);
            if (!inDb || !downloadedSubmissionPath.toFile().exists()) {
                downloadSubmission(form, instanceId, token, runnerStatus, tracker, currentSubmissionNumber, totalSubmissions);
                if (downloadedSubmissionPath.toFile().exists()) {
                    XmlElement root = XmlElement.from(new String(readAllBytes(downloadedSubmissionPath)));
                    SubmissionMetaData metaData = new SubmissionMetaData(root);
                    metaData.getVersion().ifPresent(submissionVersions::add);
                }
            } else {
                tracker.trackSubmissionAlreadyDownloaded(currentSubmissionNumber, totalSubmissions);
            }
            List<CentralAttachment> attachments = getSubmissionAttachmentList(form, instanceId, token, runnerStatus, tracker, currentSubmissionNumber, totalSubmissions);
            int totalAttachments = attachments.size();
            AtomicInteger attachmentNumber = new AtomicInteger(1);
            attachments.stream().filter(attachment -> !inDb || !form.getSubmissionMediaFile(briefcaseDir, instanceId, attachment.getName()).toFile().exists()).forEach(attachment -> downloadSubmissionAttachment(form, instanceId, attachment, token, runnerStatus, tracker, currentSubmissionNumber, totalSubmissions, attachmentNumber.getAndIncrement(), totalAttachments));
            if (!runnerStatus.isCancelled() && !inDb) {
                db.putRecordedInstanceDirectory(instanceId, form.getSubmissionDir(briefcaseDir, instanceId).toFile());
            }
        });
        tracker.trackEnd();
        formMetadataPort.execute(updateAsPulled(key, briefcaseDir, form.getFormDir(briefcaseDir), submissionVersions));
        EventBus.publish(PullEvent.Success.of(form, server));
    }));
}
Also used : Job.run(org.opendatakit.briefcase.reused.job.Job.run) CentralAttachment(org.opendatakit.briefcase.reused.transfer.CentralAttachment) Response(org.opendatakit.briefcase.reused.http.response.Response) Job.supply(org.opendatakit.briefcase.reused.job.Job.supply) SubmissionMetaData(org.opendatakit.briefcase.export.SubmissionMetaData) HashSet(java.util.HashSet) FormMetadataPort(org.opendatakit.briefcase.model.form.FormMetadataPort) PullEvent(org.opendatakit.briefcase.pull.PullEvent) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) UncheckedFiles.readAllBytes(org.opendatakit.briefcase.reused.UncheckedFiles.readAllBytes) EventBus(org.bushe.swing.event.EventBus) 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) FormStatus(org.opendatakit.briefcase.model.FormStatus) FormStatusEvent(org.opendatakit.briefcase.model.FormStatusEvent) CentralServer(org.opendatakit.briefcase.reused.transfer.CentralServer) Job.allOf(org.opendatakit.briefcase.reused.job.Job.allOf) 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) Job(org.opendatakit.briefcase.reused.job.Job) XmlElement(org.opendatakit.briefcase.export.XmlElement) Path(java.nio.file.Path) SubmissionMetaData(org.opendatakit.briefcase.export.SubmissionMetaData) HashSet(java.util.HashSet) Set(java.util.Set) 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) FormKey(org.opendatakit.briefcase.model.form.FormKey)

Example 2 with Pair

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

the class SubmissionParser method getListOfSubmissionFiles.

/**
 * Returns an sorted {@link List} of {@link Path} instances pointing to all the
 * submissions of a form that belong to the given {@link DateRange}.
 * <p>
 * Each file gets briefly parsed to obtain their submission date and use it as
 * the sorting criteria and for filtering.
 */
public static List<Path> getListOfSubmissionFiles(FormMetadata formMetadata, FormDefinition formDef, DateRange dateRange, boolean smartAppend, SubmissionExportErrorCallback onParsingError) {
    Path instancesDir = formDef.getFormDir().resolve("instances");
    if (!Files.exists(instancesDir) || !Files.isReadable(instancesDir))
        return Collections.emptyList();
    // TODO Migrate this code to Try<Pair<Path, Option<OffsetDate>>> to be able to filter failed parsing attempts
    List<Pair<Path, OffsetDateTime>> paths = new ArrayList<>();
    list(instancesDir).filter(UncheckedFiles::isInstanceDir).forEach(instanceDir -> {
        Path submissionFile = instanceDir.resolve("submission.xml");
        try {
            Optional<OffsetDateTime> submissionDate = readSubmissionDate(submissionFile);
            paths.add(Pair.of(submissionFile, submissionDate.orElse(OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC))));
        } catch (Throwable t) {
            log.error("Parse error attempting to read instance date", t);
            EventBus.publish(ExportEvent.failureSubmission(formDef, instanceDir.getFileName().toString(), t));
            onParsingError.accept(submissionFile, "Parse error attempting to read instance date");
        }
    });
    return paths.parallelStream().filter(pair -> {
        boolean inRange = dateRange.contains(pair.getRight());
        boolean afterLastExportedSubmission = !smartAppend || formMetadata.getLastExportedSubmission().map(s -> s.isBefore(pair.getRight())).orElse(true);
        return inRange && afterLastExportedSubmission;
    }).map(Pair::getLeft).collect(toList());
}
Also used : Path(java.nio.file.Path) OffsetDateTime(java.time.OffsetDateTime) ArrayList(java.util.ArrayList) Pair(org.opendatakit.briefcase.reused.Pair)

Example 3 with Pair

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

the class CsvFieldMappers method aggregatedAuditFile.

private static Stream<Pair<String, String>> aggregatedAuditFile(String formName, String localId, Path workingDir, ExportConfiguration configuration, XmlElement e) {
    if (!e.hasValue())
        return empty(e.fqn() + "-aggregated");
    Path sourceFile = workingDir.resolve(e.getValue());
    // When the source file doesn't exist, we return an empty string
    if (!exists(sourceFile))
        return Stream.of(Pair.of(e.fqn() + "-aggregated", ""));
    // Process the audit file contents and append the instance ID column to all lines
    List<String> sourceLines = lines(sourceFile).collect(toList());
    // We prepend the submission's instance ID to all body lines
    List<String> bodyLines = sourceLines.subList(1, sourceLines.size()).stream().map(line -> localId + "," + line).collect(toList());
    Path destinationFile = configuration.getAuditPath(formName);
    write(destinationFile, bodyLines, APPEND);
    return Stream.of(Pair.of(e.fqn() + "-aggregated", destinationFile.getFileName().toString()));
}
Also used : Path(java.nio.file.Path) IntStream(java.util.stream.IntStream) DateTimeFormatterBuilder(java.time.format.DateTimeFormatterBuilder) ChronoField(java.time.temporal.ChronoField) UncheckedFiles.stripFileExtension(org.opendatakit.briefcase.reused.UncheckedFiles.stripFileExtension) BINARY(org.javarosa.core.model.DataType.BINARY) Iso8601Helpers.parseTime(org.opendatakit.briefcase.reused.Iso8601Helpers.parseTime) UncheckedFiles.copy(org.opendatakit.briefcase.reused.UncheckedFiles.copy) HashMap(java.util.HashMap) DATE(org.javarosa.core.model.DataType.DATE) UncheckedFiles.getFileExtension(org.opendatakit.briefcase.reused.UncheckedFiles.getFileExtension) Function(java.util.function.Function) GEOPOINT(org.javarosa.core.model.DataType.GEOPOINT) APPEND(java.nio.file.StandardOpenOption.APPEND) Iso8601Helpers.parseDateTime(org.opendatakit.briefcase.reused.Iso8601Helpers.parseDateTime) StringUtils.stripIllegalChars(org.opendatakit.briefcase.util.StringUtils.stripIllegalChars) Map(java.util.Map) Pair(org.opendatakit.briefcase.reused.Pair) ZoneOffset(java.time.ZoneOffset) REPLACE_EXISTING(java.nio.file.StandardCopyOption.REPLACE_EXISTING) Path(java.nio.file.Path) DataType(org.javarosa.core.model.DataType) OptionalProduct(org.opendatakit.briefcase.reused.OptionalProduct) TIME(org.javarosa.core.model.DataType.TIME) Files(java.nio.file.Files) TextStyle(java.time.format.TextStyle) NULL(org.javarosa.core.model.DataType.NULL) DATE_TIME(org.javarosa.core.model.DataType.DATE_TIME) UncheckedFiles.createDirectories(org.opendatakit.briefcase.reused.UncheckedFiles.createDirectories) UncheckedFiles.exists(org.opendatakit.briefcase.reused.UncheckedFiles.exists) UncheckedFiles.lines(org.opendatakit.briefcase.reused.UncheckedFiles.lines) Objects(java.util.Objects) Collectors.toList(java.util.stream.Collectors.toList) List(java.util.List) UncheckedFiles.write(org.opendatakit.briefcase.reused.UncheckedFiles.write) OffsetDateTime(java.time.OffsetDateTime) Stream(java.util.stream.Stream) Paths(java.nio.file.Paths) LocalDate(java.time.LocalDate) DateTimeFormatter(java.time.format.DateTimeFormatter) Optional(java.util.Optional) UncheckedFiles.getMd5Hash(org.opendatakit.briefcase.reused.UncheckedFiles.getMd5Hash)

Example 4 with Pair

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

the class CsvFieldMappers method binary.

private static Stream<Pair<String, String>> binary(XmlElement element, Path workingDir, ExportConfiguration configuration) {
    if (!element.hasValue())
        return empty(element.fqn());
    String sourceFilename = element.getValue();
    if (!configuration.resolveExportMedia())
        return Stream.of(Pair.of(element.fqn(), sourceFilename));
    if (!Files.exists(configuration.getExportMediaPath()))
        createDirectories(configuration.getExportMediaPath());
    Path sourceFile = workingDir.resolve(sourceFilename);
    // When the source file doesn't exist, we return the input value
    if (!exists(sourceFile))
        return Stream.of(Pair.of(element.fqn(), Paths.get("media").resolve(sourceFilename).toString()));
    // When the destination file doesn't exist, we copy the source file
    // there and return its path relative to the instance folder
    Path destinationFile = configuration.getExportMediaPath().resolve(sourceFilename);
    if (!exists(destinationFile)) {
        copy(sourceFile, destinationFile);
        return Stream.of(Pair.of(element.fqn(), Paths.get("media").resolve(destinationFile.getFileName()).toString()));
    }
    // When the destination file has the same hash as the source file,
    // we don't do any side-effect and return its path relative to the
    // instance folder
    Boolean sameHash = OptionalProduct.all(getMd5Hash(sourceFile), getMd5Hash(destinationFile)).map(Objects::equals).orElse(false);
    if (sameHash)
        return Stream.of(Pair.of(element.fqn(), Paths.get("media").resolve(destinationFile.getFileName()).toString()));
    // When the hashes are different, we compute the next sequential suffix for
    // the a new destination file to avoid overwriting the one we found already
    // there. We try every number in the sequence until we find one that won't
    // produce a destination file that exists in the output directory.
    String namePart = stripFileExtension(sourceFilename);
    String extPart = getFileExtension(sourceFilename).map(extension -> "." + extension).orElse("");
    int sequenceSuffix = 2;
    Path sequentialDestinationFile;
    do {
        sequentialDestinationFile = configuration.getExportMediaPath().resolve(String.format("%s-%d%s", namePart, sequenceSuffix++, extPart));
    } while (exists(sequentialDestinationFile));
    // Now that we have a valid destination file, we copy the source file
    // there and return its path relative to the instance folder
    copy(sourceFile, sequentialDestinationFile);
    return Stream.of(Pair.of(element.fqn(), Paths.get("media").resolve(sequentialDestinationFile.getFileName()).toString()));
}
Also used : Path(java.nio.file.Path) IntStream(java.util.stream.IntStream) DateTimeFormatterBuilder(java.time.format.DateTimeFormatterBuilder) ChronoField(java.time.temporal.ChronoField) UncheckedFiles.stripFileExtension(org.opendatakit.briefcase.reused.UncheckedFiles.stripFileExtension) BINARY(org.javarosa.core.model.DataType.BINARY) Iso8601Helpers.parseTime(org.opendatakit.briefcase.reused.Iso8601Helpers.parseTime) UncheckedFiles.copy(org.opendatakit.briefcase.reused.UncheckedFiles.copy) HashMap(java.util.HashMap) DATE(org.javarosa.core.model.DataType.DATE) UncheckedFiles.getFileExtension(org.opendatakit.briefcase.reused.UncheckedFiles.getFileExtension) Function(java.util.function.Function) GEOPOINT(org.javarosa.core.model.DataType.GEOPOINT) APPEND(java.nio.file.StandardOpenOption.APPEND) Iso8601Helpers.parseDateTime(org.opendatakit.briefcase.reused.Iso8601Helpers.parseDateTime) StringUtils.stripIllegalChars(org.opendatakit.briefcase.util.StringUtils.stripIllegalChars) Map(java.util.Map) Pair(org.opendatakit.briefcase.reused.Pair) ZoneOffset(java.time.ZoneOffset) REPLACE_EXISTING(java.nio.file.StandardCopyOption.REPLACE_EXISTING) Path(java.nio.file.Path) DataType(org.javarosa.core.model.DataType) OptionalProduct(org.opendatakit.briefcase.reused.OptionalProduct) TIME(org.javarosa.core.model.DataType.TIME) Files(java.nio.file.Files) TextStyle(java.time.format.TextStyle) NULL(org.javarosa.core.model.DataType.NULL) DATE_TIME(org.javarosa.core.model.DataType.DATE_TIME) UncheckedFiles.createDirectories(org.opendatakit.briefcase.reused.UncheckedFiles.createDirectories) UncheckedFiles.exists(org.opendatakit.briefcase.reused.UncheckedFiles.exists) UncheckedFiles.lines(org.opendatakit.briefcase.reused.UncheckedFiles.lines) Objects(java.util.Objects) Collectors.toList(java.util.stream.Collectors.toList) List(java.util.List) UncheckedFiles.write(org.opendatakit.briefcase.reused.UncheckedFiles.write) OffsetDateTime(java.time.OffsetDateTime) Stream(java.util.stream.Stream) Paths(java.nio.file.Paths) LocalDate(java.time.LocalDate) DateTimeFormatter(java.time.format.DateTimeFormatter) Optional(java.util.Optional) UncheckedFiles.getMd5Hash(org.opendatakit.briefcase.reused.UncheckedFiles.getMd5Hash)

Example 5 with Pair

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

the class GeoJsonTest method getFeatures.

@SafeVarargs
private static List<Feature> getFeatures(Pair<DataType, String>... contents) throws XmlPullParserException, IOException {
    AtomicInteger seq = new AtomicInteger(1);
    List<Pair<ModelBuilder, String>> fieldsAndContents = Stream.of(contents).map(pair1 -> {
        String fieldName1 = "some-field-" + seq.getAndIncrement();
        return pair1.map(type -> ModelBuilder.field(fieldName1, type), c -> c);
    }).collect(toList());
    Model model = ModelBuilder.instance(fieldsAndContents.stream().map(Pair::getLeft).collect(toList())).build();
    StringBuilder xml = new StringBuilder("<data instanceID=\"uuid:39f3dd36-161e-45cb-a1a4-395831d253a7\">");
    fieldsAndContents.forEach(pair -> xml.append("<").append(pair.getLeft().getName()).append(">").append(pair.getRight()).append("</").append(pair.getLeft().getName()).append(">"));
    xml.append("</data>");
    XmlElement root = ModelBuilder.parseXmlElement(xml.toString());
    Submission submission = Submission.notValidated(Paths.get("/some/path"), Paths.get("/some/path"), root, new SubmissionMetaData(root), Optional.empty(), Optional.empty());
    return GeoJson.toFeatures(model, submission).collect(Collectors.toList());
}
Also used : GEOPOINT(org.javarosa.core.model.DataType.GEOPOINT) Feature(org.geojson.Feature) Assert.assertThat(org.junit.Assert.assertThat) Collectors.toMap(java.util.stream.Collectors.toMap) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) LineString(org.geojson.LineString) Map(java.util.Map) Matchers.hasSize(org.hamcrest.Matchers.hasSize) Pair(org.opendatakit.briefcase.reused.Pair) DataType(org.javarosa.core.model.DataType) Polygon(org.geojson.Polygon) LngLatAlt(org.geojson.LngLatAlt) Description(org.hamcrest.Description) Predicate(java.util.function.Predicate) Collection(java.util.Collection) IOException(java.io.IOException) Test(org.junit.Test) Collectors(java.util.stream.Collectors) TypeSafeMatcher(org.hamcrest.TypeSafeMatcher) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) Collectors.toList(java.util.stream.Collectors.toList) List(java.util.List) Stream(java.util.stream.Stream) GEOSHAPE(org.javarosa.core.model.DataType.GEOSHAPE) Paths(java.nio.file.Paths) Point(org.geojson.Point) Matcher(org.hamcrest.Matcher) Optional(java.util.Optional) Matchers.is(org.hamcrest.Matchers.is) GEOTRACE(org.javarosa.core.model.DataType.GEOTRACE) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) LineString(org.geojson.LineString) Pair(org.opendatakit.briefcase.reused.Pair)

Aggregations

Pair (org.opendatakit.briefcase.reused.Pair)10 Path (java.nio.file.Path)9 List (java.util.List)8 Optional (java.util.Optional)7 Collectors.toList (java.util.stream.Collectors.toList)7 Paths (java.nio.file.Paths)5 OffsetDateTime (java.time.OffsetDateTime)5 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)5 Stream (java.util.stream.Stream)5 IOException (java.io.IOException)4 DateTimeFormatter (java.time.format.DateTimeFormatter)4 ArrayList (java.util.ArrayList)4 Map (java.util.Map)4 IntStream (java.util.stream.IntStream)4 XmlElement (org.opendatakit.briefcase.export.XmlElement)4 FormStatus (org.opendatakit.briefcase.model.FormStatus)4 UncheckedFiles.createDirectories (org.opendatakit.briefcase.reused.UncheckedFiles.createDirectories)4 URL (java.net.URL)3 Files (java.nio.file.Files)3 REPLACE_EXISTING (java.nio.file.StandardCopyOption.REPLACE_EXISTING)3