001package ezvcard.property; 002 003import java.util.LinkedHashMap; 004import java.util.List; 005import java.util.Map; 006 007import org.w3c.dom.Document; 008import org.w3c.dom.Element; 009import org.w3c.dom.Node; 010import org.xml.sax.SAXException; 011 012import ezvcard.SupportedVersions; 013import ezvcard.VCard; 014import ezvcard.VCardVersion; 015import ezvcard.ValidationWarning; 016import ezvcard.util.XmlUtils; 017 018/* 019 Copyright (c) 2012-2023, Michael Angstadt 020 All rights reserved. 021 022 Redistribution and use in source and binary forms, with or without 023 modification, are permitted provided that the following conditions are met: 024 025 1. Redistributions of source code must retain the above copyright notice, this 026 list of conditions and the following disclaimer. 027 2. Redistributions in binary form must reproduce the above copyright notice, 028 this list of conditions and the following disclaimer in the documentation 029 and/or other materials provided with the distribution. 030 031 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 032 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 033 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 034 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 035 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 036 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 037 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 038 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 039 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 040 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 041 042 The views and conclusions contained in the software and documentation are those 043 of the authors and should not be interpreted as representing official policies, 044 either expressed or implied, of the FreeBSD Project. 045 */ 046 047/** 048 * <p> 049 * Contains an XML element that was not recognized when parsing an xCard 050 * (XML-formatted vCard). 051 * </p> 052 * 053 * <p> 054 * <b>Code sample</b> 055 * </p> 056 * 057 * <pre class="brush:java"> 058 * VCard vcard = new VCard(); 059 * 060 * Xml xml = new Xml("<b>Some xml</b>"); 061 * vcard.addXml(xml); 062 * </pre> 063 * 064 * <p> 065 * <b>Property name:</b> {@code XML} 066 * </p> 067 * <p> 068 * <b>Supported versions:</b> {@code 4.0} 069 * </p> 070 * @author Michael Angstadt 071 * @see <a href="http://tools.ietf.org/html/rfc6350#page-27">RFC 6350 p.27</a> 072 */ 073/* 074 * Note: This class does not extend SimpleProperty because of issues 075 * implementing "equals". SimpleProperty's "equals" method calls the "equals" 076 * method on the "value" field. However, equals method for the "Document" class 077 * does not check for true equality. 078 */ 079@SupportedVersions(VCardVersion.V4_0) 080public class Xml extends VCardProperty implements HasAltId { 081 private Document value; 082 083 /** 084 * Creates an XML property. 085 * @param xml the XML to use as the property's value 086 * @throws SAXException if the XML cannot be parsed 087 */ 088 public Xml(String xml) throws SAXException { 089 this((xml == null) ? null : XmlUtils.toDocument(xml)); 090 } 091 092 /** 093 * Creates an XML property. 094 * @param element the XML element to use as the property's value (the 095 * element is imported into an empty {@link Document} object) 096 */ 097 public Xml(Element element) { 098 this((element == null) ? null : detachElement(element)); 099 } 100 101 private static Document detachElement(Element element) { 102 Document document = XmlUtils.createDocument(); 103 Node imported = document.importNode(element, true); 104 document.appendChild(imported); 105 return document; 106 } 107 108 /** 109 * Creates an XML property. 110 * @param document the XML document to use as the property's value 111 */ 112 public Xml(Document document) { 113 this.value = document; 114 } 115 116 /** 117 * Copy constructor. 118 * @param original the property to make a copy of 119 */ 120 public Xml(Xml original) { 121 super(original); 122 if (original.value != null) { 123 Element root = original.value.getDocumentElement(); 124 value = (root == null) ? XmlUtils.createDocument() : detachElement(root); 125 } 126 } 127 128 /** 129 * Gets the value of this property. 130 * @return the value or null if not set 131 */ 132 public Document getValue() { 133 return value; 134 } 135 136 /** 137 * Sets the value of this property. 138 * @param value the value 139 */ 140 public void setValue(Document value) { 141 this.value = value; 142 } 143 144 //@Override 145 public String getAltId() { 146 return parameters.getAltId(); 147 } 148 149 //@Override 150 public void setAltId(String altId) { 151 parameters.setAltId(altId); 152 } 153 154 @Override 155 protected void _validate(List<ValidationWarning> warnings, VCardVersion version, VCard vcard) { 156 if (value == null) { 157 warnings.add(new ValidationWarning(8)); 158 } 159 } 160 161 @Override 162 protected Map<String, Object> toStringValues() { 163 Map<String, Object> values = new LinkedHashMap<>(); 164 values.put("value", (value == null) ? "null" : XmlUtils.toString(value)); 165 return values; 166 } 167 168 @Override 169 public Xml copy() { 170 return new Xml(this); 171 } 172 173 @Override 174 public int hashCode() { 175 final int prime = 31; 176 int result = super.hashCode(); 177 result = prime * result + ((value == null) ? 0 : XmlUtils.toString(value).hashCode()); 178 return result; 179 } 180 181 @Override 182 public boolean equals(Object obj) { 183 if (this == obj) return true; 184 if (!super.equals(obj)) return false; 185 Xml other = (Xml) obj; 186 if (value == null) { 187 if (other.value != null) return false; 188 } else { 189 if (other.value == null) return false; 190 if (!XmlUtils.toString(value).equals(XmlUtils.toString(other.value))) return false; 191 } 192 return true; 193 } 194}