Search in sources :

Example 21 with Element

use of org.kxml2.kdom.Element in project javarosa by opendatakit.

the class XFormSerializingVisitor method visit.

/*
     * (non-Javadoc)
     * @see org.javarosa.core.model.utils.ITreeVisitor#visit(org.javarosa.core.model.DataModelTree)
     */
public void visit(FormInstance tree) {
    theXmlDoc = new Document();
    // TreeElement root = tree.getRoot();
    TreeElement root = tree.resolveReference(rootRef);
    // catch that case and just start at the root.
    if (root == null) {
        root = tree.getRoot();
    }
    if (root != null) {
        theXmlDoc.addChild(Node.ELEMENT, serializeNode(root));
    }
    Element top = theXmlDoc.getElement(0);
    String[] prefixes = tree.getNamespacePrefixes();
    for (int i = 0; i < prefixes.length; ++i) {
        top.setPrefix(prefixes[i], tree.getNamespaceURI(prefixes[i]));
    }
    if (tree.schema != null) {
        top.setNamespace(tree.schema);
        top.setPrefix("", tree.schema);
    }
}
Also used : TreeElement(org.javarosa.core.model.instance.TreeElement) Element(org.kxml2.kdom.Element) Document(org.kxml2.kdom.Document) TreeElement(org.javarosa.core.model.instance.TreeElement)

Example 22 with Element

use of org.kxml2.kdom.Element in project briefcase by opendatakit.

the class BaseFormParserForJavaRosa method getBindingsForTreeElement.

/**
 * Get all recorded bindings for a given TreeElement
 *
 * @param treeElement
 * @return
 */
private List<Element> getBindingsForTreeElement(TreeElement treeElement) {
    List<Element> l = new ArrayList<>();
    String nodeset = "/" + getTreeElementPath(treeElement);
    for (int i = 0; i < this.bindElements.size(); i++) {
        Element element = this.bindElements.get(i);
        if (element.getAttributeValue("", NODESET_ATTR).equalsIgnoreCase(nodeset)) {
            l.add(element);
        }
    }
    return (l);
}
Also used : TreeElement(org.javarosa.core.model.instance.TreeElement) AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement) Element(org.kxml2.kdom.Element) ArrayList(java.util.ArrayList)

Example 23 with Element

use of org.kxml2.kdom.Element in project briefcase by opendatakit.

the class BaseFormParserForJavaRosa method compareTreeElements.

/**
 * Compare two parsed TreeElements to assess their level of structural
 * difference (if any).
 *
 * @param treeElement1
 * @param treeElement2
 * @return XFORMS_SHARE_INSTANCE when bodies differ but instances and bindings
 *     are identical; XFORMS_SHARE_SCHEMA when bodies and/or bindings
 *     differ, but database structure remains unchanged; XFORMS_DIFFERENT
 *     when forms are different enough to affect database structure and/or
 *     encryption.
 */
