package co.codewizards.cloudstore.core.bean;
import static co.codewizards.cloudstore.core.util.AssertUtil.*;
import static co.codewizards.cloudstore.core.util.ReflectionUtil.*;
import static co.codewizards.cloudstore.core.util.Util.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
public class BeanSupport<B, P extends PropertyBase> {
private final B bean;
private final PropertyChangeSupport propertyChangeSupport;
public BeanSupport(final B bean) {
this.bean = assertNotNull(bean, "bean");
propertyChangeSupport = new PropertyChangeSupport(bean);
}
public B getBean() {
return bean;
}
public void setPropertyValue(final P property, final Object value) {
assertNotNull(property, "property");
final Object old;
synchronized (getMutex()) {
old = getFieldValue(bean, property.name());
if (isEqual(property, old, value))
return;
setFieldValue(bean, property.name(), value);
}
// We *must* fire the event *outside* of the *synchronized* block to make sure the listeners
// do not run into a dead-lock!
firePropertyChange(property, old, value);
}
public <V> V getPropertyValue(P property) {
synchronized (getMutex()) {
return getFieldValue(bean, property.name());
}
}
protected Object getMutex() {
return bean;
}
protected boolean isEqual(final P property, final Object oldValue, final Object newValue) {
return equal(oldValue, newValue);
}
public void addPropertyChangeListener(final PropertyChangeListener listener) {
assertNotNull(listener, "listener");
propertyChangeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(final PropertyChangeListener listener) {
assertNotNull(listener, "listener");
propertyChangeSupport.removePropertyChangeListener(listener);
}
public void addPropertyChangeListener(final P property, final PropertyChangeListener listener) {
assertNotNull(property, "property");
assertNotNull(listener, "listener");
propertyChangeSupport.addPropertyChangeListener(property.name(), listener);
}
public void removePropertyChangeListener(final P property, final PropertyChangeListener listener) {
assertNotNull(property, "property");
assertNotNull(listener, "listener");
propertyChangeSupport.removePropertyChangeListener(property.name(), listener);
}
public void firePropertyChange(final P property, Object oldValue, Object newValue) {
assertNotNull(property, "property");
propertyChangeSupport.firePropertyChange(property.name(), oldValue, newValue);
}
}