001: /*
002: * $Id: AbstractDataGridView.java 460150 2006-04-06 15:37:06Z ivaynberg $
003: * $Revision: 460150 $ $Date: 2006-04-06 17:37:06 +0200 (Thu, 06 Apr 2006) $
004: *
005: * ==================================================================== Licensed
006: * under the Apache License, Version 2.0 (the "License"); you may not use this
007: * file except in compliance with the License. You may obtain a copy of the
008: * License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015: * License for the specific language governing permissions and limitations under
016: * the License.
017: */
018: package wicket.extensions.markup.html.repeater.data.grid;
019:
020: import java.io.Serializable;
021: import java.util.Iterator;
022:
023: import wicket.WicketRuntimeException;
024: import wicket.extensions.markup.html.repeater.data.DataViewBase;
025: import wicket.extensions.markup.html.repeater.data.IDataProvider;
026: import wicket.extensions.markup.html.repeater.refreshing.Item;
027: import wicket.extensions.markup.html.repeater.refreshing.RefreshingView;
028: import wicket.extensions.markup.html.repeater.util.ArrayIteratorAdapter;
029: import wicket.model.IModel;
030: import wicket.model.Model;
031:
032: /**
033: * Acts as a base for data-grid views. Unlike a data view a data-grid view
034: * populates both rows and columns. The columns are populated by an array of
035: * provided ICellPopulator objects.
036: *
037: * @see DataGridView
038: *
039: * @author Igor Vaynberg (ivaynberg)
040: *
041: */
042: public abstract class AbstractDataGridView extends DataViewBase {
043: private static final long serialVersionUID = 1L;
044:
045: private static final String CELL_REPEATER_ID = "cells";
046: private static final String CELL_ITEM_ID = "cell";
047:
048: private ICellPopulator[] populators;
049:
050: private transient ArrayIteratorAdapter populatorsIteratorCache;
051:
052: /**
053: * Constructor
054: *
055: * @param id
056: * component id
057: * @param populators
058: * array of ICellPopulator objects that will be used to populate
059: * cell items
060: * @param dataProvider
061: * data provider
062: */
063: public AbstractDataGridView(String id, ICellPopulator[] populators,
064: IDataProvider dataProvider) {
065: super (id, dataProvider);
066:
067: this .populators = populators;
068: }
069:
070: /**
071: * Returns iterator over ICellPopulator elements in the populators array.
072: * This method caches the iterator implemenation in a transient member
073: * instance.
074: *
075: * @return iterator over ICellPopulator elements in the populators array
076: */
077: private Iterator getPopulatorsIterator() {
078: if (populatorsIteratorCache == null) {
079: populatorsIteratorCache = new ArrayIteratorAdapter(
080: internalGetPopulators()) {
081:
082: protected IModel model(Object object) {
083: return new Model((Serializable) object);
084: }
085:
086: };
087: } else {
088: populatorsIteratorCache.reset();
089: }
090: return populatorsIteratorCache;
091: }
092:
093: protected final void populateItem(Item item) {
094: final IModel rowModel = item.getModel();
095:
096: // TODO Post 1.2: General: Does this need to be a refreshing view? since the rows
097: // is a refreshing view this will be recreated anyways. maybe can se
098: // orderedrepeatingview instead to simplify.
099: item.add(new RefreshingView(CELL_REPEATER_ID) {
100: private static final long serialVersionUID = 1L;
101:
102: protected Iterator getItemModels() {
103: return getPopulatorsIterator();
104: }
105:
106: protected void populateItem(Item item) {
107: final ICellPopulator populator = (ICellPopulator) item
108: .getModelObject();
109: populator.populateItem(item, CELL_ITEM_ID, rowModel);
110:
111: if (item.get("cell") == null) {
112: throw new WicketRuntimeException(
113: populator.getClass().getName()
114: + ".populateItem() failed to add a component with id ["
115: + CELL_ITEM_ID
116: + "] to the provided [cellItem] object. Make sure you call add() on cellItem ( cellItem.add(new MyComponent(componentId, rowModel) )");
117: }
118:
119: }
120:
121: protected Item newItem(String id, int index, IModel model) {
122: return newCellItem(id, index, model);
123: }
124:
125: });
126: }
127:
128: protected final ICellPopulator[] internalGetPopulators() {
129: return populators;
130: }
131:
132: protected final Item newItem(String id, int index, IModel model) {
133: return newRowItem(id, index, model);
134: }
135:
136: /**
137: * Factory method for Item container that represents a row.
138: *
139: * @see Item
140: * @see RefreshingView#newItem(String, int, IModel)
141: *
142: * @param id
143: * component id for the new data item
144: * @param index
145: * the index of the new data item
146: * @param model
147: * the model for the new data item.
148: *
149: * @return DataItem created DataItem
150: */
151: protected Item newRowItem(final String id, int index,
152: final IModel model) {
153: return new Item(id, index, model);
154: }
155:
156: /**
157: * Factory method for Item container that represents a cell.
158: *
159: * @see Item
160: * @see RefreshingView#newItem(String, int, IModel)
161: *
162: * @param id
163: * component id for the new data item
164: * @param index
165: * the index of the new data item
166: * @param model
167: * the model for the new data item
168: *
169: * @return DataItem created DataItem
170: */
171: protected Item newCellItem(final String id, int index,
172: final IModel model) {
173: return new Item(id, index, model);
174: }
175:
176: }
|