Search in sources :

Example 1 with DataInstance

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

the class XFormParser method parseDoc.

private void parseDoc(Map<String, String> namespacePrefixesByUri) {
    final CodeTimer codeTimer = new CodeTimer("Creating FormDef from parsed XML");
    _f = new FormDef();
    initState();
    final String defaultNamespace = _xmldoc.getRootElement().getNamespaceUri(null);
    parseElement(_xmldoc.getRootElement(), _f, topLevelHandlers);
    collapseRepeatGroups(_f);
    final FormInstanceParser instanceParser = new FormInstanceParser(_f, defaultNamespace, reporter, bindings, repeats, itemsets, selectOnes, selectMultis, actionTargets);
    // if this assumption is wrong, well, then we're screwed.
    if (instanceNodes.size() > 1) {
        for (int instanceIndex = 1; instanceIndex < instanceNodes.size(); instanceIndex++) {
            final Element instance = instanceNodes.get(instanceIndex);
            final String instanceId = instanceNodeIdStrs.get(instanceIndex);
            final String ediPath = getPathIfExternalDataInstance(instance.getAttributeValue(null, "src"));
            if (ediPath != null) {
                try {
                    /* todo implement better error handling */
                    _f.addNonMainInstance(ExternalDataInstance.buildFromPath(ediPath, instanceId));
                } catch (IOException | UnfullfilledRequirementsException | InvalidStructureException | XmlPullParserException e) {
                    e.printStackTrace();
                }
            } else {
                FormInstance fi = instanceParser.parseInstance(instance, false, instanceNodeIdStrs.get(instanceNodes.indexOf(instance)), namespacePrefixesByUri);
                // same situation as below
                loadNamespaces(_xmldoc.getRootElement(), fi);
                loadInstanceData(instance, fi.getRoot(), _f);
                _f.addNonMainInstance(fi);
            }
        }
    }
    // now parse the main instance
    if (mainInstanceNode != null) {
        FormInstance fi = instanceParser.parseInstance(mainInstanceNode, true, instanceNodeIdStrs.get(instanceNodes.indexOf(mainInstanceNode)), namespacePrefixesByUri);
        /*
             Load namespaces definition (map of prefixes -> URIs) into a form instance so later it can be used
             during the form instance serialization (XFormSerializingVisitor#visit). If the map is not present, then
             serializer will provide own prefixes for the namespaces present in the nodes.
             This will lead to inconsistency between prefixes used in the form definition (bindings)
             and prefixes in the form instance after the instance is restored and inserted into the form definition.
             */
        loadNamespaces(_xmldoc.getRootElement(), fi);
        addMainInstanceToFormDef(mainInstanceNode, fi);
    }
    // Clear the caches, as these may not have been initialized
    // entirely correctly during the validation steps.
    Enumeration<DataInstance> e = _f.getNonMainInstances();
    while (e.hasMoreElements()) {
        DataInstance instance = e.nextElement();
        final AbstractTreeElement treeElement = instance.getRoot();
        if (treeElement instanceof TreeElement) {
            ((TreeElement) treeElement).clearChildrenCaches();
        }
        treeElement.clearCaches();
    }
    _f.getMainInstance().getRoot().clearChildrenCaches();
    _f.getMainInstance().getRoot().clearCaches();
    codeTimer.logDone();
}
Also used : AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement) ExternalDataInstance.getPathIfExternalDataInstance(org.javarosa.core.model.instance.ExternalDataInstance.getPathIfExternalDataInstance) DataInstance(org.javarosa.core.model.instance.DataInstance) ExternalDataInstance(org.javarosa.core.model.instance.ExternalDataInstance) UnfullfilledRequirementsException(org.javarosa.xml.util.UnfullfilledRequirementsException) TreeElement(org.javarosa.core.model.instance.TreeElement) AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement) Element(org.kxml2.kdom.Element) IFormElement(org.javarosa.core.model.IFormElement) InvalidStructureException(org.javarosa.xml.util.InvalidStructureException) IOException(java.io.IOException) TreeElement(org.javarosa.core.model.instance.TreeElement) AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement) FormDef(org.javarosa.core.model.FormDef) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) FormInstance(org.javarosa.core.model.instance.FormInstance) CodeTimer(org.javarosa.core.util.CodeTimer)

Example 2 with DataInstance

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

the class XPathPathExpr method eval.