public static DifferenceResult compareTreeElements(TreeElement treeElement1, BaseFormParserForJavaRosa parser1, TreeElement treeElement2, BaseFormParserForJavaRosa parser2) {
    boolean smalldiff = false;
    boolean bigdiff = false;
    // compare names
    if (!treeElement1.getName().equals(treeElement2.getName())) {
        bigdiff = true;
    }
    // treeElement1)
    for (int i = 0; i < treeElement1.getAttributeCount(); i++) {
        String attributeNamespace = treeElement1.getAttributeNamespace(i);
        if (attributeNamespace != null && attributeNamespace.length() == 0) {
            attributeNamespace = null;
        }
        String attributeName = treeElement1.getAttributeName(i);
        String fullAttributeName = (attributeNamespace == null ? attributeName : attributeNamespace + ":" + attributeName);
        // see if there's a difference in this attribute
        if (!treeElement1.getAttributeValue(i).equals(treeElement2.getAttributeValue(attributeNamespace, attributeName))) {
            // here, changes are ALLOWED by default, unless to a listed attribute
            if (!NonchangeableInstanceAttributes.contains(fullAttributeName.toLowerCase())) {
                smalldiff = true;
            } else {
                bigdiff = true;
            }
        }
    }
    // check core instance attributes only in treeElement2
    for (int i = 0; i < treeElement2.getAttributeCount(); i++) {
        String attributeNamespace = treeElement2.getAttributeNamespace(i);
        if (attributeNamespace != null && attributeNamespace.length() == 0) {
            attributeNamespace = null;
        }
        String attributeName = treeElement2.getAttributeName(i);
        String fullAttributeName = (attributeNamespace == null ? attributeName : attributeNamespace + ":" + attributeName);
        // see if this is an attribute only in treeElement2
        if (treeElement1.getAttributeValue(attributeNamespace, attributeName) == null) {
            // here, changes are ALLOWED by default, unless to a listed attribute
            if (!NonchangeableInstanceAttributes.contains(fullAttributeName.toLowerCase())) {
                smalldiff = true;
            } else {
                bigdiff = true;
            }
        }
    }
    // note attributes don't actually include bindings; thus, check raw bindings
    // also one-by-one (starting with bindings1)
    List<Element> bindings1 = parser1.getBindingsForTreeElement(treeElement1);
    List<Element> bindings2 = parser2.getBindingsForTreeElement(treeElement2);
    for (int i = 0; i < bindings1.size(); i++) {
        Element binding = bindings1.get(i);
        for (int j = 0; j < binding.getAttributeCount(); j++) {
            String attributeNamespace = binding.getAttributeNamespace(j);
            if (attributeNamespace != null && attributeNamespace.length() == 0) {
                attributeNamespace = null;
            }
            String attributeName = binding.getAttributeName(j);
            String fullAttributeName = (attributeNamespace == null ? attributeName : attributeNamespace + ":" + attributeName);
            if (!fullAttributeName.equalsIgnoreCase(NODESET_ATTR)) {
                // see if there's a difference in this attribute
                String value1 = binding.getAttributeValue(j);
                String value2 = getBindingAttributeValue(bindings2, attributeNamespace, attributeName);
                if (!value1.equals(value2)) {
                    if (fullAttributeName.toLowerCase().equals(TYPE_ATTR) && value1 != null && value2 != null && ((value1.toLowerCase().equals("string") && value2.toLowerCase().equals("select1")) || (value1.toLowerCase().equals("select1") && value2.toLowerCase().equals("string")))) {
                        // handle changes between string and select1 data types as special
                        // (allowable) case
                        smalldiff = true;
                    } else {
                        // attribute
                        if (ChangeableBindAttributes.contains(fullAttributeName.toLowerCase())) {
                            smalldiff = true;
                        } else {
                            bigdiff = true;
                        }
                    }
                }
            }
        }
    }
    // check binding attributes only in bindings2
    for (int i = 0; i < bindings2.size(); i++) {
        Element binding = bindings2.get(i);
        for (int j = 0; j < binding.getAttributeCount(); j++) {
            String attributeNamespace = binding.getAttributeNamespace(j);
            if (attributeNamespace != null && attributeNamespace.length() == 0) {
                attributeNamespace = null;
            }
            String attributeName = binding.getAttributeName(j);
            String fullAttributeName = (attributeNamespace == null ? attributeName : attributeNamespace + ":" + attributeName);
            if (!fullAttributeName.equalsIgnoreCase(NODESET_ATTR)) {
                // see if this is an attribute only in bindings2
                if (getBindingAttributeValue(bindings1, attributeNamespace, attributeName) == null) {
                    // attribute
                    if (ChangeableBindAttributes.contains(fullAttributeName.toLowerCase())) {
                        smalldiff = true;
                    } else {
                        bigdiff = true;
                    }
                }
            }
        }
    }
    // Issue 786 -- we need to handle repeat groups.
    // If we have a repeat without a jr:template="" attribute, then
    // that element appears as a index [0] repeat within the form
    // definition and as an INDEX_TEMPLATE element (it is copied).
    // Otherwise, if you have specified the jr:template attribute,
    // it appears only as an INDEX_TEMPLATE element.
    @SuppressWarnings("unused") int template1DropCount = 0;
    // get non-template entries for treeElement1
    List<TreeElement> element1ExcludingRepeatIndex0Children = new ArrayList<>();
    for (int i = 0; i < treeElement1.getNumChildren(); i++) {
        TreeElement child = treeElement1.getChildAt(i);
        if (child.isRepeatable()) {
            if (child.getMult() != TreeReference.INDEX_TEMPLATE) {
                template1DropCount++;
                log.debug("element1:dropping " + child.getName());
                continue;
            }
            log.debug("element1:retaining " + child.getName());
        }
        element1ExcludingRepeatIndex0Children.add(child);
    }
    @SuppressWarnings("unused") int template2DropCount = 0;
    // get non-template entries for treeElement2
    Map<String, TreeElement> element2ExcludingRepeatIndex0Children = new HashMap<>();
    for (int i = 0; i < treeElement2.getNumChildren(); i++) {
        TreeElement child = treeElement2.getChildAt(i);
        if (child.isRepeatable()) {
            if (child.getMult() != TreeReference.INDEX_TEMPLATE) {
                template2DropCount++;
                log.debug("element2:dropping " + child.getName());
                continue;
            }
            log.debug("element2:retaining " + child.getName());
        }
        if (element2ExcludingRepeatIndex0Children.get(child.getName()) != null) {
            // consider children not uniquely named as big differences
            bigdiff = true;
        }
        element2ExcludingRepeatIndex0Children.put(child.getName(), child);
    }
    // compare children
    if (element1ExcludingRepeatIndex0Children.size() != element2ExcludingRepeatIndex0Children.size()) {
        // consider differences in basic structure (e.g., number and grouping of
        // fields) as big
        bigdiff = true;
    } else {
        for (int i = 0; i < element1ExcludingRepeatIndex0Children.size(); i++) {
            TreeElement childElement1 = element1ExcludingRepeatIndex0Children.get(i);
            TreeElement childElement2 = element2ExcludingRepeatIndex0Children.get(childElement1.getName());
            if (childElement2 != null) {
                // recursively compare children...
                switch(compareTreeElements(childElement1, parser1, childElement2, parser2)) {
                    case XFORMS_SHARE_SCHEMA:
                        smalldiff = true;
                        break;
                    case XFORMS_DIFFERENT:
                        bigdiff = true;
                        break;
                    default:
                        // no update for the other cases (IDENTICAL, EARLIER, MISSING, SHARE_INSTANCE)
                        break;
                }
            } else {
                // consider children not found as big differences
                bigdiff = true;
            }
        }
    }
    // return appropriate value
    if (bigdiff) {
        return (DifferenceResult.XFORMS_DIFFERENT);
    } else if (smalldiff) {
        return (DifferenceResult.XFORMS_SHARE_SCHEMA);
    } else {
        return (DifferenceResult.XFORMS_SHARE_INSTANCE);
    }
}
Also used : HashMap(java.util.HashMap) TreeElement(org.javarosa.core.model.instance.TreeElement) AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement) Element(org.kxml2.kdom.Element) ArrayList(java.util.ArrayList) TreeElement(org.javarosa.core.model.instance.TreeElement) AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement)

