package org.tessell.model.properties;
import java.util.Map;
import org.tessell.model.events.PropertyChangedHandler;
import org.tessell.model.validation.rules.Rule;
import org.tessell.model.values.Value;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.HasHandlers;
import com.google.gwt.user.client.ui.HasValue;
public interface Property<P> extends HasHandlers, HasRuleTriggers, Value<P>, HasValue<P> {
/** @return the current property value. */
P get();
/** Sets {@code value}, with marking touched, and firing events. */
void set(P value);
/** Sets {@code value}, conditionally sets touched, and firing events. */
void set(P value, boolean shouldTouch);
/** Sets {@code value} and fires events, without marking touched. */
void setInitialValue(P value);
/** Sets {@code value} whenever the property's value becomes {@code null}. */
void setDefaultValue(P value);
/** Sets {@code value} only if we're current null, without marking touched. */
void setIfNull(P value);
/**
* Re-examines the value to see if it's changed/invalid.
*
* This shouldn't need to be called directly unless there have been out-of-band
* changes (e.g. the underlying value changed without Tessell knowing about it).
*/
void reassess();
void addRule(Rule<? super P> rule);
/** @return whether the user has tried to set this property yet. */
boolean isTouched();
/** Sets whether this property has been touched by the user. */
void setTouched(boolean touched);
/** @return whether this property is required. */
boolean isRequired();
/** Sets whether this property is required. */
void setRequired(boolean required);
/** Fluent method for marking a property as touched. */
boolean touch();
/** @return whether this property is valid. */
boolean isValid();
/** @return whether this property is valid, as a property. */
Property<Boolean> valid();
/** @return whether this property is invalid *and* touched (useful for bindings), as a property. */
Property<Boolean> invalid();
/** @return whether this property has been touched, as a property. */
Property<Boolean> touched();
/** @return whether this property has been changed from it's initial value, as a property. */
Property<Boolean> changed();
/** Adds {@code downstream} as a derivative of us. */
<T extends Property<?>> T addDerived(T downstream);
/** Adds {@code downstream} as a derivative of us. */
<T extends Property<?>> T addDerived(T downstream, Object token, boolean touch);
/** Removes {@code downstream} as a derivative of us. */
<T extends Property<?>> T removeDerived(T downstream);
<T extends Property<?>> T removeDerived(T downstream, Object token);
/** Adds us as a derivative of {@code upstream} properties. */
Property<P> depends(Property<?>... upstream);
/** Adds {@code handler} to be called on property change. */
HandlerRegistration addPropertyChangedHandler(PropertyChangedHandler<P> handler);
/** Adds {@code handler} to be ran immediately and also on property change. */
HandlerRegistration nowAndOnChange(PropertyValueHandler<P> handler);
/** @return the humanized name of the property. */
String getName();
/** @return the value (non-humanized) name of the property. */
String getValueName();
/** @return a map of outstanding validation errors. */
Map<Object, String> getErrors();
/** @return a derived property that is formatted/parsed with {@code formatter}. */
<T1> FormattedProperty<T1, P> formatted(PropertyFormatter<P, T1> formatter);
/** @return a derived property that is formatted/parsed with {@code formatter}. */
<T1> FormattedProperty<T1, P> formatted(String invalidMessage, PropertyFormatter<P, T1> formatter);
/** @return a derived property that is converted with {@code converter}. */
<T1> Property<T1> as(PropertyConverter<P, T1> converter);
Property<String> asString();
/** @return a two-way property that is true/value when {@code this} equals {@code value}. */
Property<Boolean> is(P value);
/** @return a two-way property that is true/value when {@code this} equals {@code value}. */
Property<Boolean> is(P value, P whenUnsetValue);
/** @return a two-way property that is true/value when {@code this} equals {@code other}. */
Property<Boolean> is(Property<P> other);
/** @return a two-way property that is true/value when {@code this} equals {@code other}. */
Property<Boolean> is(Property<P> other, P whenUnsetValue);
/** @return a one-way property that is true when {@code this} passes {@code condition}. */
Property<Boolean> is(Condition<P> condition);
/** @return a derived property will be {@code value} if this property is {@code null}. */
Property<P> orIfNull(P value);
/** @return a read-only property that is true/false when {@code this} is set. */
Property<Boolean> isSet();
}