Specify the Correct Type of Value for an Attribute

Each CER AttributeValue has a specifyValue method to allow the attribute's value to be specified (rather than calculated). The method takes any value1, but if you specify the wrong type of value, CER will raise a runtime error:

public void incorrectValueType() {

    final FlexibleRetirementYear flexibleRetirementYear =
        FlexibleRetirementYear_Factory.getFactory().newInstance(
            session);

    /**
     * Will not work - retirementCause() expects a String, not a
     * Number.
     *
     * CER will report the message: Attempt to set the value '123'
     * (of type 'java.lang.Integer') on attribute 'retirementCause'
     * of rule class 'FlexibleRetirementYear' (which expects a
     * 'java.lang.String').
     */
    flexibleRetirementYear.retirementCause().specifyValue(123);

  }
1 Technical readers might wonder why AttributeValue.specifyValue does not use Java 5 generics to restrict the value type it can receive.

If rule class A extends rule class B, then A is free to override the derivation of any of B's attributes. A is also free to redeclare any of B's attributes to be a more-restrictive type (i.e. A's declaration of the attribute specifies its type to be a subtype of that declared by B).

The generated Java interface for A extends the generated Java interface for B. Because the accessors return calculators, rather than the value type directly, all interfaces must use wildcard extension so that the compiler will allow A's declaration of the attribute's accessor to extend that of B's. Because wildcard extension is used, specifyValue cannot restrict to a type, and thus must be declared to receive any Object.

From another point-of-view, if a Java class C were to extend Java D, then C can define a more restrictive return type for one of D's getters, but cannot restrict D's setters to a subtype - C must implement D's setter, and detect any undesirable values at runtime (although to do so might arguably violate Liskov's substitution principle).

Another justification is that when purely-dynamic rule objects are used (i.e. in an interpreted session), compile-time restriction of values cannot be used.

Thus, CER uses its knowledge of declared attribute types to detect incorrect values at runtime, not compile time.