package org.tessell.model.properties;
import java.util.Map;
import org.tessell.model.events.PropertyChangedEvent;
import org.tessell.model.events.PropertyChangedHandler;
import org.tessell.model.validation.events.RuleTriggeredHandler;
import org.tessell.model.validation.events.RuleUntriggeredHandler;
import org.tessell.model.validation.rules.Rule;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* Converts a source property from another type, using a {@link PropertyConverter}.
*
* Although technically a separate property instance, all validation rules/errors/etc.
* are deferred to our source property.
*
* @param <SP> the source property type
* @param <DP> the destination property type
*/
public class ConvertedProperty<DP, SP> extends AbstractAbstractProperty<DP> {
private final Property<SP> source;
private final PropertyConverter<SP, DP> converter;
public ConvertedProperty(final Property<SP> source, final PropertyConverter<SP, DP> converter) {
this.source = source;
this.converter = converter;
}
@Override
public String toString() {
return source.getValueName() + " " + get();
}
@Override
public DP get() {
SP value = source.get();
return (value == null) ? converter.nullValue() : converter.to(value);
}
@Override
public void set(DP value) {
throw new IllegalStateException(this + " is a derived value");
}
@Override
public void set(DP value, boolean shouldTouch) {
throw new IllegalStateException(this + " is a derived value");
}
@Override
public void setInitialValue(DP value) {
throw new IllegalStateException(this + " is a derived value");
}
@Override
public void setDefaultValue(DP value) {
throw new IllegalStateException(this + " is a derived value");
}
@Override
public DP getValue() {
return get();
}
@Override
public void setValue(DP value) {
throw new IllegalStateException(this + " is a derived value");
}
@Override
public void setValue(DP value, boolean fire) {
throw new IllegalStateException(this + " is a derived value");
}
@Override
public void setIfNull(DP value) {
throw new IllegalStateException(this + " is a derived value");
}
@Override
public HandlerRegistration addRuleTriggeredHandler(RuleTriggeredHandler handler) {
return source.addRuleTriggeredHandler(handler);
}
@Override
public HandlerRegistration addRuleUntriggeredHandler(RuleUntriggeredHandler handler) {
return source.addRuleUntriggeredHandler(handler);
}
@Override
public void reassess() {
source.reassess();
}
@Override
@SuppressWarnings("unchecked")
public void addRule(Rule<? super DP> rule) {
source.addRule((Rule<? super SP>) rule); // hm, doesn't look right
}
@Override
public boolean isTouched() {
return source.isTouched();
}
@Override
public void setTouched(boolean touched) {
source.setTouched(touched);
}
@Override
public boolean touch() {
return source.touch();
}
@Override
public boolean isValid() {
return source.isValid();
}
@Override
public Property<Boolean> valid() {
return source.valid();
}
@Override
public Property<Boolean> touched() {
return source.touched();
}
@Override
public Property<Boolean> changed() {
return source.changed();
}
@Override
public void fireEvent(GwtEvent<?> event) {
source.fireEvent(event);
}
@Override
public <T extends Property<?>> T addDerived(T downstream, Object token, boolean touch) {
return source.addDerived(downstream, token, touch);
}
@Override
public <T extends Property<?>> T removeDerived(T downstream, Object token) {
return source.removeDerived(downstream, token);
}
@Override
public Property<DP> depends(Property<?>... upstream) {
source.depends(upstream);
return this;
}
@Override
public HandlerRegistration addPropertyChangedHandler(final PropertyChangedHandler<DP> handler) {
return source.addPropertyChangedHandler(new PropertyChangedHandler<SP>() {
public void onPropertyChanged(PropertyChangedEvent<SP> event) {
DP oldValue = event.getOldValue() == null ? null : converter.to(event.getOldValue());
DP newValue = event.getNewValue() == null ? null : converter.to(event.getNewValue());
handler.onPropertyChanged(new PropertyChangedEvent<DP>(ConvertedProperty.this, oldValue, newValue));
}
});
}
@Override
public HandlerRegistration nowAndOnChange(final PropertyValueHandler<DP> handler) {
return source.nowAndOnChange(new PropertyValueHandler<SP>() {
public void onValue(SP value) {
DP newValue = value == null ? null : converter.to(value);
handler.onValue(newValue);
}
});
}
@Override
public HandlerRegistration addValueChangeHandler(final ValueChangeHandler<DP> handler) {
return source.addValueChangeHandler(new ValueChangeHandler<SP>() {
public void onValueChange(ValueChangeEvent<SP> event) {
DP newValue = event.getValue() == null ? null : converter.to(event.getValue());
// need an inner class because ValueChangedEvent's cstr is protected
handler.onValueChange(new ValueChangeEvent<DP>(newValue) {
});
}
});
}
@Override
public String getName() {
return source.getName();
}
@Override
public String getValueName() {
return source.getValueName();
}
@Override
public Map<Object, String> getErrors() {
return source.getErrors();
}
@Override
public boolean isReadOnly() {
return true;
}
@Override
public boolean isRequired() {
return source.isRequired();
}
@Override
public void setRequired(boolean required) {
source.setRequired(required);
}
}