wsharba / opendatakit

Automatically exported from code.google.com/p/opendatakit
0 stars 1 forks source link

ODK Validate not accepting (any) property() functions #1034

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Upload attached form on http://opendatakit.org/use/xlsform/

What is the expected output? What do you see instead?

Successful transformation to XForm expected. Instead get this error: 

Error: ODK Validate Errors:
org.javarosa.core.log.WrappedException: Error evaluating field 'a': No storage 
factory has been set; I don't know what kind of storage utility to create. 
Either set a storage factory, or register your StorageUtilitys directly. => 
java.lang.RuntimeException[No storage factory has been set; I don't know what 
kind of storage utility to create. Either set a storage factory, or register 
your StorageUtilitys directly.]

What version of the product are you using? On what operating system?
latest on http://opendatakit.org/use/xlsform/ (also seen on ona.io)

Original issue reported on code.google.com by mart...@enketo.org on 22 Jul 2014 at 8:12

Attachments:

GoogleCodeExporter commented 9 years ago
Actually, I would prefer this is not fixed. The property function has nothing 
to do with XPath, cannot be evaluated in XPath, and therefore shouldn't exist.

Original comment by mart...@enketo.org on 22 Jul 2014 at 8:29

GoogleCodeExporter commented 9 years ago
This is just another function, like string-length(). It provides access to the 
properties in the PropertyManager (which are otherwise only available via the 
jr:property hack.

Original comment by mitchellsundt@gmail.com on 8 Aug 2014 at 12:19

GoogleCodeExporter commented 9 years ago
No it isn't. As you said it requires something called a "PropertyManager".
Hence it cannot be evaluated by an XPath evaluator and is not an XPath
function.

Original comment by mart...@enketo.org on 8 Aug 2014 at 12:26

GoogleCodeExporter commented 9 years ago
To clarify: the PropertyManager holds things like deviceId (e.g., Mac address), 
the username and email of the logged-in user, phone number and SIM serial 
number of the device, etc. 

The fact that "property('deviceId')" uses a PropertyManager is not important -- 
it is just a function retrieving metadata about the context of execution of the 
form.

Original comment by mitchellsundt@gmail.com on 8 Aug 2014 at 4:57

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Thanks Mitch,

To clarify from my side. I think all XForm functions should be XPath functions 
which means they are evaluated on a single XML document (or not require 
anything external at all like '1 + 2'). 

So in the case of property(), what would in my opinion be the way to get this 
functionality is to extract the value from the <meta> group in the instance. 
This would mean implementing metadata differently (e.g. ideally without any 
bindings) with fixed paths and fixed nodeNames and a fixed way of populating 
with a value. If the meta node exists, it is populated. We could then either 
use a property() function or just refer to the meta node name with the 
${instanceID} syntax. XLSForm could facilitate this by e.g. adding some 
tolerance for the nodenames in the syntax (that all create the same strict 
XForm output).

In that case the PropertyManager would not be used inside the property() 
function but only to populate meta nodes. Property values can be retrieved with 
XPath from these meta nodes.

I guess we could also have XLSForm automatically add the meta nodes to the 
XForm output if a certain property is referred to in the property function. 
E.g. if the form contains property('deviceid'), it adds the /data/meta/deviceID 
to the XForm instance. The property() XPath function simply maps the argument 
'deviceid' to /data/meta/deviceID.

Original comment by mart...@enketo.org on 8 Aug 2014 at 5:42

GoogleCodeExporter commented 9 years ago
I deleted and then edited and re-submitted my previous reply. See online.

Original comment by mart...@enketo.org on 8 Aug 2014 at 5:45

GoogleCodeExporter commented 9 years ago
I think there is still some confusion...

The property('propertyname') function is used to access data about the context 
in which the form is being filled out so that you can use it in a calculate 
binding to populate a field in the form (or as part of any general computation):

<bind nodeset="/data/meta/deviceSim" type="string" 
calculate="property('simserial')" />

The old form of this was largely undocumented. I believe this would accomplish 
the same thing:

<bind nodeset="/data/meta/deviceSim" type="string" 
      jr:preload="property" jr:preloadParams="simserial" />

In the XLS file, see the "Metadata" section in XLSForm.org for the way the 
XLSForm supported a limited set of jr:preload context properties by reserving 
'name' values and treating them as special (and placing them in a non-obvious 
place in the form).

The property('name') function just generalizes access to these 
execution-context values so that a code change in XLSForm and in JavaRosa is 
not needed if the context wants to expose a different piece of information 
about itself. e.g., what client browser version it is running in, the 
IP-address of the client, etc.

It also avoids the special 'name' handling and just returns the value.

Original comment by mitchellsundt@gmail.com on 8 Aug 2014 at 6:50

GoogleCodeExporter commented 9 years ago
Thanks for the explaining this further.

I'm all for removing jr:preload-ers. The suggestion I made above (largely 
similar to https://bitbucket.org/javarosa/javarosa/wiki/OpenRosaMetaDataSchema) 
does this (in a more elegant way).

The issue I have remains if the property() function is a function users can add 
to calculate fields. Any function in a calculate or constraint or relevant 
**should be a proper XPath function**, therefore not requiring some external 
object. The property values should be saved to XML first, before they can be 
retrieved by an XPath function, just because of the way any XPath Evaluator 
works (or should work). The only way you can deviate from this is by passing 
some kind of property object as an additional parameter to property() which we 
don't want of course.

You need to be able to create an ODK-compliant app by taking an XPath Evaluator 
off the shelf (like I did for Enketo) and extend it with the custom functions. 
All these functions are evaluated on an XML Document. They don't have access to 
anything outside the XPath Evaluator and the XML Document except built-in 
language features.

Original comment by mart...@enketo.org on 8 Aug 2014 at 7:28