public XPathNodeset eval(DataInstance m, EvaluationContext ec) {
    TreeReference genericRef = getReference();
    TreeReference ref;
    if (genericRef.getContext() == TreeReference.CONTEXT_ORIGINAL) {
        ref = genericRef.contextualize(ec.getOriginalContext());
    } else {
        ref = genericRef.contextualize(ec.getContextRef());
    }
    // check if this nodeset refers to a non-main instance
    if (ref.getInstanceName() != null && ref.isAbsolute()) {
        DataInstance nonMain = ec.getInstance(ref.getInstanceName());
        if (nonMain != null) {
            m = nonMain;
        } else {
            throw new XPathMissingInstanceException(ref.getInstanceName(), "Instance referenced by " + ref.toString(true) + " does not exist");
        }
    } else {
        // TODO: We should really stop passing 'm' around and start just getting the right instance from ec
        // at a more central level
        m = ec.getMainInstance();
        if (m == null) {
            String refStr = ref == null ? "" : ref.toString(true);
            throw new XPathException("Cannot evaluate the reference [" + refStr + "] in the current evaluation context. No default instance has been declared!");
        }
    }
    // regardless of the above, we want to ensure there is a definition
    if (m.getRoot() == null) {
        // This instance is _declared_, but doesn't actually have any data in it.
        throw new XPathMissingInstanceException(ref.getInstanceName(), "Instance referenced by " + ref.toString(true) + " has not been loaded");
    }
    // this makes no sense...
    // if (ref.isAbsolute() && m.getTemplatePath(ref) == null) {
    // List<TreeReference> nodesetRefs = new List<TreeReference>();
    // return new XPathNodeset(nodesetRefs, m, ec);
    // }
    List<TreeReference> nodesetRefs = ec.expandReference(ref);
    // to fix conditions based on non-relevant data, filter the nodeset by relevancy
    for (int i = 0; i < nodesetRefs.size(); i++) {
        if (!m.resolveReference(nodesetRefs.get(i)).isRelevant()) {
            nodesetRefs.remove(i);
            i--;
        }
    }
    return new XPathNodeset(nodesetRefs, m, ec);
}
Also used : DataInstance(org.javarosa.core.model.instance.DataInstance) XPathException(org.javarosa.xpath.XPathException) TreeReference(org.javarosa.core.model.instance.TreeReference) XPathNodeset(org.javarosa.xpath.XPathNodeset) XPathMissingInstanceException(org.javarosa.xpath.XPathMissingInstanceException)

Example 3 with DataInstance

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

the class FormDef method readExternal.

/**
 * Reads the form definition object from the supplied stream.
 * <p/>
 * Requires that the instance has been set to a prototype of the instance
 * that should be used for deserialization.
 *
 * @param dis - the stream to read from.
 * @throws IOException
 * @throws InstantiationException
 * @throws IllegalAccessException
 */
@Override
public void readExternal(DataInputStream dis, PrototypeFactory pf) throws IOException, DeserializationException {
    setID(ExtUtil.readInt(dis));
    setName(ExtUtil.nullIfEmpty(ExtUtil.readString(dis)));
    setTitle((String) ExtUtil.read(dis, new ExtWrapNullable(String.class), pf));
    setChildren((List<IFormElement>) ExtUtil.read(dis, new ExtWrapListPoly(), pf));
    setInstance((FormInstance) ExtUtil.read(dis, FormInstance.class, pf));
    setLocalizer((Localizer) ExtUtil.read(dis, new ExtWrapNullable(Localizer.class), pf));
    List<Condition> vcond = (List<Condition>) ExtUtil.read(dis, new ExtWrapList(Condition.class), pf);
    for (Condition condition : vcond) {
        addTriggerable(condition);
    }
    List<Recalculate> vcalc = (List<Recalculate>) ExtUtil.read(dis, new ExtWrapList(Recalculate.class), pf);
    for (Recalculate recalculate : vcalc) {
        addTriggerable(recalculate);
    }
    finalizeTriggerables();
    outputFragments = (List<IConditionExpr>) ExtUtil.read(dis, new ExtWrapListPoly(), pf);
    submissionProfiles = (HashMap<String, SubmissionProfile>) ExtUtil.read(dis, new ExtWrapMap(String.class, SubmissionProfile.class));
    formInstances = (HashMap<String, DataInstance>) ExtUtil.read(dis, new ExtWrapMap(String.class, new ExtWrapTagged()), pf);
    eventListeners = (HashMap<String, List<Action>>) ExtUtil.read(dis, new ExtWrapMap(String.class, new ExtWrapListPoly()), pf);
    extensions = (List<XFormExtension>) ExtUtil.read(dis, new ExtWrapListPoly(), pf);
    resetEvaluationContext();
}
Also used : Condition(org.javarosa.core.model.condition.Condition) IConditionExpr(org.javarosa.core.model.condition.IConditionExpr) DataInstance(org.javarosa.core.model.instance.DataInstance) Recalculate(org.javarosa.core.model.condition.Recalculate) ExtWrapTagged(org.javarosa.core.util.externalizable.ExtWrapTagged) ExtWrapMap(org.javarosa.core.util.externalizable.ExtWrapMap) Localizer(org.javarosa.core.services.locale.Localizer) ExtWrapListPoly(org.javarosa.core.util.externalizable.ExtWrapListPoly) List(java.util.List) ArrayList(java.util.ArrayList) ExtWrapList(org.javarosa.core.util.externalizable.ExtWrapList) ExtWrapList(org.javarosa.core.util.externalizable.ExtWrapList) ExtWrapNullable(org.javarosa.core.util.externalizable.ExtWrapNullable)

