content: /*
   * 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);
          }
      }
  }
  