public static <K extends Serializable, V, C extends Collection<V> & Serializable> void replaceValueInMultivaluedCache( Cache<K, C> cache, V oldValue, V newValue )
    {
        if ( newValue.equals( oldValue ) )
        {
            return;
        }

        // In some cache implementations, the entry-set is unmodifiable. To guard against potential
        // future changes of this implementation (that would make the implementation incompatible with
        // these cache implementations), the entry-set that's operated on in this implementation is
        // explicitly wrapped in an unmodifiable collection. That forces this implementation to be
        // compatible with the 'lowest common denominator'.
        final Set<Map.Entry<K, C>> entries = Collections.unmodifiableSet( cache.entrySet() );

        for ( final Map.Entry<K, C> entry : entries )
        {
            final K key = entry.getKey();

            final Lock lock = cache.getLock( key );
            lock.lock();
            try
            {
                final C elements = entry.getValue();

                // Replace all instances of the element from the entry value.
                boolean changed = false;
                while ( elements.remove( oldValue ) )
                {
                    elements.add( newValue );
                    changed = true;
                }

                if ( changed )
                {
                    // The cluster-based cache needs an explicit 'put' to cause the change to propagate.
                    cache.put( entry.getKey(), elements );
                }
            }
            finally
            {
                lock.unlock();
            }
        }
    }
Replaces an element in a cache that has collection-based values.

Every instance of the old value that is found in a collection-based value is removed, and for each such removal,
the new value is added to the cache. Note that no guarantees regarding collection order are given.

Cache entries for which the value-collection does contain the old value are left unchanged.

The implementation of this method is designed to be compatible with both clustered as well as non-clustered caches.

@param cache    The cache from which to remove the element (cannot be null).
@param oldValue The element to be replaced (can be null only if the value-Collection supports null values).
@param newValue The replacement element (can be null only if the value-Collection supports null values).
@param <K> the type of key contained by the cache
@param <V> the type of value contained by the cache
@param <C> the type of collection contained by the cache
xmppserver/src/main/java/org/jivesoftware/util/cache/CacheUtil.java