# Groovy Syntax

## Operators

Groovy Operators

### Arithmetic Operators

Operator Purpose Examples
`+` Addition `2 + 2 = 4`
`-` Subtraction `2 - 2 = 0`, `4 - 2 = 2`
`*` Multiplication `2 * 2 = 4`, `4 * 2 = 8`, `10 * 0 = 0`
`/` Division `10 / 5 = 2`
`%` Modulo (remainder) `4 % 3 = 1`, `10 % 2 = 0`
`**` Power `2 ** 2 = 4`, `5 ** 2 = 25`,`2 ** 4 = 16`

### Relational Operators

Relational operators are used to compare two objects. In groovy the following operators are available. The result of an expression using a relational operator is either `TRUE` or `FALSE`.

Operator Purpose Examples
`==` Equals `1 + 2 == 3`, `TRUE`, `1 + 2 == 4`, `FALSE`
`!=` Different (does not equal) `1 + 3 != 4`, `FALSE`, `3 != 2.5`, `TRUE`, `“model” == “MODEL”`, `TRUE`
`>` Greater than `0 > 8`, `FALSE`, `0 > -2`, `TRUE`, `0 > 0`, `FALSE`
`>=` Greater than or equal to `0 >= 8`, `FALSE`, `0 >= -2`, `TRUE`, `0 >= 0`, `TRUE`
`<` Less than `0 < 8`, `TRUE`, `0 < -2`, `FALSE`, `0 < 0`, `FALSE`
`<=` Less than or equal to `0 <= 8`, `TRUE`, `0 <= -2`, `FALSE`, `0 <=`0, `TRUE`

### Logical Operators

Logical operators allow us to combine boolean expressions:

Operator Purpose Examples
`&&` and `true && true`, `TRUE`, `true && false`, `FALSE`, `(1 == 1) && (1 > 2)`, `FALSE`
`||` or `true || true`, `TRUE`, `true || false`, `FALSE`
`!` not `!true`, `FALSE`, `!false`, `TRUE`

## If/Else Statements

If/Else statements are used to perform different actions based on conditional statements.

### Basic if/else logic

As an example, let’s say we want to write an expression that when provided with an hour of the day (24 hour clock), returns to us whether the time is AM or PM.

One logical, plain language solution would be to say, if the hour provided is less than 12, return AM, if not, return PM. Let’s implement this in groovy.

``````if (hour < 12) {
“AM”
} else {
“PM”
}
``````

Here is what is going on. We start the if statement with `if`, followed by an expression in parenthesis. The expression in the parenthesis will be evaluated for truth. If the expression is `TRUE`, groovy will return the value in the curly braces. If it is `FALSE`, it will move on to the next statement.

We should go through the calculations a few times to make sure we know what is happening and our logic is sound.

Example Evaluation
`hour = 6` `6 < 12` is `TRUE`, the expression returns `AM`
`hour = 20` `20 < 12` is `FALSE`, the expression skips the first set of curly braces. It then evaluates the `else` statement, which is always `TRUE` and therefore returns `PM`.
`hour = 12` `12 < 12` is `FALSE`, the expression skips the first set of curly braces. It then evaluates the `else` statement, which is always `TRUE` and therefore returns `PM`. For more on operators, read here.
`hour = 26` `26 < 12` is `FALSE`, the expression skips the first set of curly braces. It then evaluates the `else` statement, which is always `TRUE` and therefore returns `PM`. But wait, this doesn’t make sense since there is no hour 26 in a day.
`hour = -5` `-5 < 12` is `TRUE`, the expression returns `AM`. Once again, this doesn’t make sense in the context of our problem because hours in the day cannot be negative.

### Expanding our if/else logic

As we witnessed in the example above, sometimes we need to expand our if/else statements in order to include more logic. One way to do this is to add an `else if` to our expression, in order to evaluate additional conditions. After considering the last two examples above, we can expand our pseudo code into, if the hour provided is not between 0 and 24, inclusive, return an error, otherwise, if the hour provided is less than 12, return AM, if not, return PM. Let’s implement this in groovy.

``````if (h < 0 || h > 24) {
"Error"
} else if (h < 12) {
"AM"
} else {
"PM"
}
``````

Once again, we can walk through the expression to make sure we know what is going on. First we evaluate `(h < 0)`, then `(h > 24)`. If either is `TRUE`, meaning `h` is outside our range of 0 - 24, our expression returns `Error`. If both are `FALSE`, groovy will move on and evaluated the next statement, just as we did in our example above.

For good measure, let’s run through our examples again.

Example Evaluation
`hour = 6` `6 < 0` is `FALSE`, `6 > 24` is `FALSE`, `6 < 12` is `TRUE`, the expression returns `AM`.
`hour = 20` `20 < 0` is `FALSE`, `20 > 24` is `FALSE`, `20 < 12` is `FALSE`, the expression skips the first set of curly braces. It then evaluates the `else` statement, which is always `TRUE` and therefore returns `PM`.
`hour = 12` `12 < 0` is `FALSE`, `12 > 24` is `FALSE`, `12 < 12` is `FALSE`, the expression skips the first set of curly braces. It then evaluates the `else` statement, which is always `TRUE` and therefore returns `PM`.
`hour = 26` `26 < 0` is `FALSE`, `26 > 24` is `TRUE`, the expression returns `Error`
`hour = -5` `-5 < 0` is `TRUE`, `-5 > 24` is `FALSE`, the expression returns `Error`

