Skip Headers
Oracle® Fusion Applications Developer's Guide
11g Release 1 (11.1.3)

Part Number E15524-03
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

6 Defining Defaulting and Derivation Logic

This chapter describes how to define your defaulting and derivation logic, how to use Groovy (a Java-like scripting language), and how to use Oracle Application Development Framework (Oracle ADF) validators and convertor hints instead of using messages.

This chapter includes the following sections:

6.1 Understanding Entity Object Defaulting and Derivation Logic

Defaulting logic means assigning attribute values when a row or entity object is first created or refreshed. (The logic is not re-applied when the entity object is changed.) Defaulting is achieved either declaratively in the default field of the attribute or programmatically by adding code to the EOImpl.

Derivation logic means assigning attribute values when some other attributes have changed. Derivation is achieved either declaratively in the default field of the transient attribute or by using a validator, or programmatically by adding code to the EOImpl.

Figure 6-1, illustrates what you need to consider when determining whether to implement defaulting or derivation logic.

Figure 6-1 Defaulting and Derivation — Decision Tree

Defaulting and Derivation - Decision Tree

When implementing defaulting or derivation logic, you should also consider the following factors:

6.2 Using Groovy Scripting Language

ADF Business Components now provide integrated support for Groovy (a Java-like scripting language), which is dynamically compiled and evaluated at run-time. Because it is dynamically compiled, Groovy script can be stored inline in the XML and is eligible for customization. Groovy also supports object access via dot-separated notation, which means you can now use syntax such as empno instead of getAttribute(EMPNO).

You can embed Groovy script into various declarative areas, including:

6.2.1 Keywords and Available Names

As with the original Script implementation, the current object is passed into the script as "this" object. Therefore, to refer to any attribute inside the current object simply use the attribute name. For example, in an attribute or validator expression for an entity, to refer to an attribute named Ename, the script may say return Ename.

There is one top-level reserved name, adf, which is used to get to objects that the framework makes available to the Groovy script. Currently, these objects are:

  • ADFContext (adf.context)

  • Object on which the expression is being applied (adf.object)

  • Error handler that lets the validator generate exceptions or warnings (adf.error)

All other names come from the context in which the script is applied:

  • Variable - gets the Variable, structureDef in which it is contained via getStructureDef method on VariableImpl.

  • Transient Attribute - gets the Entity or ViewRow as its context so that all attributes in the entity are accessible by name. Any method on the entity may be invoked by directly calling the entity method as if you were writing a method in the entity subclass.

    Tip:

    Only public methods on the entity are available to call.

    You also need to call the method using the "object" keyword, such as adf.object.createUnqualifiedRowSet(). The "object" keyword is equivalent to the "this" keyword in Java. Without it, in transient expressions, the method is assumed to exist on the script object itself, which it does not.

  • Validator - gets the Validator context JboValidatorContext merged with the Entity on which the validator is applied. This is done so that you can use:

    • newValue and oldValue to get to the values being validated

    • sourceRow to get to the Entity or ViewRow on which the validator is applied

    • All attribute names in the Entity or ViewRow as top-level names

6.2.2 Scripting Logic

Groovy scripting logic is similar to Expression Language (EL) because you can use a "." separated path to get to a value inside an object. Note that if a Java object implements Map, only the map lookup is performed instead of the bean style property lookup. However, for Maps that extend JboAbstractMap you get the same EL behavior, which is map first followed by bean lookup. This is due to the implementation of get in JboAbstractMap.

