ItEr23S10CUAsignacionGrupoRecursosAPlanificacionItEr22S10: Adding row renderers based on DetailItem columns

This commit is contained in:
Óscar González Fernández 2009-08-26 11:28:22 +02:00
parent fe0d44447a
commit 336ec127d4
3 changed files with 320 additions and 0 deletions

View file

@ -0,0 +1,10 @@
package org.zkoss.ganttz.timetracker;
import org.zkoss.ganttz.timetracker.zoom.DetailItem;
import org.zkoss.zk.ui.Component;
public interface ICellForDetailItemRenderer<T> {
Component cellFor(DetailItem item, T data);
}

View file

@ -0,0 +1,105 @@
package org.zkoss.ganttz.timetracker;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang.Validate;
import org.zkoss.ganttz.timetracker.zoom.DetailItem;
import org.zkoss.zk.ui.Component;
import org.zkoss.zul.Row;
import org.zkoss.zul.RowRenderer;
public class OnDetailItemsRowRenderer<T> implements RowRenderer {
public static <T> OnDetailItemsRowRenderer<T> create(
ICellForDetailItemRenderer<T> cellRenderer,
Collection<DetailItem> detailItems) {
return create(inferGenericType(cellRenderer), cellRenderer, detailItems);
}
public static <T> OnDetailItemsRowRenderer<T> create(Class<T> type,
ICellForDetailItemRenderer<T> cellRenderer,
Collection<DetailItem> detailItems) {
return new OnDetailItemsRowRenderer<T>(type, cellRenderer, detailItems);
}
private static <T> Class<T> inferGenericType(
ICellForDetailItemRenderer<T> renderer) {
ParameterizedType parametrizedType = findRenderererInterfaceType(renderer);
Type[] actualTypeArguments = parametrizedType.getActualTypeArguments();
Type type = actualTypeArguments[0];
if (!isActualType(type)) {
informCannotBeInferred(renderer);
}
return (Class<T>) actualTypeArguments[0];
}
private static boolean isActualType(Type t) {
return t instanceof Class;
}
private static ParameterizedType findRenderererInterfaceType(
ICellForDetailItemRenderer<?> renderer) {
Type[] genericInterfaces = renderer.getClass().getGenericInterfaces();
for (Type type : genericInterfaces) {
if (isTypeForInterface(type, ICellForDetailItemRenderer.class)) {
if (type instanceof ParameterizedType) {
return (ParameterizedType) type;
} else
informCannotBeInferred(renderer);
}
}
throw new RuntimeException("shouldn't reach here. Uncovered case for "
+ renderer);
}
private static boolean isTypeForInterface(Type type,
Class<?> interfaceBeingSearched) {
if (type instanceof ParameterizedType) {
ParameterizedType p = (ParameterizedType) type;
Type rawType = p.getRawType();
return rawType.equals(interfaceBeingSearched);
}
return type.equals(interfaceBeingSearched);
}
private static void informCannotBeInferred(
ICellForDetailItemRenderer<?> renderer) {
throw new IllegalArgumentException(
"the generic type cannot be inferred "
+ "if actual type parameters are not declared "
+ "or implements the raw interface: "
+ renderer.getClass().getName());
}
private final List<DetailItem> detailItems;
private final ICellForDetailItemRenderer<T> cellRenderer;
private Class<T> type;
private OnDetailItemsRowRenderer(Class<T> type,
ICellForDetailItemRenderer<T> cellRenderer,
Collection<DetailItem> detailItems) {
Validate.notNull(type);
Validate.notNull(detailItems);
Validate.notNull(cellRenderer);
Validate.noNullElements(detailItems);
this.cellRenderer = cellRenderer;
this.detailItems = new ArrayList<DetailItem>(detailItems);
this.type = type;
}
@Override
public void render(Row row, Object data) {
if (!type.isInstance(data))
throw new IllegalArgumentException(data + " is not instance of "
+ type);
for (DetailItem item : detailItems) {
Component child = cellRenderer.cellFor(item, type.cast(data));
child.setParent(row);
}
}
}

View file

