001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.forms.formmodel;
018:
019: import java.util.ArrayList;
020: import java.util.Iterator;
021: import java.util.List;
022:
023: import org.apache.cocoon.forms.binding.BindingException;
024: import org.apache.cocoon.forms.binding.RepeaterItem;
025: import org.apache.cocoon.forms.binding.RepeaterJXPathCollection;
026: import org.apache.cocoon.forms.datatype.StaticSelectionList;
027: import org.apache.cocoon.xml.AttributesImpl;
028:
029: public class EnhancedRepeater extends Repeater {
030: private RepeaterJXPathCollection collection;
031: private String customPageFieldId;
032: private Field customPageField;
033:
034: // pagination
035: private int currentPage;
036: private int pageSize;
037:
038: public EnhancedRepeater(RepeaterDefinition repeaterDefinition) {
039: super (repeaterDefinition);
040: this .currentPage = this .definition.getInitialPage();
041: this .pageSize = this .definition.getPageSize();
042: this .customPageFieldId = this .definition.getCustomPageId();
043: }
044:
045: public void doPageLoad() throws BindingException {
046: clearAllRows();
047: collection.flushCachedItems();
048: int start = getStartIndex();
049: List items = collection.getItems(start, this .pageSize);
050: for (Iterator iter = items.iterator(); iter.hasNext();) {
051: RepeaterItem item = (RepeaterItem) iter.next();
052: if (item == null)
053: break;
054: if (item.getRow() != null) {
055: addRow(item.getRow());
056: } else {
057: RepeaterRow this Row = addRow();
058: item.setRow(this Row);
059: collection.getAdapter().populateRow(item);
060: }
061: }
062:
063: // set customPageField
064: if (this .customPageField != null) {
065: StaticSelectionList selectionList = new StaticSelectionList(
066: this .customPageField.getDatatype());
067: int j;
068: for (j = 0; j <= this .getMaxPage(); j++) {
069: selectionList.addItem(new Integer(j), (j + 1) + "");
070: }
071: this .customPageField.setSelectionList(selectionList);
072: this .customPageField
073: .setValue(new Integer(this .currentPage));
074: }
075: }
076:
077: /**
078: * save current page to cache-collections (updatedRows, deleted rows, insertedRows)
079: * @throws BindingException
080: */
081: public void doPageSave() throws BindingException {
082: List tempUpdatedRows = new ArrayList();
083: List tempInsertedRows = new ArrayList();
084:
085: List cache = collection.getCachedItems();
086: // iterate rows in the form model...
087: int formRowCount = getSize();
088: for (int i = 0; i < formRowCount; i++) {
089: Repeater.RepeaterRow this Row = getRow(i);
090: boolean found = false;
091: for (int j = 0; j < cache.size(); j++) {
092: RepeaterItem item = (RepeaterItem) cache.get(j);
093: if (item == null)
094: break;
095: if (item.getRow() == this Row) {
096: // Found the matching row
097: // TODO we need a way to know if the row was really modified or not, maybe a FormHandler?
098: tempUpdatedRows.add(item);
099: found = true;
100: break;
101: }
102: }
103: if (!found) {
104: tempInsertedRows.add(this Row);
105: }
106: }
107:
108: List toDelete = new ArrayList();
109: for (int j = 0; j < cache.size(); j++) {
110: RepeaterItem item = (RepeaterItem) cache.get(j);
111: if (item == null)
112: break;
113: boolean found = false;
114: for (int i = 0; i < formRowCount; i++) {
115: Repeater.RepeaterRow this Row = getRow(i);
116: if (this Row == item.getRow()) {
117: found = true;
118: break;
119: }
120: }
121: if (!found) {
122: toDelete.add(item);
123: }
124: }
125: for (Iterator iter = tempUpdatedRows.iterator(); iter.hasNext();) {
126: RepeaterItem ele = (RepeaterItem) iter.next();
127: collection.updateRow(ele);
128: }
129: for (Iterator iter = tempInsertedRows.iterator(); iter
130: .hasNext();) {
131: RepeaterRow row = (RepeaterRow) iter.next();
132: collection.addRow(row);
133: }
134: for (Iterator iter = toDelete.iterator(); iter.hasNext();) {
135: RepeaterItem ele = (RepeaterItem) iter.next();
136: collection.deleteRow(ele);
137: }
138: collection.flushCachedItems();
139: }
140:
141: private int getStartIndex() {
142: return this .currentPage * this .pageSize;
143: }
144:
145: public int getMaxPage() {
146: return ((int) (Math.ceil((double) collection
147: .getActualCollectionSize()
148: / (double) pageSize))) - 1;
149: }
150:
151: public int getCustomPageWidgetValue() {
152: return ((Integer) this .customPageField.getValue()).intValue();
153: }
154:
155: public int getCurrentPage() {
156: return currentPage;
157: }
158:
159: /*
160: * convenience methods for presentation
161: */
162:
163: public int getDisplayableCurrentPage() {
164: return this .getCurrentPage() + 1;
165: }
166:
167: public int getDisplayableLastPage() {
168: // increment if we created a new page for insertion
169: if (this .getCurrentPage() > this .getMaxPage()) {
170: return this .getMaxPage() + 2;
171: }
172: return this .getMaxPage() + 1;
173: }
174:
175: public boolean isFirstPage() {
176: return this .getCurrentPage() == 0;
177: }
178:
179: public boolean isLastPage() {
180: return this .getCurrentPage() >= this .getMaxPage();
181: }
182:
183: public int getPageSize() {
184: return pageSize;
185: }
186:
187: public void setPageSize(int pageSize) {
188: this .pageSize = pageSize;
189: }
190:
191: public boolean isEnhanced() {
192: return true;
193: }
194:
195: public AttributesImpl getXMLElementAttributes() {
196: AttributesImpl elementAttributes = super
197: .getXMLElementAttributes();
198: if (this .pageSize < Integer.MAX_VALUE) {
199: elementAttributes.addCDATAAttribute("page", String
200: .valueOf(currentPage));
201: }
202: return elementAttributes;
203: }
204:
205: private void addRow(RepeaterRow row) {
206: rows.add(row);
207: getForm().addWidgetUpdate(this );
208: }
209:
210: private void clearAllRows() {
211: rows.clear();
212: getForm().addWidgetUpdate(this );
213: }
214:
215: public void setCollection(RepeaterJXPathCollection collection) {
216: this .collection = collection;
217: }
218:
219: public void initialize() {
220: super .initialize();
221: Widget widget = getForm().lookupWidget(this .customPageFieldId);
222: if (widget instanceof Field) {
223: this .customPageField = (Field) widget;
224: }
225: }
226:
227: public RepeaterJXPathCollection getCollection() {
228: return collection;
229: }
230:
231: public void refreshPage() throws BindingException {
232: doPageSave();
233: doPageLoad();
234: }
235:
236: public void goToPage(int page) throws BindingException {
237: doPageSave();
238: this .currentPage = page;
239: doPageLoad();
240: }
241:
242: public void sortBy(String field) throws BindingException {
243: doPageSave();
244: this .collection.sortBy(field);
245: this .currentPage = 0;
246: doPageLoad();
247: }
248:
249: public void setFilter(String field, Object value)
250: throws BindingException {
251: doPageSave();
252: this .collection.filter(field, value);
253: this .currentPage = 0;
254: doPageLoad();
255: }
256:
257: }
|