Differences between revisions 4 and 5

Deletions are marked like this. Additions are marked like this.
Line 197: Line 197:
||'''Sample Expression'''||`#f = :[ @@floor(#this.l / 2) == @@floor(#this.r / 2) ], #ENV.unique( { 0,1,2,3,4,5 } )`|| ||'''Sample Expression'''||`#f = :[ @@floor(#this.l / 2) == @@floor(#this.r / 2) ], #ENV.unique( { 0,1,2,3,4,5 }, #f )`||

Report Utility Functions

When defining the data set in a report, the columns are specified using OGNL expressions. While the OGNL language makes it very easy to navigate the graph of objects inside the Web-CAT data store, there are some other tasks, such as iteration, that require a non-trivial amount of work to write in OGNL alone. Therefore, we have provided a set of utility functions that can be called from within OGNL expressions to greatly simplify some common tasks.

These utility functions are provided as members of the global #ENV variable that is available to any OGNL expression in a report. To call one of these functions, simply use the standard notation: #ENV.functionName(arguments...).

Many of the utility functions take OGNL lambda expressions as arguments, to operate on the elements in a collection. To simplify the documentation below, these lambda expressions will be categorized as one of the types below:

  • UnaryOp: an expression that takes a single argument, denoted by #this. The return type and value are arbitrary.

  • BinaryOp: an expression that takes two arguments, denoted by #this.l and #this.r (that is, the left- and right-hand sides). The return type and value are arbitrary.

  • UnaryPredicate: an expression that takes a single argument, denoted by #this and has a Boolean return type.

  • BinaryPredicate: an expression that takes two arguments, denoted by #this.l and #this.r, and has a Boolean return type.

An important note: Due to the way OGNL parses expressions, a lambda expression cannot be included directly inside the function call; it must be stored in a variable first. In other words,

    #ENV.accumulate( {1,2,3}, :[ #this.l + #this.r ] )

will not work as expected. The above expression must be rewritten as follows:

    #f = :[ #this.l + #this.r ], #ENV.accumulate( {1,2,3}, #f )

Common OGNL Idioms

Many of the functions described below are modeled after the STL algorithms found in C++. Two common ones, fill and generate, are left out because they are already available through standard OGNL expressions.

To create a list containing n copies of a value, as fill would do, you can "project" across a number: (n).{ value }. For example, (5).{ 'test' } would return the list { 'test', 'test', 'test', 'test', 'test' }.

The generate algorithm can be written in the same way, by using an expression instead of a constant value in the projection. For example, to generate a list of five random numbers, one could use (5).{ @@random() }.

Available Functions

  • accumulate: compute the sum of the elements in a list
  • adjacentDifference: compute the adjacent differences of the elements in a list
  • countIf: count the number of elements in a list that satisfy a condition
  • forEach: evaluate an expression for each element in a list
  • innerProduct: compute the scalar inner product of two lists
  • joinLists: append two or more lists together
  • joinMaps: merge the keys and values of two or more maps
  • partialSum: compute the partial sums of the elements in a list
  • range: create a list containing the integers in a range
  • randomSample: randomly sample elements from a list
  • randomShuffle: randomly shuffle elements in a list
  • reverse: reverse the contents of a list
  • unique: remove consecutive duplicate items in a list

accumulate

Signature

Object accumulate( List list )

Description

Returns the sum of the elements in list. Addition is performed with an initial value of zero (or the empty string in the case of strings) using the OGNL + (plus) operator and the results will conform to any such type conversions that may take place.

Sample Expression

#ENV.accumulate( {1,2,3,4,5} )

Sample Result

15

Sample Expression

#ENV.accumulate( {'a','b','c','d','e'} )

Sample Result

'abcde'

Version

Requires Reporter x.y.z or higher.

Signature

Object accumulate( List list, Object initial, BinaryOp binOp )

Description

Returns the generalized sum of the elements in list. Addition is performed with an initial value of initial using the specified binOp expression; #this.l is the sum computed thus far, and #this.r is the next item in the list to be added.

Sample Expression

