blob: 717b2e82502e0a3ad68668f644768b2c13c81d22 [file] [log] [blame]
/*
* 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.woody.binding;
import java.util.Iterator;
import org.apache.avalon.framework.logger.Logger;
import org.apache.cocoon.woody.formmodel.Repeater;
import org.apache.cocoon.woody.formmodel.Widget;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.Pointer;
/**
* Simple binding for repeaters: on save, first deletes the target data
* before recreating it from scratch.
* <p>
* For a smarter binding that avoids deletion and recreation, consider
* {@link org.apache.cocoon.woody.binding.RepeaterJXPathBinding}
*
* @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
* @version CVS $Id$
*/
public class SimpleRepeaterJXPathBinding extends JXPathBindingBase {
private final String repeaterId;
private final String repeaterPath;
private final String rowPath;
private final boolean clearOnLoad;
private final JXPathBindingBase rowBinding;
private final boolean deleteIfEmpty;
public SimpleRepeaterJXPathBinding(
JXPathBindingBuilderBase.CommonAttributes commonAtts,
String repeaterId, String repeaterPath, String rowPath,
boolean clearOnLoad, boolean deleteIfEmpty,
JXPathBindingBase rowBinding) {
super(commonAtts);
this.repeaterId = repeaterId;
this.repeaterPath = repeaterPath;
this.rowPath = rowPath;
this.rowBinding = rowBinding;
this.clearOnLoad = clearOnLoad;
this.deleteIfEmpty = deleteIfEmpty;
}
public void doLoad(Widget frmModel, JXPathContext jctx)
throws BindingException {
// Find the repeater and clear it
Repeater repeater = (Repeater)frmModel.getWidget(this.repeaterId);
if (this.clearOnLoad) {
repeater.removeRows();
}
// Move to repeater context
Pointer ptr = jctx.getPointer(this.repeaterPath);
if (ptr.getNode() != null) {
// There are some nodes to load from
JXPathContext repeaterContext = jctx.getRelativeContext(ptr);
// build a jxpath iterator for pointers
Iterator rowPointers = repeaterContext.iteratePointers(this.rowPath);
//iterate through it
int rowNum = 0;
while (rowPointers.hasNext()) {
// Get a row. It is created if needed (depends on clearOnLoad)
Repeater.RepeaterRow thisRow;
if (repeater.getSize() > rowNum) {
thisRow = repeater.getRow(rowNum);
} else {
thisRow = repeater.addRow();
}
rowNum++;
// make a jxpath sub context on the iterated element
Pointer jxp = (Pointer) rowPointers.next();
JXPathContext rowContext = repeaterContext.getRelativeContext(jxp);
this.rowBinding.loadFormFromModel(thisRow, rowContext);
}
}
if (getLogger().isDebugEnabled()) {
getLogger().debug("done loading rows " + toString());
}
}
public void doSave(Widget frmModel, JXPathContext jctx)
throws BindingException {
// Find the repeater
Repeater repeater = (Repeater)frmModel.getWidget(this.repeaterId);
if (repeater.getSize() == 0 && this.deleteIfEmpty) {
// Repeater is empty : erase all
jctx.removeAll(this.repeaterPath);
} else {
// Repeater is not empty
// Move to repeater context and create the path if needed
JXPathContext repeaterContext =
jctx.getRelativeContext(jctx.createPath(this.repeaterPath));
// Delete all that is already present
repeaterContext.removeAll(this.rowPath);
for (int i = 0; i < repeater.getSize(); i++) {
Pointer rowPtr = repeaterContext.createPath(
this.rowPath + '[' + (i+1) + ']');
JXPathContext rowContext =
repeaterContext.getRelativeContext(rowPtr);
this.rowBinding.saveFormToModel(repeater.getRow(i),
rowContext);
}
}
}
public String toString() {
return this.getClass().getName()+ " [widget=" + this.repeaterId +
", xpath=" + this.repeaterPath + "]";
}
public void enableLogging(Logger logger) {
super.enableLogging(logger);
this.rowBinding.enableLogging(logger);
}
}