Showing posts with label Groovy. Show all posts
Showing posts with label Groovy. Show all posts

23 Jun 2012

Dependent LOV in a Search Form

Let's say we have a ViewObject with a LOV enabled attribute.

 The ViewAccessor's ViewObject has a bind variable.


In our use case we have a method in the ViewObjectImpl calculating value for this bind variable.

    public Integer getDealTypeID() {

        return someCalculatedValue;

    }


So, we can put a groovy expression "viewObject.dealTypeID" to the ViewAccessor's definition:


And it works fine everywhere except Search Form. If our LOV enabled attribute is used in a View Criteria and triggered from a Search form we will get something like this: JBO-25077: Name dealTypeID not found in the given object: oracle.adf.model.bean.DCDataVO. The object for the groovy script in case of a SearchForm is DCDataRow that is built internally by the af:query mechanism.
If we change the groovy expression to this "dataProvider.viewCriteria.viewObject.dealTypeID",
the Search Form will start to work, but the normal form will be broken. So, we have to understand somehow where the groovy expression is triggered from. The "adf.isCriteriaRow" expression can help us and our groovy script will look like this:

if (adf.isCriteriaRow)  
  return dataProvider.viewCriteria.viewObject.dealTypeID; 
else   
  return viewObject.dealTypeID;


This script will work in both cases!
But... That's all fine for R1 only . In R2 the expression "adf.isCriteriaRow" is not working in this case and the groovy script for R2 will look a bit ugly:


if (object.getClass().getName().endsWith('DCCriteriaValueRowImpl'))     
   return viewCriteria.viewObject.dealTypeID;  
else   
   return viewObject.dealTypeID;


That's it!.



20 May 2012

Working with VO's built-in aggregation functions

When we work with View Link accessors or Association accessors we can use Groovy for aggregation calculations in a very convenient way. Groovy API provides five predefined functions:
  • accessor.sum("expr")
  • accessor.count("expr")
  • accessor.avg("expr")
  • accessor.min("expr")
  • accessor.max("expr")
This API is commonly used to calculate values of transient attributes in the master VO's.  But what if we don't have any master-detail relationship and don't have any accessors? We just have a ViewObject and we need to do some aggregation calculations on it - this is very common use case.  The common practice for this issue is to write custom Java method in the ViewObjectImpl class. But we have already five (that is enough for most cases) built-in methods used by the Groovy API. These methods are implemented by the ViewRowSetImpl (extends RowSetHelper) class and as any useful methods these ones are private. Groovy API uses InvokerHelper class to invoke them as it could be easily seen from the call stack. Let's do the same. Off-course these built-in methods can be deprecated in the future in the latest versions of ADF and we should be aware of that, but until it has not happened we do the following:
 
     1. Create an inner helper class in our ViewObjectImpl
   private class AgrFuncHelper extends HashMap
  {
    private String funcName;

    public AgrFuncHelper(String funcName) 
    {
      super();
      this.funcName = funcName;  
    }


    public Object get(Object key) 
    {
      //Invoke private method
      //of our DefaultRowSet (sum,count,avg,min,max)
      //key is argument expression for the aggr funcion being called
      //sum("Salary")

      return InvokerHelper.invokeMethod(getDefaultRowSet(), funcName, key);
    }

  }

 
    2. Publish aggregation methods
  public Map getSum() 
  {
    return new AgrFuncHelper("sum");
  }
  
  public Map getCount() 
  {
    return new AgrFuncHelper("count");
  }

 
   3. Use the methods in jspx
<af:outputText value="#{bindings.EmployeesView1Iterator.viewObject.sum['Salary']}"                        
   id="ot12"/>
<af:outputText value="#{bindings.EmployeesView1Iterator.viewObject.count['*']}" 
  id="ot13"/>
 


That's it!

2 May 2011

Adding Groovy validation expression programmatically

In this post I'm going to show how you can add Groovy validation rule for an entity's attribute programmatically "on-the-fly". When you build Groovy expression to validate the value of an attribute, you can use predefined keywords "newValue" and "oldValue" referring to the old and new values of the attribute correspondingly.
In the following piece of code we can see how to add Groovy validation expression for some attribute checking that new value of the attribute is not greater than 20:

    //Groovy validation expression
    private static final String VALIDATION_EXPR="newValue <= 20";
    
    //Keyword in the message bundles resource file
    //exprvalue_err=Value must not be greater than {0}   
    private static final String EXPR_VALUE_ERROR="exprvalue_err";    
    private static final int EXPR_MAX_VALUE=20;    
    
    private void addExpressionValidator(AttributeDef at) {
        //creating new validator
        JboExpressionValidator jcv = new JboExpressionValidator(false, VALIDATION_EXPR);
        
        //setting error message
        jcv.setErrorMsgId(EXPR_VALUE_ERROR);
        
        //setting value for the message's token {0}
        HashMap errvaluesMap = new HashMap();
        errvaluesMap.put("0", EXPR_MAX_VALUE);         
        jcv.setErrorMsgExpressions(errvaluesMap);                
        
        //adding validator to the attribute's validators list
        ((AttributeDefImpl) at).addValidator(jcv);
    }


That was really easy!