package nl.fontys.sofa.limo.view.node.property;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import org.openide.nodes.PropertySupport;
/**
* Stupid property used to be able to listen to changes in the property window.
*
* @author Dominik Kaisers {@literal <d.kaisers@student.fontys.nl>}
*/
public class StupidProperty<T> extends PropertySupport.Reflection<T> {
/**
* Property guard to prevent wrong input
*/
public interface PropertyGuard<T> {
boolean accept(T value);
}
/**
* Property Change Listeners for the property.
*/
private final ArrayList<PropertyChangeListener> listeners;
private PropertyGuard<T> guard;
/**
* Create new StupidProperty with reflection methods.
*
* @param instance Object containing value.
* @param valueType Type of value.
* @param getter Getter method.
* @param setter Setter method.
*/
public StupidProperty(Object instance, Class<T> valueType, Method getter, Method setter) {
super(instance, valueType, getter, setter);
listeners = new ArrayList<>();
}
/**
* Create new StupidProperty with method names.
*
* @param instance Object containing value.
* @param valueType Type of value.
* @param getter Getter name.
* @param setter Setter name.
* @throws NoSuchMethodException Thrown if getter or setter not found.
*/
public StupidProperty(Object instance, Class<T> valueType, String getter, String setter) throws NoSuchMethodException {
super(instance, valueType, getter, setter);
listeners = new ArrayList<>();
}
/**
* Create new StupidProperty with property name.
*
* @param instance Object containing value.
* @param valueType Type of value.
* @param property Property name (field in class).
* @throws NoSuchMethodException Thrownif getter or setter for property not
* found.
*/
public StupidProperty(Object instance, Class<T> valueType, String property) throws NoSuchMethodException {
super(instance, valueType, property);
listeners = new ArrayList<>();
}
/**
* Sets a property guard
*
* @param guard new property guard
*/
public void setPropertyGuard(PropertyGuard<T> guard) {
this.guard = guard;
}
/**
* Set the value of the property and notify listeners.
*
* @param val new value.
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
@Override
public void setValue(T val) throws IllegalAccessException, InvocationTargetException {
try {
if (guard == null || guard.accept(val)) {
T oldValue = getValue();
super.setValue(val);
firePropertyChange(oldValue, val);
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
throw ex;
}
}
/**
* Add listener.
*
* @param listener Listener.
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
if (listener != null) {
listeners.add(listener);
}
}
/**
* Remove listener.
*
* @param listener Listener.
*/
public void removePropertyChangeListener(PropertyChangeListener listener) {
listeners.remove(listener);
}
/**
* Notify listeners of property change.
*
* @param oldValue Old value.
* @param newValue New value.
*/
protected void firePropertyChange(T oldValue, T newValue) {
listeners.stream().forEach((listener) -> {
listener.propertyChange(new PropertyChangeEvent(this, getName(), oldValue, newValue));
});
}
}