Inner datasets
From OpenLaszlo
Design
The syntax will look like:
<view name="foo">
<dataset name='mydata'>
<pizza>
<topping>mushroom</topping>
</pizza>
</dataset>
...
</view>
or
<class name="foo">
<dataset name='mydata'>
<pizza>
<topping>mushroom</topping>
</pizza>
</dataset>
...
</class>
Issues
We'll need some syntax for accessing datasets that are in parents, like "parent.parent.mydata" or "classroot.mydata".
Are we going to allow the locally declared datasets to use the "http://" syntax to specify that their data is gets loaded at runtime?
Is a class dataset shared across all instances, or copied per instance, or is there a syntax to specify either? (This is the same as the distinction between a class member and an instance member.)
Ditto for datasets attached to a replicated view.
Implementation
Henry: The dataset object is going to get bound as a property of the parent view, so it will share the namespace just like child views do (and that means you will have a name collision if you name a child view the same name as a local dataset). When referencing a dataset in a view, hopefully the following will just work:
<view name="foo>
<dataset name="mydata">
<pizza>
<topping>mushroom</topping>
<topping>peppers</topping>
</pizza>
</dataset>
<text datapath="mydata:/topping/text()"/>
</view>
I'm not sure what scoping the xpath and LzView datapath handling code uses now when it looks up datasets by name, but I guess I'll deal with that soon enough. Maybe it will "just work".
Adam: This defintely won't "just work". The bit you are looking for isright here, in the LzParsedPath constructor:
if ( sourceindex > -1 ){
//we have a dset and possible dsource
sourceparts = pa.substring( 0 , sourceindex ).split( ":" );
if ( sourceparts.length > 1 ){
//we have a datasource and a dataset
this.context =_root.canvas[ this.trim( sourceparts[ 0 ] ) ]
[ this.trim( sourceparts[ 1 ] ) ];
} else {
var name = this.trim( sourceparts[ 0 ] );
if ( name == "new" ){
//_root.Debug.write( "setting to anondset" );
this.context = new this.AnonDatasetGenerator( this );
} else {
this.context = _root.canvas.datasets[ name ];
}
}
NB that parsed paths are currently cached based only on their string representation. This is no longer valid, since the string mydata:/a could refer to different datasets named mydata. The change will have to store a parsed representation of the datasource/dataset and then run a method on the parent object to determine which dataset is being referenced. This change will percolate throughout the the datapointer implementation -- basically anywhere the parsedpath's context is looked up, that'll have to be replaced by a method which gets the contenxt.
Henry: [NOTE this comment below is because I was worried about dataset size exceeding 64kbytes. If we just punt on that and simply issue a compiler error when the dataset gets too big, we don't need to do this junk]
My current plan is to use the the DataCompiler to compile the datasets, because it supports datasets with string values larger than 64Kbytes. There's also a limit of 64kbytes total on functions (have we run into this yet?). So, I want to use the DataCompiler because it can emit code to build an arbitrary sized dataset (but only at the top level) and so there is only one code path to maintain for creating data sets.
My idea is have the compiler collect up all the datasets which are declared anywhere in an app, and emit code that instantiates one of each of them and adds them to a top level object, with a unique key for each one. Then, when a view with datasets gets instantiated, any datasets which it contains are built by calling $once{} function which clones the needed dataset(s), using some sort of dataset-cloning function.
Question: currently compile-time datasets are created by calling this function
function lzAddLocalData(name, d) {
return new _root.LzDataset(null, {name: name, data: d });
}
I want to make a new object at the top level to which the datasets get attached, and key them by a unique ID which the compiler will emit. What is the right way to do that? Should I use a LzNode or just an anonymous object at the root level to hold these datasets?
Adam: I would use an anonymous object and add a setter to LzNode like $datasets which knows how to retrieve the dataset objects based on keys that it is passed. I think $datasets should be passed as a list, since I would expect that a node could have more than one dataset.