Consider the following information:

  • All Java methods, language constructs, and Groovy language constructs are available in the script.

  • Aggregates are implemented by calling sum(expr), count(expr), or avg(expr) on a RowSet object where expr can be any Groovy expression that returns a numeric value or number domain.

  • The defaultRowSet reserved keyword has been removed. The method EntityImpl.createUnqualifiedRowSet() replaces EntityImpl.getDefaultRowSet() and can be accessed like any other public method in EntityImpl.

  • Use the return keyword as you would in Java to return a value. That is, unless it is a single-line expression where the return is assumed to be the result of the expression itself. For example, "Sal + Comm" or "Sal > 0".

  • Do not use {} to surround the entire script because Groovy interprets { to be the beginning of a Closure object.

  • Any object that implements oracle.jbo.Row, oracle.jbo.RowSet, or oracle.jbo.ExprValueSupplier is wrapped into a Groovy Expando object. This is to extend the properties available for those objects to beyond the bean properties and also as a way to avoid introspection for most used names.

6.2.3 Groovy Expression Examples

The following are some examples of Groovy.

6.2.3.1 Querying Based on the Current Locale

Instead of using the following SQL to achieve this:

SELECT C.ISO_COUNTRY_CODE
,C.COUNTRY_NAME
FROM COUNTRY_CODES C
WHERE LANGUAGE = SYS_CONTEXT('USERENV', 'LANG')
ORDER BY C.COUNTRY_NAME

Create a bind variable and base its default value on the adf.context.locale.language expression:

6.2.3.2 Error Message Tokens

To get the attribute new value and label:

Example of using Groovy to get attr new value label.

The above example uses the following two Groovy expressions:

newValue  // This works because an attribute level validator has been created.
source.hints.ProductId.label

and

source.structureDef.name+" of type "+sourceFullName

6.2.3.3 Expression Validators

Example 6-1 is an example of an Object graph, custom error, and a warning:

Example 6-1 Object Graph, Custom Error, and a Warning

if (EmpSal >= 5000)
{
  // If EmpSal is greater than a property value set on the custom
  // properties on the root AM
  // raise a custom exception else raise a custom warning
  if (EmpSal >= source.DBTransaction.rootApplicationModule.propertiesMap.salHigh)
  {
    adf.error.raise("ExcGreaterThanApplicationLimit");
  }
  else
  {
    adf.error.warn("WarnGreaterThan5000");
  }
}
else if (EmpSal <= 1000)
  {
    adf.error.raise("ExcTooLow");
  }
return true;

Example 6-2 is an example of how to average a collection.

Example 6-2 Averaging a Collection

attribute Number EmpSal : SAL
{
  expressionValidator(expression = 
    "newValue <= source.createUnqualifiedRowSet().avg(\"EmpSal\") * 1.2");
}

Example 6-3 is an example of a built-in or custom method call on the sourceObject of this validator (sourcObject being the Entity on which this validator is being run). isAttributeChanged(String) is a public method on the EntityImpl:

Example 6-3 Built-in or Custom method Call

if (source.isAttributeChanged("EmpSal") || source.isAttributeChanged("EmpComm"))
           {
              return true;
           }
           return false;

Example 6-4 is an example of getting to oldValue / newValue of an attribute on which this validator is applied:

Example 6-4 Getting to Old Value and New Value of an Attribute

return (oldValue == null || newValue < olValue * 1.2);

Example 6-5 is an example of accessing the Entity state relative to the database and relative to the last post operation.

Use adf.object.entityState or adf.object.postState.

To get the old value of an attribute (this works in the context of a transient Entity Object attribute):

Example 6-5 Getting the Old Value of a Transient Entity Object Attribute

index = object.getStructureDef().getAttributeIndexOf("Salary");
return object.getAttribute(index, oracle.jbo.server.EntityImpl.ORIGINAL_VERSION);

Example 6-6 is an example of the WHILE construct as well as calling an accessor (Emp):

Example 6-6 While Construct and Calling an Accessor

emps = Emp;
boolean alreadyfound = false;
emps.reset();
while (emps.hasNext())
{
  if (emps.next().Job == "CLERK")
  {
    if (alreadyfound)
    {
      adfError.raise("alreadyfound");
    }
    alreadyfound = true;
  }
}
return true;

6.2.3.4 Attribute Defaulting and Calculation

Example 6-7, Example 6-8, and Example 6-9 are examples of a simple transient attribute, how to sum or count a collection, and how to create a complex calculation of a bind variable value.

Example 6-7 Simple Transient Attribute

attribute transient Integer YearSal
{
  transientexpression = "EmpSal * 12";
}

Example 6-8 Sum or Count a Collection

attribute transient Integer TotalSal
{
  transientexpression = "object.createUnqualifiedRowSet().sum(\"EmpSal\")";
}
attribute transient Integer TotalCount
{
  transientexpression = "object.createUnqualifiedRowSet().count(\"EmpSal\")";
}

Example 6-9 Complex Calculation of a Bind Variable Value

query EmpView
{
  entity Emp EmpUsage \*;
  where "SAL > :avgSal"
  orderby "1"
  bindingstyle "OracleName"

variables
  {
    Double avgSal
    kind (where)
    {
      transientexpression
      {
        totSal = 0;
        empCount =0;
        fullVO = structureDef.getApplicationModule().createViewObject("_AvgSal", 
          testp.kava.VO7.si33mt.EmpAllView");
        empCount = 0;
        while (fullVO.hasNext())
        {
          row = fullVO.next();
          sal = row.EmpSal; totalSal = totSal + sal; empCount = empCount + 1;
        }
        fullVO.remove();
        if (empCount > 0)
        {
          return (int)(totalSal / empCount);
        }
        else
        {
          return 0;
        }
      }
    }
  }
}

Example 6-10 is of an entity-attribute XML fragment where a transient expression is used to provide a default value for that attribute. This expression is evaluated before the protected create method of the entity is called. Example 6-11 is an example of an attribute defaulting with a transient attribute calculation expression.

Example 6-10 Attribute Value Defaulting

<Attribute
      Name="EmpComm"
      ColumnName="COMM"
      Type="oracle.jbo.domain.Number"
      ColumnType="NUMBER"
      SQLType="NUMERIC"
      TableName="EMP" >
<TransientExpression><![CDATA[

      if (EmpSal == null)
      {
        return null;
      }
      if (EmpDeptNum == null)
      {
        return 0;
      }
      if (EmpDeptNum > 40)
      {
        retune 500;
      }

]]></TransientExpression>

Example 6-11 Attribute Defaulting with a Transient Attribute Calculation Expression

<ViewAttribute
    Name="Total"
    IsUpdateable="false"
    AttrLoad="Each"
    IsSelected="false"
    IsPersistent="false"
    PrecisionRule="false"
    Type="java.lang.String"
    ColumnType="VARCHAR2"
    AliasName="View_ATTR"
    SQLType="VARCHAR">
<TransientExpression>
<![CDATA[
          if (Sal != null && Comm != null)
          {
          return Sal + Comm;
        }
        else
        {
          return Sal;
        }
        ]]>
</TransientExpression>

6.2.4 Defining Expressions at Design Time

An expression for an attribute can be defined using either the Attribute Editor (see Figure 6-2) or the Expression Editor (see Figure 6-3).

Figure 6-2 Entity Object — Attribute Editor

Entity Object - Attribute Editor

If you want to define a string literal instead of a Groovy expression, select Literal as the Value Type and enter the value as "My Literal Value".

Figure 6-3 Entity Object — Expression Editor

Entity Object - Expression Editor

To access the Expression Editor, click the Edit button located next to the Value text box.

Note:

Recalculate Expression is used to determine whether or not the expression needs to be recalculated as changes are made during run-time. The Recalculate option is hidden for persistent attributes. This is because Persistent attribute values are always updateable by the user and therefore, the expression of the attribute should only act as a default expression so recalculation is not necessary. For non-persistent attributes, the user can choose to always recalculate, never recalculate, or decide if recalculation is needed based on the evaluation of the recalculate expression.

6.3 Using Oracle ADF Validators and Convertor Hints

In some situations, you should consider using Oracle ADF validators or converter hints instead of using messages.

Caution:

Oracle ADF validators and converter hints can only be used with messages stored in the Strings resource bundles. They cannot be used for messages stored in the Message Dictionary.

To ensure that the user has supplied the correct sort of value or a value in a valid range, input fields can be validated using an Oracle ADF validator. Values may be converted by a converter, for example to convert a string of input characters into a value of some other type such as a date or color.

To validate or convert an input value, you add the input component to the page and then add a validator or converter to that field. Each validator and converter has some messages associated with it:

For an individual component, you can explain the error to a user in terms relating to that specific input component by overriding the hints or by adding or overriding a detailed error message.

How to override an Oracle ADF validator or converter message with new text

You may not see any messages when you follow these steps to select the Application Messages resource bundle:

  1. In JDeveloper, select the af validator tag in the UI page.

  2. Open the Property Inspector.

  3. Select the message attribute.

  4. Select the text resource.

  5. Select the Application Messages resource bundle.

In this case, you may need to override the default message from the validator. To do so, follow the procedure in "Displaying Hints and Error Messages for Validation and Conversion" in the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework.