package xapi.collect.impl;
import xapi.util.X_Runtime;
import xapi.util.api.ConvertsValue;
import xapi.util.api.MergesValues;
import xapi.util.api.Pair;
import xapi.util.impl.PairBuilder;
public class AbstractMultiInitMap <Key, Value, Params>
extends InitMapDefault<Pair<Key, Params>,Value>
implements MergesValues<Key, Params, Value>
{
private transient volatile Params params;
private boolean clearState;
protected static <Key, Value> ConvertsValue<Pair<Key, Value>, String> adapt(final ConvertsValue<Key, String> keyConverter) {
return new ConvertsValue<Pair<Key,Value>,String>() {
@Override
public String convert(Pair<Key,Value> from) {
return keyConverter.convert(from.get0());
}
};
}
@SuppressWarnings("unchecked") //ALWAYS_NULL is erased to object; anything is safe
public AbstractMultiInitMap(ConvertsValue<Key, String> keyConverter) {
super(AbstractMultiInitMap.<Key, Params>adapt(keyConverter), ALWAYS_NULL);
clearState = true;
}
public AbstractMultiInitMap(ConvertsValue<Key, String> keyConverter, ConvertsValue<Pair<Key,Params>,Value> valueConverter) {
super(AbstractMultiInitMap.<Key, Params>adapt(keyConverter), valueConverter);
clearState = true;
}
public static <Params, Value> AbstractMultiInitMap<String, Value, Params>
stringMultiInitMap(final ConvertsValue<Params, Value> converter) {
return new AbstractMultiInitMap<String, Value, Params>(PASS_THRU,
new ConvertsValue<Pair<String, Params>, Value>() {
@Override
public Value convert(Pair<String, Params> from) {
return converter.convert(from.get1());
}
});
}
public Value get(Key key, Params params) {
if (X_Runtime.isMultithreaded()) {
synchronized (getLock(key)) {
return doGet(key, params);
}
}else {
return doGet(key, params);
}
}
private Value doGet(Key key, Params params) {
this.params = params;
try {
return super.get(PairBuilder.<Key, Params>pairOf(key, params));
}finally {
if (isClearState())
this.params = null;
}
}
protected boolean isClearState() {
return clearState;
}
public void setClearState(boolean clearImmediately) {
this.clearState = clearImmediately;
}
@Override
public final Value initialize(Pair<Key, Params> params) {
Value value = null;
try {
value = valueProvider.convert(params);
} catch (Throwable e) {
logInitError(params, e);
}
if (value == null)
value = initialize(params.get0(), params.get1() == null ? defaultParams() : params.get1());
return value;
}
protected void logInitError(Pair<Key,Params> params, Throwable e) {
// Can't use X_Log, as this class is used for run-once semantics in our injectors.
System.err.println("Init error in "+getClass().getName()+" for "+params);
if (X_Runtime.isDebug()) {
while (e != null) {
e.printStackTrace();
e = e.getCause();
}
}
}
protected Params defaultParams() {
return params;
}
protected Value initialize(Key key, Params params) {
return null;
}
@Override
public Value merge(Key key1, Params key2) {
return get(key1, key2);
}
}