The behavior of DataStoreRuleObjectCreator is best explained by walking through an example. This example is based around the Universal Access Module.
An IEG script might capture income data for a household. The household can contain any number of persons, and each person can have any number of income details.
Here is a simplified view of the structure of the Datastore schema:
- Application:
- Person (0..n):
- firstName (String)
- lastName (String)
- Income (0..n):
- type (Code from the IncomeType code table)
- amount (Number)
A citizen (John) undertakes self-screening, and records evidence for his household (just John and his wife Mary) and income details (John is unemployed, Mary has two part-time jobs). John's evidence is stored as records in the Datastore:
- Application #1234:
- Person #1235:
- firstName: John
- lastName: Smith
- Income: <no records>
- Person #1236:
- firstName: Mary
- lastName: Smith
- Income #1237:
- type: Part-time
- amount: 25
- Income #1238:
- type: Part-time
- amount: 30
The CER rule set configured to be used with this type of screening contains some rule classes as follows (NB no program rule classes are shown):
<?xml version="1.0" encoding="UTF-8"?> <RuleSet name="DataStoreMappingExample" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation= "http://www.curamsoftware.com/CreoleRulesSchema.xsd"> <!-- NB no rule class for the CDS entity type "Application"; the attributes stored directly on an Application are not required by rules, so no point creating a rule object which won't get used. --> <!-- The name of this rule class matches that of a CDS entity type --> <Class name="Person"> <!-- The name of this rule attribute matches that of an attribute on the CDS entity type, and so its value will be automatically specified by the DataStoreRuleObjectRetriever. --> <Attribute name="firstName"> <!-- The type of the rule attribute must agree with the type of the CDS attribute type, otherwise CER will issue a runtime error. --> <type> <javaclass name="String"/> </type> <derivation> <specified/> </derivation> </Attribute> <!-- NB no rule attribute for the CDS attribute for lastName. --> <!-- Rule attributes matching the "childEntities_<rule class name>" pattern will receive special treatment from the DataStoreRuleObjectRetriever. The DataStoreRuleObjectRetriever will specify the value of this attribute to be all the rule objects created from the child Income records which belong to this Person's record in the CDS. --> <Attribute name="childEntities_Income"> <!-- The type must be a list of Income rule objects --> <type> <javaclass name="List"> <ruleclass name="Income"/> </javaclass> </type> <derivation> <specified/> </derivation> </Attribute> </Class> <!-- The name of this rule class does not match any CDS entity type, so the DataStoreRuleObjectRetriever will not create any rule objects for this rule class. --> <Class name="Benefit"> <Attribute name="amount"> <type> <javaclass name="Number"/> </type> <derivation> <specified/> </derivation> </Attribute> </Class> <Class name="Income"> <!-- A rule attribute named "parentEntity" will receive special treatment from the DataStoreRuleObjectRetriever. The DataStoreRuleObjectRetriever will specify the value of this attribute to be the rule object created from the Person record which is the parent of this Income record in the CDS. --> <Attribute name="parentEntity"> <!-- The type must be a single Person rule object --> <type> <ruleclass name="Person"/> </type> <derivation> <specified/> </derivation> </Attribute> <Attribute name="type"> <type> <!-- The type of this attribute must specify the correct code table, matching the CDS domain definition. --> <codetableentry table="IncomeType"/> </type> <derivation> <specified/> </derivation> </Attribute> <Attribute name="amount"> <type> <javaclass name="Number"/> </type> <derivation> <!-- This derivation will never be executed, as the DataStoreRuleObjectRetriever will automatically "specify" the value from that on the CDS record; once a value is specified CER does not attempt to calculate it. In general, attributes which expect to be populated by the DataStoreRuleObjectRetriever should be marked as <specified/> to avoid any confusion between stand-alone testing of your rule sets and testing with the DataStoreRuleObjectRetriever. --> <Number value="123"/> </derivation> </Attribute> <!-- This attribute is not present on the CDS entity type, so will not be populated. This is exactly what we want, because its value is derived from other rule attributes in the normal CER way. --> <Attribute name="isCountable"> <type> <javaclass name="Boolean"/> </type> <derivation> <choose> <type> <javaclass name="Boolean"/> </type> <test> <reference attribute="type"/> </test> <when> <condition> <Code table="IncomeType"> <String value="Full-time"/> </Code> </condition> <value> <true/> </value> </when> <when> <condition> <Code table="IncomeType"> <String value="Part-time"/> </Code> </condition> <value> <true/> </value> </when> <otherwise> <value> <false/> </value> </otherwise> </choose> </derivation> </Attribute> <!-- This rule attribute is not calculated, nor does it correspond to an attribute on the CDS entity type. If the value of this attribute is referenced at runtime, CER will report a runtime error: "Value must be specified before it is used (it cannot be calculated)." --> <Attribute name="employerName"> <type> <javaclass name="String"/> </type> <derivation> <specified/> </derivation> </Attribute> </Class> </RuleSet>
When John completes his self-screening, the Universal Access Module loads the CER rule set above, and creates a CER session.
The Universal Access Module calls the DataStoreRuleObjectCreator, and specifies the root Datastore record (Application #1234).
The DataStoreRuleObjectCreator retrieves all the descendant records of Application #1234 and processes them as follows:
Skipped, as there is no rule class named "Application" in the rule set;
creates a rule object instance of the Person rule class, with:
Specified to be "John";
Skipped, as there is no rule attribute named "lastName" on the Person rule class;
Specified to be an empty list, as there are no Income records for Person record #1235;
creates a rule object instance of the Person rule class, with:
Specified to be "Mary";
Skipped;
Specified to be a list containing Mary's two Income rule objects (created below);
creates a rule object instance of the Income rule class, with:
Specified to be the Person rule object created (above) for Mary from Person record #1236;
Specified to be the code "Part-time";
Specified to be the number "25";
Not specified, as there is no attribute named "employerName" on the Datastore entity;
creates a rule object instance of the Income rule class, with:
Specified to be the Person rule object created (above) for Mary from Person record #1236;
Specified to be the code "Part-time"; and
Specified to be the number "30".
Lastly, the Universal Access Module asks the rule set its standard questions about programs, eligibility and explanation; the rule classes for the programs (not shown in the example above) access the rule objects (created by the DataStoreRuleObjectCreator) when answering those questions.
For more information on the application Datastore and its schemas, see the Creating Datastore Schemas guide.