Help with dsl rules group filtering

Hi, i cannot find if we have documented the “filter” part of this:
SomeGroup.members.“filter”.state

for example, i have found on the forums

gAllLights.allMembers.filter[i|i.groupNames.contains("gKitchenLights")||i.groupNames.contains("gLivingRoomLights")].forEach[s|s.sendCommand(OFF)

this line finds items that belong to a nested group called gKitchenLights.

now I would like to find members that do NOT contain “Entrance” in the name of the item (not a group), and if all of those filtered items are OFF, do something…

if
( gLivingRoomLights.members.filter[i | !i.name.contains("Entrance")].state == OFF )
do something

but this line does not work, i could not find documentation of various things you can put in there…I found people using …head.state but dunno what is it

This is Rules DSL and this is using basic Rules DSL syntax.

Any time you see [ something | some code] what you are seeing what’s called a “lambda” which is a function without a name. Stuff before the | are arguments passed in and stuff after is the code to run.

You can do anything inside a function that you can do outside a function. It’s just code. But it follows the same syntax and requirements as any code.

In Rules DSL a lambda comes in two types: procedures and functions. A procedure is a lambda that doesn’t return anything. A function has a return value. The last line executed in the function is what gets returned.

Some places where a lambda is used require a procedure (e.g. createTimer) and others require a function (e.g. anything that is used by a List).

This is basically nonsense no matter where you used code like this in Rules DSL.

filter takes a function and it expects that function to return a boolean (true or false). If the filter function returns false it excludes that element from the filter. In the end you’ll end up with a list containing only those elements that passed the filter function. It passes one argument to the function which is the current element of the List to check.

So, same as you would test for this in an if statement is what you’d do in a filter.

.filter [ i | !i.name.contains("Entrance") && i.state == OFF ]

Or you can do two filters:

.filter[ i | !i.name.contains("Entrance") ].filter[ i | i.state == OFF ]

head gets the first element of a List and .state is returning the state of what is presumably an Item.

See Design Pattern: Working with Groups in Rules

Pretty much all the other rules languages except Blockly do this better as the syntax is more standard. Rules DSL takes a bunch of shortcuts and uses weird conventions which serve to obscure rather than inform.

All of this is basic Xtend syntax and capabilities and have nothing to do with openHAB itself. Therefore what documentation there is is on the Xtend reference docs which are linked to from the OH docs.

thanks for clarifications.
will this statement

.filter[ i | !i.name.contains("Entrance") ].filter[ i | i.state == OFF ]

be true if ALL filtered items are OFF, or if he finds at least one with OFF state?
I’m aiming for all OFF…

It’s a filter. The result of the filter is a new List containing only those that meet the filter criteria (i.e. the function returned true). The result of the filter isn’t a boolean (true/false). It’s a List.

The result of this is a List containing all those Items that don’t have “Entrance” in the name and which are OFF. If you have ten Items that meet that, you’ll have a List with ten elements. If you have no Items that meet that, you’ll have an empty List.

If you want to find out if all the Items that do not have “Entrance” in the name are OFF, you need additional logic. For example:

.filter[ i | !i.name.contains("Entrance") ].filter[ i | i.state != OFF ].length > 0

That statement will be true if there is at least one Item without “Entrance” in the name which is not OFF. First it gets a list of all the Items without “Entrance” in the name. Then filters that to a list of those Items that are not OFF. Finally, if the list isn’t empty (i.e. length > 0) there is at least one Item without “Entrance” in the name whose state is not OFF.

Please review the post I linked to.

Note, it might be size, instead of length. I don’t do Rules DSL anymore and can’t remember which.