package nebula.data;
import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import nebula.data.impl.BrokerBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.google.common.base.Preconditions;
/**
* 生成代理Class,代理所有共用方法调用 暂时支持代理接口,以及包含有默认构造器的Class
*
* @author wanglocal
*
* @param <T>
*/
public abstract class Broker<T> implements BrokerHandler<T> {
static final private BrokerBuilder brokerBuilder = new BrokerBuilder();
static final private Log log = LogFactory.getLog(Broker.class);
static final public <T> BrokerHandler<T> broke(Class<T> clz, T value) {
if (log.isTraceEnabled()) {
log.trace("broke" + clz.getName() + " : " + String.valueOf(value));
}
BrokerHandler<T> b = brokerBuilder.builder(clz);
b.setNewValue(value);
return b;
}
@SuppressWarnings("unchecked")
static final public <T> BrokerHandler<T> brokerOf(T value) {
return (BrokerHandler<T>) value;
}
static final public void clear() {
brokerBuilder.clear();
}
final public static <T> T update(T value, T newvalue) {
if (!(value instanceof BrokerHandler)) throw new RuntimeException("Should be brokerhandle");
@SuppressWarnings("unchecked")
BrokerHandler<T> bt = (BrokerHandler<T>) value;
bt.setNewValue(newvalue);
return bt.get();
}
@SuppressWarnings("unchecked")
final public static <T> T valueOf(T value) {
return ((BrokerHandler<T>) value).getActualValue();
}
@SuppressWarnings("unchecked")
final public static <R, T> R watch(T watch, final DataAdapter<T, R> listener) {
if (watch instanceof Broker) {
Method m = listener.getClass().getMethods()[0];
Preconditions.checkArgument("watch".equals(m.getName()));
final BrokerHandler<R> r = brokerBuilder.builder(m.getReturnType());
Broker<T> watchTo = (Broker<T>) watch;
watchTo.addWatcher(new DataWatcher<T>() {
@Override
public boolean onUpdate(T newData, T oldData) {
R newValue = listener.watch(newData, oldData);
r.setNewValue(newValue);
return false;
}
});
return (R) r;
} else {
return listener.watch(watch, watch);
}
}
protected T actualValue;
protected List<DataWatcher<T>> listeners;
protected Broker() {
}
@Override
public abstract T get();
@Override
public T getActualValue() {
return this.actualValue;
}
public void addWatcher(DataWatcher<T> listener) {
listeners = _addWatcher(listeners, listener, actualValue);
}
@Override
public void setNewValue(T newValue) {
this.actualValue = newValue;
_notify(listeners, newValue, actualValue);
}
private <TT> void _notify(List<DataWatcher<TT>> listeners, TT newValue, TT oldValue) {
boolean hasLostReference = false;
if (listeners == null) return;
for (DataWatcher<TT> listener : listeners) {
if (listener != null) {
boolean result = listener.onUpdate(newValue, oldValue);
if (result) break;
} else {
hasLostReference = true;
}
}
if (hasLostReference) {
for (int i = listeners.size() - 1; i >= 0; i--) {
DataWatcher<TT> listener = listeners.get(i);
if (listener == null) {
listeners.remove(i);
}
}
}
}
private <TT> List<DataWatcher<TT>> _addWatcher(List<DataWatcher<TT>> listeners, DataWatcher<TT> listener, TT actualValue) {
if (listeners == null) {
listeners = new CopyOnWriteArrayList<DataWatcher<TT>>();
}
listeners.add(listener);
listener.onUpdate(actualValue, null);
return listeners;
}
}