package fr.openwide.core.wicket.more.model;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collection;
import java.util.Iterator;
import org.apache.wicket.Component;
import org.apache.wicket.model.IComponentAssignedModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.IWrapModel;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterators;
import fr.openwide.core.wicket.more.markup.repeater.collection.IItemModelAwareCollectionModel;
import fr.openwide.core.wicket.more.util.model.Models;
public class ReadOnlyCollectionModel<T, C extends Collection<T>>
implements IItemModelAwareCollectionModel<T, C, IModel<T>>, IComponentAssignedModel<C> {
private static final long serialVersionUID = -6272545665317639093L;
private final IModel<? extends C> readModel;
private final Function<? super T, ? extends IModel<T>> itemModelFactory;
public static <T, C extends Collection<T>> ReadOnlyCollectionModel<T, C> of(
IModel<? extends C> model, Function<? super T, ? extends IModel<T>> keyFactory) {
return new ReadOnlyCollectionModel<T, C>(model, keyFactory);
}
protected ReadOnlyCollectionModel(IModel<? extends C> readModel, Function<? super T, ? extends IModel<T>> keyFactory) {
super();
this.readModel = checkNotNull(readModel);
this.itemModelFactory = checkNotNull(keyFactory);
}
@Override
public C getObject() {
return readModel.getObject();
}
@Override
public void setObject(C object) {
throw newReadOnlyException();
}
private UnsupportedOperationException newReadOnlyException() {
return new UnsupportedOperationException("Model " + getClass() + " is read-only");
}
@Override
public void detach() {
readModel.detach();
}
private Collection<T> internalCollection() {
C collection = readModel.getObject();
if (collection == null) {
return ImmutableSet.<T>of();
} else {
return collection;
}
}
@Override
public Iterator<IModel<T>> iterator() {
return Iterators.transform(
Models.collectionModelIterator(internalCollection()),
itemModelFactory
);
}
@Override
public final Iterator<IModel<T>> iterator(long offset, long limit) {
// Transform must be the last operation, in order to let collectionModelIterator() optimize stuff
return Iterators.transform(
Models.collectionModelIterator(internalCollection(), offset, limit),
itemModelFactory
);
}
@Override
public long size() {
C collection = readModel.getObject();
if (collection == null) {
return 0L;
} else {
return collection.size();
}
}
@Override
public void add(T value) {
throw newReadOnlyException();
}
@Override
public void remove(T value) {
throw newReadOnlyException();
}
@Override
public void clear() {
throw newReadOnlyException();
}
@Override
public IWrapModel<C> wrapOnAssignment(Component component) {
return new WrapModel(component);
}
private class WrapModel extends ReadOnlyCollectionModel<T, C> implements IWrapModel<C> {
private static final long serialVersionUID = 7996314523359141428L;
protected WrapModel(Component component) {
super(Models.wrap(readModel, component), itemModelFactory);
}
@Override
public IModel<?> getWrappedModel() {
return ReadOnlyCollectionModel.this;
}
}
}