/* * 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.binding; import java.util.Iterator; import java.util.List; import org.apache.avalon.framework.CascadingRuntimeException; import org.apache.cocoon.forms.binding.JXPathBindingBuilderBase.CommonAttributes; import org.apache.cocoon.forms.formmodel.EnhancedRepeater; import org.apache.cocoon.forms.formmodel.Repeater; import org.apache.cocoon.forms.formmodel.Widget; import org.apache.commons.collections.ListUtils; import org.apache.commons.jxpath.JXPathContext; import org.apache.commons.jxpath.Pointer; public class EnhancedRepeaterJXPathBinding extends RepeaterJXPathBinding { private String adapterClass; public EnhancedRepeaterJXPathBinding(CommonAttributes commonAtts, String repeaterId, String repeaterPath, String rowPath, String rowPathForInsert, JXPathBindingBase[] childBindings, JXPathBindingBase insertBinding, JXPathBindingBase[] deleteBindings, JXPathBindingBase[] identityBindings, String adapterClass) { super(commonAtts, repeaterId, repeaterPath, rowPath, rowPathForInsert, childBindings, insertBinding, deleteBindings, identityBindings); this.adapterClass = adapterClass; } public void doLoad(Widget frmModel, JXPathContext jxpc) throws BindingException { Repeater repeater = (Repeater) selectWidget(frmModel, super.getId()); if (!(repeater instanceof EnhancedRepeater)) { super.doLoad(frmModel, jxpc); return; } EnhancedRepeater rep = (EnhancedRepeater) repeater; RepeaterAdapter adapter; if (this.adapterClass != null) { try { adapter = (RepeaterAdapter) Class.forName(this.adapterClass).newInstance(); } catch (Exception e) { throw new CascadingRuntimeException("Cannot instantiate adapter class for advanced repeater binding", e); } } else { adapter = new RepeaterJXPathAdapter(); } RepeaterJXPathCollection collection = new RepeaterJXPathCollection(); //Pointer ptr = jxpc.getPointer(super.getRepeaterPath()); //JXPathContext repeaterContext = jxpc.getRelativeContext(ptr); collection.init(jxpc, super.getRowPath(), adapter); adapter.setBinding(this); adapter.setJXCollection(collection); rep.setCollection(collection); rep.doPageLoad(); } public void doSave(Widget frmModel, JXPathContext jxpc) throws BindingException { Repeater repeater = (Repeater) selectWidget(frmModel, super.getId()); if (!(repeater instanceof EnhancedRepeater)) { super.doSave(frmModel, jxpc); return; } EnhancedRepeater rep = (EnhancedRepeater) repeater; rep.doPageSave(); Pointer ptr = jxpc.getPointer(super.getRepeaterPath()); JXPathContext repeaterContext = jxpc.getRelativeContext(ptr); RepeaterJXPathCollection collection = rep.getCollection(); // iterate updated rows. note: we don't iterate over the whole context for (Iterator iter = collection.getUpdatedRows().iterator(); iter.hasNext();) { RepeaterItem item = (RepeaterItem) iter.next(); Repeater.RepeaterRow thisRow = item.getRow(); // Get the identity List identity = getIdentity(thisRow); if (hasNonNullElements(identity)) { // iterate nodes to find match Iterator rowPointers = repeaterContext.iteratePointers(getRowPath()); while (rowPointers.hasNext()) { Pointer jxp = (Pointer) rowPointers.next(); JXPathContext rowContext = repeaterContext.getRelativeContext(jxp); List contextIdentity = getIdentity(rowContext); if (ListUtils.isEqualList(identity, contextIdentity)) { getRowBinding().saveFormToModel(thisRow, rowContext); break; } } } else { getRowBinding().saveFormToModel(thisRow, item.getContext().getContextPointer()); } } for (Iterator iter = collection.getDeletedRows().iterator(); iter.hasNext();) { RepeaterItem item = (RepeaterItem) iter.next(); jxpc.removePath(item.getContext().createPath(".").asPath()); } // insert rows int indexCount = collection.getOriginalCollectionSize() - collection.getDeletedRows().size(); for (Iterator iter = collection.getInsertedRows().iterator(); iter.hasNext();) { indexCount++; RepeaterItem item= (RepeaterItem) iter.next(); // Perform the insert row binding. if (getInsertRowBinding() != null) { getInsertRowBinding().saveFormToModel(item.getRow(), repeaterContext); } // --> create the path to let the context be created Pointer newRowContextPointer = repeaterContext.createPath( super.getInsertRowPath() + "[" + indexCount + "]"); JXPathContext newRowContext = repeaterContext.getRelativeContext(newRowContextPointer); // + rebind to children for update super.getRowBinding().saveFormToModel(item.getRow(), newRowContext); } } }