001    package biweekly.property.marshaller;
002    
003    import java.util.HashMap;
004    import java.util.List;
005    import java.util.Map;
006    
007    import javax.xml.transform.OutputKeys;
008    
009    import org.w3c.dom.Document;
010    import org.w3c.dom.Element;
011    import org.xml.sax.SAXException;
012    
013    import biweekly.io.CannotParseException;
014    import biweekly.io.xml.XCalElement;
015    import biweekly.io.xml.XCalNamespaceContext;
016    import biweekly.parameter.ICalParameters;
017    import biweekly.property.Xml;
018    import biweekly.util.XmlUtils;
019    
020    /*
021     Copyright (c) 2013, Michael Angstadt
022     All rights reserved.
023    
024     Redistribution and use in source and binary forms, with or without
025     modification, are permitted provided that the following conditions are met: 
026    
027     1. Redistributions of source code must retain the above copyright notice, this
028     list of conditions and the following disclaimer. 
029     2. Redistributions in binary form must reproduce the above copyright notice,
030     this list of conditions and the following disclaimer in the documentation
031     and/or other materials provided with the distribution. 
032    
033     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
034     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
035     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
036     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
037     ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
038     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
039     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
040     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
041     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
042     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
043     */
044    
045    /**
046     * Marshals {@link Xml} properties.
047     * @author Michael Angstadt
048     */
049    public class XmlMarshaller extends ICalPropertyMarshaller<Xml> {
050            //TODO on writing to plain text: convert to base64 if the string contains values that are illegal within a plain text value (p.17)
051            public XmlMarshaller() {
052                    super(Xml.class, "XML");
053            }
054    
055            @Override
056            protected String _writeText(Xml property) {
057                    Document value = property.getValue();
058                    if (value == null) {
059                            return "";
060                    }
061    
062                    Map<String, String> props = new HashMap<String, String>();
063                    props.put(OutputKeys.OMIT_XML_DECLARATION, "yes");
064                    String xml = XmlUtils.toString(value, props);
065                    return escape(xml);
066            }
067    
068            @Override
069            protected Xml _parseText(String value, ICalParameters parameters, List<String> warnings) {
070                    value = unescape(value);
071                    try {
072                            return new Xml(value);
073                    } catch (SAXException e) {
074                            throw new CannotParseException("Cannot parse value as XML: " + value);
075                    }
076            }
077    
078            @Override
079            protected void _writeXml(Xml property, XCalElement element) {
080                    super._writeXml(property, element);
081                    //Xml properties are handled as a special case when writing xCal documents, so this method should never get called (see: XCalDocument class)
082            }
083    
084            @Override
085            protected Xml _parseXml(XCalElement element, ICalParameters parameters, List<String> warnings) {
086                    Xml xml = new Xml(element.getElement());
087    
088                    //remove the <parameters> element
089                    Element root = XmlUtils.getRootElement(xml.getValue());
090                    for (Element child : XmlUtils.toElementList(root.getChildNodes())) {
091                            if ("parameters".equals(child.getLocalName()) && XCalNamespaceContext.XCAL_NS.equals(child.getNamespaceURI())) {
092                                    root.removeChild(child);
093                            }
094                    }
095    
096                    return xml;
097            }
098    }