001package biweekly.property;
002
003import java.io.File;
004import java.io.FileInputStream;
005import java.io.IOException;
006import java.util.List;
007
008import biweekly.ICalVersion;
009import biweekly.Warning;
010import biweekly.component.ICalComponent;
011import biweekly.util.IOUtils;
012
013/*
014 Copyright (c) 2013-2015, Michael Angstadt
015 All rights reserved.
016
017 Redistribution and use in source and binary forms, with or without
018 modification, are permitted provided that the following conditions are met: 
019
020 1. Redistributions of source code must retain the above copyright notice, this
021 list of conditions and the following disclaimer. 
022 2. Redistributions in binary form must reproduce the above copyright notice,
023 this list of conditions and the following disclaimer in the documentation
024 and/or other materials provided with the distribution. 
025
026 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
027 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
028 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
029 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
030 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
031 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
032 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
033 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
034 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
035 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
036 */
037
038/**
039 * <p>
040 * Defines a binary resource that is associated with the component to which it
041 * belongs (such as an image or document).
042 * </p>
043 * 
044 * <p>
045 * <b>Code sample:</b>
046 * 
047 * <pre class="brush:java">
048 * VEvent event = new VEvent();
049 * 
050 * //from a byte array
051 * byte[] data = ...
052 * Attachment attach = new Attachment(&quot;image/png&quot;, data);
053 * event.addAttachment(attach);
054 * 
055 * //from a file 
056 * File file = new File(&quot;image.png&quot;);
057 * attach = new Attachment(&quot;image/png&quot;, file);
058 * event.addAttachment(attach);
059 * 
060 * //referencing a URL
061 * attach = new Attachment(&quot;image/png&quot;, &quot;http://example.com/image.png&quot;);
062 * event.addAttachment(attach);
063 * </pre>
064 * 
065 * </p>
066 * @author Michael Angstadt
067 * @see <a href="http://tools.ietf.org/html/rfc5545#page-80">RFC 5545 p.80-1</a>
068 * @see <a href="http://tools.ietf.org/html/rfc2445#page-77">RFC 2445 p.77-8</a>
069 * @see <a href="http://www.imc.org/pdi/vcal-10.doc">vCal 1.0 p.25</a>
070 */
071public class Attachment extends ICalProperty {
072        private byte[] data;
073        private String uri, contentId;
074
075        /**
076         * Creates a new attachment.
077         * @param formatType the content-type of the data (e.g. "image/png")
078         * @param file the file to attach
079         * @throws IOException if there's a problem reading from the file
080         */
081        public Attachment(String formatType, File file) throws IOException {
082                this.data = IOUtils.toByteArray(new FileInputStream(file), true);
083                setFormatType(formatType);
084        }
085
086        /**
087         * Creates a new attachment.
088         * @param formatType the content-type of the data (e.g. "image/png")
089         * @param data the binary data
090         */
091        public Attachment(String formatType, byte[] data) {
092                this.data = data;
093                setFormatType(formatType);
094        }
095
096        /**
097         * Creates a new attachment.
098         * @param formatType the content-type of the data (e.g. "image/png")
099         * @param uri a URL pointing to the resource (e.g.
100         * "http://example.com/image.png")
101         */
102        public Attachment(String formatType, String uri) {
103                this.uri = uri;
104                setFormatType(formatType);
105        }
106
107        /**
108         * Gets the attachment's binary data.
109         * @return the binary data or null if not set
110         */
111        public byte[] getData() {
112                return data;
113        }
114
115        /**
116         * Assigns binary data to the attachment's value.
117         * @param data the binary data
118         */
119        public void setData(byte[] data) {
120                this.data = data;
121                uri = null;
122        }
123
124        /**
125         * Gets the attachment's URI.
126         * @return the URI (e.g. "http://example.com/image.png") or null if not set
127         */
128        public String getUri() {
129                return uri;
130        }
131
132        /**
133         * Assigns a URI to the attachment's value.
134         * @param uri the URI (e.g. "http://example.com/image.png")
135         */
136        public void setUri(String uri) {
137                this.uri = uri;
138                data = null;
139        }
140
141        /**
142         * Gets the attachment's content ID.
143         * @return the content ID
144         */
145        public String getContentId() {
146                return contentId;
147        }
148
149        /**
150         * Assigns a content ID to the attachment's value.
151         * @param contentId the content ID
152         */
153        public void setContentId(String contentId) {
154                this.contentId = contentId;
155        }
156
157        @Override
158        public String getFormatType() {
159                return super.getFormatType();
160        }
161
162        @Override
163        public void setFormatType(String formatType) {
164                super.setFormatType(formatType);
165        }
166
167        @Override
168        protected void validate(List<ICalComponent> components, ICalVersion version, List<Warning> warnings) {
169                if (uri == null && data == null && contentId == null) {
170                        warnings.add(Warning.validate(26));
171                }
172        }
173}