#f = :[ #this.l * #this.r ], #ENV.accumulate( {1,2,3,4,5}, 1, #f )

Sample Result

120

Version

Requires Reporter x.y.z or higher.

adjacentDifference

Signature

List adjacentDifference( List list )

Description

Returns a list containing the adjacent differences of the elements in list. In other words, the (i+1)st element in the result is the difference between the (i+1)st element and the ith element in list (and the 0th elements are the same). Subtraction is performed using the OGNL – (minus) operator and the results will conform to any such type conversions that may take place.

Sample Expression

#ENV.adjacentDifference( {1,2,8,10,20} )

Sample Result

{ 1,1,6,2,10 }

Version

Requires Reporter x.y.z or higher.

Signature

List adjacentDifference( List list, BinaryOp binOp )

Description

Returns a list containing the adjacent differences of the elements in list. In other words, the (i+1)st element in the result is the difference between the (i+1)st element and the ith element in list (and the 0th elements are the same). Subtraction is performed using the specified binOp expression; #this.l is the ith element in list and #this.r is the (i+1)st.

Sample Expression

#f = :[ #this.r / #this.l ], #ENV.partialSum( {1,2,8,64,256}, #f )

Sample Result

{ 1,2,4,8,4 }

Version

Requires Reporter x.y.z or higher.

countIf

Signature

int countIf( List list, UnaryPredicate predicate )

Description

Returns the number of elements in list that satisfy predicate; that is, for which predicate returns true.

Sample Expression

#f = :[ #this % 2 == 0 ], #ENV.countIf( {1,2,3,4,5}, #f )

Sample Result

2

Version

Requires Reporter x.y.z or higher.

forEach

Signature

void forEach( List list, UnaryOp operation )

Description

Iterates over the elements in list, evaluating the lambda expression operation on each element.

Sample Expression

#x = 0, #f = :[ #x = #x + #this ], #ENV.forEach( {1,2,3}, #f ), #x

Sample Result

6

Version

Requires Reporter x.y.z or higher.

innerProduct

Signature

Number innerProduct( List list1, List list2 )

Description

Returns the inner product of list1 and list2. Elements are pairwise-multiplied with the OGNL * (multiply) operator and these products are accumulated with the OGNL + (plus) operator, so the result will conform to any type conversions that may occur there. The lists should be the same length.

Sample Expression

#ENV.innerProduct( {1,2,3}, {5,2,-2} )

Sample Result

3

Version

Requires Reporter x.y.z or higher.

Signature

Number innerProduct( List list1, List list2, Number initial )

Description

Same as above, but uses initial as the initial value for the accumulation instead of zero.

Sample Expression

#ENV.innerProduct( {1,2,3}, {5,2,-2}, 5 )

Sample Result

8

Version

Requires Reporter x.y.z or higher.

Signature

Object innerProduct( List list1, List list2, Object initial, BinaryOp addOp, BinaryOp multOp )

Description

Returns the inner product of list1 and list2. Elements are pairwise-multiplied with multOp and these products are accumulated with addOp (with an initial value of initial for the accumulation).

Version

Requires Reporter x.y.z or higher.

joinLists

Signature

List joinLists( List list1, List list2 )

Description

Returns a new list containing the elements in list1 followed by the elements in list2.

Sample Expression

#l1 = { 1,2,3 }, #l2 = { 2,3,4 }, #ENV.joinLists(#l1, #l2)

Sample Result

{ 1,2,3,2,3,4 }

Version

Requires Reporter x.y.z or higher.

Signature

List joinLists( List<List> listOfLists )

Description

A generalized version that returns a new list containing the elements of each of the lists in listOfLists, in the order they are passed.

Sample Expression

#l1 = { 1,2 }, #l2 = #{ 3,4 }, #l3 = #{ 1,4 }, #ENV.joinLists( { #l1, #l2, #l3 } )

Sample Result

{ 1,2,3,4,1,4 }

Version

Requires Reporter x.y.z or higher.

joinMaps

Signature

Map joinMaps( Map map1, Map map2 )

Description

Returns a new map containing the keys and values of the two specified maps. In the event that a key exists in both map1 and map2, the value in map2 will be used.

