The spiralcraft.data subsystem supports a standard internal XML format which is used to store and transfer data in suitable scenarios- ie. when a portable, human readable & writable text based format is called for.
The spiralcraft.data native XML format stores DataComposites (Tuples and Aggregates) and "primitives" (immutable POJOs) in XML resources using a "relationally oriented" containership model.
The outermost element an XML file of this format always represents an instance of a non-primitive Type, and is called a Type element. Each Type element in an XML document corresponds to an instance of a "primitive" (a Java object) or a data Tuple of the specified Type.
Type elements may either contain textual data (for primitive Types) or Property elements.
A Property element defines a value for a specified field of the containing Type. A Property element may contain textual data (for single-valued properties of a primitive Type), or may contain one or more Type elements as appropriate for the cardinality of the associated Field. Each property element corresponds to the assignment of data represented by child elements to a field in the parent element.
The following is an example of a Type element which represents a single Customer, albeit not very useful as it contains no data.
<example:Customer xmlns:example="class:/com/example/meta/" > </example:Customer>
The following is an example of a simple primitive Property element inside of a Type element, representing a Customer with a name assigned to it.
<example:Customer xmlns:example="class:/com/example/meta/" > <name>Joe </name> </example:Customer>
The following is an example of a primitive multi-valued Property element inside of a Type element. For the purposes of this example, the famousQuotes field is an array of Strings (otherwise known formally as a String.array in the spiralcraft.data type system.
<example:Customer
xmlns:example="class:/com/example/meta/"
>
<name>Joe
</name>
<famousQuotes>
<String>Trust me, it'll work
</String>
<String>Don't worry, we'll never get that much traffic
</String>
<String>The check is in the mail
</String>
</famousQuotes>
</example:Customer>
The following is an example of more complex Properties:
<example:Customer
xmlns:example="class:/com/example/meta/"
>
<name>Joe
</name>
<billTo>
<example:Address>
<street>123 My Way Highway
</street>
<stop>Suite 987
</stop>
<city>Nowhereville
</city>
<state>CA
</state>
<zip>94001-0010
</zip>
</example:Address>
</billTo>
<shipTo>
<example:Address>
<street>456 Warehouse Ct.
</street>
<city>Nowhereville
</city>
<state>CA
</state>
<zip>94001-0020
</zip>
</example:Address>
</shipTo>
</example:Customer>
In the native XML format, the namespace-qualified element name for Type elements constitutes a Type reference. The standardized default behavior is to resolve the local element name against the URI defined for the namespace prefix to create a Type URI.
In example #1 above, the Type URI works out to be class:/com/myexample/meta/Customer.
This URI is then resolved to a type in the standard fashion.
spiralcraft.data native XML files are usually named in one of 2 ways, depending on how they are being used.
XML data files that are part of a data Store are usually named [Type].data.xml, where [Type] is the local name of the Type being stored in the file.
Example:
Customer.data.xml Order.data.xml Invoice.data.xml
XML data files are often used to provide application components with contextual information. In this instance, the filename suffix is derived from the contained type, and the filename prefix is application specific.
Example:
FindMyCurrentOrders.query.xml (contains a Query that does something application specific) ColorChoices.string.list.xml (contains a list of Strings of color names)
ref attributeWhen creating custom Types, and in many other cases, XML data files will be authored by hand or by IDE tooling. In this scenario, the use of prototyping- a lightweight form of data inheritance- can provide flexibility and re-use.
Normally, when reading from a native XML data file, spiralcraft.data creates an empty Tuple or Aggregate for each non-primitive Type to collect the data field values and/or contents. The prototyping mechanism directs spiralcraft.data to initialize this Tuple or Aggregate from another data source before the local data field values are added.
Prototyping is accomplished by including a URI in the "ref" attribute of Type or Property element. Prototypes are always copied, and changes to the original will never be reflected in existing data (unless the data is re-read from the XML file).
The following example runs a Scan of user type MyType through a standard filter, defined in the StandardFilter.query.xml file relative to the URI of the containing resource:
<query:Query
xmlns:query="class:/spiralcraft/data/query/"
ref="StandardFilter.query.xml"
>
<debug>true
</debug>
<source>
<Scan>
<type><example:MyType.type/>
</type>
</Scan>
</source>
</query:Query>
Essentially, the outermost query is being defined by the referenced StandardFilter (which is probably a select of some sort), and is further specified here by turning on debugging and providing a contextually relevant source.
The following example creates a meeting and associates a "typical" order of food with the meeting, as detailed in the Typical.foodOrder.xml file.
<example:Meeting> <date>2009-05-23 12:00pm </date> <room>103 </room> <foodOrder ref="Typical.foodOrder.xml"/> </example:Meeting>
The syntax of the ref attribute has 3 variants:
ref="MyFile.sometype.xml"ref="myns:MyFile.sometype.xml"ref=":class:/com/my/package/MyResource.sometype.xml"Because the native XML format is used to define Types, Queries, and other metadata, it is sometimes necessary to reference a Type itself, as opposed to an instance of the Type.
By adding the ".type" suffix to a Type element name, the system will resolve the Type object itself as opposed to creating an instance of the Type.
The following example creates a Scan query, which requires a Type for its "type" property in order to know which Type to scan. In this case, we tell the Scan query to scan for all instances of the example:Customer type.
<query:Scan> <type><example:Customer.type/> </type> </query:Scan>