Search in sources :

Example 1 with InvalidReferenceException

use of org.javarosa.core.model.instance.InvalidReferenceException in project javarosa by opendatakit.

the class CompactInstanceWrapper method readTreeElement.

/**
 * recursively read in a node of the instance, by filling out the template instance
 * @param e
 * @param ref
 * @param in
 * @param pf
 * @throws IOException
 * @throws DeserializationException
 */
private void readTreeElement(TreeElement e, DataInputStream in, PrototypeFactory pf) throws IOException, DeserializationException {
    TreeElement templ = instance.getTemplatePath(e.getRef());
    boolean isGroup = !templ.isLeaf();
    if (isGroup) {
        List<String> childTypes = new ArrayList<String>(templ.getNumChildren());
        for (int i = 0; i < templ.getNumChildren(); i++) {
            String childName = templ.getChildAt(i).getName();
            if (!childTypes.contains(childName)) {
                childTypes.add(childName);
            }
        }
        for (int i = 0; i < childTypes.size(); i++) {
            String childName = childTypes.get(i);
            TreeReference childTemplRef = e.getRef().extendRef(childName, 0);
            TreeElement childTempl = instance.getTemplatePath(childTemplRef);
            boolean repeatable = childTempl.isRepeatable();
            int n = ExtUtil.readInt(in);
            boolean relevant = (n > 0);
            if (!repeatable && n > 1) {
                throw new DeserializationException("Detected repeated instances of a non-repeatable node");
            }
            if (repeatable) {
                int mult = e.getChildMultiplicity(childName);
                for (int j = mult - 1; j >= 0; j--) {
                    e.removeChild(childName, j);
                }
                for (int j = 0; j < n; j++) {
                    TreeReference dstRef = e.getRef().extendRef(childName, j);
                    try {
                        instance.copyNode(childTempl, dstRef);
                    } catch (InvalidReferenceException ire) {
                        // If there is an invalid reference, this is a malformed instance,
                        // so we'll throw a Deserialization exception.
                        TreeReference r = ire.getInvalidReference();
                        if (r == null) {
                            throw new DeserializationException("Null Reference while attempting to deserialize! " + ire.getMessage());
                        } else {
                            throw new DeserializationException("Invalid Reference while attemtping to deserialize! Reference: " + r.toString(true) + " | " + ire.getMessage());
                        }
                    }
                    TreeElement child = e.getChild(childName, j);
                    child.setRelevant(true);
                    readTreeElement(child, in, pf);
                }
            } else {
                TreeElement child = e.getChild(childName, 0);
                child.setRelevant(relevant);
                if (relevant) {
                    readTreeElement(child, in, pf);
                }
            }
        }
    } else {
        e.setValue((IAnswerData) ExtUtil.read(in, new ExtWrapAnswerData(e.getDataType())));
    }
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference) ArrayList(java.util.ArrayList) DeserializationException(org.javarosa.core.util.externalizable.DeserializationException) InvalidReferenceException(org.javarosa.core.model.instance.InvalidReferenceException) TreeElement(org.javarosa.core.model.instance.TreeElement)

Example 2 with InvalidReferenceException

use of org.javarosa.core.model.instance.InvalidReferenceException in project javarosa by opendatakit.

the class FormInstanceParser method createMissingTemplates.

// if repeatables have no template node, duplicate first as template
private void createMissingTemplates(FormInstance instance, List<TreeReference> missingTemplates) {
    // every ref is listed after a ref that could be its parent. checkRepeatsForTemplate currently behaves this way
    for (TreeReference templRef : missingTemplates) {
        final TreeReference firstMatch;
        // make template ref generic and choose first matching node
        final TreeReference ref = templRef.clone();
        for (int j = 0; j < ref.size(); j++) {
            ref.setMultiplicity(j, TreeReference.INDEX_UNBOUND);
        }
        final List<TreeReference> nodes = new EvaluationContext(instance).expandReference(ref);
        if (nodes.size() == 0) {
            // binding error; not a single node matches the repeat binding; will be reported later
            continue;
        } else {
            firstMatch = nodes.get(0);
        }
        try {
            instance.copyNode(firstMatch, templRef);
        } catch (InvalidReferenceException e) {
            reporter.warning(XFormParserReporter.TYPE_INVALID_STRUCTURE, "Could not create a default repeat template; this is almost certainly a homogeneity error! Your form will not work! (Failed on " + templRef.toString() + ")", null);
        }
        trimRepeatChildren(instance.resolveReference(templRef));
    }
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference) EvaluationContext(org.javarosa.core.model.condition.EvaluationContext) Constraint(org.javarosa.core.model.condition.Constraint) InvalidReferenceException(org.javarosa.core.model.instance.InvalidReferenceException)

Example 3 with InvalidReferenceException

use of org.javarosa.core.model.instance.InvalidReferenceException in project javarosa by opendatakit.

the class FormEntryModel method createModelIfNecessary.

