The ADF BC aggregate functions are often very useful. The ADF developers guide says the following on aggregate functions:
You can use the following built-in aggregate functions on ADF RowSet objects:
These aggregate functions accept a string-value argument that is interpreted as a Groovy expression that is evaluated in the context of each row in the rowset as the aggregate is being computed. The Groovy expression must return a numeric value (or number domain). For example:
rowSetAttr.sum(GroovyExpr)
rowSetAttr.count(GroovyExpr)
rowSetAttr.avg(GroovyExpr)
rowSetAttr.min(GroovyExpr)
rowSetAttr.max(GroovyExpr)
employeesInDept.sum("Sal")or
employeesInDept.sum("Sal!=0?Sal:0 + Comm!=0?Comm:0")
The API
An important disadvantage of these functions is that you can only use these on RowSets and only from inside Groovy scripts. Wouldn’t it be nice if we could use these functions anywhere we want, e.g. also in “normal” Java code? It turns out this is actually quite easy, because ADF BC exposes the most important parts of the Groovy implementation in its API.
Using the API we get the following for free:
- Simplified syntax when refering to attribute values. (E.g. we can use
Price * Quantity
instead ofrow.getPrice().multiply(row.getQuantity())
.) - Automatic conversion of
oracle.jbo.domain.*
values to Java types (for easy manipulation in Groovy). - Some special ADF BC expressions, such as
adf.currentDate
. - The mentioned aggregate functions.
GroovySupport
As an example (based on my work for one of my projects), I created the GroovySupport class.
Some examples of its use in Application Module methods:
/** * Get the sum of all salaries of employees that are not manager in the current department * (including new employee rows that have not yet been committed to the database). * * @return the sum */ public Number getSumOfSalaries() { GroovySupport groovy = GroovySupport.get(getEmployeesInDepartment()); return groovy.sum("Salary", "!Job.JobTitle.contains('Manager')"); } /** * Get the first free EmployeeId starting at 100. * * @return the first free EmployeeId. */ public int getFirstFreeEmployeeId() { return GroovySupport.get(getEmployees()).firstFreeInteger("EmployeeId", 100); } /** * Get the estimated cost of commission to sales. * * @return the estimated cost */ public Number getCommissionEstimates() { GroovySupport groovy = GroovySupport.get(getEmployees()); return groovy.sum("CommissionPct * Salary", "CommissionPct && Salary && JobId.startsWith('SA')"); } /** * Limit the commission percentage of all employees to the given amount. * * @param limit the new limit */ public void setCommissionPctLimit(BigDecimal limit) { GroovySupport groovy = GroovySupport.get(getEmployees()); // Unfortunately setting values in Groovy is not simplified by the ADF BC API. Perhaps // we can extend this and simplify it? It would be nice to use expressions like: // CommissionPct = 0.10 // Perhaps I will look into it in the (distant?) future. String expr = "adf.object.setCommissionPct(new oracle.jbo.domain.Number("+limit+"))"; groovy.doForAllRows(expr, "CommissionPct && CommissionPct > "+limit); }
For more information look at the documentation in the GroovySupport code.
Download the GroovySupport class.