package gueei.binding;
import gueei.binding.utility.WeakList;
import java.util.ArrayList;
import java.util.Collection;
public class Observable<T> implements IObservable<T> {
@Override
public String toString() {
if (!isNull())
return mValue.toString();
return "null";
}
private WeakList<Observer> observers = new WeakList<Observer>();
private T mValue;
private final Class<T> mType;
public Observable(Class<T> type){
mType = type;
}
public Observable(Class<T> type, T initValue){
this(type);
mValue = initValue;
}
/* (non-Javadoc)
* @see gueei.binding.IObservable#subscribe(gueei.binding.Observer)
*/
public void subscribe(Observer o){
observers.add(o);
}
/* (non-Javadoc)
* @see gueei.binding.IObservable#unsubscribe(gueei.binding.Observer)
*/
public void unsubscribe(Observer o){
observers.remove(o);
}
/* (non-Javadoc)
* @see gueei.binding.IObservable#notifyChanged(java.lang.Object)
*/
public final void notifyChanged(Object initiator){
ArrayList<Object> initiators = new ArrayList<Object>();
initiators.add(initiator);
this.notifyChanged(initiators);
}
/* (non-Javadoc)
* @see gueei.binding.IObservable#notifyChanged(java.util.AbstractCollection)
*/
public final void notifyChanged(Collection<Object> initiators){
initiators.add(this);
for(Object o: observers.toArray()){
if (initiators.contains(o)) continue;
((Observer)o).onPropertyChanged(this, initiators);
}
}
/* (non-Javadoc)
* @see gueei.binding.IObservable#notifyChanged()
*/
public final void notifyChanged(){
ArrayList<Object> initiators = new ArrayList<Object>();
notifyChanged(initiators);
}
/* (non-Javadoc)
* @see gueei.binding.IObservable#set(T, java.util.AbstractCollection)
*/
public final void set(T newValue, Collection<Object> initiators){
if (initiators.contains(this)) return;
doSetValue(newValue, initiators);
initiators.add(this);
notifyChanged(initiators);
}
// Intenral use only.
public void _setObject(Object newValue, Collection<Object> initiators){
try{
T value = this.getType().cast(newValue);
if (value==null) return;
this.set(value, initiators);
}catch(ClassCastException e){
BindingLog.warning("Observable._setObject",
String.format("Failed to assign value: '%s' to observable of type: '%s', type mismatch",
newValue, this.getType()));
return;
}
}
public final void set(T newValue){
doSetValue(newValue, new ArrayList<Object>());
notifyChanged(this);
}
protected void doSetValue(T newValue, Collection<Object> initiators){
mValue = newValue;
}
protected final void setWithoutNotify(T newValue){
mValue = newValue;
}
public T get(){
return mValue;
}
public final Class<T> getType() {
return mType;
}
public Observer[] getAllObservers() {
return observers.toItemArray(new Observer[0]);
}
@Override
public boolean isNull() {
return mValue==null;
}
}