blob: dc85e9660ed13c76a28666a9012cf5cd0b2ce0ed [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 java.util.LinkedList;
import java.util.Locale;
import org.apache.avalon.framework.logger.Logger;
import org.apache.cocoon.woody.datatype.convertor.Convertor;
import org.apache.cocoon.woody.formmodel.Widget;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.Pointer;
/**
* Simple binding for multi fields: on save, first deletes the target data
* before recreating it from scratch.
*
* @version CVS $Id$
*/
public class MultiValueJXPathBinding extends JXPathBindingBase {
private final String multiValueId;
private final String multiValuePath;
private final String rowPath;
private final JXPathBindingBase updateBinding;
private final Convertor convertor;
private final Locale convertorLocale;
public MultiValueJXPathBinding(
JXPathBindingBuilderBase.CommonAttributes commonAtts, String multiValueId,
String multiValuePath, String rowPath,
JXPathBindingBase[] updateBindings, Convertor convertor, Locale convertorLocale) {
super(commonAtts);
this.multiValueId = multiValueId;
this.multiValuePath = multiValuePath;
this.rowPath = rowPath;
this.updateBinding = new ComposedJXPathBindingBase(JXPathBindingBuilderBase.CommonAttributes.DEFAULT, updateBindings);
this.convertor = convertor;
this.convertorLocale = convertorLocale;
}
public void doLoad(Widget frmModel, JXPathContext jctx) throws BindingException {
Widget widget = frmModel.getWidget(this.multiValueId);
if (widget == null) {
throw new BindingException("The widget with the ID [" + this.multiValueId
+ "] referenced in the binding does not exist in the form definition.");
}
// Move to multi value context
Pointer ptr = jctx.getPointer(this.multiValuePath);
if (ptr.getNode() != null) {
// There are some nodes to load from
JXPathContext multiValueContext = jctx.getRelativeContext(ptr);
// build a jxpath iterator for pointers
Iterator rowPointers = multiValueContext.iterate(this.rowPath);
LinkedList list = new LinkedList();
while (rowPointers.hasNext()) {
Object value = rowPointers.next();
if (value != null && convertor != null) {
if (value instanceof String) {
value = convertor.convertFromString((String)value, convertorLocale, null);
} else {
getLogger().warn("Convertor ignored on backend-value which isn't of type String.");
}
}
list.add(value);
}
widget.setValue(list.toArray());
}
if (getLogger().isDebugEnabled())
getLogger().debug("done loading values " + toString());
}
public void doSave(Widget frmModel, JXPathContext jctx) throws BindingException {
Widget widget = frmModel.getWidget(this.multiValueId);
Object[] values = (Object[])widget.getValue();
JXPathContext multiValueContext = jctx.getRelativeContext(jctx.createPath(this.multiValuePath));
// Delete all that is already present
multiValueContext.removeAll(this.rowPath);
boolean update = false;
if (values != null) {
// first update the values
for (int i = 0; i < values.length; i++) {
String path = this.rowPath + '[' + (i+1) + ']';
Pointer rowPtr = multiValueContext.createPath(path);
Object value = values[i];
if (value != null && convertor != null) {
value = convertor.convertToString(value, convertorLocale, null);
}
rowPtr.setValue(value);
}
// now perform any other bindings that need to be performed when the value is updated
this.updateBinding.saveFormToModel(frmModel, multiValueContext);
update = true;
}
if (getLogger().isDebugEnabled()) {
getLogger().debug("done saving " + toString() + " -- on-update == " + update);
}
}
public String toString() {
return "MultiValueJXPathBinding [widget=" + this.multiValueId + ", xpath=" + this.multiValuePath + "]";
}
public void enableLogging(Logger logger) {
super.enableLogging(logger);
this.updateBinding.enableLogging(logger);
}
}