/** * Copyright (C) 2011 * Michael Mosmann <michael@mosmann.de> * Jan Bernitt <unknown@email.de> * * with contributions from * nobody yet * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.flapdoodle.wicket.model; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.wicket.model.AbstractReadOnlyModel; import org.apache.wicket.model.IModel; import de.flapdoodle.functions.Function1; import de.flapdoodle.functions.Function2; import de.flapdoodle.functions.Function3; import de.flapdoodle.wicket.model.transformation.Functions; import de.flapdoodle.wicket.model.transformation.Lazy; import de.flapdoodle.wicket.model.transformation.ModelSet; /** * wicket model support functions */ public abstract class Models { private Models() { // no instance } /** * Creates a model based on a set of models and a function. * <ul> * <li>step 1: create a model set</li> * <li>step 2: provide a function</li> * </ul> * IModel<X> model=Models.on(source).apply(function); * * @param <T> model type * @param source source model * @return model set with one model */ public static <T> ModelSet.Set1<T> on(IModel<T> source) { return new ModelSet.Set1<T>(source); } /** * Creates a model based on a set of models and a function. * <ul> * <li>step 1: create a model set</li> * <li>step 2: provide a function</li> * </ul> * IModel<X> model=Models.on(first,second).apply(function); * * @param <T1> first model type * @param <T2> second model type * @param first first source model * @param second second source model * @return model set with two models */ public static <T1, T2> ModelSet.Set2<T1, T2> on(IModel<T1> first, IModel<T2> second) { return new ModelSet.Set2<T1, T2>(first, second); } /** * Creates a model based on a set of models and a function. * <ul> * <li>step 1: create a model set</li> * <li>step 2: provide a function</li> * </ul> * IModel<X> model=Models.on(first,second,third).apply(function); * * @param <T1> first model type * @param <T2> second model type * @param <T3> third model type * @param first first source model * @param second second source model * @param third second source model * @return model set with three models */ public static <T1, T2, T3> ModelSet.Set3<T1, T2, T3> on(IModel<T1> first, IModel<T2> second, IModel<T3> third) { return new ModelSet.Set3<T1, T2, T3>(first, second, third); } /** * Creates a model based on a function and a set of models. * <ul> * <li>step 1: provide a function</li> * <li>step 2: chose matching models</li> * </ul> * IModel<X> model=Models.apply(function).to(source); * * @param <R> resulting model type * @param <T> source model type * @param function transforming function * @return a function reference */ public static <R,T> Functions.Reference1<R,T> apply(Function1<R, T> function) { return new Functions.Reference1<R,T>(function); } /** * Creates a model based on a function and a set of models. * <ul> * <li>step 1: provide a function</li> * <li>step 2: chose matching models</li> * </ul> * IModel<X> model=Models.apply(function).to(first,second); * * @param <R> resulting model type * @param <T1> first source model type * @param <T2> second source model type * @param function transforming function * @return a function reference */ public static <R,T1,T2> Functions.Reference2<R,T1,T2> apply(Function2<R, T1, T2> function) { return new Functions.Reference2<R,T1,T2>(function); } /** * Creates a model based on a function and a set of models. * <ul> * <li>step 1: provide a function</li> * <li>step 2: chose matching models</li> * </ul> * IModel<X> model=Models.apply(function).to(first,second,third); * * @param <R> resulting model type * @param <T1> first source model type * @param <T2> second source model type * @param <T3> third source model type * @param function transforming function * @return a function reference */ public static <R,T1,T2,T3> Functions.Reference3<R,T1,T2,T3> apply(Function3<R, T1, T2, T3> function) { return new Functions.Reference3<R,T1,T2,T3>(function); } /** * Creates a model based on a function and a set of models. * <ul> * <li>step 1: provide a function</li> * <li>step 2: chose matching models</li> * </ul> * IModel<X> model=Models.applyLazy(function).to(source); * * @param <R> resulting model type * @param <T> source model type * @param function transforming function * @return a function reference */ public static <R,T> Functions.LazyReference1<R,T> applyLazy(Function1<R, ? super Lazy<? extends T>> function) { return new Functions.LazyReference1<R,T>(function); } /** * Creates a model based on a function and a set of models. * <ul> * <li>step 1: provide a function</li> * <li>step 2: chose matching models</li> * </ul> * IModel<X> model=Models.applyLazy(function).to(first,second); * * @param <R> resulting model type * @param <T1> first source model type * @param <T2> second source model type * @param function transforming function * @return a function reference */ public static <R,T1,T2> Functions.LazyReference2<R,T1,T2> applyLazy(Function2<R, ? super Lazy<? extends T1>, ? super Lazy<? extends T2>> function) { return new Functions.LazyReference2<R,T1,T2>(function); } /** * Creates a model based on a function and a set of models. * <ul> * <li>step 1: provide a function</li> * <li>step 2: chose matching models</li> * </ul> * IModel<X> model=Models.applyLazy(function).to(first,second,third); * * @param <R> resulting model type * @param <T1> first source model type * @param <T2> second source model type * @param <T3> third source model type * @param function transforming function * @return a function reference */ public static <R,T1,T2,T3> Functions.LazyReference3<R,T1,T2,T3> applyLazy(Function3<R, ? super Lazy<? extends T1>, ? super Lazy<? extends T2>, ? super Lazy<? extends T3>> function) { return new Functions.LazyReference3<R,T1,T2,T3>(function); } /** * creates a read only model from a list and make the model list unmodifiable on read access * @param <T> list type * @param source source model * @return resulting model */ public static <T> IModel<List<T>> unmodifiable(IModel<? extends List<? extends T>> source) { return Models.on(source).apply(new UnmodifiableIfNotNull<T>()); } /** * creates a read only model from a list, the list is unmodifiable * @param <T> list type * @param list * @return resulting model */ public static <T> IModel<List<T>> unmodifiable(final List<T> list) { return new AbstractReadOnlyDetachedModel<List<T>>() { @Override protected List<T> load() { return Collections.unmodifiableList(list); } }; } /** * creates a model which returns an empty list of source list is null * @param source source * @return resulting model */ public static <T> IModel<List<T>> emptyIfNull(IModel<List<T>> source) { return Models.on(source).apply(new EmptyListIfNull<T>()); } /** * creates a read only version of a model, setObject will throw an exception * @param source source * @return model of same type */ public static <T> IModel<T> readOnly(IModel<T> source) { return Models.on(source).apply(new Noop<T>()); } private static final class UnmodifiableIfNotNull<T> implements Function1<List<T>, List<? extends T>> { @Override public List<T> apply(List<? extends T> value) { return value!=null ? Collections.unmodifiableList(value) : null; } } private static final class EmptyListIfNull<T> implements Function1<List<T>, List<T>> { @Override public List<T> apply(List<T> value) { return value!=null ? value : new ArrayList<T>(); } } private static final class Noop<T> implements Function1<T, T> { public T apply(T value) { return value; } } }