Search in sources :

Example 6 with EvaluationContext

use of org.javarosa.core.model.condition.EvaluationContext in project javarosa by opendatakit.

the class XPathEvalTest method testEval.

private void testEval(String expr, FormInstance model, EvaluationContext ec, Object expected) {
    XPathExpression xpe = null;
    boolean exceptionExpected = (expected instanceof XPathException);
    if (ec == null) {
        ec = new EvaluationContext(model);
    }
    try {
        xpe = XPathParseTool.parseXPath(expr);
    } catch (XPathSyntaxException xpse) {
        System.out.println("Parsing " + expr + " failed with " + xpse.toString());
    }
    if (xpe == null) {
        fail("Null expression or syntax error");
    }
    try {
        Object result = xpe.eval(model, ec);
        if (exceptionExpected) {
            fail("Expected exception, expression : " + expr);
        } else if ((result instanceof Double && expected instanceof Double)) {
            if (!expected.equals(result)) {
                System.out.println(String.format("%s result %s differed from expected %s", expr, result, expected));
            }
            assertEquals((Double) expected, (Double) result, 1e-12);
        } else if (result instanceof XPathNodeset && expected instanceof XPathNodeset) {
            XPathNodeset expectedAsXPathNodeset = (XPathNodeset) expected;
            XPathNodeset resultAsXPathNodeset = (XPathNodeset) result;
            assertEquals(expectedAsXPathNodeset.size(), resultAsXPathNodeset.size());
            assertEquals(expectedAsXPathNodeset.getRefAt(0), resultAsXPathNodeset.getRefAt(0));
            assertEquals(expectedAsXPathNodeset.unpack(), resultAsXPathNodeset.unpack());
            assertEquals(expectedAsXPathNodeset.toArgList().length, resultAsXPathNodeset.toArgList().length);
            for (int i = 0; i < expectedAsXPathNodeset.toArgList().length; i++) {
                assertEquals(expectedAsXPathNodeset.toArgList()[i], resultAsXPathNodeset.toArgList()[i]);
            }
        } else {
            assertEquals(expected, result);
        }
    } catch (XPathException xpex) {
        if (!exceptionExpected) {
            fail("Unexpected exception: " + xpex);
        } else if (xpex.getClass() != expected.getClass()) {
            fail("Did not get expected exception type");
        }
    }
}
Also used : XPathExpression(org.javarosa.xpath.expr.XPathExpression) XPathSyntaxException(org.javarosa.xpath.parser.XPathSyntaxException) XPathException(org.javarosa.xpath.XPathException) XPathNodeset(org.javarosa.xpath.XPathNodeset) EvaluationContext(org.javarosa.core.model.condition.EvaluationContext)

Example 7 with EvaluationContext

use of org.javarosa.core.model.condition.EvaluationContext 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 8 with EvaluationContext

use of org.javarosa.core.model.condition.EvaluationContext in project javarosa by opendatakit.

the class FormDef method resetEvaluationContext.

private void resetEvaluationContext() {
    EvaluationContext ec = new EvaluationContext(null);
    ec = new EvaluationContext(mainInstance, formInstances, ec);
    initEvalContext(ec);
    this.exprEvalContext = ec;
}
Also used : EvaluationContext(org.javarosa.core.model.condition.EvaluationContext)

Example 9 with EvaluationContext

use of org.javarosa.core.model.condition.EvaluationContext in project javarosa by opendatakit.

the class FormDef method evaluateConstraint.

public boolean evaluateConstraint(TreeReference ref, IAnswerData data) {
    if (data == null) {
        return true;
    }
    TreeElement node = mainInstance.resolveReference(ref);
    Constraint c = node.getConstraint();
    if (c == null) {
        return true;
    }
    EvaluationContext ec = new EvaluationContext(exprEvalContext, ref);
    ec.isConstraint = true;
    ec.candidateValue = data;
    boolean result = c.constraint.eval(mainInstance, ec);
    getEventNotifier().publishEvent(new Event("Constraint", new EvaluationResult(ref, result)));
    return result;
}
Also used : Constraint(org.javarosa.core.model.condition.Constraint) Event(org.javarosa.debug.Event) EvaluationContext(org.javarosa.core.model.condition.EvaluationContext) EvaluationResult(org.javarosa.debug.EvaluationResult) TreeElement(org.javarosa.core.model.instance.TreeElement)

