001package ezvcard.io.scribe; 002 003import java.util.HashMap; 004import java.util.Map; 005 006import javax.xml.transform.OutputKeys; 007 008import org.w3c.dom.Document; 009import org.w3c.dom.Element; 010import org.xml.sax.SAXException; 011 012import com.github.mangstadt.vinnie.io.VObjectPropertyValues; 013 014import ezvcard.VCardDataType; 015import ezvcard.VCardVersion; 016import ezvcard.io.CannotParseException; 017import ezvcard.io.ParseContext; 018import ezvcard.io.json.JCardValue; 019import ezvcard.io.text.WriteContext; 020import ezvcard.io.xml.XCardElement; 021import ezvcard.parameter.VCardParameters; 022import ezvcard.property.Xml; 023import ezvcard.util.XmlUtils; 024 025/* 026 Copyright (c) 2012-2023, Michael Angstadt 027 All rights reserved. 028 029 Redistribution and use in source and binary forms, with or without 030 modification, are permitted provided that the following conditions are met: 031 032 1. Redistributions of source code must retain the above copyright notice, this 033 list of conditions and the following disclaimer. 034 2. Redistributions in binary form must reproduce the above copyright notice, 035 this list of conditions and the following disclaimer in the documentation 036 and/or other materials provided with the distribution. 037 038 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 039 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 040 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 041 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 042 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 043 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 044 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 045 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 046 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 047 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 048 */ 049 050/** 051 * Marshals {@link Xml} properties. 052 * @author Michael Angstadt 053 */ 054public class XmlScribe extends VCardPropertyScribe<Xml> { 055 public XmlScribe() { 056 super(Xml.class, "XML"); 057 } 058 059 @Override 060 protected VCardDataType _defaultDataType(VCardVersion version) { 061 return VCardDataType.TEXT; 062 } 063 064 @Override 065 protected String _writeText(Xml property, WriteContext context) { 066 Document value = property.getValue(); 067 if (value == null) { 068 return ""; 069 } 070 071 String xml = valueToString(value); 072 return escape(xml, context); 073 } 074 075 @Override 076 protected Xml _parseText(String value, VCardDataType dataType, VCardParameters parameters, ParseContext context) { 077 value = VObjectPropertyValues.unescape(value); 078 try { 079 return new Xml(value); 080 } catch (SAXException e) { 081 throw new CannotParseException(21); 082 } 083 } 084 085 @Override 086 protected void _writeXml(Xml property, XCardElement element) { 087 //Xml properties are handled as a special case when writing xCard documents, so this method should never get called (see: "XCardDocument" class) 088 super._writeXml(property, element); 089 } 090 091 @Override 092 protected Xml _parseXml(XCardElement element, VCardParameters parameters, ParseContext context) { 093 Xml xml = new Xml(element.element()); 094 095 //remove the <parameters> element 096 Element root = xml.getValue().getDocumentElement(); 097 for (Element child : XmlUtils.toElementList(root.getChildNodes())) { 098 if ("parameters".equals(child.getLocalName()) && VCardVersion.V4_0.getXmlNamespace().equals(child.getNamespaceURI())) { 099 root.removeChild(child); 100 } 101 } 102 103 return xml; 104 } 105 106 @Override 107 protected JCardValue _writeJson(Xml property) { 108 String xml = null; 109 Document value = property.getValue(); 110 if (value != null) { 111 xml = valueToString(value); 112 } 113 114 return JCardValue.single(xml); 115 } 116 117 @Override 118 protected Xml _parseJson(JCardValue value, VCardDataType dataType, VCardParameters parameters, ParseContext context) { 119 try { 120 String xml = value.asSingle(); 121 return xml.isEmpty() ? new Xml((Document) null) : new Xml(xml); 122 } catch (SAXException e) { 123 throw new CannotParseException(22); 124 } 125 } 126 127 private String valueToString(Document document) { 128 Map<String, String> props = new HashMap<>(); 129 props.put(OutputKeys.OMIT_XML_DECLARATION, "yes"); 130 return XmlUtils.toString(document, props); 131 } 132}