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:
- I'm curious why you want to do this.
- A
ForwardingMap
seems fine for this. What's cumbersome about it? - 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.
精彩评论