Search in sources :

Example 1 with XPathNodeset

use of org.javarosa.xpath.XPathNodeset in project collect by opendatakit.

the class ItemsetWidget method getSelectionArgs.

private String[] getSelectionArgs(List<String> arguments, String nodesetStr, FormController formController) {
    // +1 is for the list_name
    String[] selectionArgs = new String[arguments.size() + 1];
    // parse out the list name, between the ''
    String listName = nodesetStr.substring(nodesetStr.indexOf('\'') + 1, nodesetStr.lastIndexOf('\''));
    // first argument is always listname
    selectionArgs[0] = listName;
    if (formController == null) {
        Timber.w("Can't instantiate ItemsetWidget with a null FormController.");
        return null;
    }
    // loop through the arguments, evaluate any expressions and build the query string for the DB
    for (int i = 0; i < arguments.size(); i++) {
        XPathExpression xpr;
        try {
            xpr = parseTool.parseXPath(arguments.get(i));
        } catch (XPathSyntaxException e) {
            Timber.e(e);
            TextView error = new TextView(getContext());
            error.setText(String.format(getContext().getString(R.string.parser_exception), arguments.get(i)));
            addAnswerView(error);
            break;
        }
        if (xpr != null) {
            FormDef form = formController.getFormDef();
            TreeElement treeElement = form.getMainInstance().resolveReference(formEntryPrompt.getIndex().getReference());
            EvaluationContext ec = new EvaluationContext(form.getEvaluationContext(), treeElement.getRef());
            Object value = xpr.eval(form.getMainInstance(), ec);
            if (value == null) {
                return null;
            } else {
                if (value instanceof XPathNodeset) {
                    value = ((XPathNodeset) value).getValAt(0);
                }
                selectionArgs[i + 1] = value.toString();
            }
        }
    }
    return selectionArgs;
}
Also used : XPathExpression(org.javarosa.xpath.expr.XPathExpression) XPathSyntaxException(org.javarosa.xpath.parser.XPathSyntaxException) FormDef(org.javarosa.core.model.FormDef) TextView(android.widget.TextView) XPathNodeset(org.javarosa.xpath.XPathNodeset) EvaluationContext(org.javarosa.core.model.condition.EvaluationContext) SuppressLint(android.annotation.SuppressLint) TreeElement(org.javarosa.core.model.instance.TreeElement)

Example 2 with XPathNodeset

use of org.javarosa.xpath.XPathNodeset in project javarosa by opendatakit.

the class XPathEvalTest method doTests.