Sample Expression

#m1 = #{ 'a': 1 }, #m2 = #{ 'b': 2 }, #ENV.joinMaps(#m1, #m2)

Sample Result

#{ 'a': 1, 'b': 2 }

Version

Requires Reporter x.y.z or higher.

Signature

Map joinMaps( List<Map> listOfMaps )

Description

A generalized version that returns a new map containing the keys and values from each map in the specified list of maps. In the event that a key exists in multiple maps, the values in the maps later in the list are used.

Sample Expression

#m1 = #{ 'a': 1 }, #m2 = #{ 'b': 2 }, #m3 = #{ 'c': 3 }, #ENV.joinMaps( { #m1, #m2, #m3 } )

Sample Result

#{ 'a': 1, 'b': 2, 'c': 3 }

Version

Requires Reporter x.y.z or higher.

partialSum

Signature

List partialSum( List list )

Description

Returns a list containing the partial sums of the elements in list. In other words, the ith element in the result is the sum of the 0th through ith elements in list. Addition is performed using the OGNL + (plus) operator and the results will conform to any such type conversions that may take place.

Sample Expression

#ENV.partialSum( {1,2,3,4,5} )

Sample Result

{ 1,3,6,10,15 }

Sample Expression

#ENV.partialSum( {'a','b','c','d','e'} )

Sample Result

{ 'a','ab','abc','abcd','abcde' }

Version

Requires Reporter x.y.z or higher.

Signature

List partialSum( List list, BinaryOp binOp )

Description

Returns a list containing the partial sums of the elements in list. In other words, the ith element in the result is the sum of the 0th through ith elements in list. Addition is performed using the specified binOp expression; #this.l is the sum computed thus far, and #this.r is the next item in the list to be added.

Sample Expression

#f = :[ #this.l * #this.r ], #ENV.partialSum( {1,2,3,4,5}, #f )

Sample Result

{ 1,2,6,24,120 }

Version

Requires Reporter x.y.z or higher.

range

Signature

List range( int start, int end )

Description

Returns a list containing the integers start through end, inclusive. end is assumed to be greater than or equal to start.

Sample Expression

#ENV.range(5,10)

Sample Result

{ 5,6,7,8,9,10 }

Version

Requires Reporter x.y.z or higher.

randomSample

Signature

List randomSample( List list, int sampleSize )

Description

Returns a list containing sampleSize elements randomly sampled from list.

Sample Expression

#ENV.randomSample( { 1,2,3,4,5,6 }, 3 )

Sample Result

{ 1,3,4 }

Version

Requires Reporter x.y.z or higher.

randomShuffle

Signature

List randomShuffle( List list )

Description

Returns a copy of list with the elements in randomly shuffled order.

Sample Expression

#ENV.reverse( { 1,2,3,4,5,6 } )

Sample Result

{ 4,1,6,3,2,5 }

Version

Requires Reporter x.y.z or higher.

reverse

Signature

List reverse( List list )

Description

Returns a copy of list with the elements in reverse order.

Sample Expression

#ENV.reverse( { 1,2,3,4,5,6 } )

Sample Result

{ 6,5,4,3,2,1 }

Version

Requires Reporter x.y.z or higher.

unique

Signature

List unique( List list )

Description

Returns a copy of list where consecutive equivalent elements have been removed. Elements are considered equivalent if they are equal according to the OGNL == (equality) operator, including any type conversions that may occur.

Sample Expression

#ENV.unique( { 1,1,2,2,2,3,2,4,5 } )

Sample Result

{ 1,2,3,2,4,5 }

Version

Requires Reporter x.y.z or higher.

Signature

List unique( List list, BinaryPredicate predicate )

Description

Returns a copy of list where consecutive equivalent elements have been removed. Elements are considered equivalent if predicate returns true.

Sample Expression

#f = :[ @@floor(#this.l / 2) == @@floor(#this.r / 2) ], #ENV.unique( { 0,1,2,3,4,5 }, #f )

Sample Result

{ 0,2,4 }

Version

Requires Reporter x.y.z or higher.