001package biweekly.io.scribe.property; 002 003import biweekly.ICalDataType; 004import biweekly.ICalVersion; 005import biweekly.io.ParseContext; 006import biweekly.io.WriteContext; 007import biweekly.io.json.JCalValue; 008import biweekly.io.xml.XCalElement; 009import biweekly.parameter.Encoding; 010import biweekly.parameter.ICalParameters; 011import biweekly.property.Attachment; 012import biweekly.util.org.apache.commons.codec.binary.Base64; 013 014/* 015 Copyright (c) 2013-2015, Michael Angstadt 016 All rights reserved. 017 018 Redistribution and use in source and binary forms, with or without 019 modification, are permitted provided that the following conditions are met: 020 021 1. Redistributions of source code must retain the above copyright notice, this 022 list of conditions and the following disclaimer. 023 2. Redistributions in binary form must reproduce the above copyright notice, 024 this list of conditions and the following disclaimer in the documentation 025 and/or other materials provided with the distribution. 026 027 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 028 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 029 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 030 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 031 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 032 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 033 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 034 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 035 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 036 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 037 */ 038 039/** 040 * Marshals {@link Attachment} properties. 041 * @author Michael Angstadt 042 */ 043public class AttachmentScribe extends ICalPropertyScribe<Attachment> { 044 public AttachmentScribe() { 045 super(Attachment.class, "ATTACH", ICalDataType.URI); 046 } 047 048 @Override 049 protected ICalParameters _prepareParameters(Attachment property, WriteContext context) { 050 ICalParameters copy = new ICalParameters(property.getParameters()); 051 052 if (property.getUri() != null) { 053 copy.setEncoding(null); 054 } else if (property.getData() != null) { 055 copy.setEncoding(Encoding.BASE64); 056 } 057 058 return copy; 059 } 060 061 @Override 062 protected ICalDataType _dataType(Attachment property, ICalVersion version) { 063 if (property.getUri() != null) { 064 return (version == ICalVersion.V1_0) ? ICalDataType.URL : ICalDataType.URI; 065 } 066 if (property.getData() != null) { 067 return ICalDataType.BINARY; 068 } 069 if (property.getContentId() != null) { 070 return (version == ICalVersion.V1_0) ? ICalDataType.CONTENT_ID : ICalDataType.URI; 071 } 072 return defaultDataType(version); 073 } 074 075 @Override 076 protected String _writeText(Attachment property, WriteContext context) { 077 String uri = property.getUri(); 078 if (uri != null) { 079 return uri; 080 } 081 082 byte data[] = property.getData(); 083 if (data != null) { 084 return Base64.encodeBase64String(data); 085 } 086 087 String contentId = property.getContentId(); 088 if (contentId != null) { 089 return (context.getVersion() == ICalVersion.V1_0) ? contentId : "CID:" + contentId; 090 } 091 092 return ""; 093 } 094 095 @Override 096 protected Attachment _parseText(String value, ICalDataType dataType, ICalParameters parameters, ParseContext context) { 097 value = unescape(value); 098 099 if (dataType == ICalDataType.BINARY || parameters.getEncoding() == Encoding.BASE64) { 100 return new Attachment(null, Base64.decodeBase64(value)); 101 } 102 return new Attachment(null, value); 103 } 104 105 @Override 106 protected void _writeXml(Attachment property, XCalElement element, WriteContext context) { 107 String uri = property.getUri(); 108 if (uri != null) { 109 element.append(ICalDataType.URI, uri); 110 return; 111 } 112 113 byte data[] = property.getData(); 114 if (data != null) { 115 element.append(ICalDataType.BINARY, Base64.encodeBase64String(data)); 116 return; 117 } 118 119 element.append(defaultDataType(context.getVersion()), ""); 120 } 121 122 @Override 123 protected Attachment _parseXml(XCalElement element, ICalParameters parameters, ParseContext context) { 124 String uri = element.first(ICalDataType.URI); 125 if (uri != null) { 126 return new Attachment(null, uri); 127 } 128 129 String base64Data = element.first(ICalDataType.BINARY); 130 if (base64Data != null) { 131 return new Attachment(null, Base64.decodeBase64(base64Data)); //formatType will be set when the parameters are assigned to the property object 132 } 133 134 throw missingXmlElements(ICalDataType.URI, ICalDataType.BINARY); 135 } 136 137 @Override 138 protected JCalValue _writeJson(Attachment property, WriteContext context) { 139 String uri = property.getUri(); 140 if (uri != null) { 141 return JCalValue.single(uri); 142 } 143 144 byte data[] = property.getData(); 145 if (data != null) { 146 return JCalValue.single(Base64.encodeBase64String(data)); 147 } 148 149 return JCalValue.single(""); 150 } 151 152 @Override 153 protected Attachment _parseJson(JCalValue value, ICalDataType dataType, ICalParameters parameters, ParseContext context) { 154 String valueStr = value.asSingle(); 155 156 if (dataType == ICalDataType.BINARY) { 157 return new Attachment(null, Base64.decodeBase64(valueStr)); 158 } 159 return new Attachment(null, valueStr); 160 } 161}