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-2018, 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 return super._dataType(property, version); 061 } 062 063 @Override 064 protected void _prepareParameters(Key property, VCardParameters copy, VCardVersion version, VCard vcard) { 065 if (property.getText() != null) { 066 MediaTypeParameter contentType = property.getContentType(); 067 if (contentType == null) { 068 contentType = new MediaTypeParameter(null, null, null); 069 } 070 071 copy.setEncoding(null); 072 073 switch (version) { 074 case V2_1: 075 copy.setType(contentType.getValue()); 076 copy.setMediaType(null); 077 break; 078 case V3_0: 079 copy.setType(contentType.getValue()); 080 copy.setMediaType(null); 081 break; 082 case V4_0: 083 copy.setMediaType(contentType.getMediaType()); 084 break; 085 } 086 087 return; 088 } 089 090 super._prepareParameters(property, copy, version, vcard); 091 } 092 093 @Override 094 protected String _writeText(Key property, WriteContext context) { 095 String text = property.getText(); 096 if (text != null) { 097 return text; 098 } 099 100 return super._writeText(property, context); 101 } 102 103 @Override 104 protected Key _parseText(String value, VCardDataType dataType, VCardParameters parameters, ParseContext context) { 105 value = VObjectPropertyValues.unescape(value); 106 107 /* 108 * Parse as text if VALUE parameter is explicitly set to TEXT. 109 */ 110 if (dataType == VCardDataType.TEXT) { 111 KeyType contentType = parseContentTypeFromValueAndParameters(value, parameters, context.getVersion()); 112 Key property = new Key(); 113 property.setText(value, contentType); 114 return property; 115 } 116 117 return parse(value, dataType, parameters, context.getVersion()); 118 } 119 120 @Override 121 protected void _writeXml(Key property, XCardElement parent) { 122 String text = property.getText(); 123 if (text != null) { 124 parent.append(VCardDataType.TEXT, text); 125 return; 126 } 127 128 super._writeXml(property, parent); 129 } 130 131 @Override 132 protected Key _parseXml(XCardElement element, VCardParameters parameters, ParseContext context) { 133 String text = element.first(VCardDataType.TEXT); 134 if (text != null) { 135 KeyType contentType = parseContentTypeFromValueAndParameters(text, parameters, element.version()); 136 Key property = new Key(); 137 property.setText(text, contentType); 138 return property; 139 } 140 141 String value = element.first(VCardDataType.URI); 142 if (value != null) { 143 return parse(value, VCardDataType.URI, parameters, element.version()); 144 } 145 146 throw missingXmlElements(VCardDataType.URI, VCardDataType.TEXT); 147 } 148 149 @Override 150 protected JCardValue _writeJson(Key property) { 151 String text = property.getText(); 152 if (text != null) { 153 return JCardValue.single(text); 154 } 155 156 return super._writeJson(property); 157 } 158 159 @Override 160 protected Key _parseJson(JCardValue value, VCardDataType dataType, VCardParameters parameters, ParseContext context) { 161 if (dataType == VCardDataType.TEXT) { 162 String valueStr = value.asSingle(); 163 KeyType contentType = parseContentTypeFromValueAndParameters(valueStr, parameters, VCardVersion.V4_0); 164 Key property = new Key(); 165 property.setText(valueStr, contentType); 166 return property; 167 } 168 169 return super._parseJson(value, dataType, parameters, context); 170 } 171 172 @Override 173 protected KeyType _mediaTypeFromTypeParameter(String type) { 174 return KeyType.get(type, null, null); 175 } 176 177 @Override 178 protected KeyType _mediaTypeFromMediaTypeParameter(String mediaType) { 179 return KeyType.get(null, mediaType, null); 180 } 181 182 @Override 183 protected KeyType _mediaTypeFromFileExtension(String extension) { 184 return KeyType.find(null, null, extension); 185 } 186 187 @Override 188 protected Key _newInstance(String uri, KeyType contentType) { 189 return new Key(uri, contentType); 190 } 191 192 @Override 193 protected Key _newInstance(byte[] data, KeyType contentType) { 194 return new Key(data, contentType); 195 } 196 197 @Override 198 protected Key cannotUnmarshalValue(String value, VCardVersion version, KeyType contentType) { 199 switch (version) { 200 case V2_1: 201 case V3_0: 202 /* 203 * It wasn't explicitly defined as a URI, and didn't have an 204 * ENCODING parameter, so treat it as text. 205 */ 206 Key key = new Key(); 207 key.setText(value, contentType); 208 return key; 209 case V4_0: 210 /* 211 * It wasn't explicitly defined as a text value, and it could not be 212 * parsed as a data URI, so treat it as a generic URI. 213 */ 214 return new Key(value, contentType); 215 } 216 217 return null; 218 } 219}