001    package ezvcard.types;
002    
003    import java.io.File;
004    import java.io.IOException;
005    import java.io.InputStream;
006    import java.util.List;
007    
008    import ezvcard.io.SkipMeException;
009    import ezvcard.parameters.ImageTypeParameter;
010    import ezvcard.util.DataUri;
011    import ezvcard.util.HCardElement;
012    
013    /*
014     Copyright (c) 2012, 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     The views and conclusions contained in the software and documentation are those
038     of the authors and should not be interpreted as representing official policies, 
039     either expressed or implied, of the FreeBSD Project.
040     */
041    
042    /**
043     * A photo attached to the vCard (such as a portrait of the person).
044     * 
045     * <p>
046     * <b>Adding a photo</b>
047     * </p>
048     * 
049     * <pre>
050     * VCard vcard = new VCard();
051     * 
052     * //URL
053     * PhotoType photo = new PhotoType("http://www.mywebsite.com/mugshot.jpg", ImageTypeParameter.JPEG);
054     * vcard.addPhoto(photo);
055     * 
056     * //binary data
057     * byte data[] = ...
058     * photo = new PhotoType(data, ImageTypeParameter.JPEG);
059     * vcard.addPhoto(photo);
060     * 
061     * //if "ImageTypeParameter" does not have the pre-defined constant that you need, then create a new instance
062     * //arg 1: the value of the 2.1/3.0 TYPE parameter
063     * //arg 2: the value to use for the 4.0 MEDIATYPE parameter and for 4.0 data URIs
064     * //arg 3: the file extension of the data type (optional)
065     * ImageKeyTypeParameter param = new ImageTypeParameter("bmp", "image/x-ms-bmp", "bmp");
066     * photo = new PhotoType("http://www.mywebsite.com/mugshot.bmp", param);
067     * vcard.addPhoto(photo);
068     * </pre>
069     * 
070     * <p>
071     * <b>Getting the photos</b>
072     * </p>
073     * 
074     * <pre>
075     * VCard vcard = ...
076     * 
077     * int fileCount = 0;
078     * for (PhotoType photo : vcard.getPhotos()){
079     *   //the photo will have either a URL or a binary data
080     *   if (photo.getData() == null){
081     *     System.out.println("Photo URL: " + photo.getUrl());
082     *   } else {
083     *     ImageTypeParameter type = photo.getContentType();
084     *     
085     *     if (type == null) {
086     *       //the vCard may not have any content type data associated with the photo
087     *       System.out.println("Saving a photo file...");
088     *     } else {
089     *       System.out.println("Saving a \"" + type.getMediaType() + "\" file...");
090     *     }
091     *     
092     *     String folder;
093     *     if (type == ImageTypeParameter.JPEG){ //it is safe to use "==" instead of "equals()"
094     *       folder = "photos";
095     *     } else {
096     *       folder = "images";
097     *     }
098     *     
099     *     byte data[] = photo.getData();
100     *     String filename = "photo" + fileCount;
101     *     if (type != null && type.getExtension() != null){
102     *      filename += "." + type.getExtension();
103     *     }
104     *     OutputStream out = new FileOutputStream(new File(folder, filename));
105     *     out.write(data);
106     *     out.close();
107     *     fileCount++;
108     *   }
109     * }
110     * </pre>
111     * 
112     * <p>
113     * vCard property name: PHOTO
114     * </p>
115     * <p>
116     * vCard versions: 2.1, 3.0, 4.0
117     * </p>
118     * @author Michael Angstadt
119     */
120    public class PhotoType extends BinaryType<ImageTypeParameter> {
121            public static final String NAME = "PHOTO";
122    
123            public PhotoType() {
124                    super(NAME);
125            }
126    
127            /**
128             * @param url the URL to the photo
129             * @param type the content type (e.g. JPEG)
130             */
131            public PhotoType(String url, ImageTypeParameter type) {
132                    super(NAME, url, type);
133            }
134    
135            /**
136             * @param data the binary data of the photo
137             * @param type the content type (e.g. JPEG)
138             */
139            public PhotoType(byte[] data, ImageTypeParameter type) {
140                    super(NAME, data, type);
141            }
142    
143            /**
144             * @param in an input stream to the binary data (will be closed)
145             * @param type the content type (e.g. JPEG)
146             * @throws IOException if there's a problem reading from the input stream
147             */
148            public PhotoType(InputStream in, ImageTypeParameter type) throws IOException {
149                    super(NAME, in, type);
150            }
151    
152            /**
153             * @param file the image file
154             * @param type the content type (e.g. JPEG)
155             * @throws IOException if there's a problem reading from the file
156             */
157            public PhotoType(File file, ImageTypeParameter type) throws IOException {
158                    super(NAME, file, type);
159            }
160    
161            @Override
162            protected ImageTypeParameter buildTypeObj(String type) {
163                    ImageTypeParameter param = ImageTypeParameter.valueOf(type);
164                    if (param == null) {
165                            param = new ImageTypeParameter(type, "image/" + type, null);
166                    }
167                    return param;
168            }
169    
170            @Override
171            protected ImageTypeParameter buildMediaTypeObj(String mediaType) {
172                    ImageTypeParameter p = ImageTypeParameter.findByMediaType(mediaType);
173                    if (p == null) {
174                            int slashPos = mediaType.indexOf('/');
175                            String type;
176                            if (slashPos == -1 || slashPos < mediaType.length() - 1) {
177                                    type = "";
178                            } else {
179                                    type = mediaType.substring(slashPos + 1);
180                            }
181                            p = new ImageTypeParameter(type, mediaType, null);
182                    }
183                    return p;
184            }
185    
186            @Override
187            protected void doUnmarshalHtml(HCardElement element, List<String> warnings) {
188                    String elementName = element.tagName();
189                    if ("img".equals(elementName)) {
190                            String src = element.absUrl("src");
191                            if (src.length() > 0) {
192                                    try {
193                                            DataUri uri = new DataUri(src);
194                                            ImageTypeParameter mediaType = buildMediaTypeObj(uri.getContentType());
195                                            setData(uri.getData(), mediaType);
196                                    } catch (IllegalArgumentException e) {
197                                            //TODO create buildTypeObjFromExtension() method
198                                            setUrl(src, null);
199                                    }
200                            } else {
201                                    throw new SkipMeException("<img> tag does not have a \"src\" attribute.");
202                            }
203                    } else {
204                            super.doUnmarshalHtml(element, warnings);
205                    }
206            }
207    }