001package ezvcard.io.scribe; 002 003import com.github.mangstadt.vinnie.io.VObjectPropertyValues; 004 005import ezvcard.VCard; 006import ezvcard.VCardDataType; 007import ezvcard.VCardVersion; 008import ezvcard.io.ParseContext; 009import ezvcard.io.json.JCardValue; 010import ezvcard.io.text.WriteContext; 011import ezvcard.io.xml.XCardElement; 012import ezvcard.parameter.KeyType; 013import ezvcard.parameter.MediaTypeParameter; 014import ezvcard.parameter.VCardParameters; 015import ezvcard.property.Key; 016 017/* 018 Copyright (c) 2012-2026, Michael Angstadt 019 All rights reserved. 020 021 Redistribution and use in source and binary forms, with or without 022 modification, are permitted provided that the following conditions are met: 023 024 1. Redistributions of source code must retain the above copyright notice, this 025 list of conditions and the following disclaimer. 026 2. Redistributions in binary form must reproduce the above copyright notice, 027 this list of conditions and the following disclaimer in the documentation 028 and/or other materials provided with the distribution. 029 030 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 031 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 032 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 033 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 034 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 035 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 036 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 037 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 038 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 039 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 040 */ 041 042/** 043 * Marshals {@link Key} properties. 044 * @author Michael Angstadt 045 */ 046public class KeyScribe extends BinaryPropertyScribe<Key, KeyType> { 047 public KeyScribe() { 048 super(Key.class, "KEY"); 049 } 050 051 @Override 052 protected VCardDataType _dataType(Key property, VCardVersion version) { 053 /* 054 * Only include a "VALUE=TEXT" parameter if it's a 4.0 vCard. 055 */ 056 if (version == VCardVersion.V4_0 && property.getText() != null) { 057 return VCardDataType.TEXT; 058 } 059 060 /* 061 * Always use the URI data type with URL/URIs for consistency (even 062 * though 2.1 technically only supports the "URL" data type). 063 */ 064 if (property.getUrl() != null) { 065 return VCardDataType.URI; 066 } 067 068 return super._dataType(property, version); 069 } 070 071 @Override 072 protected void _prepareParameters(Key property, VCardParameters copy, VCardVersion version, VCard vcard) { 073 if (property.getText() != null) { 074 MediaTypeParameter contentType = property.getContentType(); 075 if (contentType == null) { 076 contentType = new MediaTypeParameter(null, null, null); 077 } 078 079 copy.setEncoding(null); 080 081 switch (version) { 082 case V2_1: 083 case V3_0: 084 copy.setType(contentType.getValue()); 085 copy.setMediaType(null); 086 break; 087 case V4_0: 088 copy.setMediaType(contentType.getMediaType()); 089 break; 090 } 091 092 return; 093 } 094 095 super._prepareParameters(property, copy, version, vcard); 096 } 097 098 @Override 099 protected String _writeText(Key property, WriteContext context) { 100 String text = property.getText(); 101 if (text != null) { 102 return text; 103 } 104 105 return super._writeText(property, context); 106 } 107 108 @Override 109 protected Key _parseText(String value, VCardDataType dataType, VCardParameters parameters, ParseContext context) { 110 value = VObjectPropertyValues.unescape(value); 111 112 /* 113 * Parse as text if VALUE parameter is explicitly set to TEXT. 114 */ 115 if (dataType == VCardDataType.TEXT) { 116 KeyType contentType = parseContentTypeFromValueAndParameters(value, parameters, context.getVersion()); 117 Key property = new Key(); 118 property.setText(value, contentType); 119 return property; 120 } 121 122 return parse(value, dataType, parameters, context.getVersion()); 123 } 124 125 @Override 126 protected void _writeXml(Key property, XCardElement parent) { 127 String text = property.getText(); 128 if (text != null) { 129 parent.append(VCardDataType.TEXT, text); 130 return; 131 } 132 133 super._writeXml(property, parent); 134 } 135 136 @Override 137 protected Key _parseXml(XCardElement element, VCardParameters parameters, ParseContext context) { 138 String text = element.first(VCardDataType.TEXT); 139 if (text != null) { 140 KeyType contentType = parseContentTypeFromValueAndParameters(text, parameters, element.version()); 141 Key property = new Key(); 142 property.setText(text, contentType); 143 return property; 144 } 145 146 String value = element.first(VCardDataType.URI); 147 if (value != null) { 148 return parse(value, VCardDataType.URI, parameters, element.version()); 149 } 150 151 throw missingXmlElements(VCardDataType.URI, VCardDataType.TEXT); 152 } 153 154 @Override 155 protected JCardValue _writeJson(Key property) { 156 String text = property.getText(); 157 if (text != null) { 158 return JCardValue.single(text); 159 } 160 161 return super._writeJson(property); 162 } 163 164 @Override 165 protected Key _parseJson(JCardValue value, VCardDataType dataType, VCardParameters parameters, ParseContext context) { 166 if (dataType == VCardDataType.TEXT) { 167 String valueStr = value.asSingle(); 168 KeyType contentType = parseContentTypeFromValueAndParameters(valueStr, parameters, VCardVersion.V4_0); 169 Key property = new Key(); 170 property.setText(valueStr, contentType); 171 return property; 172 } 173 174 return super._parseJson(value, dataType, parameters, context); 175 } 176 177 @Override 178 protected KeyType _mediaTypeFromTypeParameter(String type) { 179 return KeyType.get(type, null, null); 180 } 181 182 @Override 183 protected KeyType _mediaTypeFromMediaTypeParameter(String mediaType) { 184 return KeyType.get(null, mediaType, null); 185 } 186 187 @Override 188 protected KeyType _mediaTypeFromFileExtension(String extension) { 189 return KeyType.find(null, null, extension); 190 } 191 192 @Override 193 protected Key _newInstance(String uri, KeyType contentType) { 194 return new Key(uri, contentType); 195 } 196 197 @Override 198 protected Key _newInstance(byte[] data, KeyType contentType) { 199 return new Key(data, contentType); 200 } 201 202 @Override 203 protected Key cannotUnmarshalValue(String value, VCardVersion version, KeyType contentType) { 204 switch (version) { 205 case V2_1: 206 case V3_0: 207 /* 208 * It wasn't explicitly defined as a URI, and didn't have an 209 * ENCODING parameter, so treat it as text. 210 */ 211 Key key = new Key(); 212 key.setText(value, contentType); 213 return key; 214 case V4_0: 215 /* 216 * It wasn't explicitly defined as a text value, and it could not be 217 * parsed as a data URI, so treat it as a generic URI. 218 */ 219 return new Key(value, contentType); 220 } 221 222 return null; 223 } 224}