001: /*
002: * Copyright 2001-2008 Hippo (www.hippo.nl)
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package nl.hippo.cocoon.forms.binding;
017:
018: import java.io.IOException;
019: import java.io.StringReader;
020: import java.util.Properties;
021:
022: import javax.xml.parsers.DocumentBuilder;
023: import javax.xml.parsers.DocumentBuilderFactory;
024: import javax.xml.parsers.ParserConfigurationException;
025: import javax.xml.transform.OutputKeys;
026:
027: import org.apache.cocoon.ProcessingException;
028: import org.apache.cocoon.forms.binding.AbstractCustomBinding;
029: import org.apache.cocoon.forms.binding.BindingException;
030: import org.apache.cocoon.forms.formmodel.Widget;
031: import org.apache.cocoon.xml.XMLUtils;
032: import org.apache.commons.jxpath.JXPathContext;
033: import org.apache.commons.jxpath.Pointer;
034: import org.apache.commons.jxpath.ri.model.beans.NullPropertyPointer;
035: import org.w3c.dom.Document;
036: import org.w3c.dom.Node;
037: import org.w3c.dom.NodeList;
038: import org.xml.sax.InputSource;
039: import org.xml.sax.SAXException;
040:
041: /**
042: * Custom binding for form elements containing XML as a string.
043: * It is assumed that the XML in the string has one unique root node
044: * as top level element.
045: *
046: * @author <a href="mailto:j.joachimsthal@hippo.nl">Jasha Joachimsthal</a>
047: */
048: public class ChildXmlAsStringBinding extends AbstractCustomBinding {
049:
050: /**
051: * Serializes the node as String on load.
052: *
053: * @throws BindingException
054: * @see org.apache.cocoon.forms.binding.AbstractCustomBinding#doLoad(org.apache.cocoon.forms.formmodel.Widget,
055: * org.apache.commons.jxpath.JXPathContext)
056: */
057: protected void doLoad(Widget widget, JXPathContext context)
058: throws BindingException {
059: Pointer pointer = context.getPointer(this .getXpath());
060: Node contextNode = (Node) pointer.getNode();
061: try {
062: Properties props = new Properties();
063: props.put(OutputKeys.OMIT_XML_DECLARATION, "yes");
064:
065: String xmlAsString = new String("");
066: if (contextNode != null && contextNode.hasChildNodes()) {
067: NodeList children = contextNode.getChildNodes();
068: for (int i = 0; i < children.getLength(); i++) {
069: xmlAsString = xmlAsString
070: + XMLUtils.serializeNode((Node) children
071: .item(i), props);
072: }
073: }
074: widget.setValue(xmlAsString);
075: } catch (ProcessingException e) {
076: throw new BindingException("Unable to serialize node", e);
077: }
078: }
079:
080: /**
081: * Parses and imports the XML String on save.
082: *
083: * @throws IOException
084: * @throws SAXException
085: * @see org.apache.cocoon.forms.binding.AbstractCustomBinding#doSave(org.apache.cocoon.forms.formmodel.Widget,
086: * org.apache.commons.jxpath.JXPathContext)
087: */
088: protected void doSave(Widget widget, JXPathContext context)
089: throws BindingException, SAXException, IOException {
090: DocumentBuilder builder = null;
091: DocumentBuilderFactory factory = DocumentBuilderFactory
092: .newInstance();
093: try {
094: builder = factory.newDocumentBuilder();
095: } catch (ParserConfigurationException e) {
096: throw new BindingException("Problem getting a parser", e);
097: }
098: String content = (String) widget.getValue();
099: if (content != null) {
100: content = content.replaceAll("\r\n|\n", "");
101:
102: Document dom = builder.parse(new InputSource(
103: new StringReader(content)));
104: Pointer pointer = context.getPointer(this .getXpath());
105: if (pointer instanceof NullPropertyPointer) {
106: pointer = context.createPath(this .getXpath());
107: }
108: Node contextNode = (Node) pointer.getNode();
109: Node result = contextNode.getOwnerDocument().importNode(
110: dom.getDocumentElement(), true);
111:
112: // remove all of the context node's current children
113: while (contextNode.hasChildNodes()) {
114: contextNode.removeChild(contextNode.getFirstChild());
115: }
116:
117: // append new children to context node
118: Node child = result;
119: while (child != null) {
120: Node clonedChild = child.cloneNode(true);
121: contextNode.appendChild(clonedChild);
122: child = child.getNextSibling();
123: }
124: } else {
125: Pointer pointer = context.getPointer(this .getXpath());
126: if (!(pointer instanceof NullPropertyPointer)) {
127: Node contextNode = (Node) pointer.getNode();
128: while (contextNode.hasChildNodes()) {
129: contextNode
130: .removeChild(contextNode.getFirstChild());
131: }
132: }
133: }
134: content = "";
135:
136: }
137:
138: }
|