/**
 * For the current index: Checks whether the index represents a node which
 * should exist given a non-interactive repeat, along with a count for that
 * repeat which is beneath the dynamic level specified.
 *
 * If this index does represent such a node, the new model for the repeat is
 * created behind the scenes and the index for the initial question is
 * returned.
 *
 * Note: This method will not prevent the addition of new repeat elements in
 * the interface, it will merely use the xforms repeat hint to create new
 * nodes that are assumed to exist
 *
 * @param index The index to be evaluated as to whether the underlying model is
 *        hinted to exist
 */
private void createModelIfNecessary(FormIndex index) {
    if (index.isInForm()) {
        IFormElement e = getForm().getChild(index);
        if (e instanceof GroupDef) {
            GroupDef g = (GroupDef) e;
            if (g.getRepeat() && g.getCountReference() != null) {
                // Lu Gram: repeat count XPath needs to be contextualized for nested repeat groups
                TreeReference countRef = FormInstance.unpackReference(g.getCountReference());
                TreeReference contextualized = countRef.contextualize(index.getReference());
                IAnswerData count = getForm().getMainInstance().resolveReference(contextualized).getValue();
                if (count != null) {
                    long fullcount = ((Integer) count.getValue()).intValue();
                    TreeReference ref = getForm().getChildInstanceRef(index);
                    TreeElement element = getForm().getMainInstance().resolveReference(ref);
                    if (element == null) {
                        if (index.getTerminal().getInstanceIndex() < fullcount) {
                            try {
                                getForm().createNewRepeat(index);
                            } catch (InvalidReferenceException ire) {
                                Std.printStack(ire);
                                throw new RuntimeException("Invalid Reference while creting new repeat!" + ire.getMessage());
                            }
                        }
                    }
                }
            }
        }
    }
}
Also used : IAnswerData(org.javarosa.core.model.data.IAnswerData) IFormElement(org.javarosa.core.model.IFormElement) TreeReference(org.javarosa.core.model.instance.TreeReference) GroupDef(org.javarosa.core.model.GroupDef) InvalidReferenceException(org.javarosa.core.model.instance.InvalidReferenceException) TreeElement(org.javarosa.core.model.instance.TreeElement)

Example 4 with InvalidReferenceException

use of org.javarosa.core.model.instance.InvalidReferenceException in project javarosa by opendatakit.

the class FormEntryController method answerQuestion.

/**
 * Attempts to save the answer at the specified FormIndex into the
 * datamodel.
 *
 * @param index
 * @param data
 * @return OK if save was successful, error if a constraint was violated.
 */
public int answerQuestion(FormIndex index, IAnswerData data, boolean midSurvey) {
    QuestionDef q = model.getQuestionPrompt(index).getQuestion();
    if (model.getEvent(index) != FormEntryController.EVENT_QUESTION) {
        throw new RuntimeException("Non-Question object at the form index.");
    }
    TreeElement element = model.getTreeElement(index);
    boolean complexQuestion = q.isComplex();
    boolean hasConstraints = false;
    if (element.isRequired() && data == null) {
        return ANSWER_REQUIRED_BUT_EMPTY;
    } else if (!complexQuestion && !model.getForm().evaluateConstraint(index.getReference(), data)) {
        return ANSWER_CONSTRAINT_VIOLATED;
    } else if (!complexQuestion) {
        commitAnswer(element, index, data, midSurvey);
        return ANSWER_OK;
    } else if (complexQuestion && hasConstraints) {
        // TODO: itemsets: don't currently evaluate constraints for itemset/copy -- haven't figured out how handle it yet
        throw new RuntimeException("Itemsets do not currently evaluate constraints. Your constraint will not work, please remove it before proceeding.");
    } else {
        try {
            model.getForm().copyItemsetAnswer(q, element, data, midSurvey);
        } catch (InvalidReferenceException ire) {
            Std.printStack(ire);
            throw new RuntimeException("Invalid reference while copying itemset answer: " + ire.getMessage());
        }
        return ANSWER_OK;
    }
}
Also used : QuestionDef(org.javarosa.core.model.QuestionDef) InvalidReferenceException(org.javarosa.core.model.instance.InvalidReferenceException) TreeElement(org.javarosa.core.model.instance.TreeElement)

Aggregations

InvalidReferenceException (org.javarosa.core.model.instance.InvalidReferenceException)4 TreeElement (org.javarosa.core.model.instance.TreeElement)3 TreeReference (org.javarosa.core.model.instance.TreeReference)3 ArrayList (java.util.ArrayList)1 GroupDef (org.javarosa.core.model.GroupDef)1 IFormElement (org.javarosa.core.model.IFormElement)1 QuestionDef (org.javarosa.core.model.QuestionDef)1 Constraint (org.javarosa.core.model.condition.Constraint)1 EvaluationContext (org.javarosa.core.model.condition.EvaluationContext)1 IAnswerData (org.javarosa.core.model.data.IAnswerData)1 DeserializationException (org.javarosa.core.util.externalizable.DeserializationException)1