/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package info.ineighborhood.cardme.io; import info.ineighborhood.cardme.util.Base64Wrapper; import info.ineighborhood.cardme.util.ISOFormat; import info.ineighborhood.cardme.util.ISOUtils; import info.ineighborhood.cardme.util.VCardUtils; import info.ineighborhood.cardme.vcard.EncodingType; import info.ineighborhood.cardme.vcard.VCard; import info.ineighborhood.cardme.vcard.VCardType; import info.ineighborhood.cardme.vcard.VCardVersion; import info.ineighborhood.cardme.vcard.errors.ErrorSeverity; import info.ineighborhood.cardme.vcard.errors.VCardBuildException; import info.ineighborhood.cardme.vcard.errors.VCardError; import info.ineighborhood.cardme.vcard.errors.VCardErrorHandling; import info.ineighborhood.cardme.vcard.errors.VCardException; import info.ineighborhood.cardme.vcard.features.AddressFeature; import info.ineighborhood.cardme.vcard.features.AgentFeature; import info.ineighborhood.cardme.vcard.features.BeginFeature; import info.ineighborhood.cardme.vcard.features.BirthdayFeature; import info.ineighborhood.cardme.vcard.features.CategoriesFeature; import info.ineighborhood.cardme.vcard.features.ClassFeature; import info.ineighborhood.cardme.vcard.features.DisplayableNameFeature; import info.ineighborhood.cardme.vcard.features.EmailFeature; import info.ineighborhood.cardme.vcard.features.EndFeature; import info.ineighborhood.cardme.vcard.features.ExtendedFeature; import info.ineighborhood.cardme.vcard.features.FormattedNameFeature; import info.ineighborhood.cardme.vcard.features.GeographicPositionFeature; import info.ineighborhood.cardme.vcard.features.KeyFeature; import info.ineighborhood.cardme.vcard.features.LabelFeature; import info.ineighborhood.cardme.vcard.features.LogoFeature; import info.ineighborhood.cardme.vcard.features.MailerFeature; import info.ineighborhood.cardme.vcard.features.NameFeature; import info.ineighborhood.cardme.vcard.features.NicknameFeature; import info.ineighborhood.cardme.vcard.features.NoteFeature; import info.ineighborhood.cardme.vcard.features.OrganizationFeature; import info.ineighborhood.cardme.vcard.features.PhotoFeature; import info.ineighborhood.cardme.vcard.features.ProductIdFeature; import info.ineighborhood.cardme.vcard.features.ProfileFeature; import info.ineighborhood.cardme.vcard.features.RevisionFeature; import info.ineighborhood.cardme.vcard.features.RoleFeature; import info.ineighborhood.cardme.vcard.features.SortStringFeature; import info.ineighborhood.cardme.vcard.features.SoundFeature; import info.ineighborhood.cardme.vcard.features.SourceFeature; import info.ineighborhood.cardme.vcard.features.TelephoneFeature; import info.ineighborhood.cardme.vcard.features.TimeZoneFeature; import info.ineighborhood.cardme.vcard.features.TitleFeature; import info.ineighborhood.cardme.vcard.features.UIDFeature; import info.ineighborhood.cardme.vcard.features.URLFeature; import info.ineighborhood.cardme.vcard.features.VersionFeature; import info.ineighborhood.cardme.vcard.types.parameters.AddressParameterType; import info.ineighborhood.cardme.vcard.types.parameters.EmailParameterType; import info.ineighborhood.cardme.vcard.types.parameters.LabelParameterType; import info.ineighborhood.cardme.vcard.types.parameters.TelephoneParameterType; import info.ineighborhood.cardme.vcard.types.parameters.TimeZoneParameterType; import info.ineighborhood.cardme.vcard.types.parameters.XAddressParameterType; import info.ineighborhood.cardme.vcard.types.parameters.XEmailParameterType; import info.ineighborhood.cardme.vcard.types.parameters.XLabelParameterType; import info.ineighborhood.cardme.vcard.types.parameters.XTelephoneParameterType; import java.util.Iterator; /** * Copyright (c) 2004, Neighborhood Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Neighborhood Technologies nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * * @author George El-Haddad * <br/> * Jun 23, 2006 * <br/> * <br/> * * @author Wolfgang Fahl * <br/> * Dec 01, 2009 * */ public class VCardWriter { /** * <p>The VCard we set so that we can output it * into a textual .VCF formatted string.</p> */ private VCard vcard = null; /** * <p>The output version of the vcard. This is * where we specify which version VCard we want * to output.</p> */ private VCardVersion outputVersion = null; /** * <p>Selects which line/data folding scheme should * be used. The default is to use the standard RFC-2426 * folding scheme of 75 max characters per line. Some * applications use less ... or more.</p> */ private FoldingScheme foldingScheme = null; /** * <p>Selects from a list of application compatibility modes * to use when formatting the output of the vcard. Some applications * expect a certain type of formatting or non-standard types.</p> */ private CompatibilityMode compatMode = null; /** * <p>If set true then any exception that occurs will be thrown * when using this class. The alternative is to store each exception * inside the VCard object. These errors can be retrieved after * the writing process.</p> */ private boolean isThrowsExceptions = true; /** * <p>Creates a new VCardWriter with default parameters.</p> * * @throws VCardException */ public VCardWriter() throws VCardException { this(null,null,null); } /** * <p>Creates a new VCardWriter with a specified version.</p> * * @see VCardVersion * * @param outputVersion * @throws VCardException */ public VCardWriter(VCardVersion outputVersion) throws VCardException { this(outputVersion, null, null); } /** * <p>Creates a new VCardWriter with a specified version and folding scheme.</p> * * @see VCardVersion * @see FoldingScheme * * @param outputVersion * @param foldingScheme * @throws VCardException */ public VCardWriter(VCardVersion outputVersion, FoldingScheme foldingScheme) throws VCardException { this(outputVersion, foldingScheme, null); } /** * <p>Creates a new VCardWriter with a specified version and compatibility mode.</p> * * @see VCardVersion * @see CompatibilityMode * * @param outputVersion * @param compatMode * @throws VCardException */ public VCardWriter(VCardVersion outputVersion, CompatibilityMode compatMode) throws VCardException { this(outputVersion, null, compatMode); } /** * <p>Creates a new VCardWriter with a specified version, folding scheme and compatibility mode.</p> * * @see VCardVersion * @see FoldingScheme * @see CompatibilityMode * * @param outputVersion * @param foldingScheme * @param compatMode * @throws VCardException */ public VCardWriter(VCardVersion outputVersion, FoldingScheme foldingScheme, CompatibilityMode compatMode) throws VCardException { setOutputVersion(outputVersion); setFoldingScheme(foldingScheme); setCompatibilityMode(compatMode); } /** * <p>Returns the VCard that was set. * Null if no vcard was set.</p> * * @return {@link VCard} */ public VCard getVCard() { return vcard; } /** * <p>Sets the vcard to be outputted.</p> * * @param vcard * @throws VCardException */ public void setVCard(VCard vcard) throws VCardException { if(vcard == null) { throw new VCardException("Cannot set a null vcard."); } this.vcard = vcard; if(vcard instanceof VCardErrorHandling) { isThrowsExceptions = ((VCardErrorHandling)vcard).isThrowExceptions(); } } /** * <p>Sets the VCard format to output to. * If null {@link VCardVersion}.V3_0 is used.</p> * * @param outputVersion */ public void setOutputVersion(VCardVersion outputVersion) throws VCardException { if(outputVersion == null) { this.outputVersion = VCardVersion.V3_0; } else { if(outputVersion == VCardVersion.V2_1 || outputVersion == VCardVersion.V4_0) { throw new VCardException("Version "+outputVersion+" not supported."); } this.outputVersion = outputVersion; } } /** * <p>Sets the folding scheme to use when folding long lines. * If null {@link FoldingScheme}.MIME_DIR is used.</p> * * @param foldingScheme */ public void setFoldingScheme(FoldingScheme foldingScheme) { if(foldingScheme == null) { this.foldingScheme = FoldingScheme.MIME_DIR; } else { this.foldingScheme = foldingScheme; } } /** * <p>Sets the compatibility mode for outputting the vcard. * If null {@link CompatibilityMode}.RFC2426 is used.</p> * * @param compatMode */ public void setCompatibilityMode(CompatibilityMode compatMode) { if(compatMode == null) { this.compatMode = CompatibilityMode.RFC2426; } else { this.compatMode = compatMode; } } /** * <p>Constructs a String in a suitable format to be written out * as a .VCF file. This method will throw {@link VCardException}s only * if the given VCard is set to throw exceptions. If not then exceptions * are silently collected.</p> * * @return {@link String} */ public String buildVCardString() { if(vcard == null) { throw new VCardException("Cannot build a null VCard."); } StringBuilder sb = new StringBuilder(); /* * Begin * Must be present. */ try { buildBeginFeature(sb, vcard.getBegin()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.FATAL); } } /* * Version * Must be present. */ try { buildVersionFeature(sb, vcard.getVersion()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.FATAL); } } /* * Name * Must be present. */ try { buildNameFeature(sb, vcard.getName()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.FATAL); } } /* * Formatted Name * Must be present. */ try { buildFormattedNameFeature(sb, vcard.getFormattedName()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.FATAL); } } /* * Displayable Name */ if(vcard.hasDisplayableNameFeature()) { try { buildDisplayableNameFeature(sb, vcard.getDisplayableNameFeature()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.FATAL); } } } /* * Profile */ if(vcard.hasProfile()) { try { buildProfileFeature(sb, vcard.getProfile()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.FATAL); } } } /* * Source */ if(vcard.hasSource()) { try { buildSourceFeature(sb, vcard.getSource()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.FATAL); } } } /* * Nicknames * TODO nicknames are present in Outlook mode with V2.1 */ if(vcard.hasNicknames()) { try { buildNicknames(sb, vcard.getNicknames()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } /* * Title */ if(vcard.hasTitle()) { try { buildTitleFeature(sb, vcard.getTitle()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } /* * Role */ if(vcard.hasRole()) { try { buildRoleFeature(sb, vcard.getRole()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } /* * Geographic Position */ if(vcard.hasGeographicPosition()) { try { buildGeographicPositionFeature(sb, vcard.getGeographicPosition()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } /* * Organizations */ if(vcard.hasOrganizations()) { try { buildOrganization(sb, vcard.getOrganizations()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } /* * Mailer */ if(vcard.hasMailer()) { try { buildMailerFeature(sb, vcard.getMailer()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } /* * Time Zone */ if(vcard.hasTimeZone()) { try { buildTimeZoneFeature(sb, vcard.getTimeZone()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } /* * URL */ if(vcard.hasURLs()) { Iterator<URLFeature> urls = vcard.getURLs(); while(urls.hasNext()) { URLFeature urlFeature = urls.next(); try { buildUrlFeature(sb, urlFeature); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } } /* * Revision */ if(vcard.hasRevision()) { try { buildRevisionFeature(sb, vcard.getRevision()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } /* * UID */ if(vcard.hasUID()) { try { buildUidFeature(sb, vcard.getUID()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } /* * Birthday */ if(vcard.hasBirthday()) { try { buildBirthdayFeature(sb, vcard.getBirthDay()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } /* * Addresses & Labels */ if(vcard.hasAddresses()) { Iterator<AddressFeature> addresses = vcard.getAddresses(); while(addresses.hasNext()) { AddressFeature address = addresses.next(); try { buildAddressFeature(sb, address); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } if(vcard.hasLabel(address)) { LabelFeature label = vcard.getLabelFor(address); try { buildLabelFeature(sb, label); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } } } /* * Telephone Numbers */ if(vcard.hasTelephoneNumbers()) { Iterator<TelephoneFeature> telephones = vcard.getTelephoneNumbers(); while(telephones.hasNext()) { TelephoneFeature telephone = telephones.next(); try { buildTelephoneFeature(sb, telephone); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } } /* * Email */ if(vcard.hasEmails()) { Iterator<EmailFeature> emails = vcard.getEmails(); while(emails.hasNext()) { EmailFeature email = emails.next(); try { buildEmailFeature(sb, email); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } } /* * Notes */ if(vcard.hasNotes()) { Iterator<NoteFeature> notes = vcard.getNotes(); while(notes.hasNext()) { NoteFeature note = notes.next(); try { buildNoteFeature(sb, note); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } } /* * Categories */ if(vcard.hasCategories()) { try { buildCategoriesFeature(sb, vcard.getCategories()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } /* * Security Class */ if(vcard.hasSecurityClass()) { try { buildClassFeature(sb, vcard.getSecurityClass()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } /* * Product ID */ if(vcard.hasProductId()) { try { buildProductIdFeature(sb, vcard.getProductId()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } /* * Sort String */ if(vcard.hasSortString()) { try { buildSortStringFeature(sb, vcard.getSortString()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } /* * Keys */ if(vcard.hasKeys()) { Iterator<KeyFeature> keys = vcard.getKeys(); while(keys.hasNext()) { KeyFeature key = keys.next(); try { buildKeyFeature(sb, key); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } } /* * Photos */ if(vcard.hasPhotos()) { Iterator<PhotoFeature> photos = vcard.getPhotos(); while(photos.hasNext()) { PhotoFeature photo = photos.next(); try { buildPhotoFeature(sb, photo); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } } /* * Logos */ if(vcard.hasLogos()) { Iterator<LogoFeature> logos = vcard.getLogos(); while(logos.hasNext()) { LogoFeature logo = logos.next(); try { buildLogoFeature(sb, logo); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } } /* * Sounds */ if(vcard.hasSounds()) { Iterator<SoundFeature> sounds = vcard.getSounds(); while(sounds.hasNext()) { SoundFeature sound = sounds.next(); try { buildSoundFeature(sb, sound); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } } /* * Agents */ if(vcard.hasAgents()) { Iterator<AgentFeature> agents = vcard.getAgents(); while(agents.hasNext()) { AgentFeature agent = agents.next(); try { buildAgentFeature(sb, agent); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } } /* * Extensions */ if(vcard.hasExtendedTypes()) { Iterator<ExtendedFeature> extensions = vcard.getExtendedTypes(); while(extensions.hasNext()) { ExtendedFeature extension = extensions.next(); try { buildExtendedFeature(sb, extension); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.WARNING); } } } } /* * End * Must be present. */ try { buildEndFeature(sb, vcard.getEnd()); } catch(VCardBuildException vbe) { if(isThrowsExceptions) { throw new VCardException(vbe.getMessage(), vbe); } else { handleError(vbe.getMessage(), vbe, ErrorSeverity.FATAL); } } return sb.toString(); } /** * <p>Builds the begin feature as a String.</p> * * @param sb * - StringBuilder to append to * @param beginFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when begin feature is null */ private void buildBeginFeature(StringBuilder sb, BeginFeature beginFeature) throws VCardBuildException { try { if(beginFeature != null) { if(beginFeature.hasGroup()) { sb.append(beginFeature.getGroup()); sb.append("."); } sb.append(beginFeature.getTypeString()); sb.append(":VCARD"); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("Cannot continue because BeginFeature ("+VCardType.BEGIN.getType()+") is null."); } } catch(Exception ex) { throw new VCardBuildException("BeginFeature ("+VCardType.BEGIN.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the end feature as a String.</p> * * @param sb * - StringBuilder to append to * @param beginFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when end feature is null */ private void buildEndFeature(StringBuilder sb, EndFeature endFeature) throws VCardBuildException { try { if(endFeature != null) { if(endFeature.hasGroup()) { sb.append(endFeature.getGroup()); sb.append("."); } sb.append(endFeature.getTypeString()); sb.append(":VCARD"); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("Cannot continue because EndFeature ("+VCardType.END.getType()+") is null."); } } catch(Exception ex) { throw new VCardBuildException("EndFeature ("+VCardType.END.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the version feature as a String.</p> * * @param sb * - StringBuilder to append to * @param versionFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when version feature is null */ private void buildVersionFeature(StringBuilder sb, VersionFeature versionFeature) throws VCardBuildException { try { if(versionFeature != null) { if(versionFeature.hasGroup()) { sb.append(versionFeature.getGroup()); sb.append("."); } sb.append(versionFeature.getTypeString()); sb.append(":"); sb.append(versionFeature.getVersion().getVersion()); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("Cannot continue because VersionFeature ("+VCardType.VERSION.getType()+") is null."); } } catch(Exception ex) { throw new VCardBuildException("VersionFeature ("+VCardType.VERSION.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the name feature as a String. The order in which the name feature is built * is as follows: Family Name, Given Name, Additional Names, Honorific Prefixes, and Honorific Suffixes. * More details of the exact syntax are described in the {@link NameFeature} class itself.</p> * * @param sb * - StringBuilder to append to * @param nameFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the name feature is null */ private void buildNameFeature(StringBuilder sb, NameFeature nameFeature) throws VCardBuildException { try { if(nameFeature != null) { StringBuilder tmpSb = new StringBuilder(); if(nameFeature.hasGroup()) { tmpSb.append(nameFeature.getGroup()); tmpSb.append("."); } tmpSb.append(nameFeature.getTypeString()); tmpSb.append(":"); if(nameFeature.hasFamilyName()) { tmpSb.append(VCardUtils.escapeString(nameFeature.getFamilyName())); } tmpSb.append(";"); if(nameFeature.hasGivenName()) { tmpSb.append(VCardUtils.escapeString(nameFeature.getGivenName())); } tmpSb.append(";"); if(nameFeature.hasAdditionalNames()) { Iterator<String> additionalNames = nameFeature.getAdditionalNames(); while(additionalNames.hasNext()) { String addName = additionalNames.next(); tmpSb.append(VCardUtils.escapeString(addName)); tmpSb.append(","); } tmpSb.deleteCharAt(tmpSb.length()-1); // remove trailing comma } tmpSb.append(";"); if(nameFeature.hasHonorificPrefixes()) { Iterator<String> prefixes = nameFeature.getHonorificPrefixes(); while(prefixes.hasNext()) { String prefix = prefixes.next(); tmpSb.append(VCardUtils.escapeString(prefix)); tmpSb.append(","); } tmpSb.deleteCharAt(tmpSb.length()-1); } tmpSb.append(";"); if(nameFeature.hasHonorificSuffixes()) { Iterator<String> suffixes = nameFeature.getHonorificSuffixes(); while(suffixes.hasNext()) { String suffix = suffixes.next(); tmpSb.append(VCardUtils.escapeString(suffix)); tmpSb.append(","); } tmpSb.deleteCharAt(tmpSb.length()-1); } String tmpNameLine = tmpSb.toString(); String foldedNameLine = VCardUtils.foldLine(tmpNameLine, foldingScheme); sb.append(foldedNameLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("NameFeature ("+VCardType.N.getType()+") cannot be left null."); } } catch(Exception ex) { throw new VCardBuildException("NameFeature ("+VCardType.N.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the formatted name feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param formattedNameFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the formatted name feature is null */ private void buildFormattedNameFeature(StringBuilder sb, FormattedNameFeature formattedNameFeature) throws VCardBuildException { try { if(formattedNameFeature != null) { String formattedName = formattedNameFeature.getFormattedName(); StringBuilder tmpSb = new StringBuilder(); if(formattedNameFeature.hasGroup()) { tmpSb.append(formattedNameFeature.getGroup()); tmpSb.append("."); } tmpSb.append(formattedNameFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(VCardUtils.escapeString(formattedName)); String tmpFormattedNameLine = tmpSb.toString(); String foldedFormattedNameLine = VCardUtils.foldLine(tmpFormattedNameLine, foldingScheme); sb.append(foldedFormattedNameLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("FormattedNameFeature ("+VCardType.FN.getType()+") cannot be left null."); } } catch(Exception ex) { throw new VCardBuildException("FormattedNameFeature ("+VCardType.FN.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the displayable name as a String</p> * * @param sb * - The StringBuilder to append to * @param formattedNameFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the displayable name feature is null */ private void buildDisplayableNameFeature(StringBuilder sb, DisplayableNameFeature displayableNameFeature) throws VCardBuildException { try { if(displayableNameFeature != null) { String displayableName = displayableNameFeature.getName(); StringBuilder tmpSb = new StringBuilder(); if(displayableNameFeature.hasGroup()) { tmpSb.append(displayableNameFeature.getGroup()); tmpSb.append("."); } tmpSb.append(displayableNameFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(VCardUtils.escapeString(displayableName)); String tmpDisplayableNameLine = tmpSb.toString(); String foldedDisplayableNameLine = VCardUtils.foldLine(tmpDisplayableNameLine, foldingScheme); sb.append(foldedDisplayableNameLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("DisplayableNameFeature ("+VCardType.NAME.getType()+") cannot be left null."); } } catch(Exception ex) { throw new VCardBuildException("DisplayableNameFeature ("+VCardType.NAME.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the profile as a String</p> * * @param sb * - The StringBuilder to append to * @param formattedNameFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the profile feature is null */ private void buildProfileFeature(StringBuilder sb, ProfileFeature profileFeature) throws VCardBuildException { try { if(profileFeature != null) { String profile = profileFeature.getProfile(); StringBuilder tmpSb = new StringBuilder(); if(profileFeature.hasGroup()) { tmpSb.append(profileFeature.getGroup()); tmpSb.append("."); } tmpSb.append(profileFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(VCardUtils.escapeString(profile)); String tmpProfileLine = tmpSb.toString(); String foldedProfileLine = VCardUtils.foldLine(tmpProfileLine, foldingScheme); sb.append(foldedProfileLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("ProfileFeature ("+VCardType.PROFILE.getType()+") cannot be left null."); } } catch(Exception ex) { throw new VCardBuildException("ProfileFeature ("+VCardType.PROFILE.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the source as a String</p> * * @param sb * - The StringBuilder to append to * @param formattedNameFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the source feature is null */ private void buildSourceFeature(StringBuilder sb, SourceFeature sourceFeature) throws VCardBuildException { try { if(sourceFeature != null) { String source = sourceFeature.getSource(); StringBuilder tmpSb = new StringBuilder(); if(sourceFeature.hasGroup()) { tmpSb.append(sourceFeature.getGroup()); tmpSb.append("."); } tmpSb.append(sourceFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(VCardUtils.escapeString(source)); String tmpSourceLine = tmpSb.toString(); String foldedSourceLine = VCardUtils.foldLine(tmpSourceLine, foldingScheme); sb.append(foldedSourceLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("SourceFeature ("+VCardType.SOURCE.getType()+") cannot be left null."); } } catch(Exception ex) { throw new VCardBuildException("SourceFeature ("+VCardType.SOURCE.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the title feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param titleFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the title feature is null */ private void buildTitleFeature(StringBuilder sb, TitleFeature titleFeature) throws VCardBuildException { try { if(titleFeature != null) { if(titleFeature.hasTitle()) { String title = titleFeature.getTitle(); StringBuilder tmpSb = new StringBuilder(); if(titleFeature.hasGroup()) { tmpSb.append(titleFeature.getGroup()); tmpSb.append("."); } tmpSb.append(titleFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(VCardUtils.escapeString(title)); String tmpTitleLine = tmpSb.toString(); String foldedTitleLine = VCardUtils.foldLine(tmpTitleLine, foldingScheme); sb.append(foldedTitleLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("TitleFeature ("+VCardType.TITLE.getType()+") exists but is emtpy."); } } } catch(Exception ex) { throw new VCardBuildException("TitleFeature ("+VCardType.TITLE.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the role feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param roleFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the role feature is null */ private void buildRoleFeature(StringBuilder sb, RoleFeature roleFeature) throws VCardBuildException { try { if(roleFeature != null) { if(roleFeature.hasRole()) { String role = roleFeature.getRole(); StringBuilder tmpSb = new StringBuilder(); if(roleFeature.hasGroup()) { tmpSb.append(roleFeature.getGroup()); tmpSb.append("."); } tmpSb.append(roleFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(VCardUtils.escapeString(role)); String tmpRoleLine = tmpSb.toString(); String foldedRoleLine = VCardUtils.foldLine(tmpRoleLine, foldingScheme); sb.append(foldedRoleLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("RoleFeature ("+VCardType.ROLE.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("RoleFeature ("+VCardType.ROLE.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the geographic position feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param geographicPositionFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the geographic position feature is null */ private void buildGeographicPositionFeature(StringBuilder sb, GeographicPositionFeature geographicPositionFeature) throws VCardBuildException { try { if(geographicPositionFeature != null) { StringBuilder tmpSb = new StringBuilder(); if(geographicPositionFeature.hasGroup()) { tmpSb.append(geographicPositionFeature.getGroup()); tmpSb.append("."); } tmpSb.append(geographicPositionFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(VCardUtils.getGeographicPositionFormatter().format(geographicPositionFeature.getLatitude())); tmpSb.append(";"); tmpSb.append(VCardUtils.getGeographicPositionFormatter().format(geographicPositionFeature.getLongitude())); String tmpGeoLine = tmpSb.toString(); String foldedGeoLine = VCardUtils.foldLine(tmpGeoLine, foldingScheme); sb.append(foldedGeoLine); sb.append(VCardUtils.CRLF); } } catch(Exception ex) { throw new VCardBuildException("GeographicPositionFeature ("+VCardType.GEO.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the organization feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param organizationFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the organization feature is null */ private void buildOrganization(StringBuilder sb, OrganizationFeature organizationFeature) throws VCardBuildException { try { if(organizationFeature != null) { if(organizationFeature.hasOrganizations()) { StringBuilder tmpSb = new StringBuilder(); if(organizationFeature.hasGroup()) { tmpSb.append(organizationFeature.getGroup()); tmpSb.append("."); } tmpSb.append(organizationFeature.getTypeString()); tmpSb.append(":"); Iterator<String> orgs = organizationFeature.getOrganizations(); while(orgs.hasNext()) { String org = orgs.next(); tmpSb.append(VCardUtils.escapeString(org)); tmpSb.append(";"); } tmpSb.deleteCharAt(tmpSb.length()-1); String tmpOrgLine = tmpSb.toString(); String foldedOrgLine = VCardUtils.foldLine(tmpOrgLine, foldingScheme); sb.append(foldedOrgLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("OrganizationFeature ("+VCardType.ORG.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("OrganizationFeature ("+VCardType.ORG.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the mailer feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param mailerFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the mailer feature is null */ private void buildMailerFeature(StringBuilder sb, MailerFeature mailerFeature) throws VCardBuildException { try { if(mailerFeature != null) { if(mailerFeature.hasMailer()) { StringBuilder tmpSb = new StringBuilder(); if(mailerFeature.hasGroup()) { tmpSb.append(mailerFeature.getGroup()); tmpSb.append("."); } tmpSb.append(mailerFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(VCardUtils.escapeString(mailerFeature.getMailer())); String tmpMailerLine = tmpSb.toString(); String foldedMailerLine = VCardUtils.foldLine(tmpMailerLine, foldingScheme); sb.append(foldedMailerLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("MailerFeature ("+VCardType.MAILER.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("MailerFeature ("+VCardType.MAILER.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the time zone feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param timeZoneFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the time zone feature is null */ private void buildTimeZoneFeature(StringBuilder sb, TimeZoneFeature timeZoneFeature) throws VCardBuildException { try { if(timeZoneFeature != null) { StringBuilder tmpSb = new StringBuilder(); if(timeZoneFeature.hasGroup()) { tmpSb.append(timeZoneFeature.getGroup()); tmpSb.append("."); } tmpSb.append(timeZoneFeature.getTypeString()); if(timeZoneFeature.getTimeZone() == null && timeZoneFeature.getTextValue() != null) { tmpSb.append(";"); tmpSb.append(TimeZoneParameterType.VALUE.getType()); tmpSb.append("=TEXT:"); tmpSb.append(timeZoneFeature.getTextValue()); } else { tmpSb.append(":"); tmpSb.append(timeZoneFeature.getIso8601Offset()); } String tmpTimeZoneLine = tmpSb.toString(); String foldedTimeZoneLine = VCardUtils.foldLine(tmpTimeZoneLine, foldingScheme); sb.append(foldedTimeZoneLine); sb.append(VCardUtils.CRLF); } } catch(Exception ex) { throw new VCardBuildException("TimeZoneFeature ("+VCardType.TZ.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the URL feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param urlFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the URL feature is null */ private void buildUrlFeature(StringBuilder sb, URLFeature urlFeature) throws VCardBuildException { try { if(urlFeature != null) { if(urlFeature.hasURL()) { StringBuilder tmpSb = new StringBuilder(); if(urlFeature.hasGroup()) { tmpSb.append(urlFeature.getGroup()); tmpSb.append("."); } tmpSb.append(urlFeature.getTypeString()); tmpSb.append(":"); String url = urlFeature.getURL().toString(); if(VCardUtils.needsEscaping(url)) { tmpSb.append(VCardUtils.escapeString(url)); } else { tmpSb.append(url); } String tmpUrlLine = tmpSb.toString(); String foldedUrlLine = VCardUtils.foldLine(tmpUrlLine, foldingScheme); sb.append(foldedUrlLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("URLFeature ("+VCardType.URL.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("URLFeature ("+VCardType.URL.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the revision feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param revisionFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the revision feature is null */ private void buildRevisionFeature(StringBuilder sb, RevisionFeature revisionFeature) throws VCardBuildException { try { if(revisionFeature != null) { if(revisionFeature.hasRevision()) { StringBuilder tmpSb = new StringBuilder(); if(revisionFeature.hasGroup()) { tmpSb.append(revisionFeature.getGroup()); tmpSb.append("."); } tmpSb.append(revisionFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(ISOUtils.toISO8601_UTC_Time(revisionFeature.getRevision(), ISOFormat.ISO8601_EXTENDED)); String tmpRevisionLine = tmpSb.toString(); String foldedRevisionLine = VCardUtils.foldLine(tmpRevisionLine, foldingScheme); sb.append(foldedRevisionLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("RevisionFeature ("+VCardType.REV.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("RevisionFeature ("+VCardType.REV.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the UID feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param uidFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the uid feature is null */ private void buildUidFeature(StringBuilder sb, UIDFeature uidFeature) throws VCardBuildException { try { if(uidFeature != null) { if(uidFeature.hasUID()) { StringBuilder tmpSb = new StringBuilder(); if(uidFeature.hasGroup()) { tmpSb.append(uidFeature.getGroup()); tmpSb.append("."); } tmpSb.append(uidFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(uidFeature.getUID()); String tmpUidLine = tmpSb.toString(); String foldedUidLine = VCardUtils.foldLine(tmpUidLine, foldingScheme); sb.append(foldedUidLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("UIDFeature ("+VCardType.UID.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("UIDFeature ("+VCardType.UID.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the birthday feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param birthdayFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the birthday feature is null */ private void buildBirthdayFeature(StringBuilder sb, BirthdayFeature birthdayFeature) throws VCardBuildException { try { if(birthdayFeature != null) { StringBuilder tmpSb = new StringBuilder(); if(birthdayFeature.hasGroup()) { tmpSb.append(birthdayFeature.getGroup()); tmpSb.append("."); } tmpSb.append(birthdayFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(ISOUtils.toISO8601_Date(birthdayFeature.getBirthday(), ISOFormat.ISO8601_EXTENDED)); String tmpBdayLine = tmpSb.toString(); String foldedBdayLine = VCardUtils.foldLine(tmpBdayLine, foldingScheme); sb.append(foldedBdayLine); sb.append(VCardUtils.CRLF); } } catch(Exception ex) { throw new VCardBuildException("BirthdayFeature ("+VCardType.BDAY.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the address feature as a String. The order of the address is built as follows: * post office box; the extended address; the street address; the locality; the region; the postal code; the country name. * The street address can contain multiple values separated by a comma.</p> * * @param sb * - The StringBuilder to append to * @param addressFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the address feature is null */ private void buildAddressFeature(StringBuilder sb, AddressFeature addressFeature) throws VCardBuildException { try { if(addressFeature != null) { StringBuilder tmpSb = new StringBuilder(); if(addressFeature.hasGroup()) { tmpSb.append(addressFeature.getGroup()); tmpSb.append("."); } tmpSb.append(addressFeature.getTypeString()); if(addressFeature.hasAddressParameterTypes()) { tmpSb.append(";"); Iterator<AddressParameterType> paramTypes = addressFeature.getAddressParameterTypes(); switch(addressFeature.getParameterTypeStyle()) { case PARAMETER_LIST: { while(paramTypes.hasNext()) { AddressParameterType addrType = paramTypes.next(); tmpSb.append("TYPE="); tmpSb.append(addrType.getType()); tmpSb.append(";"); } break; } case PARAMETER_VALUE_LIST: { tmpSb.append("TYPE="); while(paramTypes.hasNext()) { AddressParameterType addrType = paramTypes.next(); tmpSb.append(addrType.getType()); tmpSb.append(","); } break; } } tmpSb.deleteCharAt(tmpSb.length()-1); } if(addressFeature.hasExtendedAddressParameterTypes()) { Iterator<XAddressParameterType> xParamTypes = addressFeature.getExtendedAddressParameterTypes(); switch(addressFeature.getParameterTypeStyle()) { case PARAMETER_LIST: { tmpSb.append(";"); while(xParamTypes.hasNext()) { XAddressParameterType xAddrType = xParamTypes.next(); tmpSb.append("TYPE="); tmpSb.append(xAddrType.getXtendedTypeName()); if(xAddrType.hasXtendedTypeValue()) { tmpSb.append("="); tmpSb.append(xAddrType.getXtendedTypeValue()); } tmpSb.append(";"); } break; } case PARAMETER_VALUE_LIST: { if(addressFeature.hasAddressParameterTypes()) { //Continue from the list tmpSb.append(","); } else { //Start a new tmpSb.append(";TYPE="); } while(xParamTypes.hasNext()) { XAddressParameterType xAddrType = xParamTypes.next(); tmpSb.append(xAddrType.getXtendedTypeName()); if(xAddrType.hasXtendedTypeValue()) { tmpSb.append("="); tmpSb.append(xAddrType.getXtendedTypeValue()); } tmpSb.append(","); } break; } } tmpSb.deleteCharAt(tmpSb.length()-1); } tmpSb.append(":"); if(addressFeature.hasPostOfficebox()) { tmpSb.append(VCardUtils.escapeString(addressFeature.getPostOfficeBox())); } tmpSb.append(";"); if(addressFeature.hasExtendedAddress()) { tmpSb.append(VCardUtils.escapeString(addressFeature.getExtendedAddress())); } tmpSb.append(";"); if(addressFeature.hasStreetAddress()) { tmpSb.append(VCardUtils.escapeString(addressFeature.getStreetAddress())); } tmpSb.append(";"); if(addressFeature.hasLocality()) { tmpSb.append(VCardUtils.escapeString(addressFeature.getLocality())); } tmpSb.append(";"); if(addressFeature.hasRegion()) { tmpSb.append(VCardUtils.escapeString(addressFeature.getRegion())); } tmpSb.append(";"); if(addressFeature.hasPostalCode()) { tmpSb.append(VCardUtils.escapeString(addressFeature.getPostalCode())); } tmpSb.append(";"); if(addressFeature.hasCountryName()) { tmpSb.append(VCardUtils.escapeString(addressFeature.getCountryName())); } String tmpAddressLine = tmpSb.toString(); String foldedAddressLine = VCardUtils.foldLine(tmpAddressLine, foldingScheme); sb.append(foldedAddressLine); sb.append(VCardUtils.CRLF); } } catch(Exception ex) { throw new VCardBuildException("AddressFeature ("+VCardType.ADR.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the label feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param labelFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the label feature is null */ private void buildLabelFeature(StringBuilder sb, LabelFeature labelFeature) throws VCardBuildException { try { if(labelFeature != null) { if(labelFeature.hasLabel()) { StringBuilder tmpSb = new StringBuilder(); if(labelFeature.hasGroup()) { tmpSb.append(labelFeature.getGroup()); tmpSb.append("."); } tmpSb.append(labelFeature.getTypeString()); if(labelFeature.hasLabelParameterTypes()) { tmpSb.append(";"); Iterator<LabelParameterType> paramTypes = labelFeature.getLabelParameterTypes(); switch(labelFeature.getParameterTypeStyle()) { case PARAMETER_LIST: { while(paramTypes.hasNext()) { LabelParameterType labelType = paramTypes.next(); tmpSb.append("TYPE="); tmpSb.append(labelType.getType()); tmpSb.append(";"); } break; } case PARAMETER_VALUE_LIST: { tmpSb.append("TYPE="); while(paramTypes.hasNext()) { LabelParameterType labelType = paramTypes.next(); tmpSb.append(labelType.getType()); tmpSb.append(","); } break; } } tmpSb.deleteCharAt(tmpSb.length()-1); } if(labelFeature.hasExtendedLabelParameterTypes()) { Iterator<XLabelParameterType> xParamTypes = labelFeature.getExtendedLabelParameterTypes(); switch(labelFeature.getParameterTypeStyle()) { case PARAMETER_LIST: { tmpSb.append(";"); while(xParamTypes.hasNext()) { XLabelParameterType xLabelType = xParamTypes.next(); tmpSb.append("TYPE="); tmpSb.append(xLabelType.getXtendedTypeName()); if(xLabelType.hasXtendedTypeValue()) { tmpSb.append("="); tmpSb.append(xLabelType.getXtendedTypeValue()); } tmpSb.append(";"); } break; } case PARAMETER_VALUE_LIST: { if(labelFeature.hasLabelParameterTypes()) { //Continue from the list tmpSb.append(","); } else { //Start a new tmpSb.append(";TYPE="); } while(xParamTypes.hasNext()) { XLabelParameterType xLabelType = xParamTypes.next(); tmpSb.append(xLabelType.getXtendedTypeName()); if(xLabelType.hasXtendedTypeValue()) { tmpSb.append("="); tmpSb.append(xLabelType.getXtendedTypeValue()); } tmpSb.append(","); } break; } } tmpSb.deleteCharAt(tmpSb.length()-1); } tmpSb.append(":"); tmpSb.append(VCardUtils.escapeString(labelFeature.getLabel())); String tmpLabelLine = tmpSb.toString(); String foldedLabelLine = VCardUtils.foldLine(tmpLabelLine, foldingScheme); sb.append(foldedLabelLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("LabelFeature ("+VCardType.LABEL.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("LablelFeature ("+VCardType.LABEL.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the telephone feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param telephoneFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the telephone feature is null */ private void buildTelephoneFeature(StringBuilder sb, TelephoneFeature telephoneFeature) throws VCardBuildException { try { if(telephoneFeature != null) { if(telephoneFeature.hasTelephone()) { StringBuilder tmpSb = new StringBuilder(); if(telephoneFeature.hasGroup()) { tmpSb.append(telephoneFeature.getGroup()); tmpSb.append("."); } tmpSb.append(telephoneFeature.getTypeString()); if(telephoneFeature.hasTelephoneParameterTypes()) { tmpSb.append(";"); Iterator<TelephoneParameterType> paramTypes = telephoneFeature.getTelephoneParameterTypes(); switch(telephoneFeature.getParameterTypeStyle()) { case PARAMETER_LIST: { while(paramTypes.hasNext()) { TelephoneParameterType teleType = paramTypes.next(); tmpSb.append("TYPE="); tmpSb.append(teleType.getType()); tmpSb.append(";"); } break; } case PARAMETER_VALUE_LIST: { tmpSb.append("TYPE="); while(paramTypes.hasNext()) { TelephoneParameterType teleType = paramTypes.next(); tmpSb.append(teleType.getType()); tmpSb.append(","); } break; } } tmpSb.deleteCharAt(tmpSb.length()-1); } if(telephoneFeature.hasExtendedTelephoneParameterTypes()) { Iterator<XTelephoneParameterType> xParamTypes = telephoneFeature.getExtendedTelephoneParameterTypes(); switch(telephoneFeature.getParameterTypeStyle()) { case PARAMETER_LIST: { tmpSb.append(";"); while(xParamTypes.hasNext()) { XTelephoneParameterType xTelType = xParamTypes.next(); tmpSb.append("TYPE="); tmpSb.append(xTelType.getXtendedTypeName()); if(xTelType.hasXtendedTypeValue()) { tmpSb.append("="); tmpSb.append(xTelType.getXtendedTypeValue()); } tmpSb.append(";"); } break; } case PARAMETER_VALUE_LIST: { if(telephoneFeature.hasTelephoneParameterTypes()) { //Continue from the list tmpSb.append(","); } else { //Start a new tmpSb.append(";TYPE="); } while(xParamTypes.hasNext()) { XTelephoneParameterType xTelType = xParamTypes.next(); tmpSb.append(xTelType.getXtendedTypeName()); if(xTelType.hasXtendedTypeValue()) { tmpSb.append("="); tmpSb.append(xTelType.getXtendedTypeValue()); } tmpSb.append(","); } break; } } tmpSb.deleteCharAt(tmpSb.length()-1); } tmpSb.append(":"); tmpSb.append(telephoneFeature.getTelephone()); String tmpTelephoneLine = tmpSb.toString(); String foldedTelephoneLine = VCardUtils.foldLine(tmpTelephoneLine, foldingScheme); sb.append(foldedTelephoneLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("TelephoneFeature ("+VCardType.TEL.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("TelephoneFeature ("+VCardType.TEL.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * * <p>Builds the email feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param emailFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the email feature is null */ private void buildEmailFeature(StringBuilder sb, EmailFeature emailFeature) throws VCardBuildException { try { if(emailFeature != null) { if(emailFeature.hasEmail()) { StringBuilder tmpSb = new StringBuilder(); if(emailFeature.hasGroup()) { tmpSb.append(emailFeature.getGroup()); tmpSb.append("."); } tmpSb.append(emailFeature.getTypeString()); if(emailFeature.hasEmailParameterTypes()) { tmpSb.append(";"); Iterator<EmailParameterType> paramTypes = emailFeature.getEmailParameterTypes(); switch(emailFeature.getParameterTypeStyle()) { case PARAMETER_LIST: { while(paramTypes.hasNext()) { EmailParameterType emailParamType = paramTypes.next(); tmpSb.append("TYPE="); tmpSb.append(emailParamType.getType()); tmpSb.append(";"); } break; } case PARAMETER_VALUE_LIST: { tmpSb.append("TYPE="); while(paramTypes.hasNext()) { EmailParameterType teleType = paramTypes.next(); tmpSb.append(teleType.getType()); tmpSb.append(","); } break; } } tmpSb.deleteCharAt(tmpSb.length()-1); } if(emailFeature.hasExtendedEmailParameterTypes()) { Iterator<XEmailParameterType> xParamTypes = emailFeature.getExtendedEmailParameterTypes(); switch(emailFeature.getParameterTypeStyle()) { case PARAMETER_LIST: { tmpSb.append(";"); while(xParamTypes.hasNext()) { XEmailParameterType xEmailType = xParamTypes.next(); tmpSb.append("TYPE="); tmpSb.append(xEmailType.getXtendedTypeName()); if(xEmailType.hasXtendedTypeValue()) { tmpSb.append("="); tmpSb.append(xEmailType.getXtendedTypeValue()); } tmpSb.append(";"); } break; } case PARAMETER_VALUE_LIST: { if(emailFeature.hasEmailParameterTypes()) { //Continue from the list tmpSb.append(","); } else { //Start a new tmpSb.append(";TYPE="); } while(xParamTypes.hasNext()) { XEmailParameterType xEmailType = xParamTypes.next(); tmpSb.append(xEmailType.getXtendedTypeName()); if(xEmailType.hasXtendedTypeValue()) { tmpSb.append("="); tmpSb.append(xEmailType.getXtendedTypeValue()); } tmpSb.append(","); } break; } } tmpSb.deleteCharAt(tmpSb.length()-1); } tmpSb.append(":"); tmpSb.append(emailFeature.getEmail()); String tmpEmailLine = tmpSb.toString(); String foldedEmailLine = VCardUtils.foldLine(tmpEmailLine, foldingScheme); sb.append(foldedEmailLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("EmailFeature ("+VCardType.EMAIL.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("EmailFeature ("+VCardType.EMAIL.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds a note feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param noteFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the note feature is null */ private void buildNoteFeature(StringBuilder sb, NoteFeature noteFeature) throws VCardBuildException { try { if(noteFeature != null) { if(noteFeature.hasNote()) { StringBuilder tmpSb = new StringBuilder(); if(noteFeature.hasGroup()) { tmpSb.append(noteFeature.getGroup()); tmpSb.append("."); } tmpSb.append(noteFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(VCardUtils.escapeString(noteFeature.getNote())); String tmpNoteLine = tmpSb.toString(); String foldedNoteLine = VCardUtils.foldLine(tmpNoteLine, foldingScheme); sb.append(foldedNoteLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("NoteFeature ("+VCardType.NOTE.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("NoteFeature ("+VCardType.NOTE.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the nickname feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param nicknameFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the nickname feature is null */ private void buildNicknames(StringBuilder sb, NicknameFeature nicknameFeature) throws VCardBuildException { try { if(nicknameFeature != null) { if(nicknameFeature.hasNicknames()) { StringBuilder tmpSb = new StringBuilder(); if(nicknameFeature.hasGroup()) { tmpSb.append(nicknameFeature.getGroup()); tmpSb.append("."); } tmpSb.append(nicknameFeature.getTypeString()); tmpSb.append(":"); Iterator<String> nicknames = nicknameFeature.getNicknames(); while(nicknames.hasNext()) { String nickname = nicknames.next(); tmpSb.append(nickname); tmpSb.append(","); } tmpSb.deleteCharAt(tmpSb.length()-1); String tmpNicknameLine = tmpSb.toString(); String foldedNicknameLine = VCardUtils.foldLine(tmpNicknameLine, foldingScheme); sb.append(foldedNicknameLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("NicknameFeature ("+VCardType.NICKNAME.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("NicknameFeature ("+VCardType.NICKNAME.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the category feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param categoriesFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the categories feature is null */ private void buildCategoriesFeature(StringBuilder sb, CategoriesFeature categoriesFeature) throws VCardBuildException { try { if(categoriesFeature != null) { if(categoriesFeature.hasCategories()) { StringBuilder tmpSb = new StringBuilder(); if(categoriesFeature.hasGroup()) { tmpSb.append(categoriesFeature.getGroup()); tmpSb.append("."); } tmpSb.append(categoriesFeature.getTypeString()); tmpSb.append(":"); Iterator<String> categories = categoriesFeature.getCategories(); while(categories.hasNext()) { String category = categories.next(); tmpSb.append(category); switch(compatMode) { case KDE_ADDRESS_BOOK: { tmpSb.append("\\,"); break; } default: { tmpSb.append(","); break; } } } tmpSb.deleteCharAt(tmpSb.length()-1); String tmpCategoryLine = tmpSb.toString(); String foldedCategoryLine = VCardUtils.foldLine(tmpCategoryLine, foldingScheme); sb.append(foldedCategoryLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("CategoriesFeature ("+VCardType.CATEGORIES.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("CategoriesFeature ("+VCardType.CATEGORIES.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds the class feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param categoriesFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the categories feature is null */ private void buildClassFeature(StringBuilder sb, ClassFeature classFeature) throws VCardBuildException { try { if(classFeature != null) { if(classFeature.hasSecurityClass()) { StringBuilder tmpSb = new StringBuilder(); if(classFeature.hasGroup()) { tmpSb.append(classFeature.getGroup()); tmpSb.append("."); } tmpSb.append(classFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(classFeature.getSecurityClass()); String tmpClassLine = tmpSb.toString(); String foldedClassLine = VCardUtils.foldLine(tmpClassLine, foldingScheme); sb.append(foldedClassLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("ClassFeature ("+VCardType.CLASS.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("ClassFeature ("+VCardType.CLASS.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds a product id feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param productIdFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the product id feature is null */ private void buildProductIdFeature(StringBuilder sb, ProductIdFeature productIdFeature) throws VCardBuildException { try { if(productIdFeature != null) { if(productIdFeature.hasProductId()) { StringBuilder tmpSb = new StringBuilder(); if(productIdFeature.hasGroup()) { tmpSb.append(productIdFeature.getGroup()); tmpSb.append("."); } tmpSb.append(productIdFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(productIdFeature.getProductId()); String tmpProductIdLine = tmpSb.toString(); String foldedProductIdLine = VCardUtils.foldLine(tmpProductIdLine, foldingScheme); sb.append(foldedProductIdLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("ProductIdFeature ("+VCardType.PRODID.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("ProductIdFeature ("+VCardType.PRODID.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds a sort string feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param sortStringFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the sort string feature is null */ private void buildSortStringFeature(StringBuilder sb, SortStringFeature sortStringFeature) throws VCardBuildException { try { if(sortStringFeature != null) { if(sortStringFeature.hasSortString()) { StringBuilder tmpSb = new StringBuilder(); if(sortStringFeature.hasGroup()) { tmpSb.append(sortStringFeature.getGroup()); tmpSb.append("."); } tmpSb.append(sortStringFeature.getTypeString()); tmpSb.append(":"); tmpSb.append(sortStringFeature.getSortString()); String tmpSortStringLine = tmpSb.toString(); String foldedSortStringLine = VCardUtils.foldLine(tmpSortStringLine, foldingScheme); sb.append(foldedSortStringLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("SortStringFeature ("+VCardType.SORT_STRING.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("SortStringFeature ("+VCardType.SORT_STRING.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Build the key feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param keyFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the key feature is null */ private void buildKeyFeature(StringBuilder sb, KeyFeature keyFeature) throws VCardBuildException { try { if(keyFeature != null) { if(keyFeature.hasKey()) { StringBuilder tmpSb = new StringBuilder(); if(keyFeature.hasGroup()) { tmpSb.append(keyFeature.getGroup()); tmpSb.append("."); } tmpSb.append(keyFeature.getTypeString()); tmpSb.append(";"); String foldedKeyLine = null; tmpSb.append("ENCODING="); switch(compatMode) { case MAC_ADDRESS_BOOK: { tmpSb.append(EncodingType.BASE64.getType()); break; } case EVOLUTION: case KDE_ADDRESS_BOOK: case MS_OUTLOOK: case RFC2426: case I_PHONE: { tmpSb.append(keyFeature.getEncodingType().getType()); break; } } if(keyFeature.hasKeyTextType()) { tmpSb.append(";"); tmpSb.append("TYPE="); tmpSb.append(keyFeature.getKeyTextType().getTypeName()); } tmpSb.append(":"); switch(compatMode) { case MAC_ADDRESS_BOOK: { String b64str = null; try { byte[] keyBytes = keyFeature.getKey(); if(keyFeature.isSetCompression()) { b64str = Base64Wrapper.encode(keyBytes, Base64Wrapper.OPTIONS.GZIP_COMPRESSION); } else { b64str = Base64Wrapper.encode(keyBytes); } } catch(Exception ex) { throw new VCardBuildException(ex.getMessage(), ex); } String tmpKeyLine = tmpSb.toString(); String foldedKeyLine2 = VCardUtils.foldLine(tmpKeyLine, foldingScheme); foldedKeyLine = VCardUtils.foldLine(b64str, foldingScheme); sb.append(foldedKeyLine2); //Type declaration with param types sb.append(VCardUtils.CRLF); //Distinctive line break sb.append(FoldingScheme.MAC_ADDRESS_BOOK.getIndent()); //Indent first line break; } case EVOLUTION: case KDE_ADDRESS_BOOK: case MS_OUTLOOK: case RFC2426: case I_PHONE: { try { byte[] keyBytes = keyFeature.getKey(); if(keyFeature.isSetCompression()) { tmpSb.append(Base64Wrapper.encode(keyBytes, Base64Wrapper.OPTIONS.GZIP_COMPRESSION)); } else { tmpSb.append(Base64Wrapper.encode(keyBytes)); } } catch(Exception ex) { throw new VCardBuildException(ex.getMessage(), ex); } String tmpKeyLine = tmpSb.toString(); foldedKeyLine = VCardUtils.foldLine(tmpKeyLine, foldingScheme); break; } } sb.append(foldedKeyLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("KeyFeature ("+VCardType.KEY.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("KeyFeature ("+VCardType.KEY.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds a photo feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param photoFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the photo feature is null */ private void buildPhotoFeature(StringBuilder sb, PhotoFeature photoFeature) throws VCardBuildException { try { if(photoFeature != null) { if(photoFeature.hasPhoto()) { StringBuilder tmpSb = new StringBuilder(); if(photoFeature.hasGroup()) { tmpSb.append(photoFeature.getGroup()); tmpSb.append("."); } tmpSb.append(photoFeature.getTypeString()); tmpSb.append(";"); String foldedPhotoLine = null; if(photoFeature.isURI()) { tmpSb.append("VALUE=URI:"); tmpSb.append(photoFeature.getPhotoURI().getPath()); String tmpPhotoLine = tmpSb.toString(); foldedPhotoLine = VCardUtils.foldLine(tmpPhotoLine, foldingScheme); } else if(photoFeature.isInline()) { tmpSb.append("ENCODING="); switch(compatMode) { case MAC_ADDRESS_BOOK: { tmpSb.append(EncodingType.BASE64.getType()); break; } case EVOLUTION: case KDE_ADDRESS_BOOK: case MS_OUTLOOK: case RFC2426: case I_PHONE: { tmpSb.append(photoFeature.getEncodingType().getType()); break; } } if(photoFeature.hasImageMediaType()) { tmpSb.append(";"); tmpSb.append("TYPE="); tmpSb.append(photoFeature.getImageMediaType().getTypeName()); } tmpSb.append(":"); switch(compatMode) { case MAC_ADDRESS_BOOK: { String b64str = null; try { byte[] photoBytes = photoFeature.getPhoto(); if(photoFeature.isSetCompression()) { b64str = Base64Wrapper.encode(photoBytes, Base64Wrapper.OPTIONS.GZIP_COMPRESSION); } else { b64str = Base64Wrapper.encode(photoBytes); } } catch(Exception ex) { throw new VCardBuildException(ex.getMessage(), ex); } String tmpPhotoLine = tmpSb.toString(); String foldedPhotoLine2 = VCardUtils.foldLine(tmpPhotoLine, foldingScheme); foldedPhotoLine = VCardUtils.foldLine(b64str, foldingScheme); sb.append(foldedPhotoLine2); //Type declaration with param types sb.append(VCardUtils.CRLF); //Distinctive line break sb.append(FoldingScheme.MAC_ADDRESS_BOOK.getIndent()); //Indent first line break; } case RFC2426: case EVOLUTION: case KDE_ADDRESS_BOOK: case MS_OUTLOOK: case I_PHONE: { try { byte[] photoBytes = photoFeature.getPhoto(); if(photoFeature.isSetCompression()) { tmpSb.append(Base64Wrapper.encode(photoBytes, Base64Wrapper.OPTIONS.GZIP_COMPRESSION)); } else { tmpSb.append(Base64Wrapper.encode(photoBytes)); } } catch(Exception ex) { throw new VCardBuildException(ex.getMessage(), ex); } String tmpPhotoLine = tmpSb.toString(); foldedPhotoLine = VCardUtils.foldLine(tmpPhotoLine, foldingScheme); break; } } } else { throw new VCardBuildException("PhotoFeature ("+VCardType.PHOTO.getType()+") is not URI and not Inline, cannot proceed, must be one or the other."); } sb.append(foldedPhotoLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("PhotoFeature ("+VCardType.PHOTO.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("PhotoFeature ("+VCardType.PHOTO.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds a logo feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param logoFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the logo feature is null */ private void buildLogoFeature(StringBuilder sb, LogoFeature logoFeature) throws VCardBuildException { try { if(logoFeature != null) { if(logoFeature.hasLogo()) { StringBuilder tmpSb = new StringBuilder(); if(logoFeature.hasGroup()) { tmpSb.append(logoFeature.getGroup()); tmpSb.append("."); } tmpSb.append(logoFeature.getTypeString()); tmpSb.append(";"); String foldedLogoLine = null; if(logoFeature.isURI()) { tmpSb.append("VALUE=URI:"); tmpSb.append(logoFeature.getLogoURI().getPath()); String tmpLogoLine = tmpSb.toString(); foldedLogoLine = VCardUtils.foldLine(tmpLogoLine, foldingScheme); } else if(logoFeature.isInline()) { tmpSb.append("ENCODING="); switch(compatMode) { case MAC_ADDRESS_BOOK: { tmpSb.append(EncodingType.BASE64.getType()); break; } case EVOLUTION: case KDE_ADDRESS_BOOK: case MS_OUTLOOK: case RFC2426: case I_PHONE: { tmpSb.append(logoFeature.getEncodingType().getType()); break; } } if(logoFeature.hasImageMediaType()) { tmpSb.append(";"); tmpSb.append("TYPE="); tmpSb.append(logoFeature.getImageMediaType().getTypeName()); } tmpSb.append(":"); switch(compatMode) { case MAC_ADDRESS_BOOK: { String b64str = null; try { byte[] logoBytes = logoFeature.getLogo(); if(logoFeature.isSetCompression()) { b64str = Base64Wrapper.encode(logoBytes, Base64Wrapper.OPTIONS.GZIP_COMPRESSION); } else { b64str = Base64Wrapper.encode(logoBytes); } } catch(Exception ex) { throw new VCardBuildException(ex.getMessage(), ex); } String tmpLogoLine = tmpSb.toString(); String foldedPhotoLine2 = VCardUtils.foldLine(tmpLogoLine, foldingScheme); foldedLogoLine = VCardUtils.foldLine(b64str, foldingScheme); sb.append(foldedPhotoLine2); //Type declaration with param types sb.append(VCardUtils.CRLF); //Distinctive line break sb.append(FoldingScheme.MAC_ADDRESS_BOOK.getIndent()); //Indent first line break; } case RFC2426: case EVOLUTION: case KDE_ADDRESS_BOOK: case MS_OUTLOOK: case I_PHONE: { try { byte[] photoBytes = logoFeature.getLogo(); if(logoFeature.isSetCompression()) { tmpSb.append(Base64Wrapper.encode(photoBytes, Base64Wrapper.OPTIONS.GZIP_COMPRESSION)); } else { tmpSb.append(Base64Wrapper.encode(photoBytes)); } } catch(Exception ex) { throw new VCardBuildException(ex.getMessage(), ex); } String tmpLogoLine = tmpSb.toString(); foldedLogoLine = VCardUtils.foldLine(tmpLogoLine, foldingScheme); break; } } } else { throw new VCardBuildException("LogoFeature ("+VCardType.LOGO.getType()+") is not URI and not Inline, cannot proceed, must be one or the other."); } sb.append(foldedLogoLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("LogoFeature ("+VCardType.LOGO.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("LogoFeature ("+VCardType.LOGO.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds a sound feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param soundFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the sound feature is null */ private void buildSoundFeature(StringBuilder sb, SoundFeature soundFeature) throws VCardBuildException { try { if(soundFeature != null) { if(soundFeature.hasSound()) { StringBuilder tmpSb = new StringBuilder(); if(soundFeature.hasGroup()) { tmpSb.append(soundFeature.getGroup()); tmpSb.append("."); } tmpSb.append(soundFeature.getTypeString()); tmpSb.append(";"); String foldedSoundLine = null; if(soundFeature.isURI()) { tmpSb.append("VALUE=URI:"); tmpSb.append(soundFeature.getSoundURI().getPath()); String tmpSoundLine = tmpSb.toString(); foldedSoundLine = VCardUtils.foldLine(tmpSoundLine, foldingScheme); } else if(soundFeature.isInline()) { tmpSb.append("ENCODING="); switch(compatMode) { case MAC_ADDRESS_BOOK: { tmpSb.append(EncodingType.BASE64.getType()); break; } case EVOLUTION: case KDE_ADDRESS_BOOK: case MS_OUTLOOK: case RFC2426: case I_PHONE: { tmpSb.append(soundFeature.getEncodingType().getType()); break; } } if(soundFeature.hasAudioMediaType()) { tmpSb.append(";"); tmpSb.append("TYPE="); tmpSb.append(soundFeature.getAudioMediaType().getTypeName()); } tmpSb.append(":"); switch(compatMode) { case MAC_ADDRESS_BOOK: { String b64str = null; try { byte[] soundBytes = soundFeature.getSound(); if(soundFeature.isSetCompression()) { b64str = Base64Wrapper.encode(soundBytes, Base64Wrapper.OPTIONS.GZIP_COMPRESSION); } else { b64str = Base64Wrapper.encode(soundBytes); } } catch(Exception ex) { throw new VCardBuildException(ex.getMessage(), ex); } String tmpSoundLine = tmpSb.toString(); String foldedSoundLine2 = VCardUtils.foldLine(tmpSoundLine, foldingScheme); foldedSoundLine = VCardUtils.foldLine(b64str, foldingScheme); sb.append(foldedSoundLine2); //Type declaration with param types sb.append(VCardUtils.CRLF); //Distinctive line break sb.append(FoldingScheme.MAC_ADDRESS_BOOK.getIndent()); //Indent first line break; } case RFC2426: case EVOLUTION: case KDE_ADDRESS_BOOK: case MS_OUTLOOK: case I_PHONE: { try { byte[] soundBytes = soundFeature.getSound(); if(soundFeature.isSetCompression()) { tmpSb.append(Base64Wrapper.encode(soundBytes, Base64Wrapper.OPTIONS.GZIP_COMPRESSION)); } else { tmpSb.append(Base64Wrapper.encode(soundBytes)); } } catch(Exception ex) { throw new VCardBuildException(ex.getMessage(), ex); } String tmpSoundLine = tmpSb.toString(); foldedSoundLine = VCardUtils.foldLine(tmpSoundLine, foldingScheme); break; } } } else { throw new VCardBuildException("SoundFeature ("+VCardType.SOUND.getType()+") is not URI and not Inline, cannot proceed, must be one or the other."); } sb.append(foldedSoundLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("SoundFeature ("+VCardType.SOUND.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("SoundFeature ("+VCardType.SOUND.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds an agent feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param agentFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the agent feature is null */ private void buildAgentFeature(StringBuilder sb, AgentFeature agentFeature) throws VCardBuildException { try { if(agentFeature != null) { if(agentFeature.hasAgent()) { StringBuilder tmpSb = new StringBuilder(); if(agentFeature.hasGroup()) { tmpSb.append(agentFeature.getGroup()); tmpSb.append("."); } tmpSb.append(agentFeature.getTypeString()); if(agentFeature.isURI()) { tmpSb.append(";"); tmpSb.append("VALUE=URI:"); tmpSb.append(agentFeature.getAgentURI().getPath()); } else if(agentFeature.isInline()) { tmpSb.append(":"); VCard agentVCard = agentFeature.getAgent(); if(agentVCard instanceof VCardErrorHandling) { //Turn on error handling if available ((VCardErrorHandling)agentVCard).setThrowExceptions(true); } try { VCardWriter writer = new VCardWriter(); writer.setCompatibilityMode(this.compatMode); writer.setFoldingScheme(this.foldingScheme); writer.setOutputVersion(this.outputVersion); writer.setVCard(agentVCard); String agentVCardStr = writer.buildVCardString(); tmpSb.append(VCardUtils.escapeString(agentVCardStr)); } catch(VCardException ve) { throw new VCardBuildException(ve.getMessage(), ve); } catch(Exception ex) { throw new VCardBuildException(ex.getMessage(), ex); } String tmpAgentLine = tmpSb.toString(); String foldedAgentLine = VCardUtils.foldLine(tmpAgentLine, foldingScheme); sb.append(foldedAgentLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("AgentFeature ("+VCardType.AGENT.getType()+") is not URI and not Inline, cannot proceed, must be one or the other."); } } else { throw new VCardBuildException("AgentFeature ("+VCardType.AGENT.getType()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("AgentFeature ("+VCardType.AGENT.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Builds an extended feature as a String.</p> * * @param sb * - The StringBuilder to append to * @param extendedFeature * - The feature to output as a String * @throws VCardBuildException * Thrown when the extended feature is null */ private void buildExtendedFeature(StringBuilder sb, ExtendedFeature extendedFeature) throws VCardBuildException { try { if(extendedFeature != null) { if(extendedFeature.hasExtension()) { StringBuilder tmpSb = new StringBuilder(); if(extendedFeature.hasGroup()) { tmpSb.append(extendedFeature.getGroup()); tmpSb.append("."); } tmpSb.append(extendedFeature.getExtensionName()); tmpSb.append(":"); tmpSb.append(extendedFeature.getExtensionData()); String tmpExtendedLine = tmpSb.toString(); String foldedExtendedLine = VCardUtils.foldLine(tmpExtendedLine, foldingScheme); sb.append(foldedExtendedLine); sb.append(VCardUtils.CRLF); } else { throw new VCardBuildException("ExtendedFeature ("+extendedFeature.getExtensionName()+") exists but is empty."); } } } catch(Exception ex) { throw new VCardBuildException("ExtendedFeature ("+VCardType.XTENDED.getType()+") ["+ex.getClass().getName()+"] "+ex.getMessage(), ex); } } /** * <p>Returns true if the underlying vcard produced errors that * are storable inside the vcard itself. False if no errors were * detected and if the underlying vcard does not implement the * {@link VCardErrorHandling} interface.</p> * * @return boolean */ public boolean hasErrors() { if(vcard instanceof VCardErrorHandling) { return ((VCardErrorHandling)vcard).hasErrors(); } else { return false; } } /** * <p>Handles the occurrence of an error where there only * exists an error message and an associated severity.</p> * * @param errorMessage * - The error message * @param severity * - The severity of the error */ @SuppressWarnings("unused") private void handleError(String errorMessage, ErrorSeverity severity) { handleError(errorMessage, null, severity); } /** * <p>Handles the occurrence of an error where an exception * is thrown and needs to be tracked and associated with a severity.</p> * * @param errorMessage * - The error message * @param exception * - The exception that was thrown * @param severity * - The severity of the exception */ private void handleError(String errorMessage, Throwable exception, ErrorSeverity severity) { VCardError vError = new VCardError(); vError.setErrorMessage(errorMessage); vError.setSeverity(severity); if(exception != null) { vError.setError(exception); } ((VCardErrorHandling)vcard).addError(vError); } /** * <p>Resets the VCardWriter to its initial defaults. * Clears all data and errors.</p> */ public void reset() { setOutputVersion(null); setFoldingScheme(null); setCompatibilityMode(null); this.vcard = null; } }