package org.andork.q2;
import java.util.Map;
import org.andork.q2.QSpec.Property;
/**
* {@code QObject} (along with {@link QSpec}) provides the closest functionality
* to reflection on a POJO that is possible without actually using reflection.
* It also provides property {@linkplain #changeSupport() change support} that
* will notify listeners of any property changes, so that you don't have to
* write any boilerplate property change notification code.<br>
* <br>
* The Q doesn't stand for anything.
*
* @author andy.edwards
* @param <S>
* the type of {@link QSpec} for this object.
*/
public abstract class QMapObject<S extends QSpec> extends QObject<S> {
final Map<Property<?>, Object> values;
public QMapObject(S spec) {
super(spec);
values = createValuesMap();
for (Property<?> property : spec.propertyList) {
Object initValue = property.initValue().get();
if (initValue != null) {
values.put(property, initValue);
}
}
}
protected abstract Map<Property<?>, Object> createValuesMap();
@Override
@SuppressWarnings("unchecked")
public <T> T doGet(Property<T> property) {
return (T) values.get(property);
}
@Override
@SuppressWarnings("unchecked")
public <T> T doSet(Property<T> property, T newValue) {
T oldValue = newValue == null ? (T) values.remove(this) : (T) values.put(property, newValue);
if (!property.equals(oldValue, newValue)) {
fireObjectChanged(property, oldValue, newValue);
}
return oldValue;
}
}