开发者

Easiest way to create a MutableGuiceKeyToInstanceMap?

I'd like to find or implement a MutableGuiceKeyToInstanceMap working just like com.google.common.collect.MutableClassToInstanceMap from Guava, but using com.google.inject.Key<T> from Guice in place of Class<T>.

I couldn't find it in Guice and I can't implement it the way MutableClassToInstanceMap was implemented because of its superclass ConstrainedMap being package-private. I can't use MapConstraint.constrainedMap either, since I would get no chance to add the methods getInstance and putInstance (and without them it's all quite pointless).

Making an own copy of the ConstrainedMap class开发者_StackOverflow中文版 would force me to copy quite a few additional classes, so this isn't the way to go. Making a helper Map via MapConstraint.constrainedMap and making MutableGuiceKeyToInstanceMap extends ForwardingMap which delegates everything to the helper could work, but it's still quite cumbersome. Any better idea?

Do you think proposing to make ConstrainedMap public is a good idea?


Some thoughts:

  1. I'm curious why you want to do this.
  2. A ForwardingMap seems fine for this. What's cumbersome about it?
  3. Making ConstrainedMap public would not be a good idea.


I don't see why you don't like the combination of ForwardingMap and MapConstraint.constrainedMap. The code is quite straightforward, and looks almost exactly like what you'd get if you were to extend ConstrainedMap directly:

import com.google.common.collect.ForwardingMap;
import com.google.common.collect.MapConstraint;
import com.google.common.collect.MapConstraints;
import com.google.inject.Key;
import org.apache.commons.lang.NotImplementedException;

import java.util.HashMap;
import java.util.Map;


public final class MutableGuiceKeyToInstanceMap<B>
        extends ForwardingMap<Key<? extends B>, B> {

    /**
     * Returns a new {@code MutableGuiceKeyToInstanceMap} instance backed by a {@link
     * java.util.HashMap} using the default initial capacity and load factor.
     */
    public static <B> MutableGuiceKeyToInstanceMap<B> create() {
        return new MutableGuiceKeyToInstanceMap<B>(new HashMap<Key<? extends B>, B>());
    }

    /**
     * Returns a new {@code MutableGuiceKeyToInstanceMap} instance backed by a given
     * empty {@code backingMap}. The caller surrenders control of the backing map,
     * and thus should not allow any direct references to it to remain accessible.
     */
    public static <B> MutableGuiceKeyToInstanceMap<B> create(Map<Key<? extends B>, B> backingMap) {
        return new MutableGuiceKeyToInstanceMap<B>(backingMap);
    }


    private final Map<Key<? extends B>, B> delegate;

    private MutableGuiceKeyToInstanceMap(Map<Key<? extends B>, B> delegate) {
        this.delegate = MapConstraints.constrainedMap(delegate, VALUE_MATCHES_GUICE_KEY);
    }

    @Override
    protected Map<Key<? extends B>, B> delegate() {
        return delegate;
    }

    private static final MapConstraint<Key<?>, Object> VALUE_MATCHES_GUICE_KEY = new MapConstraint<Key<?>, Object>() {
        @Override
        public void checkKeyValue(Key<?> key, Object value) {
            matchesGuiceKey(key, value);
        }
    };

    public <T extends B> T putInstance(Key<T> key, T value) {
        return matchesGuiceKey(key, put(key, value));
    }

    public <T extends B> T getInstance(Key<T> key) {
        return matchesGuiceKey(key, get(key));
    }

    private static <B, T extends B> T matchesGuiceKey(Key<T> key, B value) {
        throw new NotImplementedException("TODO");
    }

    private static final long serialVersionUID = 0;
}

The code is pretty similar to MutableClassToInstanceMap, and there is no need to extend ForwardingMap... Sure, you need to add a delegate() method and its accompanying field, but the rest is identical.

I left out the matchesGuiceKey() implementation as an exercise for the reader. Good luck! You might need it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