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.binding;
018:
019: import java.util.Iterator;
020: import java.util.List;
021:
022: import org.apache.avalon.framework.CascadingRuntimeException;
023:
024: import org.apache.cocoon.forms.binding.JXPathBindingBuilderBase.CommonAttributes;
025: import org.apache.cocoon.forms.formmodel.EnhancedRepeater;
026: import org.apache.cocoon.forms.formmodel.Repeater;
027: import org.apache.cocoon.forms.formmodel.Widget;
028:
029: import org.apache.commons.collections.ListUtils;
030: import org.apache.commons.jxpath.JXPathContext;
031: import org.apache.commons.jxpath.Pointer;
032:
033: public class EnhancedRepeaterJXPathBinding extends
034: RepeaterJXPathBinding {
035:
036: private String adapterClass;
037:
038: public EnhancedRepeaterJXPathBinding(CommonAttributes commonAtts,
039: String repeaterId, String repeaterPath, String rowPath,
040: String rowPathForInsert, JXPathBindingBase[] childBindings,
041: JXPathBindingBase insertBinding,
042: JXPathBindingBase[] deleteBindings,
043: JXPathBindingBase[] identityBindings, String adapterClass) {
044: super (commonAtts, repeaterId, repeaterPath, rowPath,
045: rowPathForInsert, childBindings, insertBinding,
046: deleteBindings, identityBindings);
047: this .adapterClass = adapterClass;
048: }
049:
050: public void doLoad(Widget frmModel, JXPathContext jxpc)
051: throws BindingException {
052: Repeater repeater = (Repeater) selectWidget(frmModel, super
053: .getId());
054: if (!(repeater instanceof EnhancedRepeater)) {
055: super .doLoad(frmModel, jxpc);
056: return;
057: }
058:
059: EnhancedRepeater rep = (EnhancedRepeater) repeater;
060: RepeaterAdapter adapter;
061: if (this .adapterClass != null) {
062: try {
063: adapter = (RepeaterAdapter) Class.forName(
064: this .adapterClass).newInstance();
065: } catch (Exception e) {
066: throw new CascadingRuntimeException(
067: "Cannot instantiate adapter class for advanced repeater binding",
068: e);
069: }
070: } else {
071: adapter = new RepeaterJXPathAdapter();
072: }
073:
074: RepeaterJXPathCollection collection = new RepeaterJXPathCollection();
075: //Pointer ptr = jxpc.getPointer(super.getRepeaterPath());
076: //JXPathContext repeaterContext = jxpc.getRelativeContext(ptr);
077: collection.init(jxpc, super .getRowPath(), adapter);
078: adapter.setBinding(this );
079: adapter.setJXCollection(collection);
080: rep.setCollection(collection);
081: rep.doPageLoad();
082: }
083:
084: public void doSave(Widget frmModel, JXPathContext jxpc)
085: throws BindingException {
086: Repeater repeater = (Repeater) selectWidget(frmModel, super
087: .getId());
088: if (!(repeater instanceof EnhancedRepeater)) {
089: super .doSave(frmModel, jxpc);
090: return;
091: }
092:
093: EnhancedRepeater rep = (EnhancedRepeater) repeater;
094: rep.doPageSave();
095: Pointer ptr = jxpc.getPointer(super .getRepeaterPath());
096: JXPathContext repeaterContext = jxpc.getRelativeContext(ptr);
097: RepeaterJXPathCollection collection = rep.getCollection();
098: // iterate updated rows. note: we don't iterate over the whole context
099: for (Iterator iter = collection.getUpdatedRows().iterator(); iter
100: .hasNext();) {
101: RepeaterItem item = (RepeaterItem) iter.next();
102: Repeater.RepeaterRow this Row = item.getRow();
103: // Get the identity
104: List identity = getIdentity(this Row);
105: if (hasNonNullElements(identity)) {
106: // iterate nodes to find match
107: Iterator rowPointers = repeaterContext
108: .iteratePointers(getRowPath());
109: while (rowPointers.hasNext()) {
110: Pointer jxp = (Pointer) rowPointers.next();
111: JXPathContext rowContext = repeaterContext
112: .getRelativeContext(jxp);
113: List contextIdentity = getIdentity(rowContext);
114: if (ListUtils
115: .isEqualList(identity, contextIdentity)) {
116: getRowBinding().saveFormToModel(this Row,
117: rowContext);
118: break;
119: }
120: }
121: } else {
122: getRowBinding().saveFormToModel(this Row,
123: item.getContext().getContextPointer());
124: }
125: }
126:
127: for (Iterator iter = collection.getDeletedRows().iterator(); iter
128: .hasNext();) {
129: RepeaterItem item = (RepeaterItem) iter.next();
130: jxpc.removePath(item.getContext().createPath(".").asPath());
131: }
132:
133: // insert rows
134: int indexCount = collection.getOriginalCollectionSize()
135: - collection.getDeletedRows().size();
136: for (Iterator iter = collection.getInsertedRows().iterator(); iter
137: .hasNext();) {
138: indexCount++;
139: RepeaterItem item = (RepeaterItem) iter.next();
140:
141: // Perform the insert row binding.
142: if (getInsertRowBinding() != null) {
143: getInsertRowBinding().saveFormToModel(item.getRow(),
144: repeaterContext);
145: }
146: // --> create the path to let the context be created
147: Pointer newRowContextPointer = repeaterContext
148: .createPath(super .getInsertRowPath() + "["
149: + indexCount + "]");
150: JXPathContext newRowContext = repeaterContext
151: .getRelativeContext(newRowContextPointer);
152: // + rebind to children for update
153: super.getRowBinding().saveFormToModel(item.getRow(),
154: newRowContext);
155: }
156: }
157:
158: }
|