package org.openflexo.antar.binding;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.antar.binding.AbstractBinding.BindingEvaluationContext;
import org.openflexo.antar.binding.AbstractBinding.TargetObject;
import org.openflexo.logging.FlexoLogger;
import org.openflexo.toolbox.HasPropertyChangeSupport;
public class DependingObjects {
private static final Logger logger = FlexoLogger.getLogger(DependingObjects.class.getName());
public static interface HasDependencyBinding extends Observer, PropertyChangeListener {
public List<AbstractBinding> getDependencyBindings();
public List<TargetObject> getChainedBindings(AbstractBinding binding, TargetObject object);
}
private List<TargetObject> dependingObjects;
private HasDependencyBinding observerObject;
private boolean dependingObjectsAreComputed;
public DependingObjects(HasDependencyBinding observerObject) {
super();
this.observerObject = observerObject;
this.dependingObjects = new ArrayList<AbstractBinding.TargetObject>();
this.dependingObjectsAreComputed = false;
}
protected void addToDependingObjects(TargetObject object) {
dependingObjects.add(object);
}
public synchronized void refreshObserving(BindingEvaluationContext context/*, boolean debug*/) {
/*if (debug) {
logger.info("refreshObserving() for " + observerObject);
}*/
List<TargetObject> updatedDependingObjects = new ArrayList<AbstractBinding.TargetObject>();
for (AbstractBinding binding : observerObject.getDependencyBindings()) {
List<TargetObject> targetObjects = binding.getTargetObjects(context);
if (targetObjects != null) {
updatedDependingObjects.addAll(targetObjects);
if (targetObjects.size() > 0) {
List<TargetObject> chainedBindings = observerObject.getChainedBindings(binding,
targetObjects.get(targetObjects.size() - 1));
if (chainedBindings != null) {
updatedDependingObjects.addAll(chainedBindings);
}
}
}
}
Set<HasPropertyChangeSupport> set = new HashSet<HasPropertyChangeSupport>();
for (TargetObject o : updatedDependingObjects) {
if (o.target instanceof HasPropertyChangeSupport) {
set.add((HasPropertyChangeSupport) o.target);
}
}
for (HasPropertyChangeSupport hasPCSupport : set) {
if (hasPCSupport.getDeletedProperty() != null) {
updatedDependingObjects.add(new TargetObject(hasPCSupport, hasPCSupport.getDeletedProperty()));
}
}
List<TargetObject> newDependingObjects = new ArrayList<TargetObject>();
List<TargetObject> oldDependingObjects = new ArrayList<TargetObject>(dependingObjects);
for (TargetObject o : updatedDependingObjects) {
if (oldDependingObjects.contains(o)) {
oldDependingObjects.remove(o);
} else {
newDependingObjects.add(o);
}
}
for (TargetObject o : oldDependingObjects) {
dependingObjects.remove(o);
if (o.target instanceof HasPropertyChangeSupport) {
PropertyChangeSupport pcSupport = ((HasPropertyChangeSupport) o.target).getPropertyChangeSupport();
if (logger.isLoggable(Level.FINE)) {
logger.fine("Observer " + observerObject + " remove property change listener: " + o.target + " property:"
+ o.propertyName);
}
/*if (debug) {
logger.info("Observer " + observerObject + " remove property change listener: " + o.target + " property:"
+ o.propertyName);
}*/
pcSupport.removePropertyChangeListener(o.propertyName, observerObject);
} else if (o.target instanceof Observable) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Widget " + observerObject + " remove observable: " + o);
}
/*if (debug) {
logger.info("Widget " + observerObject + " remove observable: " + o);
}*/
((Observable) o.target).deleteObserver(observerObject);
}
}
for (TargetObject o : newDependingObjects) {
dependingObjects.add(o);
if (o.target instanceof HasPropertyChangeSupport) {
PropertyChangeSupport pcSupport = ((HasPropertyChangeSupport) o.target).getPropertyChangeSupport();
if (logger.isLoggable(Level.FINE)) {
logger.fine("Observer " + observerObject + " add property change listener: " + o.target + " property:" + o.propertyName);
}
/*if (debug) {
logger.info("Observer " + observerObject + " add property change listener: " + o.target + " property:" + o.propertyName);
}*/
pcSupport.addPropertyChangeListener(o.propertyName, observerObject);
} else if (o.target instanceof Observable) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Observer " + observerObject + " add observable: " + o);
}
/*if (debug) {
logger.info("Observer " + observerObject + " add observable: " + o + " for " + o.propertyName);
}*/
((Observable) o.target).addObserver(observerObject);
}
}
dependingObjectsAreComputed = true;
}
public synchronized void stopObserving() {
for (TargetObject o : dependingObjects) {
if (o.target instanceof HasPropertyChangeSupport) {
PropertyChangeSupport pcSupport = ((HasPropertyChangeSupport) o.target).getPropertyChangeSupport();
// logger.info("Widget "+getWidget()+" remove property change listener: "+o.target+" property:"+o.propertyName);
pcSupport.removePropertyChangeListener(o.propertyName, observerObject);
} else if (o.target instanceof Observable) {
// logger.info("Widget "+getWidget()+" remove observable: "+o);
((Observable) o.target).deleteObserver(observerObject);
}
}
dependingObjects.clear();
dependingObjectsAreComputed = false;
}
public boolean areDependingObjectsComputed() {
return dependingObjectsAreComputed;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("DependingObjects for " + observerObject + "\n");
for (TargetObject o : dependingObjects) {
sb.append("> " + o + "\n");
}
return sb.toString();
}
}