@ -0,0 +1,205 @@
package org.zkoss.ganttz.timetracker;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.createStrictMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.isA;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import java.util.ArrayList;
import java.util.List;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.Period;
import org.junit.Test;
import org.zkoss.ganttz.timetracker.zoom.DetailItem;
import org.zkoss.zk.ui.Component;
import org.zkoss.zul.Row;
import org.zkoss.zul.api.Label;
public class OnDetailItemsRowRendererTest {
private static class Data {
}
private static class CellRenderer implements
ICellForDetailItemRenderer<Data> {
@Override
public Component cellFor(DetailItem item, Data data) {
return null;
}
}
private static class CellRendererNotInferable<T> implements
ICellForDetailItemRenderer<T> {
@Override
public Component cellFor(DetailItem item, T data) {
return null;
}
}
private List<DetailItem> detailItems;
private OnDetailItemsRowRenderer<Data> rowRenderer;
private DateTime start;
private List<Data> data;
private void givenOnDetailItemsRowRenderer(
ICellForDetailItemRenderer<Data> cellRenderer) {
if (detailItems == null) {
givenDetailItems();
}
rowRenderer = OnDetailItemsRowRenderer.create(Data.class, cellRenderer,
detailItems);
}
private void givenDetailItems() {
detailItems = new ArrayList<DetailItem>();
start = new LocalDate(2010, 1, 1).toDateMidnight().toDateTime();
DateTime current = start;
Period period = Period.months(2);
for (int i = 1; i <= 10; i++) {
DateTime end = current.plus(period);
DetailItem detail = new DetailItem(200, i + "", current, end);
current = end;
detailItems.add(detail);
}
}
private void givenData() {
data = new ArrayList<Data>();
data.add(new Data());
data.add(new Data());
}
@Test(expected = IllegalArgumentException.class)
public void itNeedsNotNullDetailItems() {
OnDetailItemsRowRenderer.create(Data.class, createStub(), null);
}
@Test(expected = IllegalArgumentException.class)
public void itNeedsNotNullCellRenderer() {
OnDetailItemsRowRenderer.create(Data.class, null,
new ArrayList<DetailItem>());
}
@Test(expected = IllegalArgumentException.class)
public void itNeedsTheTypeAsClass() {
OnDetailItemsRowRenderer.create(null, createStub(),
new ArrayList<DetailItem>());
}
@Test
public void itCanHaveEmptyDetailItems() {
OnDetailItemsRowRenderer.create(Data.class, createStub(),
new ArrayList<DetailItem>());
}
@Test
public void itCanInferTheGenericType() {
OnDetailItemsRowRenderer.create(new CellRenderer(),
new ArrayList<DetailItem>());
}
@Test(expected = IllegalArgumentException.class)
public void ifComesFromRawTypeIsNotInferrable() {
OnDetailItemsRowRenderer.create(createStub(),
new ArrayList<DetailItem>());
}
@Test(expected = IllegalArgumentException.class)
public void ifItNotShowsTheActualTypeIsNotInferrable() {
OnDetailItemsRowRenderer.create(new CellRendererNotInferable<Data>(),
new ArrayList<DetailItem>());
}
@SuppressWarnings("serial")
@Test(expected = IllegalArgumentException.class)
public void noDetailItemCanBeNull() {
OnDetailItemsRowRenderer.create(Data.class, createStub(),
new ArrayList<DetailItem>() {
{
add(new DetailItem(300, "bla"));
add(null);
}
});
}
@Test(expected = IllegalArgumentException.class)
public void cantRenderObjectsOfOtherType() {
givenOnDetailItemsRowRenderer(createStub());
rowRenderer.render(new Row(), "");
}
private ICellForDetailItemRenderer<Data> createStub() {
return createNiceMock(ICellForDetailItemRenderer.class);
}
@Test
public void theCellRendererIsUsedForEachCell() {
givenData();
givenDetailItems();
ICellForDetailItemRenderer<Data> mock = expectTheCellRendererIsCalledForEachCell();
givenOnDetailItemsRowRenderer(mock);
renderingTheData();
verify(mock);
}
private void renderingTheData() {
for (Data d : data) {
rowRenderer.render(new Row(), d);
}
}
private ICellForDetailItemRenderer<Data> expectTheCellRendererIsCalledForEachCell() {
ICellForDetailItemRenderer<Data> mock = createStrictMock(ICellForDetailItemRenderer.class);
Label labelMock = createNiceMock(Label.class);
for (Data d : data) {
for (DetailItem item : detailItems) {
expect(mock.cellFor(item, d)).andReturn(labelMock);
}
}
replay(mock);
return mock;
}
@Test
public void theCreatedComponentsAreAddedToTheParents() {
givenData();
givenDetailItems();
ICellForDetailItemRenderer<Data> mock = createMock(ICellForDetailItemRenderer.class);
Label labelMock = expectTheCreatedLabelIsAddedToTheRow(mock);
givenOnDetailItemsRowRenderer(mock);
renderingTheData();
verify(labelMock);
}
private Label expectTheCreatedLabelIsAddedToTheRow(
ICellForDetailItemRenderer<Data> mock) {
Label labelMock = createStrictMock(Label.class);
for (Data d : data) {
for (DetailItem item : detailItems) {
expect(mock.cellFor(isA(DetailItem.class), isA(Data.class)))
.andReturn(labelMock);
labelMock.setParent(isA(Row.class));
}
}
replay(mock, labelMock);
return labelMock;
}
}