## Variables

Variables are containers for storing data values. They can store numbers, text, objects, or collections.

In Modelshop, it can be helpful and best practice to define a variable rather than call a function multiple times. Consider the following expression.

``````if (model.sampleDataList.findAll{it.exampleField > 1} == null) {
null
} else if (model.sampleDataList.findAll{it.exampleField > 1}.size == 1){
“We only have one!”
} else {
model.sampleDataList.findAll{it.exampleField > 1}.average{it.otherField}
}
``````

We make three identical `findAll` queries in this expression. First to check if the query is empty, second to see if its size is equal to 1 and finally, if the size of the collection is not null or size 1, we get the average of Other Field. This is more work for us and more work for the computer. Let’s use a variable to make this cleaner and easier.

``````def sampleQuery = model.sampleDataList.findAll{it.exampleField > 1}

if (sampleQuery == null) {
null
} else if (sampleQuery.size == 1){
“We only have one!”
} else {
sampleQuery.average{it.otherField}
}
``````

Much cleaner and neater. Additionally, if we now want to change our `findAll` query, we only have to edit one place, rather than three.

## Built-in Funtions

### Math (Beyond Arithmetic)

Modelshop has built-in functions to handle many mathematical operations beyond the arithmetic operators. These functions are organized within the Math module.

To get the absolute value:

``````Math.abs(sampleValue)
``````

To get the square route:

``````Math.sqrt(sampleValue)
``````

To get the natural logarithm:

``````Math.log(sampleValue)
``````

To get the log base 10:

``````Math.log10(sampleValue)
``````

### Dealing with Dates

Modelshop has the ability to efficiently and effectively deal with dates.

#### Today

``````Date.today()
``````

#### Date Details

Get the month:

``````sampleDate.getMonth()
``````

Get the day of the month:

``````sampleDate.getDay()
``````

Or the day of the week:

``````sampleDate.getDay()
``````

Get the year:

``````sampleDate.getYear()
``````

Get the week of the year:

``````sampleDate.getWeek()
``````

Or the week of the month:

``````sampleDate.getWeekOfMonth()
``````

``````sampleDate.getWeekOfMonth()
``````

Is it a US holiday?:

``````sampleDate.isHoliday("United States")
``````

``````sampleDate.isHoliday("Canada")
``````

#### Difference Between Dates

``````sampleDate.plusDays(1)
``````

Subtracting days:

``````sampleDate.plusDays(-5)
``````

``````sampleDate.plusBusinessDays(1)
``````

``````sampleDate.plusWeeks(1)
``````

``````sampleDate.plusMonths(1)
``````

``````sampleDate.plusYears(1)
``````

#### Difference Between Dates

In days:

``````sampleDate.ageDays(Date.today())
``````

In months:

``````sampleDate.ageMonths(Date.today())
``````

In years:

``````sampleDate.ageYears(Date.today())
``````

``````sampleDate.ageBusinessDays(Date.today())
``````

### Handling Text

Handling text can be a challenge in business intelligence and spreadsheet software. Modelshop allows more comprehensive control of text using a full programming language. Let’s go over a few of the important methods for handling text.

For these examples, let us use `sampleText = “The quick brown fox”`

#### Indexing

To access a specific letter in the text string use it’s index value:

``````sampleText[0] = T
``````
``````sampleText[1] = h
``````
``````sampleText[2] = e
``````

We can also index from the end of the text string:

``````sampleText[-1] = x
``````
``````sampleText[-2] = o
``````
``````sampleText[-3] = f
``````

Or get multiple indices:

``````sampleText[0,5,10] = Tub
``````

#### Slicing

We slice our text string using the indices as well.

``````sampleText[0..2] = The
``````
``````sampleText[4..12] = quick bro
``````

We can mix the positive and negative indices, too.

``````sampleText[0..-1] = The quick brown fox
``````

Since 0 is the index of the first letter and -1 is the index for the last, we get the entire text string.

#### Concatenation

We can also join strings together by simply using the `+` operator:

``````sampleText.split(" ")[1] + sampleText.split(" ")[0] = quickThe
``````
``````sampleText.split(" ")[1] + “ “ + sampleText.split(" ")[0] = quick The
``````

#### Text Functions

Modelshop also has several built in functions for handling text.

Slicing from the left:

``````Text.left(sampleText, 6) = The qu
``````

You may notice this is the same as:

``````sampleText[0..5]
``````

We can also split our text string:

``````sampleText.split(" ")[1] = quick
``````
``````sampleText.split(" ")[0] = The
``````

In this example, we are splitting the text where there is a space (“ ”). Then we can access each chunk by it’s index.

We can also get the length of a text string:

``````sampleText.length()
``````