package fr.openwide.core.test.wicket.more.bindable;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.util.Collection;
import org.junit.Test;
import com.google.common.collect.ImmutableList;
import fr.openwide.core.commons.util.functional.Suppliers2;
import fr.openwide.core.wicket.more.bindable.model.BindableModel;
import fr.openwide.core.wicket.more.bindable.model.IBindableCollectionModel;
import fr.openwide.core.wicket.more.bindable.model.IBindableModel;
public class TestBindableCollectionModel extends AbstractTestBindableModel {
@Test
public void alwaysReturnsSameModelInstance() {
doReturn(rootValue).when(rootModel).getObject();
IBindableModel<RootValue> bindableModel = new BindableModel<>(rootModel);
IBindableModel<?> firstCall = bindableModel.bindCollectionWithCache(
rootBinding().collectionProperty(),
Suppliers2.<CollectionPropertyItemValue>arrayList(), StubModel.<CollectionPropertyItemValue>factory()
);
IBindableModel<?> secondCall = bindableModel.bindCollectionAlreadyAdded(rootBinding().collectionProperty());
assertSame(firstCall, secondCall);
IBindableModel<?> thirdCall = bindableModel.bindCollectionWithCache(
rootBinding().collectionProperty(),
Suppliers2.<CollectionPropertyItemValue>arrayList(), StubModel.<CollectionPropertyItemValue>factory()
);
assertSame(firstCall, thirdCall);
}
@Test
public void alwaysReturnsSameModelInstanceEvenIfChained() {
doReturn(rootValue).when(rootModel).getObject();
IBindableModel<RootValue> bindableModel = new BindableModel<>(rootModel);
IBindableModel<?> directCall = bindableModel.bindCollectionWithCache(
rootBinding().compositeProperty().collectionProperty(),
Suppliers2.<CollectionPropertyItemValue>arrayList(), StubModel.<CollectionPropertyItemValue>factory()
);
IBindableModel<?> chainedCall = bindableModel.bind(rootBinding().compositeProperty())
.bindCollectionAlreadyAdded(rootBinding().collectionProperty());
assertSame(directCall, chainedCall);
IBindableModel<?> chainedCallWithCache = bindableModel.bind(rootBinding().compositeProperty())
.bindCollectionWithCache(
rootBinding().collectionProperty(),
Suppliers2.<CollectionPropertyItemValue>arrayList(), StubModel.<CollectionPropertyItemValue>factory()
);
assertSame(directCall, chainedCallWithCache);
}
@Test
public void simpleCacheUsage() {
Collection<CollectionPropertyItemValue> firstExpectedValue = ImmutableList.of(new CollectionPropertyItemValue());
Collection<CollectionPropertyItemValue> secondExpectedValue = ImmutableList.of(
new CollectionPropertyItemValue(), new CollectionPropertyItemValue()
);
rootValue.setCollectionProperty(firstExpectedValue);
doReturn(rootValue).when(rootModel).getObject();
IBindableModel<RootValue> bindableModel = new BindableModel<>(rootModel);
IBindableModel<Collection<CollectionPropertyItemValue>> propertyModel = bindableModel.bindCollectionWithCache(
rootBinding().collectionProperty(),
Suppliers2.<CollectionPropertyItemValue>arrayList(), StubModel.<CollectionPropertyItemValue>factory()
);
assertEquals(firstExpectedValue, propertyModel.getObject());
verify(rootValue).getCollectionProperty(); // Cache was initialized
rootValue.setCollectionProperty(secondExpectedValue);
propertyModel.readAll();
verify(rootValue, times(2)).getCollectionProperty(); // The value was fetched
assertEquals(secondExpectedValue, propertyModel.getObject()); // The cache was updated
verify(rootValue, times(2)).getCollectionProperty(); // Only the cache was touched, no the actual value
Collection<CollectionPropertyItemValue> valueToSet = ImmutableList.of(
new CollectionPropertyItemValue(), new CollectionPropertyItemValue(), new CollectionPropertyItemValue()
);
assertEquals(secondExpectedValue, rootValue.getCollectionProperty());
propertyModel.setObject(valueToSet);
assertEquals(secondExpectedValue, rootValue.getCollectionProperty());
// Only the cache was touched, not the actual value (which was only initialized at the start of this test)
assertEquals(valueToSet, propertyModel.getObject());
propertyModel.writeAll();
assertEquals(valueToSet, rootValue.getCollectionProperty());
assertEquals(valueToSet, propertyModel.getObject());
}
@Test
public void cacheUpdatePropagation() {
Collection<CollectionPropertyItemValue> firstExpectedValue = ImmutableList.of(new CollectionPropertyItemValue());
Collection<CollectionPropertyItemValue> secondExpectedValue = ImmutableList.of(
new CollectionPropertyItemValue(), new CollectionPropertyItemValue()
);
rootValue.setCollectionProperty(firstExpectedValue);
doReturn(rootValue).when(rootModel).getObject();
IBindableModel<RootValue> bindableModel = new BindableModel<>(rootModel);
IBindableModel<Collection<CollectionPropertyItemValue>> propertyModel = bindableModel.bindCollectionWithCache(
rootBinding().collectionProperty(),
Suppliers2.<CollectionPropertyItemValue>arrayList(), StubModel.<CollectionPropertyItemValue>factory()
);
assertEquals(firstExpectedValue, propertyModel.getObject());
verify(rootValue).getCollectionProperty(); // Cache was initialized
rootValue.setCollectionProperty(secondExpectedValue);
bindableModel.readAll();
verify(rootValue, times(2)).getCollectionProperty(); // The value was fetched
assertEquals(secondExpectedValue, propertyModel.getObject()); // The cache was updated
verify(rootValue, times(2)).getCollectionProperty(); // Only the cache was touched when calling getObject(), no the actual value
Collection<CollectionPropertyItemValue> valueToSet = ImmutableList.of(
new CollectionPropertyItemValue(), new CollectionPropertyItemValue(), new CollectionPropertyItemValue()
);
assertEquals(secondExpectedValue, rootValue.getCollectionProperty());
propertyModel.setObject(valueToSet);
assertEquals(secondExpectedValue, rootValue.getCollectionProperty());
// Only the cache was touched, not the actual value (which was only initialized at the start of this test)
assertEquals(valueToSet, propertyModel.getObject());
bindableModel.writeAll();
assertEquals(valueToSet, rootValue.getCollectionProperty());
assertEquals(valueToSet, propertyModel.getObject());
}
@Test
public void collectionModelInterfaceUsage() {
CollectionPropertyItemValue firstItem = new CollectionPropertyItemValue();
CollectionPropertyItemValue secondItem = new CollectionPropertyItemValue();
CollectionPropertyItemValue thirdItem = new CollectionPropertyItemValue();
rootValue.setCollectionProperty(ImmutableList.of(firstItem, secondItem));
doReturn(rootValue).when(rootModel).getObject();
IBindableModel<RootValue> bindableModel = new BindableModel<>(rootModel);
IBindableCollectionModel<CollectionPropertyItemValue, ?> propertyModel = bindableModel.bindCollectionWithCache(
rootBinding().collectionProperty(),
Suppliers2.<CollectionPropertyItemValue>arrayList(), StubModel.<CollectionPropertyItemValue>factory()
);
assertEquals(propertyModel.getObject(), ImmutableList.of(firstItem, secondItem)); // Cache was initialized
propertyModel.remove(secondItem);
assertEquals(ImmutableList.of(firstItem), propertyModel.getObject()); // The cache was updated
assertEquals(ImmutableList.of(firstItem, secondItem), rootValue.getCollectionProperty()); // The actual value was *not* updated
propertyModel.writeAll();
assertEquals(ImmutableList.of(firstItem), propertyModel.getObject()); // The cache was *not* updated
assertEquals(ImmutableList.of(firstItem), rootValue.getCollectionProperty()); // The actual value was updated
propertyModel.add(thirdItem);
assertEquals(ImmutableList.of(firstItem, thirdItem), propertyModel.getObject()); // The cache was updated
assertEquals(ImmutableList.of(firstItem), rootValue.getCollectionProperty()); // The actual value was *not* updated
propertyModel.writeAll();
assertEquals(ImmutableList.of(firstItem, thirdItem), propertyModel.getObject()); // The cache was *not* updated
assertEquals(ImmutableList.of(firstItem, thirdItem), rootValue.getCollectionProperty()); // The actual value was updated
propertyModel.clear();
assertEquals(ImmutableList.of(), propertyModel.getObject()); // The cache was updated
assertEquals(ImmutableList.of(firstItem, thirdItem), rootValue.getCollectionProperty()); // The actual value was *not* updated
propertyModel.writeAll();
assertEquals(ImmutableList.of(), propertyModel.getObject()); // The cache was *not* updated
assertEquals(ImmutableList.of(), rootValue.getCollectionProperty()); // The actual value was updated
}
}