Example 24 with Element

use of org.kxml2.kdom.Element in project briefcase by opendatakit.

the class ExportToCsv method processInstance.

private boolean processInstance(File instanceDir) {
    File submission = new File(instanceDir, "submission.xml");
    if (!submission.exists() || !submission.isFile()) {
        EventBus.publish(new ExportProgressEvent("Submission not found for instance directory: " + instanceDir.getPath(), briefcaseLfd));
        return false;
    }
    processedInstances++;
    EventBus.publish(new ExportProgressEvent("Processing instance: " + instanceDir.getName(), briefcaseLfd));
    EventBus.publish(new ExportProgressPercentageEvent((processedInstances * 100.0) / totalInstances, briefcaseLfd));
    // If we are encrypted, be sure the temporary directory
    // that will hold the unencrypted files is created.
    // If we aren't encrypted, the temporary directory
    // is the same as the instance directory.
    File unEncryptedDir;
    if (briefcaseLfd.isFileEncryptedForm()) {
        // create the temp directory that will hold the unencrypted
        // files. Do this in the outputDir so that the briefcase storage location
        // can be a read-only network mount. issue 676.
        Path path;
        try {
            path = Files.createTempDirectory(Paths.get(outputDir.toURI()), ".temp");
        } catch (IOException e) {
            String msg = "Unable to create temp directory.";
            log.error(msg, e);
            EventBus.publish(new ExportProgressEvent(msg + " Cause : " + e.toString(), briefcaseLfd));
            return false;
        }
        unEncryptedDir = path.toFile();
    } else {
        unEncryptedDir = instanceDir;
    }
    // parse the xml document (this is the manifest if encrypted)...
    Document doc;
    boolean isValidated = false;
    try {
        doc = XmlManipulationUtils.parseXml(submission);
    } catch (ParsingException | FileSystemException e) {
        log.error("Error parsing submission", e);
        EventBus.publish(new ExportProgressEvent(("Error parsing submission " + instanceDir.getName()) + " Cause: " + e.toString(), briefcaseLfd));
        return false;
    }
    String submissionDate = null;
    // extract the submissionDate, if present, from the attributes
    // of the root element of the submission or submission manifest (if encrypted).
    submissionDate = doc.getRootElement().getAttributeValue(null, "submissionDate");
    if (submissionDate == null || submissionDate.length() == 0) {
        submissionDate = null;
    } else {
        Date theDate = WebUtils.parseDate(submissionDate);
        DateFormat formatter = DateFormat.getDateTimeInstance();
        submissionDate = formatter.format(theDate);
        // just return true to skip records out of range
        if (startDate != null && theDate.before(startDate)) {
            log.info("Submission date is before specified, skipping: " + instanceDir.getName());
            return true;
        }
        if (endDate != null && theDate.after(endDate)) {
            log.info("Submission date is after specified, skipping: " + instanceDir.getName());
            return true;
        }
        // don't export records without dates if either date is set
        if ((startDate != null || endDate != null) && submissionDate == null) {
            log.info("No submission date found, skipping: " + instanceDir.getName());
            return true;
        }
    }
    // failure.
    try {
        if (briefcaseLfd.isFileEncryptedForm()) {
            // NOTE: this changes the value of 'doc'
            try {
                FileSystemUtils.DecryptOutcome outcome = FileSystemUtils.decryptAndValidateSubmission(doc, briefcaseLfd.getPrivateKey(), instanceDir, unEncryptedDir);
                doc = outcome.submission;
                isValidated = outcome.isValidated;
            } catch (ParsingException | CryptoException | FileSystemException e) {
                // Was unable to parse file or decrypt file or a file system error occurred
                // Hence skip this instance
                EventBus.publish(new ExportProgressEvent("Error decrypting submission " + instanceDir.getName() + " Cause: " + e.toString() + " skipping....", briefcaseLfd));
                log.info("Error decrypting submission " + instanceDir.getName() + " Cause: " + e.toString());
                // update total number of files skipped
                totalFilesSkipped++;
                return true;
            }
        }
        String instanceId = null;
        String base64EncryptedFieldKey = null;
        // find an instanceId to use...
        try {
            FormInstanceMetadata sim = XmlManipulationUtils.getFormInstanceMetadata(doc.getRootElement());
            instanceId = sim.instanceId;
            base64EncryptedFieldKey = sim.base64EncryptedFieldKey;
        } catch (ParsingException e) {
            log.error("Could not extract metadata from submission", e);
            EventBus.publish(new ExportProgressEvent("Could not extract metadata from submission " + submission.getAbsolutePath(), briefcaseLfd));
            return false;
        }
        if (instanceId == null || instanceId.length() == 0) {
            // if we have no instanceID, and there isn't any in the file,
            // use the checksum as the id.
            // NOTE: encrypted submissions always have instanceIDs.
            // This is for legacy non-OpenRosa forms.
            long checksum;
            try {
                checksum = FileUtils.checksumCRC32(submission);
            } catch (IOException e1) {
                String msg = "Failed during computing of crc";
                log.error(msg, e1);
                EventBus.publish(new ExportProgressEvent(msg + ": " + e1.getMessage(), briefcaseLfd));
                return false;
            }
            instanceId = "crc32:" + Long.toString(checksum);
        }
        if (terminationFuture.isCancelled()) {
            EventBus.publish(new ExportProgressEvent("Aborted", briefcaseLfd));
            return false;
        }
        EncryptionInformation ei = null;
        if (base64EncryptedFieldKey != null) {
            try {
                ei = new EncryptionInformation(base64EncryptedFieldKey, instanceId, briefcaseLfd.getPrivateKey());
            } catch (CryptoException e) {
                log.error("Error establishing field decryption", e);
                EventBus.publish(new ExportProgressEvent("Error establishing field decryption for submission " + instanceDir.getName() + " Cause: " + e.toString(), briefcaseLfd));
                return false;
            }
        }
        // emit the csv record...
        try {
            OutputStreamWriter osw = fileMap.get(briefcaseLfd.getSubmissionElement());
            emitString(osw, true, submissionDate);
            emitSubmissionCsv(osw, ei, doc.getRootElement(), briefcaseLfd.getSubmissionElement(), briefcaseLfd.getSubmissionElement(), false, instanceId, unEncryptedDir);
            emitString(osw, false, instanceId);
            if (briefcaseLfd.isFileEncryptedForm()) {
                emitString(osw, false, Boolean.toString(isValidated));
                if (!isValidated) {
                    EventBus.publish(new ExportProgressEvent("Decrypted submission " + instanceDir.getName() + " may be missing attachments and could not be validated.", briefcaseLfd));
                }
            }
            osw.append("\n");
            return true;
        } catch (IOException e) {
            String msg = "Failed writing csv";
            log.error(msg, e);
            EventBus.publish(new ExportProgressEvent(msg + ": " + e.getMessage(), briefcaseLfd));
            return false;
        }
    } finally {
        if (briefcaseLfd.isFileEncryptedForm()) {
            // destroy the temp directory and its contents...
            try {
                FileUtils.deleteDirectory(unEncryptedDir);
            } catch (IOException e) {
                String msg = "Unable to remove decrypted files";
                log.error(msg, e);
                EventBus.publish(new ExportProgressEvent(msg + ": " + e.getMessage(), briefcaseLfd));
                return false;
            }
        }
    }
}
Also used : Path(java.nio.file.Path) FormInstanceMetadata(org.opendatakit.briefcase.util.XmlManipulationUtils.FormInstanceMetadata) IOException(java.io.IOException) Document(org.kxml2.kdom.Document) ExportProgressEvent(org.opendatakit.briefcase.model.ExportProgressEvent) Date(java.util.Date) LocalDate(java.time.LocalDate) FileSystemException(org.opendatakit.briefcase.model.FileSystemException) ParsingException(org.opendatakit.briefcase.model.ParsingException) DateFormat(java.text.DateFormat) ExportProgressPercentageEvent(org.opendatakit.briefcase.model.ExportProgressPercentageEvent) OutputStreamWriter(java.io.OutputStreamWriter) CryptoException(org.opendatakit.briefcase.model.CryptoException) File(java.io.File)

