package net.sourceforge.cardme.io;
import net.sourceforge.cardme.util.Base64Wrapper;
import net.sourceforge.cardme.util.ISOFormat;
import net.sourceforge.cardme.util.ISOUtils;
import net.sourceforge.cardme.util.VCardUtils;
import net.sourceforge.cardme.vcard.EncodingType;
import net.sourceforge.cardme.vcard.VCard;
import net.sourceforge.cardme.vcard.VCardType;
import net.sourceforge.cardme.vcard.VCardVersion;
import net.sourceforge.cardme.vcard.errors.*;
import net.sourceforge.cardme.vcard.features.*;
import net.sourceforge.cardme.vcard.types.parameters.*;
import org.apache.commons.codec.EncoderException;
import org.apache.commons.codec.net.QuotedPrintableCodec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Iterator;
/*
* Copyright 2011 George El-Haddad. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY GEORGE EL-HADDAD ''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 GEORGE EL-HADDAD 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.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of George El-Haddad.
*/
/**
*
* @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 which 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 BinaryFoldingScheme binaryFoldingScheme = 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>Quoted Printable codec provided by apache commons-codec.
* This will created and used only where there is at least one
* type that needs it.</p>
*/
private QuotedPrintableCodec qpCodec = null;
/**
* <p>The end of line character to use. By default and by
* RFC and MIME-DIR standards the EOL character must be
* CR+LF (\r\n) but we can customize it by setting this
* variable.</p>
*/
private String eol = VCardUtils.CRLF;
/**
* <p>Creates a new VCardWriter with default parameters.</p>
*
* @throws VCardException
*/
public VCardWriter() throws VCardException {
this(null, 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, null);
}
/**
* <p>Creates a new VCardWriter with a specified version and folding scheme.</p>
*
* @see VCardVersion
* @see FoldingScheme
* @see BinaryFoldingScheme
*
* @param outputVersion
* @param foldingScheme
* @param binaryFoldingScheme
* @throws VCardException
*/
public VCardWriter(VCardVersion outputVersion, FoldingScheme foldingScheme, BinaryFoldingScheme binaryFoldingScheme) throws VCardException {
this(outputVersion, foldingScheme, binaryFoldingScheme, 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, null, compatMode);
}
/**
* <p>Creates a new VCardWriter with a specified version, folding scheme and compatibility mode.</p>
*
* @see VCardVersion
* @see FoldingScheme
* @see BinaryFoldingScheme
* @see CompatibilityMode
*
* @param outputVersion
* @param foldingScheme
* @param binaryFoldingScheme
* @param compatMode
* @throws VCardException
*/
public VCardWriter(VCardVersion outputVersion, FoldingScheme foldingScheme, BinaryFoldingScheme binaryFoldingScheme, CompatibilityMode compatMode) throws VCardException {
setOutputVersion(outputVersion);
setFoldingScheme(foldingScheme);
setBinaryfoldingScheme(binaryFoldingScheme);
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 binary folding scheme to use when folding long
* lines of data. If null {@link BinaryFoldingScheme}.MIME_DIR is used.</p>
*
* @param binaryFoldingScheme
*/
public void setBinaryfoldingScheme(BinaryFoldingScheme binaryFoldingScheme) {
if(binaryFoldingScheme == null) {
this.binaryFoldingScheme = BinaryFoldingScheme.MIME_DIR;
}
else {
this.binaryFoldingScheme = binaryFoldingScheme;
}
}
/**
* <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>Sets the EOL character to use when building the VCard.
* If not set then the default CRLF is used. See below list
* for compatible types:
* <ul>
* <li><strong>LF or <code>\n</code></strong>: Unix, GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, BeOS, Amiga, and RISC OS</li>
* <li><strong>CR or <code>\r</code></strong>: Commodore 8-bit machines, Acorn BBC, TRS-80, Apple II family, Mac OS up to version 9 and OS-9</li>
* <li><strong>CRLF or <code>\r\n</code></strong>: Microsoft Windows, DEC TOPS-10, RT-11, CP/M, MP/M, DOS (MS-DOS, PC-DOS, etc.), Atari TOS, OS/2, Symbian OS, Palm OS</li>
* </ul>
* See <a href="http://en.wikipedia.org/wiki/Newline">wikipedia</a> for more info.
* </p>
*
* @param eol
*/
public void setEOL(String eol) {
if(eol == null) {
this.eol = VCardUtils.CRLF;
}
else {
this.eol = new String(eol);
}
}
/**
* <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);
}
}
}
}
/*
* IMPP. RFC 4770 extension
*/
if(vcard.hasIMPPs()) {
Iterator<IMPPFeature> impps = vcard.getIMPPs();
while(impps.hasNext()) {
IMPPFeature imppFeature = impps.next();
try {
buildImppFeature(sb, imppFeature);
}
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(eol);
}
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 endFeature
* - 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(eol);
}
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(".");
}
if(versionFeature.getVersion() == VCardVersion.V2_1) {
//We do not support writing in v2.1, so if it has
//been set before, force it to v3.0
versionFeature.setVersion(VCardVersion.V3_0);
}
sb.append(versionFeature.getTypeString());
if(versionFeature.hasExtendedParameters()) {
buildExtendParameters(versionFeature, sb);
}
sb.append(":");
sb.append(versionFeature.getVersion().getVersion());
sb.append(eol);
}
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) {
boolean isQuotedPrintable = nameFeature.isQuotedPrintable();
StringBuilder tmpSb = new StringBuilder();
if(nameFeature.hasGroup()) {
tmpSb.append(nameFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(nameFeature.getTypeString());
if(nameFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(nameFeature.getCharset().name());
}
if(nameFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(nameFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(nameFeature.hasExtendedParameters()) {
buildExtendParameters(nameFeature, tmpSb);
}
tmpSb.append(":");
if(nameFeature.hasFamilyName()) {
tmpSb.append(escapeOrEncode(nameFeature.getFamilyName(), isQuotedPrintable, nameFeature.getCharset()));
}
tmpSb.append(";");
if(nameFeature.hasGivenName()) {
tmpSb.append(escapeOrEncode(nameFeature.getGivenName(), isQuotedPrintable, nameFeature.getCharset()));
}
tmpSb.append(";");
if(nameFeature.hasAdditionalNames()) {
Iterator<String> additionalNames = nameFeature.getAdditionalNames();
while(additionalNames.hasNext()) {
String addName = additionalNames.next();
tmpSb.append(escapeOrEncode(addName, isQuotedPrintable, nameFeature.getCharset()));
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(escapeOrEncode(prefix, isQuotedPrintable, nameFeature.getCharset()));
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(escapeOrEncode(suffix, isQuotedPrintable, nameFeature.getCharset()));
tmpSb.append(",");
}
tmpSb.deleteCharAt(tmpSb.length()-1);
}
String tmpNameLine = tmpSb.toString();
String foldedNameLine = VCardUtils.foldLine(tmpNameLine, eol, foldingScheme);
sb.append(foldedNameLine);
sb.append(eol);
}
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) {
boolean isQuotedPrintable = formattedNameFeature.isQuotedPrintable();
String formattedName = formattedNameFeature.getFormattedName();
StringBuilder tmpSb = new StringBuilder();
if(formattedNameFeature.hasGroup()) {
tmpSb.append(formattedNameFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(formattedNameFeature.getTypeString());
if(formattedNameFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(formattedNameFeature.getCharset().name());
}
if(formattedNameFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(formattedNameFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(formattedNameFeature.hasExtendedParameters()) {
buildExtendParameters(formattedNameFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(formattedName, isQuotedPrintable, formattedNameFeature.getCharset()));
String tmpFormattedNameLine = tmpSb.toString();
String foldedFormattedNameLine = VCardUtils.foldLine(tmpFormattedNameLine, eol, foldingScheme);
sb.append(foldedFormattedNameLine);
sb.append(eol);
}
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 displayableNameFeature
* - 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) {
boolean isQuotedPrintable = displayableNameFeature.isQuotedPrintable();
String displayableName = displayableNameFeature.getName();
StringBuilder tmpSb = new StringBuilder();
if(displayableNameFeature.hasGroup()) {
tmpSb.append(displayableNameFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(displayableNameFeature.getTypeString());
if(displayableNameFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(displayableNameFeature.getCharset().name());
}
if(displayableNameFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(displayableNameFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(displayableNameFeature.hasExtendedParameters()) {
buildExtendParameters(displayableNameFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(displayableName, isQuotedPrintable, displayableNameFeature.getCharset()));
String tmpDisplayableNameLine = tmpSb.toString();
String foldedDisplayableNameLine = VCardUtils.foldLine(tmpDisplayableNameLine, eol, foldingScheme);
sb.append(foldedDisplayableNameLine);
sb.append(eol);
}
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 profileFeature
* - 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) {
boolean isQuotedPrintable = profileFeature.isQuotedPrintable();
String profile = profileFeature.getProfile();
StringBuilder tmpSb = new StringBuilder();
if(profileFeature.hasGroup()) {
tmpSb.append(profileFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(profileFeature.getTypeString());
if(profileFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(profileFeature.getCharset().name());
}
if(profileFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(profileFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(profileFeature.hasExtendedParameters()) {
buildExtendParameters(profileFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(profile, isQuotedPrintable, profileFeature.getCharset()));
String tmpProfileLine = tmpSb.toString();
String foldedProfileLine = VCardUtils.foldLine(tmpProfileLine, eol, foldingScheme);
sb.append(foldedProfileLine);
sb.append(eol);
}
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 sourceFeature
* - 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) {
boolean isQuotedPrintable = sourceFeature.isQuotedPrintable();
String source = sourceFeature.getSource();
StringBuilder tmpSb = new StringBuilder();
if(sourceFeature.hasGroup()) {
tmpSb.append(sourceFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(sourceFeature.getTypeString());
if(sourceFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(sourceFeature.getCharset().name());
}
if(sourceFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(sourceFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(sourceFeature.hasExtendedParameters()) {
buildExtendParameters(sourceFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(source, isQuotedPrintable, sourceFeature.getCharset()));
String tmpSourceLine = tmpSb.toString();
String foldedSourceLine = VCardUtils.foldLine(tmpSourceLine, eol, foldingScheme);
sb.append(foldedSourceLine);
sb.append(eol);
}
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()) {
boolean isQuotedPrintable = titleFeature.isQuotedPrintable();
String title = titleFeature.getTitle();
StringBuilder tmpSb = new StringBuilder();
if(titleFeature.hasGroup()) {
tmpSb.append(titleFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(titleFeature.getTypeString());
if(titleFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(titleFeature.getCharset().name());
}
if(titleFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(titleFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(titleFeature.hasExtendedParameters()) {
buildExtendParameters(titleFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(title, isQuotedPrintable, titleFeature.getCharset()));
String tmpTitleLine = tmpSb.toString();
String foldedTitleLine = VCardUtils.foldLine(tmpTitleLine, eol, foldingScheme);
sb.append(foldedTitleLine);
sb.append(eol);
}
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()) {
boolean isQuotedPrintable = roleFeature.isQuotedPrintable();
String role = roleFeature.getRole();
StringBuilder tmpSb = new StringBuilder();
if(roleFeature.hasGroup()) {
tmpSb.append(roleFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(roleFeature.getTypeString());
if(roleFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(roleFeature.getCharset().name());
}
if(roleFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(roleFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(roleFeature.hasExtendedParameters()) {
buildExtendParameters(roleFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(role, isQuotedPrintable, roleFeature.getCharset()));
String tmpRoleLine = tmpSb.toString();
String foldedRoleLine = VCardUtils.foldLine(tmpRoleLine, eol, foldingScheme);
sb.append(foldedRoleLine);
sb.append(eol);
}
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());
if(geographicPositionFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(geographicPositionFeature.getCharset().name());
}
if(geographicPositionFeature.hasExtendedParameters()) {
buildExtendParameters(geographicPositionFeature, tmpSb);
}
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, eol, foldingScheme);
sb.append(foldedGeoLine);
sb.append(eol);
}
}
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()) {
boolean isQuotedPrintable = organizationFeature.isQuotedPrintable();
StringBuilder tmpSb = new StringBuilder();
if(organizationFeature.hasGroup()) {
tmpSb.append(organizationFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(organizationFeature.getTypeString());
if(organizationFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(organizationFeature.getCharset().name());
}
if(organizationFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(organizationFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(organizationFeature.hasExtendedParameters()) {
buildExtendParameters(organizationFeature, tmpSb);
}
tmpSb.append(":");
Iterator<String> orgs = organizationFeature.getOrganizations();
while(orgs.hasNext()) {
String org = orgs.next();
tmpSb.append(escapeOrEncode(org, isQuotedPrintable, organizationFeature.getCharset()));
tmpSb.append(";");
}
tmpSb.deleteCharAt(tmpSb.length()-1);
String tmpOrgLine = tmpSb.toString();
String foldedOrgLine = VCardUtils.foldLine(tmpOrgLine, eol, foldingScheme);
sb.append(foldedOrgLine);
sb.append(eol);
}
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()) {
boolean isQuotedPrintable = mailerFeature.isQuotedPrintable();
String mailer = mailerFeature.getMailer();
StringBuilder tmpSb = new StringBuilder();
if(mailerFeature.hasGroup()) {
tmpSb.append(mailerFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(mailerFeature.getTypeString());
if(mailerFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(mailerFeature.getCharset().name());
}
if(mailerFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(mailerFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(mailerFeature.hasExtendedParameters()) {
buildExtendParameters(mailerFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(mailer, isQuotedPrintable, mailerFeature.getCharset()));
String tmpMailerLine = tmpSb.toString();
String foldedMailerLine = VCardUtils.foldLine(tmpMailerLine, eol, foldingScheme);
sb.append(foldedMailerLine);
sb.append(eol);
}
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.getShortText() != null || timeZoneFeature.getLongText() != null) {
tmpSb.append(";");
tmpSb.append(TimeZoneParameterType.VALUE.getType());
tmpSb.append("=TEXT:");
tmpSb.append(timeZoneFeature.getIso8601Offset());
tmpSb.append(';');
if (timeZoneFeature.getShortText() != null){
tmpSb.append(timeZoneFeature.getShortText());
}
tmpSb.append(';');
if (timeZoneFeature.getLongText() != null){
tmpSb.append(timeZoneFeature.getLongText());
}
}
else {
tmpSb.append(":");
tmpSb.append(timeZoneFeature.getIso8601Offset());
}
String tmpTimeZoneLine = tmpSb.toString();
String foldedTimeZoneLine = VCardUtils.foldLine(tmpTimeZoneLine, eol, foldingScheme);
sb.append(foldedTimeZoneLine);
sb.append(eol);
}
}
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.hasRawURL()) {
boolean isQuotedPrintable = urlFeature.isQuotedPrintable();
String url = urlFeature.getRawURL();
StringBuilder tmpSb = new StringBuilder();
if(urlFeature.hasGroup()) {
tmpSb.append(urlFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(urlFeature.getTypeString());
switch(compatMode)
{
case MS_OUTLOOK:
case I_PHONE:
case GMAIL:
case MAC_ADDRESS_BOOK:
{
if(urlFeature.hasURLParameterTypes()) {
tmpSb.append(";");
Iterator<URLParameterType> paramTypes = urlFeature.getURLParameterTypes();
switch(urlFeature.getParameterTypeStyle())
{
case PARAMETER_LIST:
{
while(paramTypes.hasNext()) {
URLParameterType urlType = paramTypes.next();
tmpSb.append("TYPE=");
tmpSb.append(urlType.getType());
tmpSb.append(";");
}
break;
}
case PARAMETER_VALUE_LIST:
{
tmpSb.append("TYPE=");
while(paramTypes.hasNext()) {
URLParameterType urlType = paramTypes.next();
tmpSb.append(urlType.getType());
tmpSb.append(",");
}
break;
}
}
tmpSb.deleteCharAt(tmpSb.length()-1);
}
if(urlFeature.hasExtendedURLParameterTypes()) {
Iterator<XURLParameterType> xParamTypes = urlFeature.getExtendedURLParameterTypes();
switch(urlFeature.getParameterTypeStyle())
{
case PARAMETER_LIST:
{
tmpSb.append(";");
while(xParamTypes.hasNext()) {
XURLParameterType xUrlType = xParamTypes.next();
tmpSb.append("TYPE=");
tmpSb.append(xUrlType.getXtendedTypeName());
if(xUrlType.hasXtendedTypeValue()) {
tmpSb.append("=");
tmpSb.append(xUrlType.getXtendedTypeValue());
}
tmpSb.append(";");
}
break;
}
case PARAMETER_VALUE_LIST:
{
if(urlFeature.hasURLParameterTypes()) {
//Continue from the list
tmpSb.append(",");
}
else {
//Start a new
tmpSb.append(";TYPE=");
}
while(xParamTypes.hasNext()) {
XURLParameterType xUrlType = xParamTypes.next();
tmpSb.append(xUrlType.getXtendedTypeName());
if(xUrlType.hasXtendedTypeValue()) {
tmpSb.append("=");
tmpSb.append(xUrlType.getXtendedTypeValue());
}
tmpSb.append(",");
}
break;
}
}
tmpSb.deleteCharAt(tmpSb.length()-1);
}
break;
}
}
if(urlFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(urlFeature.getCharset().name());
}
if(urlFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(urlFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(urlFeature.hasExtendedParameters()) {
buildExtendParameters(urlFeature, tmpSb);
}
tmpSb.append(":");
switch(compatMode)
{
case GMAIL:
case I_PHONE:
case IOS_EXPORTER:
{
tmpSb.append(VCardUtils.escapeString(url));
break;
}
default:
{
tmpSb.append(url);
break;
}
}
String tmpUrlLine = tmpSb.toString();
String foldedUrlLine = VCardUtils.foldLine(tmpUrlLine, eol, foldingScheme);
sb.append(foldedUrlLine);
sb.append(eol);
}
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());
if(revisionFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(revisionFeature.getCharset().name());
}
if(revisionFeature.hasExtendedParameters()) {
buildExtendParameters(revisionFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(ISOUtils.formatISO8601Date(revisionFeature.getRevision(), ISOFormat.ISO8601_UTC_TIME_EXTENDED));
String tmpRevisionLine = tmpSb.toString();
String foldedRevisionLine = VCardUtils.foldLine(tmpRevisionLine, eol, foldingScheme);
sb.append(foldedRevisionLine);
sb.append(eol);
}
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()) {
boolean isQuotedPrintable = uidFeature.isQuotedPrintable();
String uid = uidFeature.getUID();
StringBuilder tmpSb = new StringBuilder();
if(uidFeature.hasGroup()) {
tmpSb.append(uidFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(uidFeature.getTypeString());
if(uidFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(uidFeature.getCharset().name());
}
if(uidFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(uidFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(uidFeature.hasExtendedParameters()) {
buildExtendParameters(uidFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(uid, isQuotedPrintable, uidFeature.getCharset()));
String tmpUidLine = tmpSb.toString();
String foldedUidLine = VCardUtils.foldLine(tmpUidLine, eol, foldingScheme);
sb.append(foldedUidLine);
sb.append(eol);
}
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());
if(birthdayFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(birthdayFeature.getCharset().name());
}
if(birthdayFeature.hasBirthdayParameterType()) {
BirthdayParameterType ptype = birthdayFeature.getBirthdayParameterType();
tmpSb.append(";VALUE=");
tmpSb.append(ptype.getTypeName());
}
if(birthdayFeature.hasExtendedParameters()) {
buildExtendParameters(birthdayFeature, tmpSb);
}
ISOFormat isoFormat = birthdayFeature.getISO8601Format();
tmpSb.append(":");
tmpSb.append(ISOUtils.formatISO8601Date(birthdayFeature.getBirthday(), isoFormat));
String tmpBdayLine = tmpSb.toString();
String foldedBdayLine = VCardUtils.foldLine(tmpBdayLine, eol, foldingScheme);
sb.append(foldedBdayLine);
sb.append(eol);
}
}
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) {
boolean isQuotedPrintable = addressFeature.isQuotedPrintable();
StringBuilder tmpSb = new StringBuilder();
if(addressFeature.hasGroup()) {
tmpSb.append(addressFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(addressFeature.getTypeString());
if(addressFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(addressFeature.getCharset().name());
}
if(addressFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(addressFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
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);
}
if(addressFeature.hasExtendedParameters()) {
buildExtendParameters(addressFeature, tmpSb);
}
tmpSb.append(":");
if(addressFeature.hasPostOfficebox()) {
tmpSb.append(escapeOrEncode(addressFeature.getPostOfficeBox(), isQuotedPrintable, addressFeature.getCharset()));
}
tmpSb.append(";");
if(addressFeature.hasExtendedAddress()) {
tmpSb.append(escapeOrEncode(addressFeature.getExtendedAddress(), isQuotedPrintable, addressFeature.getCharset()));
}
tmpSb.append(";");
if(addressFeature.hasStreetAddress()) {
tmpSb.append(escapeOrEncode(addressFeature.getStreetAddress(), isQuotedPrintable, addressFeature.getCharset()));
}
tmpSb.append(";");
if(addressFeature.hasLocality()) {
tmpSb.append(escapeOrEncode(addressFeature.getLocality(), isQuotedPrintable, addressFeature.getCharset()));
}
tmpSb.append(";");
if(addressFeature.hasRegion()) {
tmpSb.append(escapeOrEncode(addressFeature.getRegion(), isQuotedPrintable, addressFeature.getCharset()));
}
tmpSb.append(";");
if(addressFeature.hasPostalCode()) {
tmpSb.append(escapeOrEncode(addressFeature.getPostalCode(), isQuotedPrintable, addressFeature.getCharset()));
}
tmpSb.append(";");
if(addressFeature.hasCountryName()) {
tmpSb.append(escapeOrEncode(addressFeature.getCountryName(), isQuotedPrintable, addressFeature.getCharset()));
}
String tmpAddressLine = tmpSb.toString();
String foldedAddressLine = VCardUtils.foldLine(tmpAddressLine, eol, foldingScheme);
sb.append(foldedAddressLine);
sb.append(eol);
}
}
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()) {
boolean isQuotedPrintable = labelFeature.isQuotedPrintable();
StringBuilder tmpSb = new StringBuilder();
if(labelFeature.hasGroup()) {
tmpSb.append(labelFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(labelFeature.getTypeString());
if(labelFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(labelFeature.getCharset().name());
}
if(labelFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(labelFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
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);
}
if(labelFeature.hasExtendedParameters()) {
buildExtendParameters(labelFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(labelFeature.getLabel(), isQuotedPrintable, labelFeature.getCharset()));
String tmpLabelLine = tmpSb.toString();
String foldedLabelLine = null;
if(isQuotedPrintable) {
//RFC-822 line folding.
foldedLabelLine = VCardUtils.foldLine(tmpLabelLine, "=0D=0A=\r\n", foldingScheme);
}
else {
foldedLabelLine = VCardUtils.foldLine(tmpLabelLine, foldingScheme);
}
sb.append(foldedLabelLine);
sb.append(eol);
}
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()) {
boolean isQuotedPrintable = telephoneFeature.isQuotedPrintable();
StringBuilder tmpSb = new StringBuilder();
if(telephoneFeature.hasGroup()) {
tmpSb.append(telephoneFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(telephoneFeature.getTypeString());
if(telephoneFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(telephoneFeature.getCharset().name());
}
if(telephoneFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(telephoneFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
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);
}
if(telephoneFeature.hasExtendedParameters()) {
buildExtendParameters(telephoneFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(telephoneFeature.getTelephone(), isQuotedPrintable, telephoneFeature.getCharset()));
String tmpTelephoneLine = tmpSb.toString();
String foldedTelephoneLine = VCardUtils.foldLine(tmpTelephoneLine, eol, foldingScheme);
sb.append(foldedTelephoneLine);
sb.append(eol);
}
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()) {
boolean isQuotedPrintable = emailFeature.isQuotedPrintable();
StringBuilder tmpSb = new StringBuilder();
if(emailFeature.hasGroup()) {
tmpSb.append(emailFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(emailFeature.getTypeString());
if(emailFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(emailFeature.getCharset().name());
}
if(emailFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(emailFeature.getLanguage().getLanguageCode());
}
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);
}
EncodingType encType = emailFeature.getEncodingType();
switch(encType)
{
case BASE64:
case BINARY:
{
tmpSb.append(";ENCODING=");
tmpSb.append(encType.getType());
tmpSb.append(":");
byte[] emailBytes = null;
if(emailFeature.hasCharset()) {
emailBytes = emailFeature.getEmail().getBytes(emailFeature.getCharset().name());
}
else {
emailBytes = emailFeature.getEmail().getBytes(Charset.defaultCharset().name());
}
if(emailFeature.isSetCompression()) {
tmpSb.append(Base64Wrapper.encode(emailBytes, Base64Wrapper.OPTIONS.GZIP_COMPRESSION));
}
else {
tmpSb.append(Base64Wrapper.encode(emailBytes));
}
break;
}
case QUOTED_PRINTABLE:
{
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
default:
{
tmpSb.append(":");
tmpSb.append(escapeOrEncode(emailFeature.getEmail(), isQuotedPrintable, emailFeature.getCharset()));
break;
}
}
String tmpEmailLine = tmpSb.toString();
String foldedEmailLine = VCardUtils.foldLine(tmpEmailLine, eol, binaryFoldingScheme);
sb.append(foldedEmailLine);
sb.append(eol);
}
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()) {
boolean isQuotedPrintable = noteFeature.isQuotedPrintable();
StringBuilder tmpSb = new StringBuilder();
if(noteFeature.hasGroup()) {
tmpSb.append(noteFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(noteFeature.getTypeString());
if(noteFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(noteFeature.getCharset().name());
}
if(noteFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(noteFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(noteFeature.hasExtendedParameters()) {
buildExtendParameters(noteFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(noteFeature.getNote(), isQuotedPrintable, noteFeature.getCharset()));
String tmpNoteLine = tmpSb.toString();
String foldedNoteLine = VCardUtils.foldLine(tmpNoteLine, eol, foldingScheme);
sb.append(foldedNoteLine);
sb.append(eol);
}
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()) {
boolean isQuotedPrintable = nicknameFeature.isQuotedPrintable();
StringBuilder tmpSb = new StringBuilder();
if(nicknameFeature.hasGroup()) {
tmpSb.append(nicknameFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(nicknameFeature.getTypeString());
if(nicknameFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(nicknameFeature.getCharset().name());
}
if(nicknameFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(nicknameFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(nicknameFeature.hasExtendedParameters()) {
buildExtendParameters(nicknameFeature, tmpSb);
}
tmpSb.append(":");
Iterator<String> nicknames = nicknameFeature.getNicknames();
while(nicknames.hasNext()) {
String nickname = nicknames.next();
tmpSb.append(escapeOrEncode(nickname, isQuotedPrintable, nicknameFeature.getCharset()));
tmpSb.append(",");
}
tmpSb.deleteCharAt(tmpSb.length()-1);
String tmpNicknameLine = tmpSb.toString();
String foldedNicknameLine = VCardUtils.foldLine(tmpNicknameLine, eol, foldingScheme);
sb.append(foldedNicknameLine);
sb.append(eol);
}
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()) {
boolean isQuotedPrintable = categoriesFeature.isQuotedPrintable();
StringBuilder tmpSb = new StringBuilder();
if(categoriesFeature.hasGroup()) {
tmpSb.append(categoriesFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(categoriesFeature.getTypeString());
if(categoriesFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(categoriesFeature.getCharset().name());
}
if(categoriesFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(categoriesFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(categoriesFeature.hasExtendedParameters()) {
buildExtendParameters(categoriesFeature, tmpSb);
}
tmpSb.append(":");
Iterator<String> categories = categoriesFeature.getCategories();
while(categories.hasNext()) {
String category = categories.next();
tmpSb.append(escapeOrEncode(category, isQuotedPrintable, categoriesFeature.getCharset()));
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, eol, foldingScheme);
sb.append(foldedCategoryLine);
sb.append(eol);
}
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 classFeature
* - 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()) {
boolean isQuotedPrintable = classFeature.isQuotedPrintable();
StringBuilder tmpSb = new StringBuilder();
if(classFeature.hasGroup()) {
tmpSb.append(classFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(classFeature.getTypeString());
if(classFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(classFeature.getCharset().name());
}
if(classFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(classFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(classFeature.hasExtendedParameters()) {
buildExtendParameters(classFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(classFeature.getSecurityClass(), isQuotedPrintable, classFeature.getCharset()));
String tmpClassLine = tmpSb.toString();
String foldedClassLine = VCardUtils.foldLine(tmpClassLine, eol, foldingScheme);
sb.append(foldedClassLine);
sb.append(eol);
}
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()) {
boolean isQuotedPrintable = productIdFeature.isQuotedPrintable();
StringBuilder tmpSb = new StringBuilder();
if(productIdFeature.hasGroup()) {
tmpSb.append(productIdFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(productIdFeature.getTypeString());
if(productIdFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(productIdFeature.getCharset().name());
}
if(productIdFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(productIdFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(productIdFeature.hasExtendedParameters()) {
buildExtendParameters(productIdFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(productIdFeature.getProductId(), isQuotedPrintable, productIdFeature.getCharset()));
String tmpProductIdLine = tmpSb.toString();
String foldedProductIdLine = VCardUtils.foldLine(tmpProductIdLine, eol, foldingScheme);
sb.append(foldedProductIdLine);
sb.append(eol);
}
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()) {
boolean isQuotedPrintable = sortStringFeature.isQuotedPrintable();
StringBuilder tmpSb = new StringBuilder();
if(sortStringFeature.hasGroup()) {
tmpSb.append(sortStringFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(sortStringFeature.getTypeString());
if(sortStringFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(sortStringFeature.getCharset().name());
}
if(sortStringFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(sortStringFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(sortStringFeature.hasExtendedParameters()) {
buildExtendParameters(sortStringFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(sortStringFeature.getSortString(), isQuotedPrintable, sortStringFeature.getCharset()));
String tmpSortStringLine = tmpSb.toString();
String foldedSortStringLine = VCardUtils.foldLine(tmpSortStringLine, eol, foldingScheme);
sb.append(foldedSortStringLine);
sb.append(eol);
}
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());
if(keyFeature.hasCharset()) {
tmpSb.append(";");
tmpSb.append("CHARSET=");
tmpSb.append(keyFeature.getCharset().name());
}
// determine if the key contains binary data or text data
boolean binary = keyFeature.getEncodingType() == EncodingType.BINARY || keyFeature.getEncodingType() == EncodingType.BASE64;
// output the ENCODING parameter
// only do so if the key contains binary data
if(binary) {
tmpSb.append(";");
switch(compatMode)
{
case MS_OUTLOOK:
{
tmpSb.append("ENCODING=");
tmpSb.append(EncodingType.BASE64.getType());
break;
}
case MAC_ADDRESS_BOOK:
{
tmpSb.append(EncodingType.BASE64.getType());
break;
}
case EVOLUTION:
case KDE_ADDRESS_BOOK:
case RFC2426:
case I_PHONE:
{
tmpSb.append("ENCODING=");
tmpSb.append(keyFeature.getEncodingType().getType());
break;
}
}
}
if(keyFeature.hasKeyTextType()) {
tmpSb.append(";");
tmpSb.append("TYPE=");
tmpSb.append(keyFeature.getKeyTextType().getTypeName());
}
if(keyFeature.hasExtendedParameters()) {
buildExtendParameters(keyFeature, tmpSb);
}
tmpSb.append(":");
String foldedKeyLine = null;
switch(compatMode)
{
case MAC_ADDRESS_BOOK:
case MS_OUTLOOK:
{
String b64str = null;
byte[] keyBytes = keyFeature.getKey();
if(binary) {
try {
if(keyFeature.isSetCompression()) {
b64str = Base64Wrapper.encode(keyBytes, Base64Wrapper.OPTIONS.GZIP_COMPRESSION);
}
else {
b64str = Base64Wrapper.encode(keyBytes, Base64Wrapper.OPTIONS.NO_COMPRESSION);
}
}
catch(Exception ex) {
throw new VCardBuildException(ex.getMessage(), ex);
}
}
else {
b64str = new String(keyBytes);
}
String tmpKeyLine = tmpSb.toString();
String foldedKeyLine2 = VCardUtils.foldLine(tmpKeyLine, eol, binaryFoldingScheme);
foldedKeyLine = VCardUtils.foldLine(b64str, eol, binaryFoldingScheme);
sb.append(foldedKeyLine2); //Type declaration with param types
sb.append(eol); //Distinctive line break
sb.append(binaryFoldingScheme.getIndent()); //Indent first line
break;
}
case EVOLUTION:
case KDE_ADDRESS_BOOK:
case RFC2426:
case I_PHONE:
{
byte[] keyBytes = keyFeature.getKey();
if(binary) {
try {
if(keyFeature.isSetCompression()) {
tmpSb.append(Base64Wrapper.encode(keyBytes, Base64Wrapper.OPTIONS.GZIP_COMPRESSION));
}
else {
tmpSb.append(Base64Wrapper.encode(keyBytes, Base64Wrapper.OPTIONS.NO_COMPRESSION));
}
}
catch(Exception ex) {
throw new VCardBuildException(ex.getMessage(), ex);
}
}
else {
tmpSb.append(new String(keyBytes));
}
String tmpKeyLine = tmpSb.toString();
foldedKeyLine = VCardUtils.foldLine(tmpKeyLine, eol, binaryFoldingScheme);
break;
}
}
sb.append(foldedKeyLine);
switch(compatMode)
{
case MS_OUTLOOK:
{
sb.append(eol);
sb.append(eol);
break;
}
case RFC2426:
case EVOLUTION:
case KDE_ADDRESS_BOOK:
case I_PHONE:
case MAC_ADDRESS_BOOK:
{
sb.append(eol);
break;
}
}
}
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.hasCharset()) {
tmpSb.append("CHARSET=");
tmpSb.append(photoFeature.getCharset().name());
tmpSb.append(";");
}
if(photoFeature.isURI()) {
tmpSb.append("VALUE=URI:");
tmpSb.append(photoFeature.getPhotoURI().toString());
String tmpPhotoLine = tmpSb.toString();
foldedPhotoLine = VCardUtils.foldLine(tmpPhotoLine, eol, foldingScheme);
}
else if(photoFeature.isInline()) {
switch(compatMode)
{
case MS_OUTLOOK:
{
tmpSb.append("ENCODING=");
tmpSb.append(EncodingType.BASE64.getType());
break;
}
case MAC_ADDRESS_BOOK:
{
tmpSb.append(EncodingType.BASE64.getType());
break;
}
case EVOLUTION:
case KDE_ADDRESS_BOOK:
case RFC2426:
case I_PHONE:
{
tmpSb.append("ENCODING=");
tmpSb.append(photoFeature.getEncodingType().getType());
break;
}
}
if(photoFeature.hasImageMediaType()) {
tmpSb.append(";");
tmpSb.append("TYPE=");
tmpSb.append(photoFeature.getImageMediaType().getTypeName());
}
if(photoFeature.hasExtendedParameters()) {
buildExtendParameters(photoFeature, tmpSb);
}
tmpSb.append(":");
switch(compatMode)
{
case MS_OUTLOOK:
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, Base64Wrapper.OPTIONS.NO_COMPRESSION);
}
}
catch(Exception ex) {
throw new VCardBuildException(ex.getMessage(), ex);
}
String tmpPhotoLine = tmpSb.toString();
String foldedPhotoLine2 = VCardUtils.foldLine(tmpPhotoLine, eol, binaryFoldingScheme);
foldedPhotoLine = VCardUtils.foldLine(b64str, eol, binaryFoldingScheme);
sb.append(foldedPhotoLine2); //Type declaration with param types
sb.append(eol); //Distinctive line break
sb.append(binaryFoldingScheme.getIndent()); //Indent first line
break;
}
case RFC2426:
case EVOLUTION:
case KDE_ADDRESS_BOOK:
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, Base64Wrapper.OPTIONS.NO_COMPRESSION));
}
}
catch(Exception ex) {
throw new VCardBuildException(ex.getMessage(), ex);
}
String tmpPhotoLine = tmpSb.toString();
foldedPhotoLine = VCardUtils.foldLine(tmpPhotoLine, eol, binaryFoldingScheme);
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);
switch(compatMode)
{
case MS_OUTLOOK:
{
sb.append(eol);
sb.append(eol);
break;
}
case RFC2426:
case EVOLUTION:
case KDE_ADDRESS_BOOK:
case I_PHONE:
case MAC_ADDRESS_BOOK:
{
sb.append(eol);
break;
}
}
}
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.hasCharset()) {
tmpSb.append("CHARSET=");
tmpSb.append(logoFeature.getCharset().name());
tmpSb.append(";");
}
if(logoFeature.isURI()) {
tmpSb.append("VALUE=URI:");
tmpSb.append(logoFeature.getLogoURI().toString());
String tmpLogoLine = tmpSb.toString();
foldedLogoLine = VCardUtils.foldLine(tmpLogoLine, eol, foldingScheme);
}
else if(logoFeature.isInline()) {
switch(compatMode)
{
case MS_OUTLOOK:
{
tmpSb.append("ENCODING=");
tmpSb.append(EncodingType.BASE64.getType());
break;
}
case MAC_ADDRESS_BOOK:
{
tmpSb.append(EncodingType.BASE64.getType());
break;
}
case EVOLUTION:
case KDE_ADDRESS_BOOK:
case RFC2426:
case I_PHONE:
{
tmpSb.append("ENCODING=");
tmpSb.append(logoFeature.getEncodingType().getType());
break;
}
}
if(logoFeature.hasImageMediaType()) {
tmpSb.append(";");
tmpSb.append("TYPE=");
tmpSb.append(logoFeature.getImageMediaType().getTypeName());
}
if(logoFeature.hasExtendedParameters()) {
buildExtendParameters(logoFeature, tmpSb);
}
tmpSb.append(":");
switch(compatMode)
{
case MAC_ADDRESS_BOOK:
case MS_OUTLOOK:
{
String b64str = null;
try {
byte[] logoBytes = logoFeature.getLogo();
if(logoFeature.isSetCompression()) {
b64str = Base64Wrapper.encode(logoBytes, Base64Wrapper.OPTIONS.GZIP_COMPRESSION);
}
else {
b64str = Base64Wrapper.encode(logoBytes, Base64Wrapper.OPTIONS.NO_COMPRESSION);
}
}
catch(Exception ex) {
throw new VCardBuildException(ex.getMessage(), ex);
}
String tmpLogoLine = tmpSb.toString();
String foldedPhotoLine2 = VCardUtils.foldLine(tmpLogoLine, eol, binaryFoldingScheme);
foldedLogoLine = VCardUtils.foldLine(b64str, binaryFoldingScheme);
sb.append(foldedPhotoLine2); //Type declaration with param types
sb.append(eol); //Distinctive line break
sb.append(binaryFoldingScheme.getIndent()); //Indent first line
break;
}
case RFC2426:
case EVOLUTION:
case KDE_ADDRESS_BOOK:
case I_PHONE:
{
try {
byte[] logoBytes = logoFeature.getLogo();
if(logoFeature.isSetCompression()) {
tmpSb.append(Base64Wrapper.encode(logoBytes, Base64Wrapper.OPTIONS.GZIP_COMPRESSION));
}
else {
tmpSb.append(Base64Wrapper.encode(logoBytes, Base64Wrapper.OPTIONS.NO_COMPRESSION));
}
}
catch(Exception ex) {
throw new VCardBuildException(ex.getMessage(), ex);
}
String tmpLogoLine = tmpSb.toString();
foldedLogoLine = VCardUtils.foldLine(tmpLogoLine, eol, binaryFoldingScheme);
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);
switch(compatMode)
{
case MS_OUTLOOK:
{
sb.append(eol);
sb.append(eol);
break;
}
case RFC2426:
case EVOLUTION:
case KDE_ADDRESS_BOOK:
case I_PHONE:
case MAC_ADDRESS_BOOK:
{
sb.append(eol);
break;
}
}
}
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.hasCharset()) {
tmpSb.append("CHARSET=");
tmpSb.append(soundFeature.getCharset().name());
tmpSb.append(";");
}
if(soundFeature.isURI()) {
tmpSb.append("VALUE=URI:");
tmpSb.append(soundFeature.getSoundURI().getPath());
String tmpSoundLine = tmpSb.toString();
foldedSoundLine = VCardUtils.foldLine(tmpSoundLine, eol, foldingScheme);
}
else if(soundFeature.isInline()) {
switch(compatMode)
{
case MS_OUTLOOK:
{
tmpSb.append("ENCODING=");
tmpSb.append(EncodingType.BASE64.getType());
break;
}
case MAC_ADDRESS_BOOK:
{
tmpSb.append(EncodingType.BASE64.getType());
break;
}
case EVOLUTION:
case KDE_ADDRESS_BOOK:
case RFC2426:
case I_PHONE:
{
tmpSb.append("ENCODING=");
tmpSb.append(soundFeature.getEncodingType().getType());
break;
}
}
if(soundFeature.hasAudioMediaType()) {
tmpSb.append(";");
tmpSb.append("TYPE=");
tmpSb.append(soundFeature.getAudioMediaType().getTypeName());
}
if(soundFeature.hasExtendedParameters()) {
buildExtendParameters(soundFeature, tmpSb);
}
tmpSb.append(":");
switch(compatMode)
{
case MAC_ADDRESS_BOOK:
case MS_OUTLOOK:
{
String b64str = null;
try {
byte[] soundBytes = soundFeature.getSound();
if(soundFeature.isSetCompression()) {
b64str = Base64Wrapper.encode(soundBytes, Base64Wrapper.OPTIONS.GZIP_COMPRESSION);
}
else {
b64str = Base64Wrapper.encode(soundBytes, Base64Wrapper.OPTIONS.NO_COMPRESSION);
}
}
catch(Exception ex) {
throw new VCardBuildException(ex.getMessage(), ex);
}
String tmpSoundLine = tmpSb.toString();
String foldedSoundLine2 = VCardUtils.foldLine(tmpSoundLine, eol, binaryFoldingScheme);
foldedSoundLine = VCardUtils.foldLine(b64str, eol, binaryFoldingScheme);
sb.append(foldedSoundLine2); //Type declaration with param types
sb.append(eol); //Distinctive line break
sb.append(binaryFoldingScheme.getIndent()); //Indent first line
break;
}
case RFC2426:
case EVOLUTION:
case KDE_ADDRESS_BOOK:
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, Base64Wrapper.OPTIONS.NO_COMPRESSION));
}
}
catch(Exception ex) {
throw new VCardBuildException(ex.getMessage(), ex);
}
String tmpSoundLine = tmpSb.toString();
foldedSoundLine = VCardUtils.foldLine(tmpSoundLine, eol, binaryFoldingScheme);
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);
switch(compatMode)
{
case MS_OUTLOOK:
{
sb.append(eol);
sb.append(eol);
break;
}
case RFC2426:
case EVOLUTION:
case KDE_ADDRESS_BOOK:
case I_PHONE:
case MAC_ADDRESS_BOOK:
{
sb.append(eol);
break;
}
}
}
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.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(agentFeature.getCharset().name());
}
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, eol, foldingScheme);
sb.append(foldedAgentLine);
sb.append(eol);
}
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 the IMPP feature as a String.</p>
*
* @param sb
* - The StringBuilder to append to
* @param imppFeature
* - The feature to output as a String
* @throws VCardBuildException
* Thrown when the IMPP feature is null
*/
private void buildImppFeature(StringBuilder sb, IMPPFeature imppFeature) throws VCardBuildException {
try {
if(imppFeature != null) {
if(imppFeature.hasURI()) {
String uri = imppFeature.getURI().toString();
StringBuilder tmpSb = new StringBuilder();
if(imppFeature.hasGroup()) {
tmpSb.append(imppFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(imppFeature.getTypeString());
if(imppFeature.hasIMPPParameterTypes()) {
tmpSb.append(";");
Iterator<IMPPParameterType> paramTypes = imppFeature.getIMPPParameterTypes();
switch(imppFeature.getParameterTypeStyle())
{
case PARAMETER_LIST:
{
while(paramTypes.hasNext()) {
IMPPParameterType imppType = paramTypes.next();
tmpSb.append("TYPE=");
tmpSb.append(imppType.getType());
tmpSb.append(";");
}
break;
}
case PARAMETER_VALUE_LIST:
{
tmpSb.append("TYPE=");
while(paramTypes.hasNext()) {
IMPPParameterType imppType = paramTypes.next();
tmpSb.append(imppType.getType());
tmpSb.append(",");
}
break;
}
}
tmpSb.deleteCharAt(tmpSb.length()-1);
}
if(imppFeature.hasExtendedIMPPParameterTypes()) {
Iterator<XIMPPParameterType> xParamTypes = imppFeature.getExtendedIMPPParameterTypes();
switch(imppFeature.getParameterTypeStyle())
{
case PARAMETER_LIST:
{
tmpSb.append(";");
while(xParamTypes.hasNext()) {
XIMPPParameterType xImppType = xParamTypes.next();
tmpSb.append("TYPE=");
tmpSb.append(xImppType.getXtendedTypeName());
if(xImppType.hasXtendedTypeValue()) {
tmpSb.append("=");
tmpSb.append(xImppType.getXtendedTypeValue());
}
tmpSb.append(";");
}
break;
}
case PARAMETER_VALUE_LIST:
{
if(imppFeature.hasIMPPParameterTypes()) {
//Continue from the list
tmpSb.append(",");
}
else {
//Start a new
tmpSb.append(";TYPE=");
}
while(xParamTypes.hasNext()) {
XIMPPParameterType xImppType = xParamTypes.next();
tmpSb.append(xImppType.getXtendedTypeName());
if(xImppType.hasXtendedTypeValue()) {
tmpSb.append("=");
tmpSb.append(xImppType.getXtendedTypeValue());
}
tmpSb.append(",");
}
break;
}
}
tmpSb.deleteCharAt(tmpSb.length()-1);
}
if(imppFeature.hasExtendedParameters()) {
buildExtendParameters(imppFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(uri);
//Gmail, iPhone and iOS Exporter expect an escaped URL,
//so maybe they might expect the URI to be escaped too ?
// switch(compatMode)
// {
// case GMAIL:
// case I_PHONE:
// case IOS_EXPORTER:
// {
// tmpSb.append(VCardUtils.escapeString(uri));
// break;
// }
//
// default:
// {
// tmpSb.append(uri);
// break;
// }
// }
String tmpUrlLine = tmpSb.toString();
String foldedUrlLine = VCardUtils.foldLine(tmpUrlLine, eol, foldingScheme);
sb.append(foldedUrlLine);
sb.append(eol);
}
else {
throw new VCardBuildException("IMPPFeature ("+VCardType.IMPP.getType()+") exists but is empty.");
}
}
}
catch(Exception ex) {
throw new VCardBuildException("IMPPFeature ("+VCardType.IMPP.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()) {
boolean isQuotedPrintable = extendedFeature.isQuotedPrintable();
StringBuilder tmpSb = new StringBuilder();
if(extendedFeature.hasGroup()) {
tmpSb.append(extendedFeature.getGroup());
tmpSb.append(".");
}
tmpSb.append(extendedFeature.getExtensionName());
if(extendedFeature.hasCharset()) {
tmpSb.append(";CHARSET=");
tmpSb.append(extendedFeature.getCharset().name());
}
if(extendedFeature.hasLanguage()) {
tmpSb.append(";LANGUAGE=");
tmpSb.append(extendedFeature.getLanguage().getLanguageCode());
}
if(isQuotedPrintable) {
tmpSb.append(";ENCODING=QUOTED-PRINTABLE");
}
if(extendedFeature.hasExtendedParameters()) {
buildExtendParameters(extendedFeature, tmpSb);
}
tmpSb.append(":");
tmpSb.append(escapeOrEncode(extendedFeature.getExtensionData(), isQuotedPrintable, extendedFeature.getCharset()));
String tmpExtendedLine = tmpSb.toString();
String foldedExtendedLine = VCardUtils.foldLine(tmpExtendedLine, eol, foldingScheme);
sb.append(foldedExtendedLine);
sb.append(eol);
}
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>Builds the extended parameter types given a string builder and the
* specified feature that is guaranteed to have extended parameters.</p>
*
* @param feature
* @param sb
*/
private void buildExtendParameters(TypeTools feature, StringBuilder sb)
{
Iterator<ExtendedParameterType> xParamTypes = feature.getExtendedParameters();
switch(feature.getParameterTypeStyle())
{
case PARAMETER_LIST:
{
sb.append(";");
while(xParamTypes.hasNext()) {
ExtendedParameterType xParam = xParamTypes.next();
sb.append(xParam.getXtendedTypeName());
if(xParam.hasXtendedTypeValue()) {
sb.append("=");
sb.append(xParam.getXtendedTypeValue());
}
sb.append(";");
}
break;
}
case PARAMETER_VALUE_LIST:
{
if(feature.hasExtendedParameters()) {
//Continue from the list
sb.append(",");
}
else {
//Start a new
sb.append(";");
}
while(xParamTypes.hasNext()) {
ExtendedParameterType xParam = xParamTypes.next();
sb.append(xParam.getXtendedTypeName());
if(xParam.hasXtendedTypeValue()) {
sb.append("=");
sb.append(xParam.getXtendedTypeValue());
}
sb.append(",");
}
break;
}
}
sb.deleteCharAt(sb.length()-1);
}
/**
* <p>Helper method to escape string and encode to QUOTED-PRINTABLE if needed.
* Here we lazy create the codec only if we actually need it. The codec needs
* a charset to be defined, should it be null then it will use the default charset
* of the system.</p>
*
* @param str
* @param isQuotedPrintable
* @return {@link String}
* @throws EncoderException
* @throws UnsupportedEncodingException
*/
private String escapeOrEncode(String str, boolean isQuotedPrintable, Charset charset) throws EncoderException, UnsupportedEncodingException
{
if(isQuotedPrintable) {
if(charset == null) {
charset = Charset.defaultCharset();
}
if(qpCodec == null) {
qpCodec = new QuotedPrintableCodec();
}
return qpCodec.encode(str, charset.name());
}
else {
return VCardUtils.escapeString(str);
}
}
/**
* <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);
setBinaryfoldingScheme(null);
setCompatibilityMode(null);
setEOL(null);
this.vcard = null;
}
}