### Initial FEEL String Expression Example
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/challenge/chapter-4.mdx
This is an initial setup for a FEEL string expression. It shows how to start concatenating the 'firstName' variable. Ensure 'firstName' and 'lastName' are defined in the FEEL context.
```feel
// concatenate the first and the last name
firstName
```
--------------------------------
### Install Project Dependencies
Source: https://github.com/camunda/feel-scala/blob/main/docs/README.md
Installs the necessary dependencies for the project using yarn.
```bash
yarn install
```
--------------------------------
### Start Local Development Server
Source: https://github.com/camunda/feel-scala/blob/main/docs/README.md
Starts a local development server that automatically refreshes the browser on code changes. This is useful for active development.
```bash
yarn start
```
--------------------------------
### Start Documentation Development Server
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
Use this command to build and serve the documentation with auto-reloading for development.
```bash
npm run start
```
--------------------------------
### Start the FEEL REPL
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/playground/repl.md
Launches the FEEL REPL environment using Ammonite and the feel-repl.sc script.
```shell
amm --predef feel-repl.sc
```
--------------------------------
### Install Ammonite on Linux
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/playground/repl.md
Installs Ammonite REPL on Linux systems using a shell script.
```shell
sudo sh -c '(echo "#!/usr/bin/env sh" && curl -L https://github.com/com-lihaoyi/Ammonite/releases/download/2.4.0/2.13-2.4.0) > /usr/local/bin/amm && chmod +x /usr/local/bin/amm' && amm
```
--------------------------------
### Install Ammonite on Mac
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/playground/repl.md
Installs Ammonite REPL on Mac systems using Homebrew.
```shell
brew install ammonite-repl
```
--------------------------------
### Greet Zee with FEEL
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/challenge/challenge.mdx
Use this interactive editor to evaluate a simple FEEL expression and greet Zee. This is the starting point of the challenge.
```feel
"Hello Zee"
```
--------------------------------
### Conventional Commit Example
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
An example of a commit message following the Conventional Commits format, including a type, scope, and description.
```git
feat: add random() function
* add new built-in function random()
* it returns a random number between 0.0 and 1.0
```
--------------------------------
### Python Syntax Highlighting
Source: https://github.com/camunda/feel-scala/blob/main/docs/cheat-sheets/markdown-cheat-sheet.md
Example of Python code block with syntax highlighting.
```python
s = "Python syntax highlighting"
print(s)
```
--------------------------------
### JavaScript Syntax Highlighting
Source: https://github.com/camunda/feel-scala/blob/main/docs/cheat-sheets/markdown-cheat-sheet.md
Example of JavaScript code block with syntax highlighting.
```javascript
var s = 'JavaScript syntax highlighting';
alert(s);
```
--------------------------------
### Scala: Configure FEEL Engine
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/developer-guide/bootstrapping.md
Configure the FEEL engine during instantiation, for example, to enable external functions.
```scala
new FeelEngine(configuration = Configuration(externalFunctionsEnabled = true))
```
--------------------------------
### Calculate Arrival Time with Modulo
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/challenge/chapter-3.mdx
Use the modulo function to calculate the arrival time on a 24-hour clock, considering the total hours and a starting hour. This is useful for scenarios where you need to determine the exact time of day an event will conclude.
```feel
// use a 24 hour clock
hours + startingHour
```
```feel
modulo((hours + startingHour), modulus)
```
--------------------------------
### Define and Use a React Component in MDX
Source: https://github.com/camunda/feel-scala/blob/main/docs/cheat-sheets/mdx-cheat-sheet.md
Define a React component using JSX syntax and then use it within your Markdown content. This example shows how to create a reusable component with props for styling.
```jsx
export const Highlight = ({children, color}) => ( {children} )
```
```mdx
Docusaurus green and Facebook blue are my favorite colors.
```
--------------------------------
### Implement New Built-in Function
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
Example of implementing a new built-in function 'reverse' in Scala, including parameter definition and invocation logic.
```scala
builtinFunction("reverse", List("value")) {
case List(ValString(value)) => ValString(value.reverse)
}
```
--------------------------------
### Calculate Time Elapsed with Temporal Math
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/challenge/chapter-5.mdx
Use temporal math to calculate the time elapsed since a starting date, considering a duration in hours. This is useful for tracking progress or time passed.
```feel
// use temporal math to calculate the remaining days
date(startingDate) + duration("PT200H")
```
--------------------------------
### Filter List and Get First Element
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/samples/list-samples.md
Retrieves the first element from a list that matches a specific criterion. Ensure the data structure and attribute names match the expression.
```js
(data.attribute.packaging[unit = "Palette"])[1]
```
--------------------------------
### Implement Custom Value Mapper in Java
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/developer-guide/value-mapper-spi.md
Subclass `JavaCustomValueMapper` for Java-based custom value mapping. Override `toValue` and `unpackValue` to handle transformations. The `priority` method determines the mapper's precedence. This example maps `Custom` to `ValString` and `ValNumber` to `Double`.
```java
public class CustomJavaValueMapper extends JavaCustomValueMapper {
@Override
public Optional toValue(Object x, Function innerValueMapper) {
if (x instanceof Custom) {
final Custom c = (Custom) x;
return Optional.of(new ValString(c.getName()));
} else {
return Optional.empty();
}
}
@Override
public Optional unpackValue(Val value, Function innerValueMapper) {
if (value instanceof ValNumber) {
final ValNumber number = (ValNumber) value;
return Optional.of(number.value().doubleValue()); // map BigDecimal to Double
} else {
return Optional.empty();
}
}
@Override
public int priority() {
return 1;
}
}
```
--------------------------------
### Calculate Remaining Days Until Event
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/challenge/chapter-5.mdx
Calculate the number of days remaining until a target date by subtracting the elapsed time from the total duration between the start and target dates. This is useful for event planning and countdowns.
```feel
(date(targetDate) - date(startingDate) - duration("PT200H")) / duration("P1D")
```
--------------------------------
### Implement Custom Value Mapper in Scala
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/developer-guide/value-mapper-spi.md
Subclass `CustomValueMapper` to transform objects to FEEL `Val` types and vice-versa. Set the `priority` to define precedence. This example maps a `Custom` object to a `ValString` and a `ValNumber` to a `Double`.
```scala
class MyValueMapper extends CustomValueMapper {
override def toVal(x: Any, innerValueMapper: Any => Val): Option[Val] = x match {
case c: Custom => Some(ValString(c.getName))
case _ => None
}
override def unpackVal(value: Val, innerValueMapper: Val => Any): Option[Any] = value match {
case ValNumber(number) => Some(number.doubleValue) // map BigDecimal to Double
case _ => None
}
override val priority: Int = 1
}
```
--------------------------------
### Build JAR Files with Maven
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
Build the project's JAR files using Maven.
```bash
mvn install
```
--------------------------------
### Deploy Website to GitHub Pages
Source: https://github.com/camunda/feel-scala/blob/main/docs/README.md
Builds the website and pushes the output to the 'gh-pages' branch, specifically for deployment on GitHub Pages. Ensure you replace '' with your actual username.
```bash
GIT_USER= USE_SSH=true yarn deploy
```
--------------------------------
### Java: Configure FEEL Engine
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/developer-guide/bootstrapping.md
Configure the FEEL engine using the builder pattern, for instance, to enable external functions.
```java
new FeelEngine.Builder().enableExternalFunctions(true).build()
```
--------------------------------
### Java: Evaluate FEEL Expressions
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/developer-guide/bootstrapping.md
Use the FeelEngine builder to create an instance and evaluate FEEL expressions with a given context. Handles results or failures.
```java
public class MyProgram {
public static void main(String[] args) {
final FeelEngine engine = new FeelEngine.Builder()
.valueMapper(SpiServiceLoader.loadValueMapper())
.functionProvider(SpiServiceLoader.loadFunctionProvider())
.build();
final Map variables = Map.of("x", 21);
final Either result = engine.evalExpression(expression, variables);
if (result.isRight()) {
final Object value = result.right().get();
System.out.println("result is " + value);
} else {
final FeelEngine.Failure failure = result.left().get();
throw new RuntimeException(failure.message());
}
}
}
```
--------------------------------
### Run Tests with Maven
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
Execute all project tests using Maven.
```bash
mvn test
```
--------------------------------
### Build Static Website Content
Source: https://github.com/camunda/feel-scala/blob/main/docs/README.md
Generates the static content for the website, typically placed in the 'build' directory. This output can be hosted on any static content hosting service.
```bash
yarn build
```
--------------------------------
### Evaluate FEEL Expressions
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/playground/repl.md
Demonstrates evaluating FEEL expressions using the 'feel' function in the REPL, with and without context.
```scala
feel("1 + 3")
// evaluate an expression without any context
```
```scala
val context = Map("x" -> 3)
feel("1 + x", context)
// evaluate an expression with a map-based context
```
```scala
feel("1 + x", "{ \"x\": 3}")
// evaluate an expression with a JSON context
```
```scala
feel("\"date(\"2020-04-06\") + duration(\"P3D\")\"")
// evaluate an expression ignoring any quotes in the expression
```
--------------------------------
### Scala: Evaluate FEEL Expressions
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/developer-guide/bootstrapping.md
Instantiate the FeelEngine and use its API to evaluate FEEL expressions or unary tests with a given context.
```scala
object MyProgram {
val engine = new FeelEngine
def feel(expression: String, context: Map[String, Any]) {
val result: Either[Failure, Boolean] = engine.evalUnaryTests(expression, context)
// or
val result: Either[Failure, Any] = engine.evalExpression(expression, context)
// handle result
result
.right.map(value => println(s"result is: $value"))
.left.map(failure => println(s"failure: $failure"))
}
}
```
--------------------------------
### Live FEEL Challenge: Select Route
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/challenge/chapter-6.mdx
Use FEEL list operators to select the correct route from a list of options based on the destination. The initial context provides a list of routes, each with a list of stops.
```feel
routes
```
--------------------------------
### Add FEEL Engine Dependency
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/developer-guide/bootstrapping.md
Include the FEEL engine as a dependency in your project's pom.xml file.
```xml
org.camunda.feel
feel-engine
${VERSION}
```
--------------------------------
### FEEL Grammar: Intervals
Source: https://github.com/camunda/feel-scala/blob/main/src/main/scala/org/camunda/feel/impl/parser/feel-grammar.md
Defines the syntax for creating intervals, including open and closed start/end points, used for range comparisons.
```peg
interval = ( openIntervalStart / closedIntervalStart ) endpoint ".." endpoint ( openIntervalEnd / closedIntervalEnd )
```
```peg
openIntervalStart = "(" / "]"
```
```peg
closedIntervalStart = "["
```
```peg
openIntervalEnd = ")" / "["
```
```peg
closedIntervalEnd = "]"
```
--------------------------------
### Implement a Custom FEEL Engine Clock
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/developer-guide/feel-engine-clock-spi.md
Sub-class `FeelEngineClock` and override `getCurrentTime()` to return a custom `ZonedDateTime`. This is useful when your application uses a non-system clock.
```scala
class MyClock extends FeelEngineClock {
override def getCurrentTime(): ZonedDateTime = {
val currentMillis = ...
Instant.ofEpochMilli(currentMillis).atZone(ZoneId.systemDefault())
}
}
```
--------------------------------
### JavaScript with Line Highlighting
Source: https://github.com/camunda/feel-scala/blob/main/docs/cheat-sheets/markdown-cheat-sheet.md
Demonstrates line highlighting within a JavaScript code block using a special syntax.
```js
function highlightMe() {
console.log('This line can be highlighted!');
}
```
--------------------------------
### FEEL Grammar: Boxed Expressions (Lists, Functions, Contexts)
Source: https://github.com/camunda/feel-scala/blob/main/src/main/scala/org/camunda/feel/impl/parser/feel-grammar.md
Defines the syntax for boxed expressions, including lists, function definitions, and contexts (key-value pairs).
```peg
boxedExpression = list / functionDefinition / context
```
```peg
list = "[" ( expression ( "," expression )* )? "]"
```
```peg
functionDefinition = "function" "(" ( formalParameter ( "," formalParameter )* )? ")" ( "external" )? expression
```
```peg
formalParameter = parameterName
```
```peg
context = "{"
( contextEntry ( "," contextEntry )* )?
"}"
```
```peg
contextEntry = key ":" expression
```
```peg
key = name / stringLiteral
```
--------------------------------
### Scala: Use FEEL as Script Engine
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/developer-guide/bootstrapping.md
Integrate the FEEL engine with Java's Script Engine API (JSR 223) by obtaining a FeelScriptEngine instance.
```scala
object MyProgram {
val scriptEngineManager = new ScriptEngineManager
def feel(script: String, context: ScriptContext) {
val scriptEngine: FeelScriptEngine = scriptEngineManager.getEngineByName("feel")
val result: Object = scriptEngine.eval(script, context)
// ...
}
}
```
--------------------------------
### Structure Calculation with Context Expressions
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/samples/context-samples.md
Employ context expressions to structure complex calculations, such as finding the minimum age from a list of birthdays. Define helper functions within the context.
```js
{
age: function(birthday) (today() - birthday).years,
ages: for birthday in birthdays return age(birthday),
minAge: min(ages)
}.minAge
```
--------------------------------
### FEEL Grammar: Type Checking and Path Expressions
Source: https://github.com/camunda/feel-scala/blob/main/src/main/scala/org/camunda/feel/impl/parser/feel-grammar.md
Defines syntax for checking if an expression is an instance of a specific type and for navigating through nested structures using path expressions.
```peg
instanceOf = expression7 "instance" "of" type
```
```peg
type = qualifiedName
```
```peg
pathExpression = expression8 ( "." name )* ( "[" expression "]" )
```
--------------------------------
### Register Custom Clock via ServiceLoader
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/developer-guide/feel-engine-clock-spi.md
To register a custom clock using the Java ServiceLoader, create a file named `org.camunda.feel.FeelEngineClock` in the `META-INF/services/` directory. This file should contain the fully qualified name of your custom clock class.
```properties
org.camunda.feel.example.MyClock
```
--------------------------------
### FEEL Grammar: Logical and Comparison Operators
Source: https://github.com/camunda/feel-scala/blob/main/src/main/scala/org/camunda/feel/impl/parser/feel-grammar.md
Defines the grammar for logical operators (or, and) and various comparison operators including equality, inequality, range, and membership.
```peg
disjunction = expression3 ( "or" expression3 )*
```
```peg
conjunction = expression4 ( "and" expression )*
```
```peg
comparison = ( expression5 ( "=" / "!=" / "<" / "<=" / ">" / ">=" ) expression5 ) /
( expression5 "between" expression "and" expression ) /
( expression5 "in" "(" positiveUnaryTests ")" ) /
( expression5 "in" positiveUnaryTest )
```
--------------------------------
### Register Custom Function Providers
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/developer-guide/function-provider-spi.md
Register custom function providers by listing their fully qualified names in `META-INF/services/org.camunda.feel.context.CustomFunctionProvider` for loading via Java ServiceLoader.
```properties
org.camunda.feel.example.context.CustomScalaFunctionProvider
org.camunda.feel.example.context.CustomJavaFunctionProvider
```
--------------------------------
### Evaluate Unary Tests
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/playground/repl.md
Shows how to evaluate FEEL unary tests with different input types and contexts using the 'unaryTests' function.
```scala
unaryTests("> 3", 5)
// evaluate a unary-tests with a given input value
```
```scala
val context = Map("x" -> 3)
unaryTests("> x", 5, context)
// evaluate a unary-tests with a given input value and map-based context
```
```scala
unaryTests("> x", "5", "{ \"x\": 3}")
// evaluate a unary-tests with a given JSON input value and JSON context
```
--------------------------------
### FEEL Grammar: Literals and Values
Source: https://github.com/camunda/feel-scala/blob/main/src/main/scala/org/camunda/feel/impl/parser/feel-grammar.md
Defines various types of literals and simple values, including null, booleans, dates/times, strings, and numbers.
```peg
literal = "null" / simpleLiteral
```
```peg
simpleLiteral = booleanLiteral / dateTimeLiteral / stringLiteral / numericLiteral
```
```peg
booleanLiteral = "true" / "false"
```
```peg
dateTimeLiteral = ( "date" / "time" / "date and time" / "duration" ) "(" stringLiteral ")"
```
```peg
stringLiteral = '"' ( !('"' / verticalSpace) character )* '"'
```
```peg
numericLiteral = ( "-" )? ( ( digits ( "." digits )? ) / ( "." digits ) )
```
```peg
digits = digit ( digit )*
digit = [0-9]
```
```peg
simpleValue = simpleLiteral / qualifiedName
```
--------------------------------
### FEEL Grammar: Control Flow Expressions
Source: https://github.com/camunda/feel-scala/blob/main/src/main/scala/org/camunda/feel/impl/parser/feel-grammar.md
Defines FEEL syntax for control flow structures like for loops, if-then-else statements, and quantified expressions (some/every).
```peg
forExpression = "for" name "in" expression ( "," name "in" expression )* "return" expression
```
```peg
ifExpression = "if" expression "then" expression "else" expression
```
```peg
quantifiedExpression = ("some" / "every") (name "in" expression)+ "satisfies" expression
```
--------------------------------
### FEEL Grammar: Function Calls and Filtering
Source: https://github.com/camunda/feel-scala/blob/main/src/main/scala/org/camunda/feel/impl/parser/feel-grammar.md
Defines the grammar for invoking functions with named or positional parameters and for filtering collections using bracket notation.
```peg
filterExpression = expression9 "[" expression "]"
```
```peg
functionInvocation = expression9 parameters
```
```peg
parameters = "(" namedParameters / positionalParameters ")"
```
```peg
namedParameters = parameterName ":" expression ( "," parameterName ":" expression )*
```
```peg
parameterName = name
```
```peg
positionalParameters = ( expression ( "," expression )* )?
```
--------------------------------
### FEEL Grammar: Names and Qualifiers
Source: https://github.com/camunda/feel-scala/blob/main/src/main/scala/org/camunda/feel/impl/parser/feel-grammar.md
Defines the structure for names, qualified names, and additional symbols allowed in names, used for variables, functions, and types.
```peg
qualifiedName = name ( "." name )*
```
```peg
name = nameStart ( namePart / additionalNameSymbols )*
```
```peg
nameStart = nameStartChar ( namePartChar )*
```
```peg
namePart = ( namePartChar )+
```
```peg
nameStartChar = "?" / [A-Z] / "_" / [a-z] / [\uC0-\uD6] / [\uD8-\uF6] / [\uF8-\u2FF] / [\u370-\u37D] / [\u37F-\u1FFF] /
[\u200C-\u200D] / [\u2070-\u218F] / [\u2C00-\u2FEF] / [\u3001-\uD7FF] / [\uF900-\uFDCF] / [\uFDF0-\uFFFD] /
[\u10000-\uEFFFF]
```
```peg
namePartChar = nameStartChar / digit / [\uB7] / [\u0300-\u036F] / [\u203F-\u2040]
```
```peg
additionalNameSymbols = "." / "/" / "-" / "’" / "+" / "*"
```
--------------------------------
### Create Unix Timestamp
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/samples/temporal-samples.md
Return the current point in time as a Unix timestamp in milliseconds.
```js
(now() - date and time("1970-01-01T00:00Z")) / duration("PT1S") * 1000
```
```js
1618200039000
```
--------------------------------
### Test Built-in Function - Basic
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
A basic test case for the 'reverse' built-in function, asserting that it returns a string in reverse order.
```scala
"A reverse() function" should "return a string in reverse order" in {
reverse("adnumac") should be (ValString("camunda"))
}
```
--------------------------------
### Calculate Duration to Next Tuesday 08:00
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/samples/temporal-samples.md
Return the duration between now and the next Tuesday at 08:00.
```js
(for x in 1..7
return date and time(today(),time("08:00:00Z"))
+ duration("P"+string(x)+"D")
)[day of week(item) = "Tuesday"][1] - now()
```
--------------------------------
### Implement Custom Scala Function Provider
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/developer-guide/function-provider-spi.md
Extend `CustomFunctionProvider` and implement `getFunction` or `getFunctions` to define custom functions. The `ValFunction` includes parameter definitions and the invocation logic.
```scala
class CustomScalaFunctionProvider extends CustomFunctionProvider {
def getFunction(name: String): Option[ValFunction] = functions.get(name)
def functionNames: Iterable[String] = functions.keys
val functions: Map[String, ValFunction] = Map(
"incr" -> ValFunction(
params = List("x"),
invoke = { case List(ValNumber(x)) => ValNumber(x + 1) }
)
)
}
```
--------------------------------
### Format List of Dates
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/samples/temporal-samples.md
Transform a given list of date-time values into a custom 'day-Month-year' format.
```js
for d in dates return {
date: date(date and time(d)),
day: string(date.day),
month: substring(month of year(date), 1, 3),
year: string(date.year),
formatted: day + "-" + month + "-" + year
}.formatted
```
```js
["21-Apr-2021","22-Apr-2021"]
```
--------------------------------
### FEEL Grammar: Arithmetic Expressions
Source: https://github.com/camunda/feel-scala/blob/main/src/main/scala/org/camunda/feel/impl/parser/feel-grammar.md
Defines the structure for arithmetic operations, including addition/subtraction, multiplication/division, and exponentiation, with support for unary negation.
```peg
simpleExpressions = simpleExpression ( "," simple expression )*
simpleExpression = arithmeticExpression / simpleValue
```
```peg
arithmeticExpression = arithmeticExpression2 ( "+" arithmeticExpression2 / "-" arithmeticExpression2 )*
```
```peg
arithmeticExpression2 = arithmeticExpression3 ( "*" arithmeticExpression3 / "/" arithmeticExpression3 )*
```
```peg
arithmeticExpression3 = arithmeticExpression4 ( "**" arithmeticExpression4 )*
```
```peg
arithmeticExpression4 = ("-")? expression6
```
--------------------------------
### Evaluate FEEL Expression
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/playground/playground.mdx
Use this snippet to evaluate a FEEL expression with a given context. The expression '3 + x' will be evaluated with 'x' set to 5.
```javascript
3 + x
```
--------------------------------
### Compare Date with Offset
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/samples/temporal-samples.md
Check if a date is at least 6 months before another date.
```js
date1 < date2 + duration("P6M")
```
--------------------------------
### FEEL Grammar: Core Expressions
Source: https://github.com/camunda/feel-scala/blob/main/src/main/scala/org/camunda/feel/impl/parser/feel-grammar.md
Defines the basic structure of FEEL expressions, including textual and boxed expressions, and their recursive breakdown into more specific types.
```peg
expression = textualExpression
expression10 = boxedExpression
```
```peg
textualExpressions = textualExpression ( "," textualExpression )*
```
```peg
textualExpression = functionDefinition / forExpression / ifExpression / quantifiedExpression / expression2
```
```peg
expression2 = disjunction
```
```peg
expression3 = conjunction
```
```peg
expression4 = comparison / expression5
```
```peg
expression5 = arithmeticExpression
```
```peg
expression6 = instanceOf / expression7
```
```peg
expression7 = pathExpression
```
```peg
expression8 = filterExpression / functionInvocation / expression9
```
```peg
expression9 = literal / name / simplePositiveUnaryTest / ( "(" textualExpression ")" ) / expression10
```
--------------------------------
### Implement Custom Java Function Provider
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/developer-guide/function-provider-spi.md
Extend `JavaFunctionProvider` to define custom functions in Java. Use `JavaFunction` for function definition, specifying parameters and the invocation logic.
```java
public class CustomJavaFunctionProvider extends JavaFunctionProvider
{
private static final Map functions = new HashMap<>();
static {
final JavaFunction function = new JavaFunction(Arrays.asList("x"), args -> {
final ValNumber arg = (ValNumber) args.get(0);
int x = arg.value().intValue();
return new ValNumber(BigDecimal.valueOf(x - 1));
});
functions.put("decr", function);
}
@Override
public Optional resolveFunction(String functionName)
{
return Optional.ofNullable(functions.get(functionName));
}
@Override
public Collection getFunctionNames() {
return functions.keySet();
}
}
```
--------------------------------
### Register Value Mapper via ServiceLoader
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/developer-guide/value-mapper-spi.md
To register a custom value mapper using the Java ServiceLoader mechanism, create a file named `org.camunda.feel.valuemapper.CustomValueMapper` within the `META-INF/services/` directory. This file should contain the fully qualified name of your custom value mapper class.
```properties
org.camunda.feel.example.valuemapper.MyValueMapper
```
--------------------------------
### Calculate Duration to Next Specific Time in Timezone
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/samples/temporal-samples.md
Return the duration between now and the next time it is 09:00 in the Europe/Berlin timezone.
```js
{
time: time("09:00:00@Europe/Berlin"),
date: if (time(now()) < time) then today() else today() + duration("P1D"),
duration: date and time(date, time) - now()
}.duration
```
--------------------------------
### Evaluate FEEL Unary Tests
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/playground/playground.mdx
Use this snippet to evaluate FEEL unary tests against an input value and context. The test '< x' will be evaluated with input '3' and 'x' set to 5.
```javascript
< x
```
--------------------------------
### Calculate Total Trip Time with Rest
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/challenge/chapter-1.mdx
Use this snippet to calculate the total time for a trip, incorporating rest periods. It requires variables for distance, speed, rest duration, and rest interval.
```FEEL
// change formula considering resting time plus total time
round up(distance / speed, 0)
```
```FEEL
round up(restInHrs * (distance / speed) / restInterval + distance / speed, 0)
```
--------------------------------
### Calculate Next Weekday at Midnight
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/samples/temporal-samples.md
Return the next day that is not a weekend, occurring at midnight.
```js
(for x in 1..3
return date and time(today(),time("00:00:00Z"))
+ duration("P"+string(x)+"D")
)[not(day of week(item) in ("Saturday","Sunday"))][1]
```
--------------------------------
### FEEL Grammar: Unary Tests
Source: https://github.com/camunda/feel-scala/blob/main/src/main/scala/org/camunda/feel/impl/parser/feel-grammar.md
Defines the structure for unary tests, including negation and positive unary tests, which are used in comparisons and filtering.
```peg
unaryTests = "-" / ( "not" "(" positiveUnaryTests ")" ) / positiveUnaryTests
```
```peg
positiveUnaryTests = positiveUnaryTest ( "," positiveUnaryTest )*
```
```peg
positiveUnaryTest = "null" / simplePositiveUnaryTest
```
```peg
simpleUnaryTests = "-" / ( "not" "(" simplePositiveUnaryTests ")" ) / simplePositiveUnaryTests
```
```peg
simplePositiveUnaryTests = simplePositiveUnaryTest ( "," simplePositiveUnaryTest )*
```
```peg
simplePositiveUnaryTest = ( ( "<" / "<=" / ">" / ">=" )? endpoint ) / interval
```
```peg
endpoint = simpleValue
```
--------------------------------
### Exponentiation for Repeated Multiplication
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/challenge/chapter-2.mdx
Use exponentiation to represent repeated multiplications, such as calculating the number of heads on Lerna's Hydra after a certain number of cuts. This is useful for simplifying expressions involving powers.
```feel
// use exponentiation to represent the multiplications
2*2*2*2*2
```
```feel
base ** exponent
```
--------------------------------
### Concatenate First and Last Name in FEEL
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/challenge/chapter-4.mdx
Use this expression to combine the 'firstName' and 'lastName' variables with a space in between. This is useful for generating full names from separate components.
```feel
firstName + " " + lastName
```
--------------------------------
### Test Built-in Function - Error Handling
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
Test case to verify error handling for the 'reverse' function when the argument is not a string, expecting a specific failure report.
```scala
reverse(value = 123) should (reportFailure(FUNCTION_INVOCATION_FAILURE, "Failed to invoke function 'reverse': argument 'value' is of type 'number' but expected 'string'"))
```
--------------------------------
### Add Nullish Coalescing Operator Parsing
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
Extend the FEEL parser in `FeelParser.scala` to recognize and parse the nullish coalescing operator (`??`). This involves defining a new parser rule and integrating it into the existing expression grammar.
```scala
private def nullishCoalesching[_: P](value: Exp): P[Exp] = ???
P("??" ~ expLvl4)
.map { NullishCoalescing(value, _) }
```
```scala
| nullishCoalesching(value)
```
--------------------------------
### Test Built-in Function - Null Argument
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
Test case for the 'reverse' function when the argument is null, expecting a null result.
```scala
reverse(value = null) should be (ValNull)
```
--------------------------------
### Calculate Age from Birthday
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/samples/temporal-samples.md
Return the current age of a person based on a given birthday.
```js
years and months duration(date(birthday), today()).years
```
--------------------------------
### Test Built-in Function - Named Arguments
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
Test case for invoking the 'reverse' function using named arguments.
```scala
reverse(value = "adnumac") should be (ValString("camunda"))
```
--------------------------------
### Group List by Person
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/samples/list-samples.md
Groups a list of invoices by the 'person' attribute. This is useful for aggregating data based on a common key. The input must be a JSON object containing an 'invoices' array.
```js
for p in distinct values(invoices.person) return invoices[person = p]
```
```json
{"invoices":[
{"id":1, "person":"A", "amount": 10},
{"id":2, "person":"A", "amount": 20},
{"id":3, "person":"A", "amount": 30},
{"id":4, "person":"A", "amount": 40},
{"id":5, "person":"B", "amount": 15},
{"id":6, "person":"B", "amount": 25}
]}
```
```json
[
[
{"id":1, "person":"A", "amount": 10},
{"id":2, "person":"A", "amount": 20},
{"id":3, "person":"A", "amount": 30},
{"id":4, "person":"A", "amount": 40}
],
[
{"id":5, "person":"B", "amount": 15},
{"id":6, "person":"B", "amount": 25}
]
]
```
--------------------------------
### FEEL Solution: Find Berlin Route
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/challenge/chapter-6.mdx
This FEEL expression filters the routes to find the one that includes 'Berlin' in its stops and then selects the 'route' property of the matching route. It assumes 'Berlin' is a unique destination among the routes.
```feel
routes["Berlin" in stops][1].route
```
--------------------------------
### Define NullishCoalescing Expression Type
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
Add a new case class `NullishCoalescing` to `Exp.scala` to represent the nullish coalescing operator in the FEEL abstract syntax tree (AST).
```scala
case class NullishCoalescing(value: Exp, alternative: Exp) extends Exp
```
--------------------------------
### Validate Data with Context Expressions
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/samples/context-samples.md
Use context expressions to define validation rules and aggregate violations. This snippet checks journal entries against specific criteria.
```js
{
check1: {
error: "Document Type invalid for current year posting",
violations: collection[documentType = "S2" and glDate > startFiscalYear]
},
check2: {
error: "Document Type invalid for current year posting",
violations: collection[ledgerType = "GP" and foreignAmount != null]
},
result: ([check1, check2])[count(violations) > 0]
}
```
--------------------------------
### Adjust List Access in FEEL Evaluation
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
Modify the list access behavior in `FeelInterpreter.scala` to use zero-based indexing. This change affects how elements are retrieved from lists within FEEL expressions.
```scala
private def filterList(list: List[Val], index: Number)
```
--------------------------------
### Plain Text Code Block
Source: https://github.com/camunda/feel-scala/blob/main/docs/cheat-sheets/markdown-cheat-sheet.md
A code block without specified language, useful for plain text or mixed content.
```plaintext
No language indicated, so no syntax highlighting.
But let's throw in a tag .
```
--------------------------------
### Add Test Case for Nullish Coalescing Operator
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
Write new test cases in `InterpreterBooleanExpressionTest.scala` to verify the correct behavior of the nullish coalescing operator. Ensure tests cover scenarios where the value is null and not null.
```scala
"A nullish coalescing operator" should "return the value if the given value is not null" in { ??? }
```
```scala
it should "return the alternative if the given value is null" in { ??? }
```
--------------------------------
### Implement Nullish Coalescing Operator Evaluation
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
Handle the evaluation of the nullish coalescing operator in `FeelInterpreter.scala`. This involves adding a new case to the `eval` method to correctly return either the original value or the alternative.
```scala
case NullishCoalescing(value, alternative) => ???
// Implement the behavior and return eval(value) or eval(alternative)
```
--------------------------------
### Test Built-in Function - Error Result
Source: https://github.com/camunda/feel-scala/blob/main/CONTRIBUTING.md
Test case to verify that the 'reverse' function correctly reports an error when an internal error occurs during invocation.
```scala
reverse(value = "error") should (reportFailure(FUNCTION_INVOCATION_FAILURE, "Failed to invoke function 'reverse': something went wrong"))
```
--------------------------------
### Check if Current Day is Weekend
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/samples/temporal-samples.md
Check if the current day is on a weekend (Saturday or Sunday).
```js
day of week(today()) in ("Saturday","Sunday")
```
--------------------------------
### Merge Two Lists by ID
Source: https://github.com/camunda/feel-scala/blob/main/docs/versioned_docs/version-1.21/learn/samples/list-samples.md
Merges two lists of objects, each containing an 'id' field. It combines elements with the same 'id', prioritizing values from the second list ('y') in case of conflicts. The input must be a JSON object with 'x' and 'y' properties, each containing a 'files' array.
```js
{
ids: union(x.files.id,y.files.id),
getById: function (files,fileId)
if (count(files[id=fileId]) > 0)
then files[id=fileId][1]
else {},
merge: for id in ids return put all(getById(x.files, id), getById(y.files, id))
}.merge
```
```json
{
"x": {"files": [
{"id":1, "content":"a"},
{"id":2, "content":"b"}
]},
"y": {"files": [
{"id":1, "content":"a2"},
{"id":3, "content":"c"}
]}
}
```
```json
[
{"id":1, "content":"a2"},
{"id":2, "content":"b"},
{"id":3, "content":"c"}
]
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.