Example 4 with DataInstance

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

the class FormDef method initialize.

/**
 * meant to be called after deserialization and initialization of handlers
 *
 * @param newInstance true if the form is to be used for a new entry interaction,
 *                    false if it is using an existing IDataModel
 */
public void initialize(boolean newInstance, InstanceInitializationFactory factory) {
    for (String instanceId : formInstances.keySet()) {
        DataInstance instance = formInstances.get(instanceId);
        instance.initialize(factory, instanceId);
    }
    if (newInstance) {
        // only preload new forms (we may have to revisit
        // this)
        preloadInstance(mainInstance.getRoot());
    }
    if (getLocalizer() != null && getLocalizer().getLocale() == null) {
        getLocalizer().setToDefault();
    }
    // get fired again, but always fire this one?
    if (newInstance) {
        dispatchFormEvent(Action.EVENT_XFORMS_READY);
    }
    Collection<QuickTriggerable> qts = initializeTriggerables(TreeReference.rootRef(), false);
    dagImpl.publishSummary("Form initialized", qts);
}
Also used : DataInstance(org.javarosa.core.model.instance.DataInstance)

Example 5 with DataInstance

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

the class EvaluationContext method expandReference.

/**
 * Searches for all repeated nodes that match the pattern of the 'ref'
 * argument.
 *
 * '/' returns {'/'}
 * can handle sub-repetitions (e.g., {/a[1]/b[1], /a[1]/b[2], /a[2]/b[1]})
 *
 * @param ref Potentially ambiguous reference
 * @return Null if 'ref' is relative reference. Otherwise, returns a vector
 * of references that point to nodes that match 'ref' argument. These
 * references are unambiguous (no index will ever be INDEX_UNBOUND). Template
 * nodes won't be included when matching INDEX_UNBOUND, but will be when
 * INDEX_TEMPLATE is explicitly set.
 */
public List<TreeReference> expandReference(TreeReference ref, boolean includeTemplates) {
    if (!ref.isAbsolute()) {
        return null;
    }
    final DataInstance baseInstance = (ref.getInstanceName() != null) ? getInstance(ref.getInstanceName()) : instance;
    if (baseInstance == null) {
        throw new RuntimeException("Unable to expand reference " + ref.toString(true) + ", no appropriate instance in evaluation context");
    }
    List<TreeReference> treeReferences = new ArrayList<>(1);
    TreeReference workingRef = baseInstance.getRoot().getRef();
    expandReferenceAccumulator(ref, baseInstance, workingRef, treeReferences, includeTemplates);
    return treeReferences;
}
Also used : DataInstance(org.javarosa.core.model.instance.DataInstance) TreeReference(org.javarosa.core.model.instance.TreeReference) ArrayList(java.util.ArrayList)

Aggregations

DataInstance (org.javarosa.core.model.instance.DataInstance)7 TreeReference (org.javarosa.core.model.instance.TreeReference)4 ArrayList (java.util.ArrayList)3 FormDef (org.javarosa.core.model.FormDef)2 EvaluationContext (org.javarosa.core.model.condition.EvaluationContext)2 AbstractTreeElement (org.javarosa.core.model.instance.AbstractTreeElement)2 TreeElement (org.javarosa.core.model.instance.TreeElement)2 XPathException (org.javarosa.xpath.XPathException)2 IOException (java.io.IOException)1 List (java.util.List)1 IFormElement (org.javarosa.core.model.IFormElement)1 Condition (org.javarosa.core.model.condition.Condition)1 Constraint (org.javarosa.core.model.condition.Constraint)1 IConditionExpr (org.javarosa.core.model.condition.IConditionExpr)1 Recalculate (org.javarosa.core.model.condition.Recalculate)1 ExternalDataInstance (org.javarosa.core.model.instance.ExternalDataInstance)1 ExternalDataInstance.getPathIfExternalDataInstance (org.javarosa.core.model.instance.ExternalDataInstance.getPathIfExternalDataInstance)1 FormInstance (org.javarosa.core.model.instance.FormInstance)1 Localizer (org.javarosa.core.services.locale.Localizer)1 CodeTimer (org.javarosa.core.util.CodeTimer)1