The description Rule Attribute

Each rule class ultimately inherits from a CER "root rule class". This root class includes a description rule attribute which has a default (but not particularly helpful) implementation.

The value of a rule object's description is output in RuleDoc, and also by the toString method on a RuleObject (which many Java IDEs use when you "click" on a variable). As such, a meaningful description can be indispensable when understanding the behavior of your rule set.

You should override the default description calculation by explicitly creating a description attribute on each of your rule classes. You can use the CER Editor to create a description attribute like creating a normal attribute on any rule class. The CER rule set validator will issue a warning if you have a rule class which does not define (or inherit from another defined rule class) a description rule attribute.

The description attribute is a localizable message and (just like other rule attributes) its calculation can be as simple or as complex as is needed.

Here is an example rule set, where some rule classes provide an implementation of description:

<?xml version="1.0" encoding="UTF-8"?>
<RuleSet name="Example_description"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation=
"http://www.curamsoftware.com/CreoleRulesSchema.xsd">
  <Class name="Person">

    <Attribute name="firstName">
      <type>
        <javaclass name="String"/>
      </type>
      <derivation>
        <specified/>
      </derivation>
    </Attribute>

    <Attribute name="lastName">
      <type>
        <javaclass name="String"/>
      </type>
      <derivation>
        <specified/>
      </derivation>
    </Attribute>

    <!-- Override the default description -->
    <Attribute name="description">
      <type>
        <javaclass name="curam.creole.value.Message"/>
      </type>
      <derivation>
        <!-- Concatenate the person's first and last names -->
        <concat>
          <fixedlist>
            <listof>
              <javaclass name="Object"/>
            </listof>
            <members>

              <reference attribute="firstName"/>
              <String value=" "/>
              <reference attribute="lastName"/>
            </members>
          </fixedlist>
        </concat>
      </derivation>
    </Attribute>

  </Class>

  <Class name="Income">
    <!-- The person to which this
         income record relates. -->
    <Attribute name="person">
      <type>
        <ruleclass name="Person"/>
      </type>
      <derivation>
        <specified/>
      </derivation>
    </Attribute>
    <Attribute name="startDate">
      <type>
        <javaclass name="curam.util.type.Date"/>
      </type>
      <derivation>
        <specified/>
      </derivation>
    </Attribute>
    <Attribute name="amount">
      <type>
        <javaclass name="Number"/>
      </type>
      <derivation>
        <specified/>
      </derivation>
    </Attribute>

    <!-- Override the default description -->
    <Attribute name="description">
      <type>
        <javaclass name="curam.creole.value.Message"/>
      </type>
      <derivation>
        <!-- Concatenate the person's description and the start
 date-->
        <concat>
          <fixedlist>
            <listof>
              <javaclass name="Object"/>
            </listof>
            <members>

              <reference attribute="description">
                <reference attribute="person"/>
              </reference>
              <!-- In a real rule set, this description would use
                   a <ResourceMessage> to avoid hard-coded
                   single-language Strings.  -->
              <String value="'s income, starting on "/>
              <reference attribute="startDate"/>
            </members>
          </fixedlist>
        </concat>
      </derivation>
    </Attribute>

  </Class>

  <Class name="Benefit">
    <!-- NB no override of <description>; the CER rule set validator
         will issue a warning, and rule objects of this class will
         be more difficult to understand in RuleDoc or a Java
         integrated development environment. -->
    <!-- The person to which this
         benefit record relates. -->
    <Attribute name="person">
      <type>
        <ruleclass name="Person"/>
      </type>
      <derivation>
        <specified/>
      </derivation>
    </Attribute>

    <Attribute name="amount">
      <type>
        <javaclass name="Number"/>
      </type>
      <derivation>
        <specified/>
      </derivation>
    </Attribute>
  </Class>

</RuleSet>

And here is a test class which creates some rule objects (a Person, an Income and a Benefit):

package curam.creole.example;

import java.io.File;

import junit.framework.TestCase;
import curam.creole.execution.session.RecalculationsProhibited;
import curam.creole.execution.session.Session;
import curam.creole.execution.session.SessionDoc;
import curam.creole.execution.session.Session_Factory;
import
 curam.creole.execution.session.StronglyTypedRuleObjectFactory;
import curam.creole.ruleclass.Example_description.impl.Benefit;
import
 curam.creole.ruleclass.Example_description.impl.Benefit_Factory;
import curam.creole.ruleclass.Example_description.impl.Income;
import
 curam.creole.ruleclass.Example_description.impl.Income_Factory;
import curam.creole.ruleclass.Example_description.impl.Person;
import
 curam.creole.ruleclass.Example_description.impl.Person_Factory;
import curam.creole.storage.inmemory.InMemoryDataStorage;
import curam.util.type.Date;

/**
 * Tests the description rule attribute.
 */
public class TestDescription extends TestCase {

  /**
   * Tests the description rule attribute.
   */
  public void testDescriptions() {

    /**
     * Create a new session.
     */
    final Session session =
        Session_Factory.getFactory().newInstance(
            new RecalculationsProhibited(),
            new InMemoryDataStorage(
                new StronglyTypedRuleObjectFactory()));

    /**
     * Create a SessionDoc to report on rule objects.
     */
    final SessionDoc sessionDoc = new SessionDoc(session);

    /*
     * Create a Person rule object.
     */
    final Person person =
        Person_Factory.getFactory().newInstance(session);
    person.firstName().specifyValue("John");
    person.lastName().specifyValue("Smith");

    /*
     * Create an Income rule object.
     */
    final Income income =
        Income_Factory.getFactory().newInstance(session);
    income.person().specifyValue(person);
    income.amount().specifyValue(123);
    income.startDate().specifyValue(Date.fromISO8601("20070101"));

    /*
     * Create a Benefit rule object.
     */
    final Benefit benefit =
        Benefit_Factory.getFactory().newInstance(session);
    benefit.person().specifyValue(person);
    benefit.amount().specifyValue(234);

    /*
     * The .toString method evaluates the description rule
     * attribute
     */
    System.out.println(person.toString());

    /*
     * println calls an object's toString method to print it.
     */
    System.out.println(income);

    /*
     * The benefit rule class does not provide an implementation of
     * the description rule attribute, so we'll get a default
     * description here
     */
    System.out.println(benefit);

    /*
     * Write out SessionDoc for this session.
     */
    sessionDoc.write(new File("./gen/sessiondoc"));
>
  }

}

When the test is run, it produces this output, showing the rule object descriptions:

John Smith
John Smith's income, starting on 01/01/07 00:00
Undescribed instance of rule class 'Benefit', id '3'

At the end of the test, the session's rule objects are output as SessionDoc. The high-level SessionDoc summary shows the rule objects created, and lists each rule object's description:

Figure 1. SessionDoc showing rule object description valuesExample of the generated session documentation.

The description for the Benefit rule object is the default description; in the absence of a good implementation of description, someone reading the SessionDoc might have to navigate to the SessionDoc for the Benefit rule object in order to make sense of it:

Figure 2. SessionDoc for a rule object with no description overrideExample of the generated session documentation.

Lastly, this screen shot shows how an integrated development environment (such as Eclipse, shown) uses an object's toString method when debugging, which (for rule objects) calculates the description:

Figure 3. Use of description in an integrated development environmentEclipse example.
Tip: Remember that the aim of the description is to describe a rule object instance, not the rule class itself.

In particular, the calculation of your description rule attribute should include data that means that it is easy to distinguish between different rule object instances of your rule class.