/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at
* src/com/vodafone360/people/VODAFONE.LICENSE.txt or
* http://github.com/360/360-Engine-for-Android
* See the License for the specific language governing permissions and
* limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each file and
* include the License file at src/com/vodafone360/people/VODAFONE.LICENSE.txt.
* If applicable, add the following below this CDDL HEADER, with the fields
* enclosed by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2010 Vodafone Sales & Services Ltd. All rights reserved.
* Use is subject to license terms.
*/
package com.vodafone360.people.datatypes;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import com.vodafone360.people.service.transport.http.HttpConnectionThread;
import android.text.TextUtils;
import android.text.format.Time;
import android.util.TimeFormatException;
/**
* Helper class for handling VCard information associated with Contacts either
* from People server/client or from Native database. Also used to help with
* handling of Call log/Message log events displayed in Timeline.
*/
public class VCardHelper {
public static final char LIST_SEPARATOR = ';';
public static final char SUB_LIST_SEPARATOR = ',';
/**
* Item class representing vCard item.
*/
private static class Item {
Item(String value, boolean isSubValue) {
mValue = value;
mIsSubValue = isSubValue;
}
String mValue;
boolean mIsSubValue;
}
/**
* Handle VCard name fields.
*/
public static class Name {
public String firstname = null;
public String midname = null;
public String surname = null;
public String title = null;
public String suffixes = null;
/**
* Default constructor.
*/
public Name() {
}
/** {@inheritDoc} */
@Override
public String toString() {
final StringBuffer sb = new StringBuffer();
if(!TextUtils.isEmpty(title)) {
sb.append(title);
sb.append(' ');
}
if(!TextUtils.isEmpty(firstname)) {
sb.append(firstname);
sb.append(' ');
}
if(!TextUtils.isEmpty(midname)) {
sb.append(midname);
sb.append(' ');
}
if(!TextUtils.isEmpty(surname)) {
sb.append(surname);
sb.append(' ');
}
if(!TextUtils.isEmpty(suffixes)) {
sb.append(suffixes);
}
return sb.toString().trim();
}
}
/**
* Handle VCard organisation fields.
*/
public static class Organisation {
public String name = null;
public final List<String> unitNames = new ArrayList<String>();
/** {@inheritDoc} */
@Override
public String toString() {
return name + ", " + unitNames;
}
}
/**
* Handle VCard postal address
*/
public static class PostalAddress {
public String postOfficeBox = null;
public String addressLine1 = null;
public String addressLine2 = null;
public String city = null;
public String postCode = null;
public String county = null;
public String country = null;
/** {@inheritDoc} */
@Override
public String toString() {
final StringBuffer sb = new StringBuffer();
if(!TextUtils.isEmpty(postOfficeBox)) {
sb.append(postOfficeBox);
sb.append("\n");
}
if(!TextUtils.isEmpty(addressLine1)) {
sb.append(addressLine1);
sb.append("\n");
}
if(!TextUtils.isEmpty(addressLine2)) {
sb.append(addressLine2);
sb.append("\n");
}
if(!TextUtils.isEmpty(city)) {
sb.append(city);
sb.append("\n");
}
if(!TextUtils.isEmpty(county)) {
sb.append(county);
sb.append("\n");
}
if(!TextUtils.isEmpty(postCode)) {
sb.append(postCode);
sb.append("\n");
}
if(!TextUtils.isEmpty(country)) {
sb.append(country);
sb.append("\n");
}
if (sb.length() > 0) {
return sb.toString().substring(0, sb.length() - 1);
} else {
return "";
}
}
/**
* Whether postal address item is empty.
*
* @return false if address has any content, null otherwise
*/
public boolean isEmpty() {
return (TextUtils.isEmpty(postOfficeBox) &&
TextUtils.isEmpty(addressLine1) &&
TextUtils.isEmpty(addressLine2) &&
TextUtils.isEmpty(city) &&
TextUtils.isEmpty(county) &&
TextUtils.isEmpty(country) &&
TextUtils.isEmpty(postCode));
}
}
/**
* Create String from array of VCard items.
*
* @param itemList List array of VCard items.
* @return String constructed from array of Items.
*/
private static String createVCardList(List<Item> itemList) {
StringBuffer value = new StringBuffer();
for (int i = 0; i < itemList.size(); i++) {
Item item = itemList.get(i);
if (item.mValue != null) {
String val2 = item.mValue.replace(";", "\\;");
String val3 = val2.replace(",", "\\,");
/*
* (JT) TODO: removed the "escaping" of '/' character but my
* understanding of vCard format is that only ';' needs to be
* escaped but in the code we also escape ',' String val4 =
* val3.replace("/", "\\/");
*/
value.append(val3);
}
if (i < itemList.size() - 1) {
if (item.mIsSubValue) {
value.append(SUB_LIST_SEPARATOR);
} else {
value.append(LIST_SEPARATOR);
}
}
}
int idx = value.length() - 1;
while (idx >= 0 && (value.charAt(idx) == ';' || value.charAt(idx) == ',')) {
idx--;
}
return value.substring(0, idx + 1);
}
/**
* Create array of VCard items from supplied String.
*
* @param val String containing VCard items.
* @param itemList List of VCard items to populate.
*/
private static void getVCardList(String val, List<Item> itemList) {
itemList.clear();
boolean escaped = false;
int i = 0;
String currentItem = "";
for (i = 0; i < val.length(); i++) {
char ch = val.charAt(i);
if (ch == '\\') {
escaped = true;
continue;
}
if (escaped || (ch != LIST_SEPARATOR && ch != SUB_LIST_SEPARATOR)) {
currentItem += ch;
escaped = false;
continue;
}
if (ch == SUB_LIST_SEPARATOR) {
itemList.add(new Item(currentItem, true));
} else {
itemList.add(new Item(currentItem, false));
}
currentItem = "";
}
if (currentItem.length() > 0) {
itemList.add(new Item(currentItem, false));
}
}
/**
* Return next complete Item from item ListIterator as String. Sub-items are
* appended to the String.
*
* @param it ListIterator to iterate through Items.
* @return next Item.
*/
private static String nextFullItem(ListIterator<Item> it) {
StringBuffer result = new StringBuffer();
while (it.hasNext()) {
Item item = it.next();
result.append(item.mValue + " ");
if (!item.mIsSubValue) {
return result.toString().trim();
}
}
return result.toString();
}
/**
* Return List of Strings made up of next full item and sub-items retrieved
* from ListIterator.
*
* @param it ListIterator to iterate through Items.
* @return List of Strings generated from Item.
*/
private static List<String> nextFullItemArray(ListIterator<Item> it) {
List<String> stringList = new ArrayList<String>();
while (it.hasNext()) {
Item item = it.next();
stringList.add(item.mValue);
if (!item.mIsSubValue) {
return stringList;
}
}
return stringList;
}
/**
* Create a VCard string from a single value Suitable for Url, Internet
* Address, IM Address, Role, Title and Note
*
* @param textValue The string value to use
* @return A string in VCard format (does not include types)
*/
protected static String makeSingleTextValue(String textValue) {
List<Item> itemList = new ArrayList<Item>();
itemList.add(new Item(textValue, false));
return createVCardList(itemList);
}
/**
* Fetch a single string value from a VCard string Suitable for Url,
* Internet Address, IM Address, Role, Title and Note
*
* @param val A string in VCard format.
* @return the single text value.
*/
protected static String getSingleTextValue(String val) {
if (val == null) {
return null;
}
List<Item> itemList = new ArrayList<Item>();
getVCardList(val, itemList);
ListIterator<Item> it = itemList.listIterator();
return nextFullItem(it);
}
/**
* Return VCard name string from supplied Name.
*
* @param name Name item.
* @return String generated from supplied Name.
*/
public static String makeName(Name name) {
List<Item> itemList = new ArrayList<Item>();
itemList.add(new Item(name.surname, false));
itemList.add(new Item(name.firstname, false));
itemList.add(new Item(name.midname, false));
itemList.add(new Item(name.title, false));
itemList.add(new Item(name.suffixes, false));
return createVCardList(itemList);
}
/**
* Get Name object from supplied String.
*
* @param val String containing name information.
* @return Name item generated from supplied string.
*/
public static Name getName(String val) {
if (val == null) {
return null;
}
Name name = new Name();
List<Item> itemList = new ArrayList<Item>();
getVCardList(val, itemList);
ListIterator<Item> it = itemList.listIterator();
name.surname = nextFullItem(it);
name.firstname = nextFullItem(it);
name.midname = nextFullItem(it);
name.title = nextFullItem(it);
name.suffixes = nextFullItem(it);
return name;
}
/**
* Create VCard date String from supplied Time item.
*
* @param time Time item.
* @return String generated from supplied Time item.
*/
protected static String makeDate(Time time) {
List<Item> itemList = new ArrayList<Item>();
String dateString = null;
try {
dateString = time.format("%Y-%m-%d");
} catch (TimeFormatException e) {
return null;
}
itemList.add(new Item(dateString, false));
return createVCardList(itemList);
}
/**
* Get Time item from supplied String.
*
* @param val String containing time information.
* @return Time item generated from supplied String.
*/
protected static Time getDate(String val) {
if (val == null) {
return null;
}
List<Item> itemList = new ArrayList<Item>();
getVCardList(val, itemList);
ListIterator<Item> it = itemList.listIterator();
String dateString = nextFullItem(it);
dateString = dateString.replace("-", "");
Time time = new Time();
try {
time.parse(dateString);
} catch (TimeFormatException e) {
return null;
}
return time;
}
/**
* Generate VCard email address from simple String representation.
*
* @param emailAddress simple email address.
* @return email address in VCard style String.
*/
public static String makeEmail(String emailAddress) {
return makeSingleTextValue(emailAddress);
}
/**
* Create simple String representation of email address from supplied VCard
* email String.
*
* @param val VCard email String.
* @return email address as simple String.
*/
protected static String getEmail(String val) {
return getSingleTextValue(val);
}
/**
* Create VCard telephone number String.
*
* @param telNumber String containing telephone number
* @return VCatrd representation of telephone number.
*/
protected static String makeTel(String telNumber) {
return makeSingleTextValue(telNumber);
}
/**
* Get telephone number as String from VCard representation.
*
* @param val VCard representation of telephone number.
* @return String containing telephone number.
*/
protected static String getTel(String val) {
return getSingleTextValue(val);
}
/**
* Create VCard representation of postal address.
*
* @param address PostalAddress item.
* @return VCard representation of postal address.
*/
public static String makePostalAddress(PostalAddress address) {
List<Item> itemList = new ArrayList<Item>();
itemList.add(new Item(address.postOfficeBox, false));
itemList.add(new Item(address.addressLine1, false));
itemList.add(new Item(address.addressLine2, false));
itemList.add(new Item(address.city, false));
itemList.add(new Item(address.county, false));
itemList.add(new Item(address.postCode, false));
itemList.add(new Item(address.country, false));
return createVCardList(itemList);
}
/**
* Get PostalAddress from supplied string.
*
* @param val String containing address.
* @return Postal address generated from supplied String.
*/
public static PostalAddress getPostalAddress(String val) {
if (val == null) {
return null;
}
PostalAddress address = new PostalAddress();
List<Item> itemList = new ArrayList<Item>();
getVCardList(val, itemList);
ListIterator<Item> it = itemList.listIterator();
address.postOfficeBox = nextFullItem(it);
address.addressLine1 = nextFullItem(it);
address.addressLine2 = nextFullItem(it);
address.city = nextFullItem(it);
address.county = nextFullItem(it);
address.postCode = nextFullItem(it);
address.country = nextFullItem(it);
return address;
}
/**
* Create VCard Organisation item.
*
* @param org Organisation item.
* @return VCard organisation representation.
*/
public static String makeOrg(Organisation org) {
List<Item> itemList = new ArrayList<Item>();
itemList.add(new Item(org.name, false));
for (String s : org.unitNames) {
itemList.add(new Item(s, false));
}
return createVCardList(itemList);
}
/**s
* Create Organisation item from String containing VCArd organisation
* representation.
*
* @param val String containing VCard organisation.
* @return Organisation item generated.
*/
public static Organisation getOrg(String val) {
if (val == null) {
return null;
}
Organisation org = new Organisation();
List<Item> itemList = new ArrayList<Item>();
getVCardList(val, itemList);
ListIterator<Item> it = itemList.listIterator();
org.name = nextFullItem(it);
org.unitNames.addAll(nextFullItemArray(it));
return org;
}
/**
* Parses the Company name from a VCard Organization String.
*
* @param value the VCard Organization String to parse
* @return the company name or null if not found
*/
public static String parseCompanyFromOrganization(String value) {
if (value == null) return null;
int index = -1;
char prevChar = '.'; // set it to whatever is different from '\\'
for (int i = 0; i < value.length(); i++) {
if (value.charAt(i) == ';' && prevChar != '\\') {
index = i;
break;
}
prevChar = value.charAt(i);
}
return value.substring(0, index != -1 ? index : value.length());
}
/**
* Splits the VCard Organization value to return only the departments
*
* Note: it will return the ';' separated departments
*
* @param value the value to split
* @return the VCard departments or empty String if none
*/
public static String splitDepartmentsFromOrganization(String value) {
if (value == null) return "";
int index = -1;
char prevChar = '.'; // set it to whatever is different from '\\'
for (int i = 0; i < value.length(); i++) {
if (value.charAt(i) == ';' && prevChar != '\\') {
index = i;
break;
}
prevChar = value.charAt(i);
}
if (index != -1) {
return value.substring(index, value.length());
} else {
return "";
}
}
/**
* Tells whether or not the provided VCard value is empty.
*
* Note: a VCard value is empty if
* - null
* - "" empty String
* - ";;;" contains only ';'
*
* @return true if empty, false if not
*/
public static boolean isEmptyVCardValue(String value) {
if (value != null) {
char prevChar = '.';
for (int i = 0; i < value.length(); i++) {
if (value.charAt(i) != ';' && prevChar != '\\') {
return false;
}
prevChar = value.charAt(i);
}
}
return true;
}
/**
* Generate List array of items (as Strings) from single String using
* ListIterator.
*
* @param list List array to be populated
* @param val Single String containing items.
*/
protected static void getStringList(List<String> list, String val) {
if (val == null) {
return;
}
List<Item> itemList = new ArrayList<Item>();
getVCardList(val, itemList);
ListIterator<Item> it = itemList.listIterator();
while (it.hasNext()) {
Item item = it.next();
list.add(item.mValue);
}
}
}