Example 25 with Element

use of org.kxml2.kdom.Element in project briefcase by opendatakit.

the class ExportToCsv method emitSubmissionCsv.

private boolean emitSubmissionCsv(OutputStreamWriter osw, EncryptionInformation ei, Element submissionElement, TreeElement primarySet, TreeElement treeElement, boolean first, String uniquePath, File instanceDir) throws IOException {
    // OK -- group with at least one element -- assume no value...
    // TreeElement list has the begin and end tags for the nested groups.
    // Swallow the end tag by looking to see if the prior and current
    // field names are the same.
    TreeElement prior = null;
    for (int i = 0; i < treeElement.getNumChildren(); ++i) {
        TreeElement current = (TreeElement) treeElement.getChildAt(i);
        log.debug(" element name: " + current.getName());
        if ((prior != null) && (prior.getName().equals(current.getName()))) {
            // it is the end-group tag... seems to happen with two adjacent repeat
            // groups
            log.info("repeating tag at " + i + " skipping " + current.getName());
            prior = current;
        } else {
            Element ec = findElement(submissionElement, current.getName());
            switch(current.getDataType()) {
                case org.javarosa.core.model.Constants.DATATYPE_TEXT:
                /**
                 * Text question
                 * type.
                 */
                case org.javarosa.core.model.Constants.DATATYPE_INTEGER:
                /**
                 * Numeric
                 * question type. These are numbers without decimal points
                 */
                case org.javarosa.core.model.Constants.DATATYPE_DECIMAL:
                /**
                 * Decimal
                 * question type. These are numbers with decimals
                 */
                case org.javarosa.core.model.Constants.DATATYPE_CHOICE:
                /**
                 * This is a
                 * question with alist of options where not more than one option can
                 * be selected at a time.
                 */
                case org.javarosa.core.model.Constants.DATATYPE_CHOICE_LIST:
                /**
                 * This is a
                 * question with alist of options where more than one option can be
                 * selected at a time.
                 */
                case org.javarosa.core.model.Constants.DATATYPE_BOOLEAN:
                /**
                 * Question with
                 * true and false answers.
                 */
                case org.javarosa.core.model.Constants.DATATYPE_BARCODE:
                /**
                 * Question with
                 * barcode string answer.
                 */
                default:
                case org.javarosa.core.model.Constants.DATATYPE_UNSUPPORTED:
                    if (ec == null) {
                        emitString(osw, first, null);
                    } else {
                        emitString(osw, first, getSubmissionValue(ei, current, ec));
                    }
                    first = false;
                    break;
                case org.javarosa.core.model.Constants.DATATYPE_DATE:
                    /**
                     * Date question type. This has only date component without time.
                     */
                    if (ec == null) {
                        emitString(osw, first, null);
                    } else {
                        String value = getSubmissionValue(ei, current, ec);
                        if (value == null || value.length() == 0) {
                            emitString(osw, first, null);
                        } else {
                            Date date = WebUtils.parseDate(value);
                            DateFormat formatter = DateFormat.getDateInstance();
                            emitString(osw, first, formatter.format(date));
                        }
                    }
                    first = false;
                    break;
                case org.javarosa.core.model.Constants.DATATYPE_TIME:
                    /**
                     * Time question type. This has only time element without date
                     */
                    if (ec == null) {
                        emitString(osw, first, null);
                    } else {
                        String value = getSubmissionValue(ei, current, ec);
                        if (value == null || value.length() == 0) {
                            emitString(osw, first, null);
                        } else {
                            Date date = WebUtils.parseDate(value);
                            DateFormat formatter = DateFormat.getTimeInstance();
                            emitString(osw, first, formatter.format(date));
                        }
                    }
                    first = false;
                    break;
                case org.javarosa.core.model.Constants.DATATYPE_DATE_TIME:
                    /**
                     * Date and Time question type. This has both the date and time
                     * components
                     */
                    if (ec == null) {
                        emitString(osw, first, null);
                    } else {
                        String value = getSubmissionValue(ei, current, ec);
                        if (value == null || value.length() == 0) {
                            emitString(osw, first, null);
                        } else {
                            Date date = WebUtils.parseDate(value);
                            DateFormat formatter = DateFormat.getDateTimeInstance();
                            emitString(osw, first, formatter.format(date));
                        }
                    }
                    first = false;
                    break;
                case org.javarosa.core.model.Constants.DATATYPE_GEOPOINT:
                    /**
                     * Question with location answer.
                     */
                    String compositeValue = (ec == null) ? null : getSubmissionValue(ei, current, ec);
                    compositeValue = (compositeValue == null) ? null : compositeValue.trim();
                    // emit separate lat, long, alt, acc columns...
                    if (compositeValue == null || compositeValue.length() == 0) {
                        for (int count = 0; count < 4; ++count) {
                            emitString(osw, first, null);
                            first = false;
                        }
                    } else {
                        String[] values = compositeValue.split(" ");
                        for (String value : values) {
                            emitString(osw, first, value);
                            first = false;
                        }
                        for (int count = values.length; count < 4; ++count) {
                            emitString(osw, first, null);
                            first = false;
                        }
                    }
                    break;
                case org.javarosa.core.model.Constants.DATATYPE_BINARY:
                    /**
                     * Question with external binary answer.
                     */
                    String binaryFilename = getSubmissionValue(ei, current, ec);
                    if (binaryFilename == null || binaryFilename.length() == 0) {
                        emitString(osw, first, null);
                        first = false;
                    } else {
                        if (exportMedia) {
                            if (!outputMediaDir.exists()) {
                                if (!outputMediaDir.mkdir()) {
                                    EventBus.publish(new ExportProgressEvent("Unable to create destination media directory", briefcaseLfd));
                                    return false;
                                }
                            }
                            int dotIndex = binaryFilename.lastIndexOf(".");
                            String namePart = (dotIndex == -1) ? binaryFilename : binaryFilename.substring(0, dotIndex);
                            String extPart = (dotIndex == -1) ? "" : binaryFilename.substring(dotIndex);
                            File binaryFile = new File(instanceDir, binaryFilename);
                            String destBinaryFilename = binaryFilename;
                            int version = 1;
                            File destFile = new File(outputMediaDir, destBinaryFilename);
                            boolean exists = false;
                            String binaryFileHash = null;
                            String destFileHash = null;
                            if (destFile.exists() && binaryFile.exists()) {
                                binaryFileHash = FileSystemUtils.getMd5Hash(binaryFile);
                                while (destFile.exists()) {
                                    if (fileHashMap.containsKey(destFile.getName())) {
                                        destFileHash = fileHashMap.get(destFile.getName());
                                    } else {
                                        destFileHash = FileSystemUtils.getMd5Hash(destFile);
                                        if (destFileHash != null) {
                                            fileHashMap.put(destFile.getName(), destFileHash);
                                        }
                                    }
                                    if (binaryFileHash != null && destFileHash != null && destFileHash.equals(binaryFileHash)) {
                                        exists = true;
                                        break;
                                    }
                                    destBinaryFilename = namePart + "-" + (++version) + extPart;
                                    destFile = new File(outputMediaDir, destBinaryFilename);
                                }
                            }
                            if (binaryFile.exists() && exists == false) {
                                FileUtils.copyFile(binaryFile, destFile);
                            }
                            emitString(osw, first, MEDIA_DIR + File.separator + destFile.getName());
                        } else {
                            emitString(osw, first, binaryFilename);
                        }
                        first = false;
                    }
                    break;
                case org.javarosa.core.model.Constants.DATATYPE_NULL:
                    /*
           * for nodes that
           * have no data,
           * or data type
           * otherwise
           * unknown
           */
                    if (current.isRepeatable()) {
                        if (prior == null || !current.getName().equals(prior.getName())) {
                            // repeatable group...
                            if (ec == null) {
                                emitString(osw, first, null);
                                first = false;
                            } else {
                                String uniqueGroupPath = uniquePath + "/" + getFullName(current, primarySet);
                                emitString(osw, first, uniqueGroupPath);
                                first = false;
                                // first time processing this repeat group (ignore templates)
                                List<Element> ecl = findElementList(submissionElement, current.getName());
                                emitRepeatingGroupCsv(ei, ecl, current, uniquePath, uniqueGroupPath, instanceDir);
                            }
                        }
                    } else if (current.getNumChildren() == 0 && current != briefcaseLfd.getSubmissionElement()) {
                        // assume fields that don't have children are string fields.
                        if (ec == null) {
                            emitString(osw, first, null);
                            first = false;
                        } else {
                            emitString(osw, first, getSubmissionValue(ei, current, ec));
                            first = false;
                        }
                    } else {
                        /* one or more children -- this is a non-repeating group */
                        first = emitSubmissionCsv(osw, ei, ec, primarySet, current, first, uniquePath, instanceDir);
                    }
                    break;
            }
            prior = current;
        }
    }
    return first;
}
Also used : TreeElement(org.javarosa.core.model.instance.TreeElement) AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement) Element(org.kxml2.kdom.Element) DateFormat(java.text.DateFormat) ExportProgressEvent(org.opendatakit.briefcase.model.ExportProgressEvent) File(java.io.File) Date(java.util.Date) LocalDate(java.time.LocalDate) TreeElement(org.javarosa.core.model.instance.TreeElement) AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement)

Aggregations

Element (org.kxml2.kdom.Element)50 TreeElement (org.javarosa.core.model.instance.TreeElement)25 AbstractTreeElement (org.javarosa.core.model.instance.AbstractTreeElement)23 ArrayList (java.util.ArrayList)21 IOException (java.io.IOException)17 IFormElement (org.javarosa.core.model.IFormElement)17 KXmlParser (org.kxml2.io.KXmlParser)12 XmlPullParserException (org.xmlpull.v1.XmlPullParserException)12 File (java.io.File)8 Test (org.junit.Test)7 ParsingException (org.opendatakit.briefcase.model.ParsingException)7 XmlPullParser (org.xmlpull.v1.XmlPullParser)7 Document (org.kxml2.kdom.Document)6 UnsupportedEncodingException (java.io.UnsupportedEncodingException)4 FileInputStream (java.io.FileInputStream)3 FileNotFoundException (java.io.FileNotFoundException)3 OutputStreamWriter (java.io.OutputStreamWriter)3 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)3 HashMap (java.util.HashMap)3 KXmlSerializer (org.kxml2.io.KXmlSerializer)3