package fr.openwide.core.wicket.more.bindable.model; import java.util.Collection; import java.util.Map; import org.apache.wicket.model.IModel; import org.bindgen.BindingRoot; import com.google.common.base.Function; import com.google.common.base.Supplier; import fr.openwide.core.wicket.more.bindable.exception.NoSuchModelException; import fr.openwide.core.wicket.more.markup.repeater.collection.ICollectionModel; import fr.openwide.core.wicket.more.markup.repeater.map.IMapModel; /** * An {@link IModel} that also provides centralized access to its properties (referenced using * {@link BindingRoot Bindings}), which allows it to provide value caching capabilities. */ public interface IBindableModel<T> extends IModel<T> { /** * Returns a model bound to <code>binding</code>, with an internal cache, using the <code>workingCopyProposal</code>. * <p>If {@link #bindWithCache(BindingRoot, IModel)} has already been called, the exact same model will be returned. * <p>When {@link #readAll()} is called on this {@link IBindableModel}, {@link #readAll()} will automatically be called * on the returned model. * <p>When {@link #readAllUnder(BindingRoot)} is called on this {@link IBindableModel}, {@link #readAllUnder(BindingRoot)} will * automatically be called on the returned model. * <p>When {@link #writeAll()} is called on this {@link IBindableModel}, {@link #writeAll()} will automatically * be called on the returned model. */ <T2> IBindableModel<T2> bind(BindingRoot<? super T, T2> binding); /** * Returns a model bound to <code>binding</code>, with an internal cache, using the <code>workingCopyProposal</code>. * <p>If {@link #bindWithCache(BindingRoot, IModel)} or {@link #bind(BindingRoot)} has already been called for * the same property, the exact same model will be returned. * <p>When {@link #readAll()} is called on this {@link IBindableModel}, {@link #readAll()} will automatically be called * on the returned model. * <p>When {@link #readAllUnder(BindingRoot)} is called on this {@link IBindableModel}, {@link #readAllUnder(BindingRoot)} will * automatically be called on the returned model. * <p>When {@link #writeAll()} is called on this {@link IBindableModel}, {@link #writeAll()} will automatically * be called on the returned model. */ <T2> IBindableModel<T2> bindWithCache(BindingRoot<? super T, T2> binding, IModel<T2> workingCopyProposal); /** * Returns a {@link ICollectionModel} which caches the content of the collection, and whose items models are * instances of a specific type of {@link IModel}, chosen by the user, which allows the user to define how * to serialize items. * * <p>Optionally, item models may be instances of {@link IBindableModel}, which allows the * user to define what to cache on these models. */ <T2, C extends Collection<T2>> IBindableCollectionModel<T2, C> bindCollectionWithCache( BindingRoot<? super T, C> binding, Supplier<? extends C> newCollectionSupplier, Function<? super T2, ? extends IModel<T2>> itemModelFunction); /** * @return A previously created model collection tied to the given binding. * @throws NoSuchModelException If no collection model was added for the given binding. */ <T2, C extends Collection<T2>> IBindableCollectionModel<T2, C> bindCollectionAlreadyAdded(BindingRoot<? super T, C> binding); /** * Returns a {@link IMapModel} which caches the content of the map, and whose items models are * instances of a specific type of {@link IModel}, chosen by the user, which allows the user to define how * to serialize keys and values. * * <p>Optionally, key and/or value models may be instances of {@link IBindableModel}, which allows the * user to define what to cache on these models. */ <K, V, M extends Map<K, V>> IBindableMapModel<K, V, M> bindMapWithCache( BindingRoot<? super T, M> binding, Supplier<? extends M> newMapSupplier, Function<? super K, ? extends IModel<K>> keyModelFunction, Function<? super V, ? extends IModel<V>> valueModelFunction); /** * @return A previously created model collection tied to the given binding. * @throws NoSuchModelException If no collection model was added for the given binding. */ <K, V, M extends Map<K, V>> IBindableMapModel<K, V, M> bindMapAlreadyAdded(BindingRoot<? super T, M> binding); /** * If this model is cached, writes the cache to the reference model. */ void write(); /** * If this model is cached (i.e. if the underlying model is a WorkingCopyModel), writes the cache to the reference model. * <p>Also calls {@link #writeAll()} on all the models previously returned by {@link #bindWithCache(BindingRoot, IModel)}, * {@link #bindCollectionWithCache(BindingRoot, Supplier, Function)} or * {@link #bindMapWithCache(BindingRoot, Supplier, Function, Function)}. */ void writeAll(); /** * If this model is cached (i.e. if the underlying model is a WorkingCopyModel), reads from the reference model to the cache. * <p>Also calls {@link #readAll()} on all the models previously returned by {@link #bindWithCache(BindingRoot, IModel)}, * {@link #bindCollectionWithCache(BindingRoot, Supplier, Function)} or * {@link #bindMapWithCache(BindingRoot, Supplier, Function, Function)}. */ void readAll(); /** * <p>Calls {@link #readAll()} on all the models previously returned by {@link #bindWithCache(BindingRoot, IModel)}, * {@link #bindCollectionWithCache(BindingRoot, Supplier, Function)} or * {@link #bindMapWithCache(BindingRoot, Supplier, Function, Function)}. */ void readAllExceptMainModel(); /** * <p>Calls {@link #readAll()} on all the models previously returned by {@link #bindWithCache(BindingRoot, IModel)}, * {@link #bindCollectionWithCache(BindingRoot, Supplier, Function)} or * {@link #bindMapWithCache(BindingRoot, Supplier, Function, Function)}. */ <T2> void readAllUnder(BindingRoot<? super T, T2> binding); /** * Calls {@link IModel#setObject(Object)} on the given model with the current model object as a parameter, and keeps * a reference to the given model so that it will be returned by {@link #getInitialValueModel()}. * <p>This allows to keep the initial value of this model in a separate model so that it may be retrieved later. */ void setInitialValueModel(IModel<T> initialValueModel); /** * @return The model previously assigned with {@link #setInitialValueModel(IModel)}, or <code>null</code> if * there is none. */ IModel<T> getInitialValueModel(); }