001: /*
002: * Copyright 2001-2007 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.w3c.dom.Document;
035: import org.w3c.dom.Node;
036: import org.xml.sax.InputSource;
037: import org.xml.sax.SAXException;
038:
039: /**
040: * Custom binding for form elements containing XML as a string.
041: * It is assumed that the XML in the string includes the current context node
042: * as top level element.
043: *
044: * @author <a href="mailto:n.vankampenhout@hippo.nl">Niels van Kampenhout</a>
045: */
046: public class XmlAsStringBinding extends AbstractCustomBinding {
047:
048: /**
049: * Serializes the node as String on load.
050: *
051: * @throws BindingException
052: * @see org.apache.cocoon.forms.binding.AbstractCustomBinding#doLoad(org.apache.cocoon.forms.formmodel.Widget,
053: * org.apache.commons.jxpath.JXPathContext)
054: */
055: protected void doLoad(Widget widget, JXPathContext context)
056: throws BindingException {
057: Pointer pointer = context.getPointer(this .getXpath());
058: Node contextNode = (Node) pointer.getNode();
059: try {
060: Properties props = new Properties();
061: props.put(OutputKeys.OMIT_XML_DECLARATION, "yes");
062: String xmlAsString = XMLUtils.serializeNode(contextNode,
063: props);
064: widget.setValue(xmlAsString);
065: } catch (ProcessingException e) {
066: throw new BindingException("Unable to serialize node", e);
067: }
068: }
069:
070: /**
071: * Parses and imports the XML String on save.
072: *
073: * @throws IOException
074: * @throws SAXException
075: * @see org.apache.cocoon.forms.binding.AbstractCustomBinding#doSave(org.apache.cocoon.forms.formmodel.Widget,
076: * org.apache.commons.jxpath.JXPathContext)
077: */
078: protected void doSave(Widget widget, JXPathContext context)
079: throws BindingException, SAXException, IOException {
080: DocumentBuilder builder = null;
081: DocumentBuilderFactory factory = DocumentBuilderFactory
082: .newInstance();
083: try {
084: builder = factory.newDocumentBuilder();
085: } catch (ParserConfigurationException e) {
086: throw new BindingException("Problem getting a parser", e);
087: }
088: String content = (String) widget.getValue();
089: content = content.replaceAll("\r\n|\n", "");
090: if (content != null) {
091:
092: Document dom = builder.parse(new InputSource(
093: new StringReader(content)));
094: Pointer pointer = context.getPointer(this .getXpath());
095: Node contextNode = (Node) pointer.getNode();
096: Node result = contextNode.getOwnerDocument().importNode(
097: dom.getDocumentElement(), true);
098:
099: // remove all of the context node's current children
100: while (contextNode.hasChildNodes()) {
101: contextNode.removeChild(contextNode.getFirstChild());
102: }
103:
104: // append new children to context node
105: Node child = result.getFirstChild();
106: while (child != null) {
107: Node clonedChild = child.cloneNode(true);
108: contextNode.appendChild(clonedChild);
109: child = child.getNextSibling();
110: }
111: }
112:
113: content = "";
114:
115: }
116:
117: }
|