public void doTests() {
    EvaluationContext ec = getFunctionHandlers();
    FormInstance instance = createTestInstance();
    FormInstance countNonEmptyInstance = createCountNonEmptyTestInstance();
    logTestCategory("counting");
    testEval("count(/data/path)", countNonEmptyInstance, null, 5.0);
    testEval("count-non-empty(/data/path)", countNonEmptyInstance, null, 3);
    logTestCategory("unsupporteds");
    testEval("/union | /expr", new XPathUnsupportedException());
    testEval("/descendant::blah", new XPathUnsupportedException());
    testEval("/cant//support", new XPathUnsupportedException());
    testEval("/text()", new XPathUnsupportedException());
    testEval("/namespace:*", new XPathUnsupportedException());
    testEval("(filter-expr)[5]", instance, null, new XPathUnsupportedException());
    testEval("(filter-expr)/data", instance, null, new XPathUnsupportedException());
    logTestCategory("numeric literals");
    testEval("5", 5.0);
    testEval("555555.555", 555555.555);
    testEval(".000555", 0.000555);
    testEval("0", 0.0);
    testEval("-5", -5.0);
    testEval("-0", -0.0);
    testEval("1230000000000000000000", 1.23e21);
    testEval("0.00000000000000000123", 1.23e-18);
    logTestCategory("string literals");
    testEval("''", "");
    testEval("'\"'", "\"");
    testEval("\"test string\"", "test string");
    testEval("'   '", "   ");
    logTestCategory("type conversions");
    testEval("true()", TRUE);
    testEval("false()", FALSE);
    testEval("boolean(true())", TRUE);
    testEval("boolean(false())", FALSE);
    testEval("boolean(1)", TRUE);
    testEval("boolean(-1)", TRUE);
    testEval("boolean(0.0001)", TRUE);
    testEval("boolean(0)", FALSE);
    testEval("boolean(-0)", FALSE);
    testEval("boolean(number('NaN'))", FALSE);
    testEval("boolean(1 div 0)", TRUE);
    testEval("boolean(-1 div 0)", TRUE);
    testEval("boolean('')", FALSE);
    testEval("boolean('asdf')", TRUE);
    testEval("boolean('  ')", TRUE);
    testEval("boolean('false')", TRUE);
    testEval("boolean(date('2000-01-01'))", TRUE);
    testEval("boolean(convertible())", null, ec, TRUE);
    testEval("boolean(inconvertible())", null, ec, new XPathTypeMismatchException());
    testEval("number(true())", 1.0);
    testEval("number(false())", 0.0);
    testEval("number('100')", 100.0);
    testEval("number('100.001')", 100.001);
    testEval("number('.1001')", 0.1001);
    testEval("number('1230000000000000000000')", 1.23e21);
    testEval("number('0.00000000000000000123')", 1.23e-18);
    testEval("number('0')", 0.0);
    testEval("number('-0')", -0.0);
    testEval("number(' -12345.6789  ')", -12345.6789);
    testEval("number('NaN')", NaN);
    testEval("number('not a number')", NaN);
    testEval("number('- 17')", NaN);
    testEval("number('  ')", NaN);
    testEval("number('')", NaN);
    testEval("number('Infinity')", NaN);
    testEval("number('1.1e6')", NaN);
    testEval("number('34.56.7')", NaN);
    testEval("number(10)", 10.0);
    testEval("number(0)", 0.0);
    testEval("number(-0)", -0.0);
    testEval("number(-123.5)", -123.5);
    testEval("number(number('NaN'))", NaN);
    testEval("number(1 div 0)", POSITIVE_INFINITY);
    testEval("number(-1 div 0)", NEGATIVE_INFINITY);
    testEval("number(date('1970-01-01'))", 0.0);
    testEval("number(date('1970-01-02'))", 1.0);
    testEval("number(date('1969-12-31'))", -1.0);
    testEval("number(date('2008-09-05'))", 14127.0);
    testEval("number(date('1941-12-07'))", -10252.0);
    testEval("number(convertible())", null, ec, 5.0);
    testEval("number(inconvertible())", null, ec, new XPathTypeMismatchException());
    testEval("string(true())", "true");
    testEval("string(false())", "false");
    testEval("string(number('NaN'))", "NaN");
    testEval("string(1 div 0)", "Infinity");
    testEval("string(-1 div 0)", "-Infinity");
    testEval("string(0)", "0");
    testEval("string(-0)", "0");
    testEval("string(123456.0000)", "123456");
    testEval("string(-123456)", "-123456");
    testEval("string(1)", "1");
    testEval("string(-1)", "-1");
    testEval("string(.557586)", "0.557586");
    // broken: testEval("string(1230000000000000000000)", "1230000000000000000000");
    // broken: testEval("string(0.00000000000000000123)", "0.00000000000000000123");
    testEval("string('')", "");
    testEval("string('  ')", "  ");
    testEval("string('a string')", "a string");
    testEval("string(date('1989-11-09'))", "1989-11-09");
    testEval("string(convertible())", null, ec, "hi");
    testEval("string(inconvertible())", null, ec, new XPathTypeMismatchException());
    logTestCategory("substring functions");
    testEval("substr('hello',0)", "hello");
    testEval("substr('hello',0,5)", "hello");
    testEval("substr('hello',1)", "ello");
    testEval("substr('hello',1,5)", "ello");
    testEval("substr('hello',1,4)", "ell");
    testEval("substr('hello',-2)", "lo");
    testEval("substr('hello',0,-1)", "hell");
    testEval("contains('a', 'a')", true);
    testEval("contains('a', 'b')", false);
    testEval("contains('abc', 'b')", true);
    testEval("contains('abc', 'bcd')", false);
    testEval("not(contains('a', 'b'))", true);
    testEval("starts-with('abc', 'a')", true);
    testEval("starts-with('', 'a')", false);
    testEval("starts-with('', '')", true);
    testEval("ends-with('abc', 'a')", false);
    testEval("ends-with('abc', 'c')", true);
    testEval("ends-with('', '')", true);
    logTestCategory("date functions");
    testEval("date('2000-01-01')", DateUtils.getDate(2000, 1, 1));
    testEval("date('1945-04-26')", DateUtils.getDate(1945, 4, 26));
    testEval("date('1996-02-29')", DateUtils.getDate(1996, 2, 29));
    testEval("date('1983-09-31')", new XPathTypeMismatchException());
    testEval("date('not a date')", new XPathTypeMismatchException());
    testEval("date(0)", DateUtils.getDate(1970, 1, 1));
    testEval("date(6.5)", DateUtils.getDate(1970, 1, 7));
    testEval("date(1)", DateUtils.getDate(1970, 1, 2));
    testEval("date(-1)", DateUtils.getDate(1969, 12, 31));
    testEval("date(14127)", DateUtils.getDate(2008, 9, 5));
    testEval("date(-10252)", DateUtils.getDate(1941, 12, 7));
    testEval("date(date('1989-11-09'))", DateUtils.getDate(1989, 11, 9));
    testEval("date(true())", new XPathTypeMismatchException());
    testEval("date(convertible())", null, ec, new XPathTypeMismatchException());
    // note: there are lots of time and timezone-like issues with dates that should be tested (particularly DST changes),
    // but it's just too hard and client-dependent, so not doing it now
    // basically:
    // dates cannot reliably be compared/used across time zones (an issue with the code)
    // any time-of-day or DST should be ignored when comparing/using a date (an issue with testing)
    /* other built-in functions */
    testEval("format-date('2018-01-02T10:20:30.123', \"%Y-%m-%e %H:%M:%S\")", "2018-01-2 10:20:30");
    logTestCategory("boolean functions");
    testEval("not(true())", FALSE);
    testEval("not(false())", TRUE);
    testEval("not('')", TRUE);
    testEval("boolean-from-string('true')", TRUE);
    testEval("boolean-from-string('false')", FALSE);
    testEval("boolean-from-string('whatever')", FALSE);
    testEval("boolean-from-string('1')", TRUE);
    testEval("boolean-from-string('0')", FALSE);
    testEval("boolean-from-string(1)", TRUE);
    testEval("boolean-from-string(1.0)", TRUE);
    testEval("boolean-from-string(1.0001)", FALSE);
    testEval("boolean-from-string(true())", TRUE);
    testEval("if(true(), 5, 'abc')", 5.0);
    testEval("if(false(), 5, 'abc')", "abc");
    testEval("if(6 > 7, 5, 'abc')", "abc");
    testEval("if('', 5, 'abc')", "abc");
    testEval("selected('apple baby crimson', 'apple')", TRUE);
    testEval("selected('apple baby crimson', 'baby')", TRUE);
    testEval("selected('apple baby crimson', 'crimson')", TRUE);
    testEval("selected('apple baby crimson', '  baby  ')", TRUE);
    testEval("selected('apple baby crimson', 'babby')", FALSE);
    testEval("selected('apple baby crimson', 'bab')", FALSE);
    testEval("selected('apple', 'apple')", TRUE);
    testEval("selected('apple', 'ovoid')", FALSE);
    testEval("selected('', 'apple')", FALSE);
    logTestCategory("math operators");
    testEval("5.5 + 5.5", 11.0);
    testEval("0 + 0", 0.0);
    testEval("6.1 - 7.8", -1.7);
    testEval("-3 + 4", 1.0);
    testEval("3 + -4", -1.0);
    testEval("1 - 2 - 3", -4.0);
    testEval("1 - (2 - 3)", 2.0);
    testEval("-(8*5)", -40.0);
    testEval("-'19'", -19.0);
    testEval("1.1 * -1.1", -1.21);
    testEval("-10 div -4", 2.5);
    testEval("2 * 3 div 8 * 2", 1.5);
    testEval("3 + 3 * 3", 12.0);
    testEval("1 div 0", POSITIVE_INFINITY);
    testEval("-1 div 0", NEGATIVE_INFINITY);
    testEval("0 div 0", NaN);
    testEval("3.1 mod 3.1", 0.0);
    testEval("5 mod 3.1", 1.9);
    testEval("2 mod 3.1", 2.0);
    testEval("0 mod 3.1", 0.0);
    testEval("5 mod -3", 2.0);
    testEval("-5 mod 3", -2.0);
    testEval("-5 mod -3", -2.0);
    testEval("5 mod 0", NaN);
    testEval("5 * (6 + 7)", 65.0);
    testEval("'123' * '456'", 56088.0);
    logTestCategory("math functions");
    testEval("abs(-3.5)", 3.5);
    // round, with a single argument
    testEval("round('14.29123456789')", 14.0);
    testEval("round('14.6')", 15.0);
    // round, with two arguments
    testEval("round('14.29123456789', 0)", 14.0);
    testEval("round('14.29123456789', 1)", 14.3);
    testEval("round('14.29123456789', 1.5)", 14.3);
    testEval("round('14.29123456789', 2)", 14.29);
    testEval("round('14.29123456789', 3)", 14.291);
    testEval("round('14.29123456789', 4)", 14.2912);
    testEval("round('12345.14',     1)", 12345.1);
    testEval("round('-12345.14',    1)", -12345.1);
    testEval("round('12345.12345',  0)", 12345.0);
    testEval("round('12345.12345', -1)", 12350.0);
    testEval("round('12345.12345', -2)", 12300.0);
    testEval("round('12350.12345', -2)", 12400.0);
    testEval("round('12345.12345', -3)", 12000.0);
    // round, with a comma instead of a decimal point
    testEval("round('4,6'            )", 5.0);
    // XPath specification tests
    testEval("round('1 div 0', 0)", NaN);
    testEval("round('14.5')", 15.0);
    testEval("round('NaN')", NaN);
    testEval("round('-NaN')", -NaN);
    testEval("round('0')", 0.0);
    testEval("round('-0')", -0.0);
    testEval("round('-0.5')", -0.0);
    // non US format
    testEval("round('14,6')", 15.0);
    // Java 8 tests deprecated by XPath 3.0 specification
    // See discussion at https://github.com/opendatakit/javarosa/pull/42#issuecomment-299527754
    testEval("round('12345.15',     1)", 12345.2);
    testEval("round('-12345.15',    1)", -12345.1);
    logTestCategory("strange operators");
    testEval("true() + 8", 9.0);
    testEval("date('2008-09-08') - date('1983-10-06')", 9104.0);
    testEval("true() and true()", TRUE);
    testEval("true() and false()", FALSE);
    testEval("false() and false()", FALSE);
    testEval("true() or true()", TRUE);
    testEval("true() or false()", TRUE);
    testEval("false() or false()", FALSE);
    testEval("true() or true() and false()", TRUE);
    testEval("(true() or true()) and false()", FALSE);
    // short-circuiting
    testEval("true() or date('')", TRUE);
    // short-circuiting
    testEval("false() and date('')", FALSE);
    testEval("'' or 17", TRUE);
    testEval("false() or 0 + 2", TRUE);
    testEval("(false() or 0) + 2", 2.0);
    testEval("4 < 5", TRUE);
    testEval("5 < 5", FALSE);
    testEval("6 < 5", FALSE);
    testEval("4 <= 5", TRUE);
    testEval("5 <= 5", TRUE);
    testEval("6 <= 5", FALSE);
    testEval("4 > 5", FALSE);
    testEval("5 > 5", FALSE);
    testEval("6 > 5", TRUE);
    testEval("4 >= 5", FALSE);
    testEval("5 >= 5", TRUE);
    testEval("6 >= 5", TRUE);
    testEval("-3 > -6", TRUE);
    logTestCategory("odd comparisons");
    testEval("true() > 0.9999", TRUE);
    // no string comparison: converted to number
    testEval("'-17' > '-172'", TRUE);
    // no string comparison: converted to NaN
    testEval("'abc' < 'abcd'", FALSE);
    testEval("date('2001-12-26') > date('2001-12-25')", TRUE);
    testEval("date('1969-07-20') < date('1969-07-21')", TRUE);
    testEval("false() and false() < true()", FALSE);
    testEval("(false() and false()) < true()", TRUE);
    testEval("6 < 7 - 4", FALSE);
    testEval("(6 < 7) - 4", -3.0);
    testEval("3 < 4 < 5", TRUE);
    testEval("3 < (4 < 5)", FALSE);
    testEval("true() = true()", TRUE);
    testEval("true() = false()", FALSE);
    testEval("true() != true()", FALSE);
    testEval("true() != false()", TRUE);
    testEval("3 = 3", TRUE);
    testEval("3 = 4", FALSE);
    testEval("3 != 3", FALSE);
    testEval("3 != 4", TRUE);
    // handle floating point rounding
    testEval("6.1 - 7.8 = -1.7", TRUE);
    testEval("'abc' = 'abc'", TRUE);
    testEval("'abc' = 'def'", FALSE);
    testEval("'abc' != 'abc'", FALSE);
    testEval("'abc' != 'def'", TRUE);
    testEval("'' = ''", TRUE);
    testEval("true() = 17", TRUE);
    testEval("0 = false()", TRUE);
    testEval("true() = 'true'", TRUE);
    testEval("17 = '17.0000000'", TRUE);
    testEval("'0017.' = 17", TRUE);
    testEval("'017.' = '17.000'", FALSE);
    testEval("date('2004-05-01') = date('2004-05-01')", TRUE);
    testEval("true() != date('1999-09-09')", FALSE);
    testEval("false() and true() != true()", FALSE);
    testEval("(false() and true()) != true()", TRUE);
    testEval("-3 < 3 = 6 >= 6", TRUE);
    logTestCategory("functions, including custom function handlers");
    testEval("true(5)", new XPathUnhandledException());
    testEval("number()", new XPathUnhandledException());
    testEval("string('too', 'many', 'args')", new XPathUnhandledException());
    testEval("not-a-function()", new XPathUnhandledException());
    testEval("testfunc()", null, ec, TRUE);
    testEval("add(3, 5)", null, ec, 8.0);
    testEval("add('17', '-14')", null, ec, 3.0);
    logTestCategory("proto");
    testEval("proto()", null, ec, new XPathTypeMismatchException());
    testEval("proto(5, 5)", null, ec, "[Double:5.0,Double:5.0]");
    testEval("proto(6)", null, ec, "[Double:6.0]");
    testEval("proto('asdf')", null, ec, "[Double:NaN]");
    // note: args treated as doubles because
    testEval("proto('7', '7')", null, ec, "[Double:7.0,Double:7.0]");
    // (double, double) prototype takes precedence and strings are convertible to doubles
    testEval("proto(1.1, 'asdf', true())", null, ec, "[Double:1.1,String:asdf,Boolean:true]");
    testEval("proto(false(), false(), false())", null, ec, "[Double:0.0,String:false,Boolean:false]");
    testEval("proto(1.1, 'asdf', inconvertible())", null, ec, new XPathTypeMismatchException());
    testEval("proto(1.1, 'asdf', true(), 16)", null, ec, new XPathTypeMismatchException());
    logTestCategory("raw");
    testEval("raw()", null, ec, "[]");
    testEval("raw(5, 5)", null, ec, "[Double:5.0,Double:5.0]");
    testEval("raw('7', '7')", null, ec, "[String:7,String:7]");
    // convertible to prototype
    testEval("raw('1.1', 'asdf', 17)", null, ec, "[Double:1.1,String:asdf,Boolean:true]");
    testEval("raw(get-custom(false()), get-custom(true()))", null, ec, "[CustomType:,CustomSubType:]");
    logTestCategory("concat");
    testEval("concat()", null, ec, "");
    testEval("concat('a')", null, ec, "a");
    testEval("concat('a','b','')", null, ec, "ab");
    testEval("concat('ab','cde','','fgh',1,false(),'ijklmnop')", null, ec, "abcdefgh1falseijklmnop");
    testEval("check-types(55, '55', false(), '1999-09-09', get-custom(false()))", null, ec, TRUE);
    testEval("check-types(55, '55', false(), '1999-09-09', get-custom(true()))", null, ec, TRUE);
    logTestCategory("regex");
    testEval("regex('12345','[0-9]+')", null, ec, TRUE);
    testEval("pow(2, 2)", 4.0);
    testEval("pow(2, 0)", 1.0);
    testEval("pow(0, 4)", 0.0);
    testEval("pow(2.5, 2)", 6.25);
    testEval("pow(0.5, 2)", .25);
    testEval("pow(-1, 2)", 1.0);
    testEval("pow(-1, 3)", -1.0);
    // So raising things to decimal powers is.... very hard
    // to evaluated exactly due to double floating point
    // precision. We'll try for things with clean answers
    testEval("pow(4, 0.5)", 2.0);
    testEval("pow(16, 0.25)", 2.0);
    logTestCategory("variable refs");
    EvaluationContext varContext = getVariableContext();
    testEval("$var_float_five", null, varContext, 5.0);
    testEval("$var_string_five", null, varContext, "five");
    testEval("$var_int_five", null, varContext, 5.0);
    testEval("$var_double_five", null, varContext, 5.0);
    logTestCategory("node referencing");
    // happy flow scenario where the index node is not blank
    FormInstance testInstance = createTestDataForIndexedRepeatFunction(1);
    XPathNodeset expected = createExpectedNodesetFromIndexedRepeatFunction(testInstance, 1, "name");
    testEval("indexed-repeat( /data/repeat/name , /data/repeat , /data/index1 )", testInstance, null, expected);
    // situation where the referenced index node is blank and the default value (0 which means the first repeat group) is used
    testInstance = createTestDataForIndexedRepeatFunction(null);
    expected = createExpectedNodesetFromIndexedRepeatFunction(testInstance, 0, "name");
    testEval("indexed-repeat( /data/repeat/name , /data/repeat , /data/index1 )", testInstance, null, expected);
    logTestCategory("crypto functions");
    // Support for all 5 supported digest algorithms (required and optional) and default base64 encoding
    testEval("digest('some text', 'MD5', 'base64')", "VS4hzUzZkYZ448Gg30kbww==");
    testEval("digest('some text', 'SHA-1', 'base64')", "N6pjx3OY2VRHMmLhoAV8HmMu2nc=");
    testEval("digest('some text', 'SHA-256', 'base64')", "uU9vElx546X/qoJvWEwQ1SraZp5nYgUbgmtVd20FrtI=");
    testEval("digest('some text', 'SHA-384', 'base64')", "zJTsPphzwLmnJIZEKVj2cQZ833e5QnQW0DFEDMYgQeLuE0RJhEfsDO2fcENGG9Hz");
    testEval("digest('some text', 'SHA-512', 'base64')", "4nMrrtyj6sFAeChjfeHbynAsP8ns4Wz1Nt241hOc2F3+dGS4I1spgm9gjM9KxkPimxnGN4WKPYcQpZER30LdtQ==");
    // Support for hexadecimal encoding
    testEval("digest('some text', 'MD5', 'hex')", "552e21cd4cd9918678e3c1a0df491bc3");
    // Support for optional third argument (defaults to 'base64')
    testEval("digest('some text', 'MD5')", "VS4hzUzZkYZ448Gg30kbww==");
    try {
        testEval("null-proto()", null, ec, new XPathUnhandledException());
        fail("Did not get expected null pointer");
    } catch (NullPointerException npe) {
    // expected
    }
    ec.addFunctionHandler(read);
    ec.addFunctionHandler(write);
    read.val = "testing-read";
    testEval("read()", null, ec, "testing-read");
    testEval("write('testing-write')", null, ec, TRUE);
    if (!"testing-write".equals(write.val))
        fail("Custom function handler did not successfully send data to external source");
}
Also used : XPathNodeset(org.javarosa.xpath.XPathNodeset) EvaluationContext(org.javarosa.core.model.condition.EvaluationContext) XPathTypeMismatchException(org.javarosa.xpath.XPathTypeMismatchException) FormInstance(org.javarosa.core.model.instance.FormInstance) XPathUnhandledException(org.javarosa.xpath.XPathUnhandledException) XPathUnsupportedException(org.javarosa.xpath.XPathUnsupportedException)

