@Override
    public void entryAdded(@Nonnull final K key, @Nullable final V value, @Nonnull final NodeID nodeID) {
        synchronized (mutex.intern(key)) {
            reverseCacheRepresentation.computeIfAbsent(nodeID, k -> new HashSet<>()).add(key);

            if (uniqueOwnerExpected && !DISABLE_OPTIMIZATION.getValue()) {
                // As the entry is now owned by the nodeID processed above, it can no longer be owned by any of the others.
                reverseCacheRepresentation.forEach((k, v) -> {
                    if (!k.equals(nodeID)) {
                        v.remove(key);
                    }
                });
            }
        }
    }
Cache entry listener implementation that maintains a reverse lookup map for the cache that is being observed, which
is used to identify what cluster node is the logical owner of a particular cache entry. This information is typically
useful in scenarios where a cluster node drops out of the cluster requiring the remaining nodes to have to inform
their connected entities of what resources have become unavailable.

This implementation can be used in scenarios where exactly one cluster node 'owns' data (eg: client connection), as
well as in scenarios where more than one cluster node 'owns' data (eg: component sessions). Instances can be
configured to expect a unique owner (through a boolean argument in the constructor). When operating in that mode, an
entry addition or update will cause entries for other nodes to be removed. This can be particularly helpful when
events arrive 'out of order' (which could lead to data inconsistencies).

This implementation assumes that the cluster node on which the cache entry change originates is an owner of the
corresponding entry.
xmppserver/src/main/java/org/jivesoftware/util/cache/ReverseLookupUpdatingCacheEntryListener.java