package fr.openwide.core.wicket.more.model;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import org.apache.wicket.Component;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IComponentAssignedModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.IWrapModel;
import org.apache.wicket.model.Model;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import fr.openwide.core.wicket.more.markup.html.factory.AbstractDetachableFactory;
import fr.openwide.core.wicket.more.markup.html.factory.IDetachableFactory;
import fr.openwide.core.wicket.more.util.model.Models;
public class ReadOnlyModel<F, T> extends AbstractReadOnlyModel<T> implements IComponentAssignedModel<T> {
private static final long serialVersionUID = -6272545665317639093L;
private final IModel<? extends F> readModel;
private final Function<? super F, ? extends T> function;
public static final <F, T> IDetachableFactory<IModel<F>, IModel<T>> factory(final Function<? super F, T> function) {
return new AbstractDetachableFactory<IModel<F>, IModel<T>>() {
private static final long serialVersionUID = 1L;
@Override
public IModel<T> create(IModel<F> parameter) {
return new ReadOnlyModel<F, T>(parameter, function);
}
@Override
public String toString() {
return ReadOnlyModel.class.getSimpleName() + ".factory(" + function + ")";
}
};
}
public static <T> ReadOnlyModel<T, T> of(IModel<? extends T> model) {
return new ReadOnlyModel<T, T>(model, Functions.<T>identity());
}
public static <T extends Serializable> ReadOnlyModel<T, T> of(T object) {
return new ReadOnlyModel<T, T>(Model.of(object), Functions.<T>identity());
}
public static <F, T> ReadOnlyModel<F, T> of(IModel<F> model, Function<? super F, ? extends T> function) {
return new ReadOnlyModel<F, T>(model, function);
}
public static <F extends Serializable, T> ReadOnlyModel<F, T> of(F object, Function<? super F, ? extends T> function) {
return new ReadOnlyModel<F, T>(Model.of(object), function);
}
protected ReadOnlyModel(IModel<? extends F> readModel, Function<? super F, ? extends T> function) {
super();
checkNotNull(readModel);
checkNotNull(function);
this.readModel = readModel;
this.function = function;
}
@Override
public T getObject() {
return function.apply(readModel.getObject());
}
@Override
public void detach() {
super.detach();
readModel.detach();
}
@Override
public IWrapModel<T> wrapOnAssignment(Component component) {
return new WrapModel(component);
}
private class WrapModel extends ReadOnlyModel<F, T> implements IWrapModel<T> {
private static final long serialVersionUID = 7996314523359141428L;
protected WrapModel(Component component) {
super(Models.wrap(readModel, component), function);
}
@Override
public IModel<?> getWrappedModel() {
return ReadOnlyModel.this;
}
}
}