Example 3 with XPathNodeset

use of org.javarosa.xpath.XPathNodeset 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 4 with XPathNodeset

use of org.javarosa.xpath.XPathNodeset 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 5 with XPathNodeset

use of org.javarosa.xpath.XPathNodeset in project collect by opendatakit.

the class ExternalAppsUtils method populateParameters.

public static void populateParameters(Intent intent, Map<String, String> exParams, TreeReference reference) throws ExternalParamsException {
    FormDef formDef = Collect.getInstance().getFormController().getFormDef();
    FormInstance formInstance = formDef.getInstance();
    EvaluationContext evaluationContext = new EvaluationContext(formDef.getEvaluationContext(), reference);
    if (exParams != null) {
        for (Map.Entry<String, String> paramEntry : exParams.entrySet()) {
            String paramEntryValue = paramEntry.getValue();
            try {
                Object result;
                if (paramEntryValue.startsWith("'")) {
                    // but not require an ending quote
                    if (paramEntryValue.endsWith("'")) {
                        result = paramEntryValue.substring(1, paramEntryValue.length() - 1);
                    } else {
                        result = paramEntryValue.substring(1, paramEntryValue.length());
                    }
                } else if (paramEntryValue.startsWith("/")) {
                    // treat this is an xpath
                    XPathPathExpr pathExpr = XPathReference.getPathExpr(paramEntryValue);
                    XPathNodeset xpathNodeset = pathExpr.eval(formInstance, evaluationContext);
                    result = XPathFuncExpr.unpack(xpathNodeset);
                } else if (paramEntryValue.equals("instanceProviderID()")) {
                    // instanceProviderID returns -1 if the current instance has not been
                    // saved to disk already
                    String path = Collect.getInstance().getFormController().getInstanceFile().getAbsolutePath();
                    String instanceProviderID = "-1";
                    Cursor c = new InstancesDao().getInstancesCursorForFilePath(path);
                    if (c != null && c.getCount() > 0) {
                        // should only ever be one
                        c.moveToFirst();
                        instanceProviderID = c.getString(c.getColumnIndex(InstanceColumns._ID));
                    }
                    if (c != null) {
                        c.close();
                    }
                    result = instanceProviderID;
                } else {
                    // treat this is a function
                    XPathExpression xpathExpression = XPathParseTool.parseXPath(paramEntryValue);
                    result = xpathExpression.eval(formInstance, evaluationContext);
                }
                if (result != null && result instanceof Serializable) {
                    intent.putExtra(paramEntry.getKey(), (Serializable) result);
                }
            } catch (Exception e) {
                throw new ExternalParamsException("Could not evaluate '" + paramEntryValue + "'", e);
            }
        }
    }
}
Also used : XPathExpression(org.javarosa.xpath.expr.XPathExpression) Serializable(java.io.Serializable) XPathPathExpr(org.javarosa.xpath.expr.XPathPathExpr) Cursor(android.database.Cursor) ExternalParamsException(org.odk.collect.android.exception.ExternalParamsException) ExternalParamsException(org.odk.collect.android.exception.ExternalParamsException) InstancesDao(org.odk.collect.android.dao.InstancesDao) FormDef(org.javarosa.core.model.FormDef) XPathNodeset(org.javarosa.xpath.XPathNodeset) EvaluationContext(org.javarosa.core.model.condition.EvaluationContext) FormInstance(org.javarosa.core.model.instance.FormInstance) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Aggregations

XPathNodeset (org.javarosa.xpath.XPathNodeset)6 EvaluationContext (org.javarosa.core.model.condition.EvaluationContext)4 FormInstance (org.javarosa.core.model.instance.FormInstance)3 XPathExpression (org.javarosa.xpath.expr.XPathExpression)3 FormDef (org.javarosa.core.model.FormDef)2 XPathException (org.javarosa.xpath.XPathException)2 XPathTypeMismatchException (org.javarosa.xpath.XPathTypeMismatchException)2 XPathUnhandledException (org.javarosa.xpath.XPathUnhandledException)2 XPathSyntaxException (org.javarosa.xpath.parser.XPathSyntaxException)2 SuppressLint (android.annotation.SuppressLint)1 Cursor (android.database.Cursor)1 TextView (android.widget.TextView)1 IOException (java.io.IOException)1 Serializable (java.io.Serializable)1 ArrayList (java.util.ArrayList)1 Date (java.util.Date)1 LinkedHashMap (java.util.LinkedHashMap)1 List (java.util.List)1 Map (java.util.Map)1 IFunctionHandler (org.javarosa.core.model.condition.IFunctionHandler)1