Search in sources :

Example 11 with FormInstance

use of org.javarosa.core.model.instance.FormInstance 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 12 with FormInstance

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

the class XPathEvalTest method createTestDataForIndexedRepeatFunction.

private FormInstance createTestDataForIndexedRepeatFunction(Integer indexNodeValue) {
    TreeElement root = new TreeElement("data");
    TreeElement repeat = new TreeElement("repeat");
    TreeElement repeatChild = new TreeElement("name");
    repeatChild.setAnswer(new StringData("A"));
    repeat.addChild(repeatChild);
    root.addChild(repeat);
    repeat = new TreeElement("repeat");
    repeatChild = new TreeElement("name");
    repeatChild.setAnswer(new StringData("B"));
    repeat.addChild(repeatChild);
    root.addChild(repeat);
    repeat = new TreeElement("repeat");
    repeatChild = new TreeElement("name");
    repeatChild.setAnswer(new StringData("C"));
    repeat.addChild(repeatChild);
    root.addChild(repeat);
    TreeElement index = new TreeElement("index1");
    if (indexNodeValue != null) {
        index.setValue(new IntegerData(1));
    }
    return new FormInstance(root);
}
Also used : IntegerData(org.javarosa.core.model.data.IntegerData) StringData(org.javarosa.core.model.data.StringData) FormInstance(org.javarosa.core.model.instance.FormInstance) TreeElement(org.javarosa.core.model.instance.TreeElement)

Example 13 with FormInstance

use of org.javarosa.core.model.instance.FormInstance 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 14 with FormInstance

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

the class FormInstanceParser method buildRepeatTree.

/**
 * Builds a pseudo-data model tree that describes the repeat structure of the instance. The
 * result is a FormInstance collapsed where all indexes are 0, and repeatable nodes are flagged as such.
 * Ignores (invalid) repeats that bind outside the top-level instance data node. Returns null if no repeats.
 */
private static FormInstance buildRepeatTree(List<TreeReference> repeatRefs, String topLevelName) {
    TreeElement root = new TreeElement(null, 0);
    for (TreeReference repeatRef : repeatRefs) {
        // check and see if this references a repeat from a non-main instance, if so, skip it
        if (repeatRef.getInstanceName() != null) {
            continue;
        }
        if (repeatRef.size() <= 1) {
            // invalid repeat: binds too high. ignore for now and error will be raised in verifyBindings
            continue;
        }
        TreeElement cur = root;
        for (int j = 0; j < repeatRef.size(); j++) {
            String name = repeatRef.getName(j);
            TreeElement child = cur.getChild(name, 0);
            if (child == null) {
                child = new TreeElement(name, 0);
                cur.addChild(child);
            }
            cur = child;
        }
        cur.setRepeatable(true);
    }
    return (root.getNumChildren() == 0) ? null : new FormInstance(root.getChild(topLevelName, TreeReference.DEFAULT_MULTIPLICITY));
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference) FormInstance(org.javarosa.core.model.instance.FormInstance) Constraint(org.javarosa.core.model.condition.Constraint) TreeElement(org.javarosa.core.model.instance.TreeElement)

Example 15 with FormInstance

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

the class XFormsModule method registerModule.

public void registerModule() {
    String[] classes = { "org.javarosa.model.xform.XPathReference", "org.javarosa.xpath.XPathConditional" };
    PrototypeManager.registerPrototypes(classes);
    PrototypeManager.registerPrototypes(XPathParseTool.xpathClasses);
    RestoreUtils.xfFact = new IXFormyFactory() {

        public TreeReference ref(String refStr) {
            return FormInstance.unpackReference(new XPathReference(refStr));
        }

        public IDataPayload serializeInstance(FormInstance dm) {
            try {
                return (new XFormSerializingVisitor()).createSerializedPayload(dm);
            } catch (IOException e) {
                return null;
            }
        }

        public FormInstance parseRestore(byte[] data, Class restorableType) {
            return XFormParser.restoreDataModel(data, restorableType);
        }

        public IAnswerData parseData(String textVal, int dataType, TreeReference ref, FormDef f) {
            return XFormAnswerDataParser.getAnswerData(textVal, dataType, XFormParser.ghettoGetQuestionDef(dataType, f, ref));
        }

        public String serializeData(IAnswerData data) {
            return (String) (new XFormAnswerDataSerializer().serializeAnswerData(data));
        }

        public IConditionExpr refToPathExpr(TreeReference ref) {
            return new XPathConditional(XPathPathExpr.fromRef(ref));
        }
    };
}
Also used : IAnswerData(org.javarosa.core.model.data.IAnswerData) IConditionExpr(org.javarosa.core.model.condition.IConditionExpr) IXFormyFactory(org.javarosa.core.model.util.restorable.IXFormyFactory) IOException(java.io.IOException) XFormAnswerDataSerializer(org.javarosa.xform.util.XFormAnswerDataSerializer) TreeReference(org.javarosa.core.model.instance.TreeReference) FormDef(org.javarosa.core.model.FormDef) FormInstance(org.javarosa.core.model.instance.FormInstance) XPathConditional(org.javarosa.xpath.XPathConditional) IDataPayload(org.javarosa.core.services.transport.payload.IDataPayload)

Aggregations

FormInstance (org.javarosa.core.model.instance.FormInstance)32 TreeElement (org.javarosa.core.model.instance.TreeElement)16 TreeReference (org.javarosa.core.model.instance.TreeReference)8 Test (org.junit.Test)7 InstanceInitializationFactory (org.javarosa.core.model.instance.InstanceInitializationFactory)6 FormDef (org.javarosa.core.model.FormDef)5 AbstractTreeElement (org.javarosa.core.model.instance.AbstractTreeElement)5 IOException (java.io.IOException)4 EvaluationContext (org.javarosa.core.model.condition.EvaluationContext)3 StringData (org.javarosa.core.model.data.StringData)3 ByteArrayPayload (org.javarosa.core.services.transport.payload.ByteArrayPayload)3 XFormSerializingVisitor (org.javarosa.model.xform.XFormSerializingVisitor)3 XPathNodeset (org.javarosa.xpath.XPathNodeset)3 ArrayList (java.util.ArrayList)2 Date (java.util.Date)2 IFormElement (org.javarosa.core.model.IFormElement)2 ITreeVisitor (org.javarosa.core.model.instance.utils.ITreeVisitor)2 XPathTypeMismatchException (org.javarosa.xpath.XPathTypeMismatchException)2 XPathUnhandledException (org.javarosa.xpath.XPathUnhandledException)2 Cursor (android.database.Cursor)1