Using GroupItems as the key in a Hash Map

I’ve been debugging a rule off and on for a long time. What happens is when my flakey RasPi in the garage goes offline I’m sent a notification. I put a flag into a global Map<GroupItem, Boolean> so when the machine comes back I want to send another notification saying as such if this flag is set.

If I use a SwitchItem as the key this works like a charm. When I use a GroupItem as the key it doesn’t work. I get “null” when I try to pull the flag out of the map even when I know for certain that GroupItem is a key in that map.

If I use the name of the group and a Map<String, Boolean> it works like a charm (my current workaround).

Could this point to .equals not working on GroupItem? It looks like it uses the GenericItem’s implementation of equals which does a check on the state as the last check. If a new GroupItem is created every time the rule is executed then in my use case below equals will always return false because the group’s state is now different than it was when I added the flag to the key.

If my analysis is correct, should I post a bug report or just leave using the name as an acceptable work around until OH2 comes out and we see if it is fixed then and if not then file the report? I’d hate to make busy work on code that is about to become deprecated. Clearly it isn’t a problem others have encountered.

Here is a simplified version of the code. NOTE: I also have a Map<GroupItem, Timer> below, but the code works even if that Map doesn’t work, which is why I haven’t see this behavior until now.

Below fails as written but if I use gr.name as the key it works as expected.

val Map<GroupItem, Timer> timers = newHashMap
val Map<GroupItem, Boolean> notified = newHashMap

val Functions$Function3 procChange = [ GroupItem gr, Map<GroupItem, Timer> timers, Map<GroupItem, Boolean> notified |
    if(gr.state == OFF) {
        if(timers.get(gr) == null || timers.get(gr).hasTerminated) {
            timers.put(gr, createTimer(now.plusMinutes(1), [|
                if(gr.state == OFF) {
                    Notification_Proxy.postUpdate("The " + gr.name + " controller is still offline after one minute")
                    notified.put(gr, true)
                }
                timers.put(gr, null)
            ])
        }
    }
    else { // Now ON
        if(timers.get(gr) != null) {
            timers.get(gr).cancel
            timers.put(gr, null)
        }

        if(notified.get(gr)) {
            Notification_Proxy.postUpdate(gr.name + " is back online")
            notified.put(gr, false)
        }
    }
]

I would not hold onto Item objects in a Map or any other way, because items can be reloaded if the files change, and you would be holding onto not-the-item. If you instead used names and

val Map<String, Timer> timers = newHashMap
val Map<String, Boolean> notified = newHashMap

with their item names, would that work the same?

That is the work around that I’m using. And in this case I was using the GroupItem (and SwitchItem in other rules which do work as keys in maps) as the key so it isn’t like I’m trying to post updates or commands to a stale Item.

I’ve been toying with the idea of a gotchas type page in the wiki with a list of the common problem and subtle problems (e.g., adding openhab user to dialout group, rrd4j every minute strategy, etc) and how to fix them. Not using an Item as a key in a Map would fit this category.