Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Proofreading

...

Table of Contents
maxLevel1

Ternary Operator ? x : y

This operator is used to simplify the following syntax:

Code Block
languagegroovy
titleCase 1: complicated Complicated syntax
if (product.label != null && product.label.length() > 0) {
	return product.label
} else {
	return 'N/A'
}

You can rewrite the above statement using the ternary operator:

Code Block
titleCase 2: simplified Simplified syntax
return (product.label != null && product.label.length() > 0) ? product.label : 'N/A'

And then simplify it even more since not-empty check in Groovy can be done like this:

Code Block
titleCase 3: simplified Simplified syntax
return product.label ? product.label : 'N/A'

Elvis Operator ?:

This operator is used to provide a default fallback value if certain variable is empty or null. If the expression in the middle of the ternary operator is identical to its first expression, you should simplify the return statement from the previous example above using ?: operator:

Code Block
languagegroovy
titleCase 1: preferred Preferred syntax
return product.label ?: 'N/A' // Elvis operator

This can be useful if you need, for example, to always return a date when target date is not set:

Code Block
languagegroovy
titleCase 2: common Common example - target date
date = api.targetDate() ?: new Date() // if target date is null, return the current date

...

Code Block
languagegroovy
titleCase 3: common Common example - input parameter adjustment
lookback = api.decimalUserEntry('Look-back period (default: 20)') ?: 20 // if the user doesn't specify the look-back period, it will default to 20

...

Info

In case you wonder why this is called Elvis operator: (smile)

?: →  rotate 90° right → → 

Safe Navigation Operator ?.

This operator provides a not-null check before accessing a value from object. Whenever you access object's attribute or method you should check for a non-null reference like this:

Code Block
languagegroovy
titleCase 1: functionally Functionally correct, but complicated syntax
if (date) {
	return date.format('yyyy-MM-dd')
} 
return null

...

Code Block
languagegroovy
titleCase 2: simplified Simplified syntax
return date ? date.format('yyyy-MM-dd') : null

...

Code Block
languagegroovy
titleCase 3: preffered Preffered syntax
return date?.format('yyyy-MM-dd')

...

Code Block
languagegroovy
titleCase 4: multiple Multiple occurences for safe navigation operator
return product?.attribute21?.toBigDecimal()

Spread Operator *

Imagine the following api.find with many filters:

Code Block
languagegroovy
titleCase 1: functionally Functionally correct, but complicated syntax
api.find('P', Filter.equal("attribute1", "P"), Filter.or(Filter.equal("attribute2", "Red"), Filter.equal("attribute2", "Green"), Filter.equal("attribute2", "Blue")),Filter.equal("attribute3", 123))

It works fine, but is it's very difficult to read right? Therefore a the following syntax is preferred:

Code Block
languagegroovy
titleCase 2: preferred Preferred syntax, easy to read
def filter = Filter.and(
	Filter.equal("attribute1", "P"),
	Filter.or(
		Filter.equal("attribute2", "Red"),
		Filter.equal("attribute2", "Green"),
		Filter.equal("attribute2", "Blue"),
	),
	Filter.equal("attribute3", 123),
)

api.find('P', filter)

It is now much easier to read what the filter is supposed to return and also distinguish the priorities between AND and OR, right?

Sometimes you may find the following syntax that has identical meaning:

Code Block
languagegroovy
titleCase 3: alternative Alternative syntax, easy to read
def filters = [
	Filter.equal("attribute1", "P"),
	Filter.or(
		Filter.equal("attribute2", "Red"),
		Filter.equal("attribute2", "Green"),
		Filter.equal("attribute2", "Blue"),
	),
	Filter.equal("attribute3", 123),
]

// notice the * char. This will unwrap each item of the collection and pass it to the method as a separate parameter
api.find('P', *filters)

...

Code Block
languagegroovy
titleCase 4: wrong Wrong syntax - missing *
api.find('P', filters)

Groovy compiler will throw a compilation error since no version of api.find() does accept accepts a collection as argument but only a variable number of Filter objects:

Code Block
languagegroovy
No signature of method: net.pricefx.formulaengine.scripting.SandboxAPI.find() is applicable for argument types: (java.lang.String, java.util.ArrayList) values: [P, [`attribute1` = "P", (`attribute2` = "Red" or `attribute2` = "Green" or `attribute2` = "Blue"), ...]]
Possible solutions: find(), find(java.lang.String, [Lcom.googlecode.genericdao.search.Filter;), find(java.lang.String, int, [Lcom.googlecode.genericdao.search.Filter;), find(groovy.lang.Closure), find(java.lang.String, int, java.lang.String, [Lcom.googlecode.genericdao.search.Filter;), uuid()

Spaceship Operator <=>

This operator delegates to the compareTo method of the left-side operand and passes it the right-side operand.  

...

It is best when mixed with a sort methodsort method.

Code Block
languagegroovy
def competitors = api.productExtension('Competition')
def sortedByName = competitors .sort { a, b -> return a.attribute1 <=> b.attribute1 } // assuming attribute1 is the name of the competitor

...