Example 10 with EvaluationContext

use of org.javarosa.core.model.condition.EvaluationContext in project javarosa by opendatakit.

the class FormDef method initEvalContext.

/**
 * @param ec The new Evaluation Context
 */
private void initEvalContext(EvaluationContext ec) {
    if (!ec.getFunctionHandlers().containsKey("jr:itext")) {
        final FormDef f = this;
        ec.addFunctionHandler(new IFunctionHandler() {

            @Override
            public String getName() {
                return "jr:itext";
            }

            @Override
            public Object eval(Object[] args, EvaluationContext ec) {
                String textID = (String) args[0];
                try {
                    // SUUUUPER HACKY
                    String form = ec.getOutputTextForm();
                    if (form != null) {
                        textID = textID + ";" + form;
                        String result = f.getLocalizer().getRawText(f.getLocalizer().getLocale(), textID);
                        return result == null ? "" : result;
                    } else {
                        String text = f.getLocalizer().getText(textID);
                        return text == null ? "[itext:" + textID + "]" : text;
                    }
                } catch (NoSuchElementException nsee) {
                    return "[nolocale]";
                }
            }

            @Override
            public List<Class[]> getPrototypes() {
                Class[] proto = { String.class };
                List<Class[]> v = new ArrayList<Class[]>(1);
                v.add(proto);
                return v;
            }

            @Override
            public boolean rawArgs() {
                return false;
            }

            @Override
            public boolean realTime() {
                return false;
            }
        });
    }
    /*
       * function to reverse a select value into the display label for that
       * choice in the question it came from
       * 
       * arg 1: select value arg 2: string xpath referring to origin question;
       * must be absolute path
       * 
       * this won't work at all if the original label needed to be
       * processed/calculated in some way (<output>s, etc.) (is this even
       * allowed?) likely won't work with multi-media labels _might_ work for
       * itemsets, but probably not very well or at all; could potentially work
       * better if we had some context info DOES work with localization
       * 
       * it's mainly intended for the simple case of reversing a question with
       * compile-time-static fields, for use inside an <output>
       */
    if (!ec.getFunctionHandlers().containsKey("jr:choice-name")) {
        final FormDef f = this;
        ec.addFunctionHandler(new IFunctionHandler() {

            @Override
            public String getName() {
                return "jr:choice-name";
            }

            @Override
            public Object eval(Object[] args, EvaluationContext ec) {
                try {
                    String value = (String) args[0];
                    String questionXpath = (String) args[1];
                    TreeReference ref = RestoreUtils.xfFact.ref(questionXpath);
                    QuestionDef q = findQuestionByRef(ref, f);
                    if (q == null || (q.getControlType() != Constants.CONTROL_SELECT_ONE && q.getControlType() != Constants.CONTROL_SELECT_MULTI)) {
                        return "";
                    }
                    // NOTE: this is highly suspect. We have no context against
                    // which to evaluate
                    // a dynamic selection list. This will generally cause that
                    // evaluation to break
                    // if any filtering is done, or, worst case, give unexpected
                    // results.
                    // 
                    // We should hook into the existing code (FormEntryPrompt) for
                    // pulling
                    // display text for select choices. however, it's hard,
                    // because we don't really have
                    // any context to work with, and all the situations where that
                    // context would be used
                    // don't make sense for trying to reverse a select value back
                    // to a label in an unrelated
                    // expression
                    List<SelectChoice> choices;
                    ItemsetBinding itemset = q.getDynamicChoices();
                    if (itemset != null) {
                        if (itemset.getChoices() == null) {
                            if (ref.isAmbiguous()) {
                                // SurveyCTO: We need a absolute "ref" to populate the dynamic choices,
                                // like we do when we populate those at FormEntryPrompt (line 251).
                                // The "ref" here is ambiguous, so we need to make it concrete first.
                                ref = ref.contextualize(ec.getContextRef());
                            }
                            f.populateDynamicChoices(itemset, ref);
                        }
                        choices = itemset.getChoices();
                    } else {
                        // static choices
                        choices = q.getChoices();
                    }
                    if (choices != null) {
                        for (SelectChoice ch : choices) {
                            if (ch.getValue().equals(value)) {
                                // this is really not ideal. we should hook into the
                                // existing code (FormEntryPrompt) for pulling
                                // display text for select choices. however, it's
                                // hard, because we don't really have
                                // any context to work with, and all the situations
                                // where that context would be used
                                // don't make sense for trying to reverse a select
                                // value back to a label in an unrelated
                                // expression
                                String textID = ch.getTextID();
                                String templateStr;
                                if (textID != null) {
                                    templateStr = f.getLocalizer().getText(textID);
                                } else {
                                    templateStr = ch.getLabelInnerText();
                                }
                                return fillTemplateString(templateStr, ref);
                            }
                        }
                    }
                    return "";
                } catch (Exception e) {
                    throw new WrappedException("error in evaluation of xpath function [choice-name]", e);
                }
            }

            @Override
            public List<Class[]> getPrototypes() {
                Class[] proto = { String.class, String.class };
                List<Class[]> v = new ArrayList<Class[]>(1);
                v.add(proto);
                return v;
            }

            @Override
            public boolean rawArgs() {
                return false;
            }

            @Override
            public boolean realTime() {
                return false;
            }
        });
    }
}
Also used : WrappedException(org.javarosa.core.log.WrappedException) IFunctionHandler(org.javarosa.core.model.condition.IFunctionHandler) XPathException(org.javarosa.xpath.XPathException) InvalidReferenceException(org.javarosa.core.model.instance.InvalidReferenceException) DeserializationException(org.javarosa.core.util.externalizable.DeserializationException) NoSuchElementException(java.util.NoSuchElementException) WrappedException(org.javarosa.core.log.WrappedException) IOException(java.io.IOException) XFormParseException(org.javarosa.xform.parse.XFormParseException) TreeReference(org.javarosa.core.model.instance.TreeReference) List(java.util.List) ArrayList(java.util.ArrayList) ExtWrapList(org.javarosa.core.util.externalizable.ExtWrapList) EvaluationContext(org.javarosa.core.model.condition.EvaluationContext) NoSuchElementException(java.util.NoSuchElementException)

Aggregations

EvaluationContext (org.javarosa.core.model.condition.EvaluationContext)28 TreeReference (org.javarosa.core.model.instance.TreeReference)16 ArrayList (java.util.ArrayList)8 Constraint (org.javarosa.core.model.condition.Constraint)8 TreeElement (org.javarosa.core.model.instance.TreeElement)8 FormDef (org.javarosa.core.model.FormDef)4 XPathNodeset (org.javarosa.xpath.XPathNodeset)4 XPathExpression (org.javarosa.xpath.expr.XPathExpression)4 FormInstance (org.javarosa.core.model.instance.FormInstance)3 EvaluationResult (org.javarosa.debug.EvaluationResult)3 Event (org.javarosa.debug.Event)3 XPathException (org.javarosa.xpath.XPathException)3 XPathSyntaxException (org.javarosa.xpath.parser.XPathSyntaxException)3 IOException (java.io.IOException)2 HashMap (java.util.HashMap)2 List (java.util.List)2 DataBinding (org.javarosa.core.model.DataBinding)2 QuestionDef (org.javarosa.core.model.QuestionDef)2 SelectChoice (org.javarosa.core.model.SelectChoice)2 IFunctionHandler (org.javarosa.core.model.condition.IFunctionHandler)2