/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon.forms.formmodel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.cocoon.forms.binding.BindingException;
import org.apache.cocoon.forms.binding.RepeaterItem;
import org.apache.cocoon.forms.binding.RepeaterJXPathCollection;
import org.apache.cocoon.forms.datatype.StaticSelectionList;
import org.apache.cocoon.xml.AttributesImpl;
public class EnhancedRepeater extends Repeater {
private RepeaterJXPathCollection collection;
private String customPageFieldId;
private Field customPageField;
// pagination
private int currentPage;
private int pageSize;
public EnhancedRepeater(RepeaterDefinition repeaterDefinition) {
super(repeaterDefinition);
this.currentPage = this.definition.getInitialPage();
this.pageSize = this.definition.getPageSize();
this.customPageFieldId = this.definition.getCustomPageId();
}
public void doPageLoad() throws BindingException {
clearAllRows();
collection.flushCachedItems();
int start = getStartIndex();
List items = collection.getItems(start, this.pageSize);
for (Iterator iter = items.iterator(); iter.hasNext();) {
RepeaterItem item = (RepeaterItem) iter.next();
if (item == null) {
break;
}
if (item.getRow() != null) {
addRow(item.getRow());
} else {
RepeaterRow thisRow = addRow();
item.setRow(thisRow);
collection.getAdapter().populateRow(item);
}
}
// set customPageField
if (this.customPageField != null) {
StaticSelectionList selectionList = new StaticSelectionList(this.customPageField.getDatatype());
int j;
for (j = 0; j <= this.getMaxPage(); j++) {
selectionList.addItem(new Integer(j), (j + 1) + "");
}
this.customPageField.setSelectionList(selectionList);
this.customPageField.setValue(new Integer(this.currentPage));
}
}
/**
* save current page to cache-collections (updatedRows, deleted rows, insertedRows)
* @throws BindingException
*/
public void doPageSave() throws BindingException {
List tempUpdatedRows = new ArrayList();
List tempInsertedRows = new ArrayList();
List cache = collection.getCachedItems();
// iterate rows in the form model...
int formRowCount = getSize();
for (int i = 0; i < formRowCount; i++) {
Repeater.RepeaterRow thisRow = getRow(i);
boolean found = false;
for (int j = 0; j < cache.size(); j++) {
RepeaterItem item = (RepeaterItem) cache.get(j);
if (item == null) {
break;
}
if (item.getRow() == thisRow) {
// Found the matching row
// TODO we need a way to know if the row was really modified or not, maybe a FormHandler?
tempUpdatedRows.add(item);
found = true;
break;
}
}
if (!found) {
tempInsertedRows.add(thisRow);
}
}
List toDelete = new ArrayList();
for (int j = 0; j < cache.size(); j++) {
RepeaterItem item = (RepeaterItem) cache.get(j);
if (item == null) {
break;
}
boolean found = false;
for (int i = 0; i < formRowCount; i++) {
Repeater.RepeaterRow thisRow = getRow(i);
if (thisRow == item.getRow()) {
found = true;
break;
}
}
if (!found) {
toDelete.add(item);
}
}
for (Iterator iter = tempUpdatedRows.iterator(); iter.hasNext();) {
RepeaterItem ele = (RepeaterItem) iter.next();
collection.updateRow(ele);
}
for (Iterator iter = tempInsertedRows.iterator(); iter.hasNext();) {
RepeaterRow row = (RepeaterRow) iter.next();
collection.addRow(row);
}
for (Iterator iter = toDelete.iterator(); iter.hasNext();) {
RepeaterItem ele = (RepeaterItem) iter.next();
collection.deleteRow(ele);
}
collection.flushCachedItems();
}
private int getStartIndex() {
return this.currentPage * this.pageSize;
}
public int getMaxPage() {
return ((int)(Math.ceil((double)collection.getActualCollectionSize() / (double)pageSize))) - 1;
}
public int getCustomPageWidgetValue() {
return ((Integer) this.customPageField.getValue()).intValue();
}
public int getCurrentPage() {
return currentPage;
}
/*
* convenience methods for presentation
*/
public int getDisplayableCurrentPage() {
return this.getCurrentPage() + 1;
}
public int getDisplayableLastPage() {
// increment if we created a new page for insertion
if (this.getCurrentPage() > this.getMaxPage()) {
return this.getMaxPage() + 2;
}
return this.getMaxPage() + 1;
}
public boolean isFirstPage() {
return this.getCurrentPage() == 0;
}
public boolean isLastPage() {
return this.getCurrentPage() >= this.getMaxPage();
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public boolean isEnhanced() {
return true;
}
public AttributesImpl getXMLElementAttributes() {
AttributesImpl elementAttributes = super.getXMLElementAttributes();
if (this.pageSize < Integer.MAX_VALUE) {
elementAttributes.addCDATAAttribute("page", String.valueOf(currentPage));
}
return elementAttributes;
}
private void addRow(RepeaterRow row) {
rows.add(row);
getForm().addWidgetUpdate(this);
}
private void clearAllRows() {
rows.clear();
getForm().addWidgetUpdate(this);
}
public void setCollection(RepeaterJXPathCollection collection) {
this.collection = collection;
}
public void initialize() {
super.initialize();
Widget widget = getForm().lookupWidget(this.customPageFieldId);
if (widget instanceof Field) {
this.customPageField = (Field) widget;
}
}
public RepeaterJXPathCollection getCollection() {
return collection;
}
public void refreshPage() throws BindingException {
doPageSave();
doPageLoad();
}
public void goToPage(int page) throws BindingException {
doPageSave();
this.currentPage = page;
doPageLoad();
}
public void sortBy(String field) throws BindingException {
doPageSave();
this.collection.sortBy(field);
this.currentPage = 0;
doPageLoad();
}
public void setFilter(String field, Object value) throws BindingException {
doPageSave();
this.collection.filter(field, value);
this.currentPage = 0;
doPageLoad();
}
}