You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ia...@apache.org on 2014/04/25 20:12:24 UTC

[1/6] CB-6521: Remove development branch

Repository: cordova-plugin-contacts
Updated Branches:
  refs/heads/dev 55ba3f258 -> fc2552522


http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/wp/Contacts.cs
----------------------------------------------------------------------
diff --git a/src/wp/Contacts.cs b/src/wp/Contacts.cs
deleted file mode 100644
index 5ae2144..0000000
--- a/src/wp/Contacts.cs
+++ /dev/null
@@ -1,693 +0,0 @@
-/*
-	Licensed under the Apache License, Version 2.0 (the "License");
-	you may not use this file except in compliance with the License.
-	You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-
-	Unless required by applicable law or agreed to in writing, software
-	distributed under the License is distributed on an "AS IS" BASIS,
-	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-	See the License for the specific language governing permissions and
-	limitations under the License.
-*/
-
-using Microsoft.Phone.Tasks;
-using Microsoft.Phone.UserData;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Globalization;
-using System.Linq;
-using System.Runtime.Serialization;
-using System.Windows;
-using DeviceContacts = Microsoft.Phone.UserData.Contacts;
-
-
-namespace WPCordovaClassLib.Cordova.Commands
-{
-    [DataContract]
-    public class SearchOptions
-    {
-        [DataMember]
-        public string filter { get; set; }
-        [DataMember]
-        public bool multiple { get; set; }
-    }
-
-    [DataContract]
-    public class ContactSearchParams
-    {
-        [DataMember]
-        public string[] fields { get; set; }
-        [DataMember]
-        public SearchOptions options { get; set; }
-    }
-
-    [DataContract]
-    public class JSONContactAddress
-    {
-        [DataMember]
-        public string formatted { get; set; }
-        [DataMember]
-        public string type { get; set; }
-        [DataMember]
-        public string streetAddress { get; set; }
-        [DataMember]
-        public string locality { get; set; }
-        [DataMember]
-        public string region { get; set; }
-        [DataMember]
-        public string postalCode { get; set; }
-        [DataMember]
-        public string country { get; set; }
-        [DataMember]
-        public bool pref { get; set; }
-    }
-
-    [DataContract]
-    public class JSONContactName
-    {
-        [DataMember]
-        public string formatted { get; set; }
-        [DataMember]
-        public string familyName { get; set; }
-        [DataMember]
-        public string givenName { get; set; }
-        [DataMember]
-        public string middleName { get; set; }
-        [DataMember]
-        public string honorificPrefix { get; set; }
-        [DataMember]
-        public string honorificSuffix { get; set; }
-    }
-
-    [DataContract]
-    public class JSONContactField
-    {
-        [DataMember]
-        public string type { get; set; }
-        [DataMember]
-        public string value { get; set; }
-        [DataMember]
-        public bool pref { get; set; }
-    }
-
-    [DataContract]
-    public class JSONContactOrganization
-    {
-        [DataMember]
-        public string type { get; set; }
-        [DataMember]
-        public string name { get; set; }
-        [DataMember]
-        public bool pref { get; set; }
-        [DataMember]
-        public string department { get; set; }
-        [DataMember]
-        public string title { get; set; }
-    }
-
-    [DataContract]
-    public class JSONContact
-    {
-        [DataMember]
-        public string id { get; set; }
-        [DataMember]
-        public string rawId { get; set; }
-        [DataMember]
-        public string displayName { get; set; }
-        [DataMember]
-        public string nickname { get; set; }
-        [DataMember]
-        public string note { get; set; }
-
-        [DataMember]
-        public JSONContactName name { get; set; }
-
-        [DataMember]
-        public JSONContactField[] emails { get; set; }
-
-        [DataMember]
-        public JSONContactField[] phoneNumbers { get; set; }
-
-        [DataMember]
-        public JSONContactField[] ims { get; set; }
-
-        [DataMember]
-        public JSONContactField[] photos { get; set; }
-
-        [DataMember]
-        public JSONContactField[] categories { get; set; }
-
-        [DataMember]
-        public JSONContactField[] urls { get; set; }
-
-        [DataMember]
-        public JSONContactOrganization[] organizations { get; set; }
-
-        [DataMember]
-        public JSONContactAddress[] addresses { get; set; }
-    }
-
-
-    public class Contacts : BaseCommand
-    {
-
-        public const int UNKNOWN_ERROR = 0;
-        public const int INVALID_ARGUMENT_ERROR = 1;
-        public const int TIMEOUT_ERROR = 2;
-        public const int PENDING_OPERATION_ERROR = 3;
-        public const int IO_ERROR = 4;
-        public const int NOT_SUPPORTED_ERROR = 5;
-        public const int PERMISSION_DENIED_ERROR = 20;
-        public const int SYNTAX_ERR = 8;
-
-        public Contacts()
-        {
-
-        }
-
-        // refer here for contact properties we can access: http://msdn.microsoft.com/en-us/library/microsoft.phone.tasks.savecontacttask_members%28v=VS.92%29.aspx
-        public void save(string jsonContact)
-        {
-
-            // jsonContact is actually an array of 1 {contact}
-            string[] args = JSON.JsonHelper.Deserialize<string[]>(jsonContact);
-
-
-            JSONContact contact = JSON.JsonHelper.Deserialize<JSONContact>(args[0]);
-
-            SaveContactTask contactTask = new SaveContactTask();
-
-            if (contact.nickname != null)
-            {
-                contactTask.Nickname = contact.nickname;
-            }
-            if (contact.urls != null && contact.urls.Length > 0)
-            {
-                contactTask.Website = contact.urls[0].value;
-            }
-            if (contact.note != null)
-            {
-                contactTask.Notes = contact.note;
-            }
-
-            #region contact.name
-            if (contact.name != null)
-            {
-                if (contact.name.givenName != null)
-                    contactTask.FirstName = contact.name.givenName;
-                if (contact.name.familyName != null)
-                    contactTask.LastName = contact.name.familyName;
-                if (contact.name.middleName != null)
-                    contactTask.MiddleName = contact.name.middleName;
-                if (contact.name.honorificSuffix != null)
-                    contactTask.Suffix = contact.name.honorificSuffix;
-                if (contact.name.honorificPrefix != null)
-                    contactTask.Title = contact.name.honorificPrefix;
-            }
-            #endregion
-
-            #region contact.org
-            if (contact.organizations != null && contact.organizations.Count() > 0)
-            {
-                contactTask.Company = contact.organizations[0].name;
-                contactTask.JobTitle = contact.organizations[0].title;
-            }
-            #endregion
-
-            #region contact.phoneNumbers
-            if (contact.phoneNumbers != null && contact.phoneNumbers.Length > 0)
-            {
-                foreach (JSONContactField field in contact.phoneNumbers)
-                {
-                    string fieldType = field.type.ToLower();
-                    if (fieldType == "work")
-                    {
-                        contactTask.WorkPhone = field.value;
-                    }
-                    else if (fieldType == "home")
-                    {
-                        contactTask.HomePhone = field.value;
-                    }
-                    else if (fieldType == "mobile")
-                    {
-                        contactTask.MobilePhone = field.value;
-                    }
-                }
-            }
-            #endregion
-
-            #region contact.emails
-
-            if (contact.emails != null && contact.emails.Length > 0)
-            {
-
-                // set up different email types if they are not explicitly defined
-                foreach (string type in new string[] { "personal", "work", "other" })
-                {
-                    foreach (JSONContactField field in contact.emails)
-                    {
-                        if (field != null && String.IsNullOrEmpty(field.type))
-                        {
-                            field.type = type;
-                            break;
-                        }
-                    }
-                }
-
-                foreach (JSONContactField field in contact.emails)
-                {
-                    if (field != null)
-                    {
-                        if (field.type != null && field.type != "other")
-                        {
-                            string fieldType = field.type.ToLower();
-                            if (fieldType == "work")
-                            {
-                                contactTask.WorkEmail = field.value;
-                            }
-                            else if (fieldType == "home" || fieldType == "personal")
-                            {
-                                contactTask.PersonalEmail = field.value;
-                            }
-                        }
-                        else
-                        {
-                            contactTask.OtherEmail = field.value;
-                        }
-                    }
-
-                }
-            }
-            #endregion
-
-            if (contact.note != null && contact.note.Length > 0)
-            {
-                contactTask.Notes = contact.note;
-            }
-
-            #region contact.addresses
-            if (contact.addresses != null && contact.addresses.Length > 0)
-            {
-                foreach (JSONContactAddress address in contact.addresses)
-                {
-                    if (address.type == null)
-                    {
-                        address.type = "home"; // set a default
-                    }
-                    string fieldType = address.type.ToLower();
-                    if (fieldType == "work")
-                    {
-                        contactTask.WorkAddressCity = address.locality;
-                        contactTask.WorkAddressCountry = address.country;
-                        contactTask.WorkAddressState = address.region;
-                        contactTask.WorkAddressStreet = address.streetAddress;
-                        contactTask.WorkAddressZipCode = address.postalCode;
-                    }
-                    else if (fieldType == "home" || fieldType == "personal")
-                    {
-                        contactTask.HomeAddressCity = address.locality;
-                        contactTask.HomeAddressCountry = address.country;
-                        contactTask.HomeAddressState = address.region;
-                        contactTask.HomeAddressStreet = address.streetAddress;
-                        contactTask.HomeAddressZipCode = address.postalCode;
-                    }
-                    else
-                    {
-                        // no other address fields available ...
-                        Debug.WriteLine("Creating contact with unsupported address type :: " + address.type);
-                    }
-                }
-            }
-            #endregion
-
-
-            contactTask.Completed += new EventHandler<SaveContactResult>(ContactSaveTaskCompleted);
-            contactTask.Show();
-        }
-
-        void ContactSaveTaskCompleted(object sender, SaveContactResult e)
-        {
-            SaveContactTask task = sender as SaveContactTask;
-
-            if (e.TaskResult == TaskResult.OK)
-            {
-
-                Deployment.Current.Dispatcher.BeginInvoke(() =>
-                {
-                    DeviceContacts deviceContacts = new DeviceContacts();
-                    deviceContacts.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(postAdd_SearchCompleted);
-
-                    string displayName = String.Format("{0}{2}{1}", task.FirstName, task.LastName, String.IsNullOrEmpty(task.FirstName) ? "" : " ");
-
-                    deviceContacts.SearchAsync(displayName, FilterKind.DisplayName, task);
-                });
-
-
-            }
-            else if (e.TaskResult == TaskResult.Cancel)
-            {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Operation cancelled."));
-            }
-        }
-
-        void postAdd_SearchCompleted(object sender, ContactsSearchEventArgs e)
-        {
-            if (e.Results.Count() > 0)
-            {
-                List<Contact> foundContacts = new List<Contact>();
-
-                int n = (from Contact contact in e.Results select contact.GetHashCode()).Max();
-                Contact newContact = (from Contact contact in e.Results
-                                      where contact.GetHashCode() == n
-                                      select contact).First();
-
-                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, FormatJSONContact(newContact, null)));
-            }
-            else
-            {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.NO_RESULT));
-            }
-        }
-
-
-
-        public void remove(string id)
-        {
-            // note id is wrapped in [] and always has exactly one string ...
-            DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "{\"code\":" + NOT_SUPPORTED_ERROR + "}"));
-        }
-
-        public void search(string searchCriteria)
-        {
-            string[] args = JSON.JsonHelper.Deserialize<string[]>(searchCriteria);
-
-            ContactSearchParams searchParams = new ContactSearchParams();
-            try
-            {
-                searchParams.fields = JSON.JsonHelper.Deserialize<string[]>(args[0]);
-                searchParams.options = JSON.JsonHelper.Deserialize<SearchOptions>(args[1]);
-            }
-            catch (Exception)
-            {
-                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, INVALID_ARGUMENT_ERROR));
-                return;
-            }
-
-            if (searchParams.options == null)
-            {
-                searchParams.options = new SearchOptions();
-                searchParams.options.filter = "";
-                searchParams.options.multiple = true;
-            }
-            else if (searchParams.options.filter == null)
-            {
-                searchParams.options.filter = "";
-            }
-
-            DeviceContacts deviceContacts = new DeviceContacts();
-            deviceContacts.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(contacts_SearchCompleted);
-
-            // default is to search all fields
-            FilterKind filterKind = FilterKind.None;
-            // if only one field is specified, we will try the 3 available DeviceContact search filters
-            if (searchParams.fields.Count() == 1)
-            {
-                if (searchParams.fields.Contains("name"))
-                {
-                    filterKind = FilterKind.DisplayName;
-                }
-                else if (searchParams.fields.Contains("emails"))
-                {
-                    filterKind = FilterKind.EmailAddress;
-                }
-                else if (searchParams.fields.Contains("phoneNumbers"))
-                {
-                    filterKind = FilterKind.PhoneNumber;
-                }
-            }
-
-            try
-            {
-
-                deviceContacts.SearchAsync(searchParams.options.filter, filterKind, searchParams);
-            }
-            catch (Exception ex)
-            {
-                Debug.WriteLine("search contacts exception :: " + ex.Message);
-            }
-        }
-
-        private void contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
-        {
-            ContactSearchParams searchParams = (ContactSearchParams)e.State;
-
-            List<Contact> foundContacts = null;
-            // used for comparing strings, ""  instantiates with InvariantCulture
-            CultureInfo culture = new CultureInfo("");
-            // make the search comparisons case insensitive.
-            CompareOptions compare_option = CompareOptions.IgnoreCase;
-
-            // if we have multiple search fields
-
-            if (!String.IsNullOrEmpty(searchParams.options.filter) && searchParams.fields.Count() > 1)
-            {
-                foundContacts = new List<Contact>();
-                if (searchParams.fields.Contains("emails"))
-                {
-                    foundContacts.AddRange(from Contact con in e.Results
-                                           from ContactEmailAddress a in con.EmailAddresses
-                                           where culture.CompareInfo.IndexOf(a.EmailAddress, searchParams.options.filter, compare_option) >= 0
-                                           select con);
-                }
-                if (searchParams.fields.Contains("displayName"))
-                {
-                    foundContacts.AddRange(from Contact con in e.Results
-                                           where culture.CompareInfo.IndexOf(con.DisplayName, searchParams.options.filter, compare_option) >= 0
-                                           select con);
-                }
-                if (searchParams.fields.Contains("name"))
-                {
-                    foundContacts.AddRange(
-                        from Contact con in e.Results
-                        where con.CompleteName != null && (
-                            (con.CompleteName.FirstName != null     && culture.CompareInfo.IndexOf(con.CompleteName.FirstName, searchParams.options.filter, compare_option) >= 0) ||
-                            (con.CompleteName.LastName != null      && culture.CompareInfo.IndexOf(con.CompleteName.LastName, searchParams.options.filter, compare_option) >= 0) ||
-                            (con.CompleteName.MiddleName != null    && culture.CompareInfo.IndexOf(con.CompleteName.MiddleName, searchParams.options.filter, compare_option) >= 0) ||
-                            (con.CompleteName.Nickname != null      && culture.CompareInfo.IndexOf(con.CompleteName.Nickname, searchParams.options.filter, compare_option) >= 0) ||
-                            (con.CompleteName.Suffix != null        && culture.CompareInfo.IndexOf(con.CompleteName.Suffix, searchParams.options.filter, compare_option) >= 0) ||
-                            (con.CompleteName.Title != null         && culture.CompareInfo.IndexOf(con.CompleteName.Title, searchParams.options.filter, compare_option) >= 0) ||
-                            (con.CompleteName.YomiFirstName != null && culture.CompareInfo.IndexOf(con.CompleteName.YomiFirstName, searchParams.options.filter, compare_option) >= 0) ||
-                            (con.CompleteName.YomiLastName != null  && culture.CompareInfo.IndexOf(con.CompleteName.YomiLastName, searchParams.options.filter, compare_option) >= 0))
-                        select con);
-                }
-                if (searchParams.fields.Contains("phoneNumbers"))
-                {
-                    foundContacts.AddRange(from Contact con in e.Results
-                                           from ContactPhoneNumber a in con.PhoneNumbers
-                                           where culture.CompareInfo.IndexOf(a.PhoneNumber, searchParams.options.filter, compare_option) >= 0
-                                           select con);
-                }
-                if (searchParams.fields.Contains("urls"))
-                {
-                    foundContacts.AddRange(from Contact con in e.Results
-                                           from string a in con.Websites
-                                           where culture.CompareInfo.IndexOf(a, searchParams.options.filter, compare_option) >= 0
-                                           select con);
-                }
-            }
-            else
-            {
-                foundContacts = new List<Contact>(e.Results);
-            }
-
-            //List<string> contactList = new List<string>();
-
-            string strResult = "";
-
-            IEnumerable<Contact> distinctContacts = foundContacts.Distinct();
-
-            foreach (Contact contact in distinctContacts)
-            {
-                strResult += FormatJSONContact(contact, null) + ",";
-                //contactList.Add(FormatJSONContact(contact, null));
-                if (!searchParams.options.multiple)
-                {
-                    break; // just return the first item
-                }
-            }
-            PluginResult result = new PluginResult(PluginResult.Status.OK);
-            result.Message = "[" + strResult.TrimEnd(',') + "]";
-            DispatchCommandResult(result);
-
-        }
-
-        private string FormatJSONPhoneNumbers(Contact con)
-        {
-            string retVal = "";
-            string contactFieldFormat = "\"type\":\"{0}\",\"value\":\"{1}\",\"pref\":\"false\"";
-            foreach (ContactPhoneNumber number in con.PhoneNumbers)
-            {
-
-                string contactField = string.Format(contactFieldFormat,
-                                                    number.Kind.ToString(),
-                                                    number.PhoneNumber);
-
-                retVal += "{" + contactField + "},";
-            }
-            return retVal.TrimEnd(',');
-        }
-
-        private string FormatJSONEmails(Contact con)
-        {
-            string retVal = "";
-            string contactFieldFormat = "\"type\":\"{0}\",\"value\":\"{1}\",\"pref\":\"false\"";
-            foreach (ContactEmailAddress address in con.EmailAddresses)
-            {
-                string contactField = string.Format(contactFieldFormat,
-                                                    address.Kind.ToString(),
-                                                    EscapeJson(address.EmailAddress));
-
-                retVal += "{" + contactField + "},";
-            }
-            return retVal.TrimEnd(',');
-        }
-
-        private string getFormattedJSONAddress(ContactAddress address, bool isPrefered)
-        {
-
-            string addressFormatString = "\"pref\":{0}," + // bool
-                          "\"type\":\"{1}\"," +
-                          "\"formatted\":\"{2}\"," +
-                          "\"streetAddress\":\"{3}\"," +
-                          "\"locality\":\"{4}\"," +
-                          "\"region\":\"{5}\"," +
-                          "\"postalCode\":\"{6}\"," +
-                          "\"country\":\"{7}\"";
-
-            string formattedAddress = EscapeJson(address.PhysicalAddress.AddressLine1 + " "
-                                    + address.PhysicalAddress.AddressLine2 + " "
-                                    + address.PhysicalAddress.City + " "
-                                    + address.PhysicalAddress.StateProvince + " "
-                                    + address.PhysicalAddress.CountryRegion + " "
-                                    + address.PhysicalAddress.PostalCode);
-
-            string jsonAddress = string.Format(addressFormatString,
-                                               isPrefered ? "\"true\"" : "\"false\"",
-                                               address.Kind.ToString(),
-                                               formattedAddress,
-                                               EscapeJson(address.PhysicalAddress.AddressLine1 + " " + address.PhysicalAddress.AddressLine2),
-                                               address.PhysicalAddress.City,
-                                               address.PhysicalAddress.StateProvince,
-                                               address.PhysicalAddress.PostalCode,
-                                               address.PhysicalAddress.CountryRegion);
-
-            //Debug.WriteLine("getFormattedJSONAddress returning :: " + jsonAddress);
-
-            return "{" + jsonAddress + "}";
-        }
-
-        private string FormatJSONAddresses(Contact con)
-        {
-            string retVal = "";
-            foreach (ContactAddress address in con.Addresses)
-            {
-                retVal += this.getFormattedJSONAddress(address, false) + ",";
-            }
-
-            //Debug.WriteLine("FormatJSONAddresses returning :: " + retVal);
-            return retVal.TrimEnd(',');
-        }
-
-        private string FormatJSONWebsites(Contact con)
-        {
-            string retVal = "";
-            foreach (string website in con.Websites)
-            {
-                retVal += "\"" + EscapeJson(website) + "\",";
-            }
-            return retVal.TrimEnd(',');
-        }
-
-        /*
-         *  formatted: The complete name of the contact. (DOMString)
-            familyName: The contacts family name. (DOMString)
-            givenName: The contacts given name. (DOMString)
-            middleName: The contacts middle name. (DOMString)
-            honorificPrefix: The contacts prefix (example Mr. or Dr.) (DOMString)
-            honorificSuffix: The contacts suffix (example Esq.). (DOMString)
-         */
-        private string FormatJSONName(Contact con)
-        {
-            string retVal = "";
-            string formatStr = "\"formatted\":\"{0}\"," +
-                                "\"familyName\":\"{1}\"," +
-                                "\"givenName\":\"{2}\"," +
-                                "\"middleName\":\"{3}\"," +
-                                "\"honorificPrefix\":\"{4}\"," +
-                                "\"honorificSuffix\":\"{5}\"";
-
-            if (con.CompleteName != null)
-            {
-                retVal = string.Format(formatStr,
-                                   EscapeJson(con.CompleteName.FirstName + " " + con.CompleteName.LastName), // TODO: does this need suffix? middlename?
-                                   EscapeJson(con.CompleteName.LastName),
-                                   EscapeJson(con.CompleteName.FirstName),
-                                   EscapeJson(con.CompleteName.MiddleName),
-                                   EscapeJson(con.CompleteName.Title),
-                                   EscapeJson(con.CompleteName.Suffix));
-            }
-            else
-            {
-                retVal = string.Format(formatStr,"","","","","","");
-            }
-
-            return "{" + retVal + "}";
-        }
-
-        private string FormatJSONContact(Contact con, string[] fields)
-        {
-
-            string contactFormatStr = "\"id\":\"{0}\"," +
-                                      "\"displayName\":\"{1}\"," +
-                                      "\"nickname\":\"{2}\"," +
-                                      "\"phoneNumbers\":[{3}]," +
-                                      "\"emails\":[{4}]," +
-                                      "\"addresses\":[{5}]," +
-                                      "\"urls\":[{6}]," +
-                                      "\"name\":{7}," +
-                                      "\"note\":\"{8}\"," +
-                                      "\"birthday\":\"{9}\"";
-
-
-            string jsonContact = String.Format(contactFormatStr,
-                                               con.GetHashCode(),
-                                               EscapeJson(con.DisplayName),
-                                               EscapeJson(con.CompleteName != null ? con.CompleteName.Nickname : ""),
-                                               FormatJSONPhoneNumbers(con),
-                                               FormatJSONEmails(con),
-                                               FormatJSONAddresses(con),
-                                               FormatJSONWebsites(con),
-                                               FormatJSONName(con),
-                                               EscapeJson(con.Notes.FirstOrDefault()),
-                                               EscapeJson(Convert.ToString(con.Birthdays.FirstOrDefault())));
-
-            return "{" + jsonContact + "}";
-
-        }
-
-        
-        private static string EscapeJson(string str)
-        {
-            if (String.IsNullOrEmpty(str))
-            {
-                return str;
-            }
-
-            return str.Replace("\n", "\\n").Replace("\r", "\\r").Replace("\t", "\\t").Replace("\"", "\\\"").Replace("&", "\\&");
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/www/Contact.js
----------------------------------------------------------------------
diff --git a/www/Contact.js b/www/Contact.js
deleted file mode 100644
index 9c46a0c..0000000
--- a/www/Contact.js
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-var argscheck = require('cordova/argscheck'),
-    exec = require('cordova/exec'),
-    ContactError = require('./ContactError'),
-    utils = require('cordova/utils');
-
-/**
-* Converts primitives into Complex Object
-* Currently only used for Date fields
-*/
-function convertIn(contact) {
-    var value = contact.birthday;
-    try {
-      contact.birthday = new Date(parseFloat(value));
-    } catch (exception){
-      console.log("Cordova Contact convertIn error: exception creating date.");
-    }
-    return contact;
-}
-
-/**
-* Converts Complex objects into primitives
-* Only conversion at present is for Dates.
-**/
-
-function convertOut(contact) {
-    var value = contact.birthday;
-    if (value !== null) {
-        // try to make it a Date object if it is not already
-        if (!utils.isDate(value)){
-            try {
-                value = new Date(value);
-            } catch(exception){
-                value = null;
-            }
-        }
-        if (utils.isDate(value)){
-            value = value.valueOf(); // convert to milliseconds
-        }
-        contact.birthday = value;
-    }
-    return contact;
-}
-
-/**
-* Contains information about a single contact.
-* @constructor
-* @param {DOMString} id unique identifier
-* @param {DOMString} displayName
-* @param {ContactName} name
-* @param {DOMString} nickname
-* @param {Array.<ContactField>} phoneNumbers array of phone numbers
-* @param {Array.<ContactField>} emails array of email addresses
-* @param {Array.<ContactAddress>} addresses array of addresses
-* @param {Array.<ContactField>} ims instant messaging user ids
-* @param {Array.<ContactOrganization>} organizations
-* @param {DOMString} birthday contact's birthday
-* @param {DOMString} note user notes about contact
-* @param {Array.<ContactField>} photos
-* @param {Array.<ContactField>} categories
-* @param {Array.<ContactField>} urls contact's web sites
-*/
-var Contact = function (id, displayName, name, nickname, phoneNumbers, emails, addresses,
-    ims, organizations, birthday, note, photos, categories, urls) {
-    this.id = id || null;
-    this.rawId = null;
-    this.displayName = displayName || null;
-    this.name = name || null; // ContactName
-    this.nickname = nickname || null;
-    this.phoneNumbers = phoneNumbers || null; // ContactField[]
-    this.emails = emails || null; // ContactField[]
-    this.addresses = addresses || null; // ContactAddress[]
-    this.ims = ims || null; // ContactField[]
-    this.organizations = organizations || null; // ContactOrganization[]
-    this.birthday = birthday || null;
-    this.note = note || null;
-    this.photos = photos || null; // ContactField[]
-    this.categories = categories || null; // ContactField[]
-    this.urls = urls || null; // ContactField[]
-};
-
-/**
-* Removes contact from device storage.
-* @param successCB success callback
-* @param errorCB error callback
-*/
-Contact.prototype.remove = function(successCB, errorCB) {
-    argscheck.checkArgs('FF', 'Contact.remove', arguments);
-    var fail = errorCB && function(code) {
-        errorCB(new ContactError(code));
-    };
-    if (this.id === null) {
-        fail(ContactError.UNKNOWN_ERROR);
-    }
-    else {
-        exec(successCB, fail, "Contacts", "remove", [this.id]);
-    }
-};
-
-/**
-* Creates a deep copy of this Contact.
-* With the contact ID set to null.
-* @return copy of this Contact
-*/
-Contact.prototype.clone = function() {
-    var clonedContact = utils.clone(this);
-    clonedContact.id = null;
-    clonedContact.rawId = null;
-
-    function nullIds(arr) {
-        if (arr) {
-            for (var i = 0; i < arr.length; ++i) {
-                arr[i].id = null;
-            }
-        }
-    }
-
-    // Loop through and clear out any id's in phones, emails, etc.
-    nullIds(clonedContact.phoneNumbers);
-    nullIds(clonedContact.emails);
-    nullIds(clonedContact.addresses);
-    nullIds(clonedContact.ims);
-    nullIds(clonedContact.organizations);
-    nullIds(clonedContact.categories);
-    nullIds(clonedContact.photos);
-    nullIds(clonedContact.urls);
-    return clonedContact;
-};
-
-/**
-* Persists contact to device storage.
-* @param successCB success callback
-* @param errorCB error callback
-*/
-Contact.prototype.save = function(successCB, errorCB) {
-    argscheck.checkArgs('FFO', 'Contact.save', arguments);
-    var fail = errorCB && function(code) {
-        errorCB(new ContactError(code));
-    };
-    var success = function(result) {
-        if (result) {
-            if (successCB) {
-                var fullContact = require('./contacts').create(result);
-                successCB(convertIn(fullContact));
-            }
-        }
-        else {
-            // no Entry object returned
-            fail(ContactError.UNKNOWN_ERROR);
-        }
-    };
-    var dupContact = convertOut(utils.clone(this));
-    exec(success, fail, "Contacts", "save", [dupContact]);
-};
-
-
-module.exports = Contact;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/www/ContactAddress.js
----------------------------------------------------------------------
diff --git a/www/ContactAddress.js b/www/ContactAddress.js
deleted file mode 100644
index 3d39086..0000000
--- a/www/ContactAddress.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
-* Contact address.
-* @constructor
-* @param {DOMString} id unique identifier, should only be set by native code
-* @param formatted // NOTE: not a W3C standard
-* @param streetAddress
-* @param locality
-* @param region
-* @param postalCode
-* @param country
-*/
-
-var ContactAddress = function(pref, type, formatted, streetAddress, locality, region, postalCode, country) {
-    this.id = null;
-    this.pref = (typeof pref != 'undefined' ? pref : false);
-    this.type = type || null;
-    this.formatted = formatted || null;
-    this.streetAddress = streetAddress || null;
-    this.locality = locality || null;
-    this.region = region || null;
-    this.postalCode = postalCode || null;
-    this.country = country || null;
-};
-
-module.exports = ContactAddress;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/www/ContactError.js
----------------------------------------------------------------------
diff --git a/www/ContactError.js b/www/ContactError.js
deleted file mode 100644
index 01b229a..0000000
--- a/www/ContactError.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
- *  ContactError.
- *  An error code assigned by an implementation when an error has occurred
- * @constructor
- */
-var ContactError = function(err) {
-    this.code = (typeof err != 'undefined' ? err : null);
-};
-
-/**
- * Error codes
- */
-ContactError.UNKNOWN_ERROR = 0;
-ContactError.INVALID_ARGUMENT_ERROR = 1;
-ContactError.TIMEOUT_ERROR = 2;
-ContactError.PENDING_OPERATION_ERROR = 3;
-ContactError.IO_ERROR = 4;
-ContactError.NOT_SUPPORTED_ERROR = 5;
-ContactError.PERMISSION_DENIED_ERROR = 20;
-
-module.exports = ContactError;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/www/ContactField.js
----------------------------------------------------------------------
diff --git a/www/ContactField.js b/www/ContactField.js
deleted file mode 100644
index e84107a..0000000
--- a/www/ContactField.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
-* Generic contact field.
-* @constructor
-* @param {DOMString} id unique identifier, should only be set by native code // NOTE: not a W3C standard
-* @param type
-* @param value
-* @param pref
-*/
-var ContactField = function(type, value, pref) {
-    this.id = null;
-    this.type = (type && type.toString()) || null;
-    this.value = (value && value.toString()) || null;
-    this.pref = (typeof pref != 'undefined' ? pref : false);
-};
-
-module.exports = ContactField;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/www/ContactFindOptions.js
----------------------------------------------------------------------
diff --git a/www/ContactFindOptions.js b/www/ContactFindOptions.js
deleted file mode 100644
index bd8bf35..0000000
--- a/www/ContactFindOptions.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
- * ContactFindOptions.
- * @constructor
- * @param filter used to match contacts against
- * @param multiple boolean used to determine if more than one contact should be returned
- */
-
-var ContactFindOptions = function(filter, multiple) {
-    this.filter = filter || '';
-    this.multiple = (typeof multiple != 'undefined' ? multiple : false);
-};
-
-module.exports = ContactFindOptions;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/www/ContactName.js
----------------------------------------------------------------------
diff --git a/www/ContactName.js b/www/ContactName.js
deleted file mode 100644
index 15cf60b..0000000
--- a/www/ContactName.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
-* Contact name.
-* @constructor
-* @param formatted // NOTE: not part of W3C standard
-* @param familyName
-* @param givenName
-* @param middle
-* @param prefix
-* @param suffix
-*/
-var ContactName = function(formatted, familyName, givenName, middle, prefix, suffix) {
-    this.formatted = formatted || null;
-    this.familyName = familyName || null;
-    this.givenName = givenName || null;
-    this.middleName = middle || null;
-    this.honorificPrefix = prefix || null;
-    this.honorificSuffix = suffix || null;
-};
-
-module.exports = ContactName;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/www/ContactOrganization.js
----------------------------------------------------------------------
diff --git a/www/ContactOrganization.js b/www/ContactOrganization.js
deleted file mode 100644
index 5dd242b..0000000
--- a/www/ContactOrganization.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
-* Contact organization.
-* @constructor
-* @param {DOMString} id unique identifier, should only be set by native code // NOTE: not a W3C standard
-* @param name
-* @param dept
-* @param title
-* @param startDate
-* @param endDate
-* @param location
-* @param desc
-*/
-
-var ContactOrganization = function(pref, type, name, dept, title) {
-    this.id = null;
-    this.pref = (typeof pref != 'undefined' ? pref : false);
-    this.type = type || null;
-    this.name = name || null;
-    this.department = dept || null;
-    this.title = title || null;
-};
-
-module.exports = ContactOrganization;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/www/contacts.js
----------------------------------------------------------------------
diff --git a/www/contacts.js b/www/contacts.js
deleted file mode 100644
index 5e6b4db..0000000
--- a/www/contacts.js
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-var argscheck = require('cordova/argscheck'),
-    exec = require('cordova/exec'),
-    ContactError = require('./ContactError'),
-    utils = require('cordova/utils'),
-    Contact = require('./Contact');
-
-/**
-* Represents a group of Contacts.
-* @constructor
-*/
-var contacts = {
-    /**
-     * Returns an array of Contacts matching the search criteria.
-     * @param fields that should be searched
-     * @param successCB success callback
-     * @param errorCB error callback
-     * @param {ContactFindOptions} options that can be applied to contact searching
-     * @return array of Contacts matching search criteria
-     */
-    find:function(fields, successCB, errorCB, options) {
-        argscheck.checkArgs('afFO', 'contacts.find', arguments);
-        if (!fields.length) {
-            errorCB && errorCB(new ContactError(ContactError.INVALID_ARGUMENT_ERROR));
-        } else {
-            var win = function(result) {
-                var cs = [];
-                for (var i = 0, l = result.length; i < l; i++) {
-                    cs.push(contacts.create(result[i]));
-                }
-                successCB(cs);
-            };
-            exec(win, errorCB, "Contacts", "search", [fields, options]);
-        }
-    },
-
-    /**
-     * This function creates a new contact, but it does not persist the contact
-     * to device storage. To persist the contact to device storage, invoke
-     * contact.save().
-     * @param properties an object whose properties will be examined to create a new Contact
-     * @returns new Contact object
-     */
-    create:function(properties) {
-        argscheck.checkArgs('O', 'contacts.create', arguments);
-        var contact = new Contact();
-        for (var i in properties) {
-            if (typeof contact[i] !== 'undefined' && properties.hasOwnProperty(i)) {
-                contact[i] = properties[i];
-            }
-        }
-        return contact;
-    }
-};
-
-module.exports = contacts;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/www/ios/Contact.js
----------------------------------------------------------------------
diff --git a/www/ios/Contact.js b/www/ios/Contact.js
deleted file mode 100644
index b40c41a..0000000
--- a/www/ios/Contact.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-var exec = require('cordova/exec'),
-    ContactError = require('./ContactError');
-
-/**
- * Provides iOS Contact.display API.
- */
-module.exports = {
-    display : function(errorCB, options) {
-        /*
-         *    Display a contact using the iOS Contact Picker UI
-         *    NOT part of W3C spec so no official documentation
-         *
-         *    @param errorCB error callback
-         *    @param options object
-         *    allowsEditing: boolean AS STRING
-         *        "true" to allow editing the contact
-         *        "false" (default) display contact
-         */
-
-        if (this.id === null) {
-            if (typeof errorCB === "function") {
-                var errorObj = new ContactError(ContactError.UNKNOWN_ERROR);
-                errorCB(errorObj);
-            }
-        }
-        else {
-            exec(null, errorCB, "Contacts","displayContact", [this.id, options]);
-        }
-    }
-};

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/www/ios/contacts.js
----------------------------------------------------------------------
diff --git a/www/ios/contacts.js b/www/ios/contacts.js
deleted file mode 100644
index 67cf421..0000000
--- a/www/ios/contacts.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-var exec = require('cordova/exec');
-
-/**
- * Provides iOS enhanced contacts API.
- */
-module.exports = {
-    newContactUI : function(successCallback) {
-        /*
-         *    Create a contact using the iOS Contact Picker UI
-         *    NOT part of W3C spec so no official documentation
-         *
-         * returns:  the id of the created contact as param to successCallback
-         */
-        exec(successCallback, null, "Contacts","newContact", []);
-    },
-    chooseContact : function(successCallback, options) {
-        /*
-         *    Select a contact using the iOS Contact Picker UI
-         *    NOT part of W3C spec so no official documentation
-         *
-         *    @param errorCB error callback
-         *    @param options object
-         *    allowsEditing: boolean AS STRING
-         *        "true" to allow editing the contact
-         *        "false" (default) display contact
-         *      fields: array of fields to return in contact object (see ContactOptions.fields)
-         *
-         *    @returns
-         *        id of contact selected
-         *        ContactObject
-         *            if no fields provided contact contains just id information
-         *            if fields provided contact object contains information for the specified fields
-         *
-         */
-         var win = function(result) {
-             var fullContact = require('./contacts').create(result);
-            successCallback(fullContact.id, fullContact);
-       };
-        exec(win, null, "Contacts","chooseContact", [options]);
-    }
-};


[2/6] CB-6521: Remove development branch

Posted by ia...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/ios/CDVContacts.m
----------------------------------------------------------------------
diff --git a/src/ios/CDVContacts.m b/src/ios/CDVContacts.m
deleted file mode 100644
index 56ca2ab..0000000
--- a/src/ios/CDVContacts.m
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
-#import "CDVContacts.h"
-#import <UIKit/UIKit.h>
-#import <Cordova/NSArray+Comparisons.h>
-#import <Cordova/NSDictionary+Extensions.h>
-//#import "CDVNotification.h"
-
-@implementation CDVContactsPicker
-
-@synthesize allowsEditing;
-@synthesize callbackId;
-@synthesize options;
-@synthesize pickedContactDictionary;
-
-@end
-@implementation CDVNewContactsController
-
-@synthesize callbackId;
-
-@end
-
-@implementation CDVContacts
-
-// no longer used since code gets AddressBook for each operation.
-// If address book changes during save or remove operation, may get error but not much we can do about it
-// If address book changes during UI creation, display or edit, we don't control any saves so no need for callback
-
-/*void addressBookChanged(ABAddressBookRef addressBook, CFDictionaryRef info, void* context)
-{
-    // note that this function is only called when another AddressBook instance modifies
-    // the address book, not the current one. For example, through an OTA MobileMe sync
-    Contacts* contacts = (Contacts*)context;
-    [contacts addressBookDirty];
-    }*/
-
-- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView
-{
-    self = (CDVContacts*)[super initWithWebView:(UIWebView*)theWebView];
-
-    /*if (self) {
-        addressBook = ABAddressBookCreate();
-        ABAddressBookRegisterExternalChangeCallback(addressBook, addressBookChanged, self);
-    }*/
-
-    return self;
-}
-
-// overridden to clean up Contact statics
-- (void)onAppTerminate
-{
-    // NSLog(@"Contacts::onAppTerminate");
-}
-
-// iPhone only method to create a new contact through the GUI
-- (void)newContact:(CDVInvokedUrlCommand*)command
-{
-    NSString* callbackId = command.callbackId;
-
-    CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
-    CDVContacts* __weak weakSelf = self;  // play it safe to avoid retain cycles
-
-    [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errCode) {
-        if (addrBook == NULL) {
-            // permission was denied or other error just return (no error callback)
-            return;
-        }
-        CDVNewContactsController* npController = [[CDVNewContactsController alloc] init];
-        npController.addressBook = addrBook;     // a CF retaining assign
-        CFRelease(addrBook);
-
-        npController.newPersonViewDelegate = self;
-        npController.callbackId = callbackId;
-
-        UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:npController];
-
-        SEL selector = NSSelectorFromString(@"presentViewController:animated:completion:");
-        if ([weakSelf.viewController respondsToSelector:selector]) {
-            [weakSelf.viewController presentViewController:navController animated:YES completion:nil];
-        } else {
-            // deprecated as of iOS >= 6.0
-            [weakSelf.viewController presentModalViewController:navController animated:YES];
-        }
-    }];
-}
-
-- (void)newPersonViewController:(ABNewPersonViewController*)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person
-{
-    ABRecordID recordId = kABRecordInvalidID;
-    CDVNewContactsController* newCP = (CDVNewContactsController*)newPersonViewController;
-    NSString* callbackId = newCP.callbackId;
-
-    if (person != NULL) {
-        // return the contact id
-        recordId = ABRecordGetRecordID(person);
-    }
-
-    if ([newPersonViewController respondsToSelector:@selector(presentingViewController)]) {
-        [[newPersonViewController presentingViewController] dismissViewControllerAnimated:YES completion:nil];
-    } else {
-        [[newPersonViewController parentViewController] dismissModalViewControllerAnimated:YES];
-    }
-
-    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:recordId];
-    [self.commandDelegate sendPluginResult:result callbackId:callbackId];
-}
-
-- (void)displayContact:(CDVInvokedUrlCommand*)command
-{
-    NSString* callbackId = command.callbackId;
-    ABRecordID recordID = [[command.arguments objectAtIndex:0] intValue];
-    NSDictionary* options = [command.arguments objectAtIndex:1 withDefault:[NSNull null]];
-    bool bEdit = [options isKindOfClass:[NSNull class]] ? false : [options existsValue:@"true" forKey:@"allowsEditing"];
-
-    CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
-    CDVContacts* __weak weakSelf = self;  // play it safe to avoid retain cycles
-
-    [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errCode) {
-        if (addrBook == NULL) {
-            // permission was denied or other error - return error
-            CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:errCode ? (int)errCode.errorCode:UNKNOWN_ERROR];
-            [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
-            return;
-        }
-        ABRecordRef rec = ABAddressBookGetPersonWithRecordID(addrBook, recordID);
-
-        if (rec) {
-            CDVDisplayContactViewController* personController = [[CDVDisplayContactViewController alloc] init];
-            personController.displayedPerson = rec;
-            personController.personViewDelegate = self;
-            personController.allowsEditing = NO;
-
-            // create this so DisplayContactViewController will have a "back" button.
-            UIViewController* parentController = [[UIViewController alloc] init];
-            UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:parentController];
-
-            [navController pushViewController:personController animated:YES];
-
-            SEL selector = NSSelectorFromString(@"presentViewController:animated:completion:");
-            if ([self.viewController respondsToSelector:selector]) {
-                [self.viewController presentViewController:navController animated:YES completion:nil];
-            } else {
-                // deprecated as of iOS >= 6.0
-                [self.viewController presentModalViewController:navController animated:YES];
-            }
-
-            if (bEdit) {
-                // create the editing controller and push it onto the stack
-                ABPersonViewController* editPersonController = [[ABPersonViewController alloc] init];
-                editPersonController.displayedPerson = rec;
-                editPersonController.personViewDelegate = self;
-                editPersonController.allowsEditing = YES;
-                [navController pushViewController:editPersonController animated:YES];
-            }
-        } else {
-            // no record, return error
-            CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:UNKNOWN_ERROR];
-            [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
-        }
-        CFRelease(addrBook);
-    }];
-}
-
-- (BOOL)personViewController:(ABPersonViewController*)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person
-                    property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue
-{
-    return YES;
-}
-
-- (void)chooseContact:(CDVInvokedUrlCommand*)command
-{
-    NSString* callbackId = command.callbackId;
-    NSDictionary* options = [command.arguments objectAtIndex:0 withDefault:[NSNull null]];
-
-    CDVContactsPicker* pickerController = [[CDVContactsPicker alloc] init];
-
-    pickerController.peoplePickerDelegate = self;
-    pickerController.callbackId = callbackId;
-    pickerController.options = options;
-    pickerController.pickedContactDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:kABRecordInvalidID], kW3ContactId, nil];
-    id allowsEditingValue = [options valueForKey:@"allowsEditing"];
-    BOOL allowsEditing = NO;
-    if ([allowsEditingValue isKindOfClass:[NSNumber class]]) {
-        allowsEditing = [(NSNumber*)allowsEditingValue boolValue];
-    }
-    pickerController.allowsEditing = allowsEditing;
-
-    SEL selector = NSSelectorFromString(@"presentViewController:animated:completion:");
-    if ([self.viewController respondsToSelector:selector]) {
-        [self.viewController presentViewController:pickerController animated:YES completion:nil];
-    } else {
-        // deprecated as of iOS >= 6.0
-        [self.viewController presentModalViewController:pickerController animated:YES];
-    }
-}
-
-- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker
-      shouldContinueAfterSelectingPerson:(ABRecordRef)person
-{
-    CDVContactsPicker* picker = (CDVContactsPicker*)peoplePicker;
-    NSNumber* pickedId = [NSNumber numberWithInt:ABRecordGetRecordID(person)];
-
-    if (picker.allowsEditing) {
-        ABPersonViewController* personController = [[ABPersonViewController alloc] init];
-        personController.displayedPerson = person;
-        personController.personViewDelegate = self;
-        personController.allowsEditing = picker.allowsEditing;
-        // store id so can get info in peoplePickerNavigationControllerDidCancel
-        picker.pickedContactDictionary = [NSDictionary dictionaryWithObjectsAndKeys:pickedId, kW3ContactId, nil];
-
-        [peoplePicker pushViewController:personController animated:YES];
-    } else {
-        // Retrieve and return pickedContact information
-        CDVContact* pickedContact = [[CDVContact alloc] initFromABRecord:(ABRecordRef)person];
-        NSArray* fields = [picker.options objectForKey:@"fields"];
-        NSDictionary* returnFields = [[CDVContact class] calcReturnFields:fields];
-        picker.pickedContactDictionary = [pickedContact toDictionary:returnFields];
-
-        CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:picker.pickedContactDictionary];
-        [self.commandDelegate sendPluginResult:result callbackId:picker.callbackId];
-
-        if ([picker respondsToSelector:@selector(presentingViewController)]) {
-            [[picker presentingViewController] dismissViewControllerAnimated:YES completion:nil];
-        } else {
-            [[picker parentViewController] dismissModalViewControllerAnimated:YES];
-        }
-    }
-    return NO;
-}
-
-- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker
-      shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
-{
-    return YES;
-}
-
-- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController*)peoplePicker
-{
-    // return contactId or invalid if none picked
-    CDVContactsPicker* picker = (CDVContactsPicker*)peoplePicker;
-
-    if (picker.allowsEditing) {
-        // get the info after possible edit
-        // if we got this far, user has already approved/ disapproved addressBook access
-        ABAddressBookRef addrBook = nil;
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000
-            if (&ABAddressBookCreateWithOptions != NULL) {
-                addrBook = ABAddressBookCreateWithOptions(NULL, NULL);
-            } else
-#endif
-        {
-            // iOS 4 & 5
-            addrBook = ABAddressBookCreate();
-        }
-        ABRecordRef person = ABAddressBookGetPersonWithRecordID(addrBook, (int)[[picker.pickedContactDictionary objectForKey:kW3ContactId] integerValue]);
-        if (person) {
-            CDVContact* pickedContact = [[CDVContact alloc] initFromABRecord:(ABRecordRef)person];
-            NSArray* fields = [picker.options objectForKey:@"fields"];
-            NSDictionary* returnFields = [[CDVContact class] calcReturnFields:fields];
-            picker.pickedContactDictionary = [pickedContact toDictionary:returnFields];
-        }
-        CFRelease(addrBook);
-    }
-    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:picker.pickedContactDictionary];
-    [self.commandDelegate sendPluginResult:result callbackId:picker.callbackId];
-
-    if ([peoplePicker respondsToSelector:@selector(presentingViewController)]) {
-        [[peoplePicker presentingViewController] dismissViewControllerAnimated:YES completion:nil];
-    } else {
-        [[peoplePicker parentViewController] dismissModalViewControllerAnimated:YES];
-    }
-}
-
-- (void)search:(CDVInvokedUrlCommand*)command
-{
-    NSString* callbackId = command.callbackId;
-    NSArray* fields = [command.arguments objectAtIndex:0];
-    NSDictionary* findOptions = [command.arguments objectAtIndex:1 withDefault:[NSNull null]];
-
-    [self.commandDelegate runInBackground:^{
-        // from Apple:  Important You must ensure that an instance of ABAddressBookRef is used by only one thread.
-        // which is why address book is created within the dispatch queue.
-        // more details here: http: //blog.byadrian.net/2012/05/05/ios-addressbook-framework-and-gcd/
-        CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
-        CDVContacts* __weak weakSelf = self;     // play it safe to avoid retain cycles
-        // it gets uglier, block within block.....
-        [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errCode) {
-            if (addrBook == NULL) {
-                // permission was denied or other error - return error
-                CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:errCode ? (int)errCode.errorCode:UNKNOWN_ERROR];
-                [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
-                return;
-            }
-
-            NSArray* foundRecords = nil;
-            // get the findOptions values
-            BOOL multiple = NO;         // default is false
-            NSString* filter = nil;
-            if (![findOptions isKindOfClass:[NSNull class]]) {
-                id value = nil;
-                filter = (NSString*)[findOptions objectForKey:@"filter"];
-                value = [findOptions objectForKey:@"multiple"];
-                if ([value isKindOfClass:[NSNumber class]]) {
-                    // multiple is a boolean that will come through as an NSNumber
-                    multiple = [(NSNumber*)value boolValue];
-                    // NSLog(@"multiple is: %d", multiple);
-                }
-            }
-
-            NSDictionary* returnFields = [[CDVContact class] calcReturnFields:fields];
-
-            NSMutableArray* matches = nil;
-            if (!filter || [filter isEqualToString:@""]) {
-                // get all records
-                foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addrBook);
-                if (foundRecords && ([foundRecords count] > 0)) {
-                    // create Contacts and put into matches array
-                    // doesn't make sense to ask for all records when multiple == NO but better check
-                    int xferCount = multiple == YES ? (int)[foundRecords count] : 1;
-                    matches = [NSMutableArray arrayWithCapacity:xferCount];
-
-                    for (int k = 0; k < xferCount; k++) {
-                        CDVContact* xferContact = [[CDVContact alloc] initFromABRecord:(__bridge ABRecordRef)[foundRecords objectAtIndex:k]];
-                        [matches addObject:xferContact];
-                        xferContact = nil;
-                    }
-                }
-            } else {
-                foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addrBook);
-                matches = [NSMutableArray arrayWithCapacity:1];
-                BOOL bFound = NO;
-                int testCount = (int)[foundRecords count];
-
-                for (int j = 0; j < testCount; j++) {
-                    CDVContact* testContact = [[CDVContact alloc] initFromABRecord:(__bridge ABRecordRef)[foundRecords objectAtIndex:j]];
-                    if (testContact) {
-                        bFound = [testContact foundValue:filter inFields:returnFields];
-                        if (bFound) {
-                            [matches addObject:testContact];
-                        }
-                        testContact = nil;
-                    }
-                }
-            }
-            NSMutableArray* returnContacts = [NSMutableArray arrayWithCapacity:1];
-
-            if ((matches != nil) && ([matches count] > 0)) {
-                // convert to JS Contacts format and return in callback
-                // - returnFields  determines what properties to return
-                @autoreleasepool {
-                    int count = multiple == YES ? (int)[matches count] : 1;
-
-                    for (int i = 0; i < count; i++) {
-                        CDVContact* newContact = [matches objectAtIndex:i];
-                        NSDictionary* aContact = [newContact toDictionary:returnFields];
-                        [returnContacts addObject:aContact];
-                    }
-                }
-            }
-            // return found contacts (array is empty if no contacts found)
-            CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:returnContacts];
-            [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
-            // NSLog(@"findCallback string: %@", jsString);
-
-            if (addrBook) {
-                CFRelease(addrBook);
-            }
-        }];
-    }];     // end of workQueue block
-
-    return;
-}
-
-- (void)save:(CDVInvokedUrlCommand*)command
-{
-    NSString* callbackId = command.callbackId;
-    NSDictionary* contactDict = [command.arguments objectAtIndex:0];
-
-    [self.commandDelegate runInBackground:^{
-        CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
-        CDVContacts* __weak weakSelf = self;     // play it safe to avoid retain cycles
-
-        [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errorCode) {
-            CDVPluginResult* result = nil;
-            if (addrBook == NULL) {
-                // permission was denied or other error - return error
-                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errorCode ? (int)errorCode.errorCode:UNKNOWN_ERROR];
-                [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
-                return;
-            }
-
-            bool bIsError = FALSE, bSuccess = FALSE;
-            BOOL bUpdate = NO;
-            CDVContactError errCode = UNKNOWN_ERROR;
-            CFErrorRef error;
-            NSNumber* cId = [contactDict valueForKey:kW3ContactId];
-            CDVContact* aContact = nil;
-            ABRecordRef rec = nil;
-            if (cId && ![cId isKindOfClass:[NSNull class]]) {
-                rec = ABAddressBookGetPersonWithRecordID(addrBook, [cId intValue]);
-                if (rec) {
-                    aContact = [[CDVContact alloc] initFromABRecord:rec];
-                    bUpdate = YES;
-                }
-            }
-            if (!aContact) {
-                aContact = [[CDVContact alloc] init];
-            }
-
-            bSuccess = [aContact setFromContactDict:contactDict asUpdate:bUpdate];
-            if (bSuccess) {
-                if (!bUpdate) {
-                    bSuccess = ABAddressBookAddRecord(addrBook, [aContact record], &error);
-                }
-                if (bSuccess) {
-                    bSuccess = ABAddressBookSave(addrBook, &error);
-                }
-                if (!bSuccess) {         // need to provide error codes
-                    bIsError = TRUE;
-                    errCode = IO_ERROR;
-                } else {
-                    // give original dictionary back?  If generate dictionary from saved contact, have no returnFields specified
-                    // so would give back all fields (which W3C spec. indicates is not desired)
-                    // for now (while testing) give back saved, full contact
-                    NSDictionary* newContact = [aContact toDictionary:[CDVContact defaultFields]];
-                    // NSString* contactStr = [newContact JSONRepresentation];
-                    result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:newContact];
-                }
-            } else {
-                bIsError = TRUE;
-                errCode = IO_ERROR;
-            }
-            CFRelease(addrBook);
-
-            if (bIsError) {
-                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:(int)errCode];
-            }
-
-            if (result) {
-                [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
-            }
-        }];
-    }];     // end of  queue
-}
-
-- (void)remove:(CDVInvokedUrlCommand*)command
-{
-    NSString* callbackId = command.callbackId;
-    NSNumber* cId = [command.arguments objectAtIndex:0];
-
-    CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
-    CDVContacts* __weak weakSelf = self;  // play it safe to avoid retain cycles
-
-    [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errorCode) {
-        CDVPluginResult* result = nil;
-        if (addrBook == NULL) {
-            // permission was denied or other error - return error
-            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errorCode ? (int)errorCode.errorCode:UNKNOWN_ERROR];
-            [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
-            return;
-        }
-
-        bool bIsError = FALSE, bSuccess = FALSE;
-        CDVContactError errCode = UNKNOWN_ERROR;
-        CFErrorRef error;
-        ABRecordRef rec = nil;
-        if (cId && ![cId isKindOfClass:[NSNull class]] && ([cId intValue] != kABRecordInvalidID)) {
-            rec = ABAddressBookGetPersonWithRecordID(addrBook, [cId intValue]);
-            if (rec) {
-                bSuccess = ABAddressBookRemoveRecord(addrBook, rec, &error);
-                if (!bSuccess) {
-                    bIsError = TRUE;
-                    errCode = IO_ERROR;
-                } else {
-                    bSuccess = ABAddressBookSave(addrBook, &error);
-                    if (!bSuccess) {
-                        bIsError = TRUE;
-                        errCode = IO_ERROR;
-                    } else {
-                        // set id to null
-                        // [contactDict setObject:[NSNull null] forKey:kW3ContactId];
-                        // result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary: contactDict];
-                        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
-                        // NSString* contactStr = [contactDict JSONRepresentation];
-                    }
-                }
-            } else {
-                // no record found return error
-                bIsError = TRUE;
-                errCode = UNKNOWN_ERROR;
-            }
-        } else {
-            // invalid contact id provided
-            bIsError = TRUE;
-            errCode = INVALID_ARGUMENT_ERROR;
-        }
-
-        if (addrBook) {
-            CFRelease(addrBook);
-        }
-        if (bIsError) {
-            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:(int)errCode];
-        }
-        if (result) {
-            [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
-        }
-    }];
-    return;
-}
-
-@end
-
-/* ABPersonViewController does not have any UI to dismiss.  Adding navigationItems to it does not work properly
- * The navigationItems are lost when the app goes into the background.  The solution was to create an empty
- * NavController in front of the ABPersonViewController. This will cause the ABPersonViewController to have a back button. By subclassing the ABPersonViewController, we can override viewDidDisappear and take down the entire NavigationController.
- */
-@implementation CDVDisplayContactViewController
-@synthesize contactsPlugin;
-
-- (void)viewWillDisappear:(BOOL)animated
-{
-    [super viewWillDisappear:animated];
-
-    if ([self respondsToSelector:@selector(presentingViewController)]) {
-        [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
-    } else {
-        [[self parentViewController] dismissModalViewControllerAnimated:YES];
-    }
-}
-
-@end
-@implementation CDVAddressBookAccessError
-
-@synthesize errorCode;
-
-- (CDVAddressBookAccessError*)initWithCode:(CDVContactError)code
-{
-    self = [super init];
-    if (self) {
-        self.errorCode = code;
-    }
-    return self;
-}
-
-@end
-
-@implementation CDVAddressBookHelper
-
-/**
- * NOTE: workerBlock is responsible for releasing the addressBook that is passed to it
- */
-- (void)createAddressBook:(CDVAddressBookWorkerBlock)workerBlock
-{
-    // TODO: this probably should be reworked - seems like the workerBlock can just create and release its own AddressBook,
-    // and also this important warning from (http://developer.apple.com/library/ios/#documentation/ContactData/Conceptual/AddressBookProgrammingGuideforiPhone/Chapters/BasicObjects.html):
-    // "Important: Instances of ABAddressBookRef cannot be used by multiple threads. Each thread must make its own instance."
-    ABAddressBookRef addressBook;
-
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000
-        if (&ABAddressBookCreateWithOptions != NULL) {
-            CFErrorRef error = nil;
-            // CFIndex status = ABAddressBookGetAuthorizationStatus();
-            addressBook = ABAddressBookCreateWithOptions(NULL, &error);
-            // NSLog(@"addressBook access: %lu", status);
-            ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
-                    // callback can occur in background, address book must be accessed on thread it was created on
-                    dispatch_sync(dispatch_get_main_queue(), ^{
-                        if (error) {
-                            workerBlock(NULL, [[CDVAddressBookAccessError alloc] initWithCode:UNKNOWN_ERROR]);
-                        } else if (!granted) {
-                            workerBlock(NULL, [[CDVAddressBookAccessError alloc] initWithCode:PERMISSION_DENIED_ERROR]);
-                        } else {
-                            // access granted
-                            workerBlock(addressBook, [[CDVAddressBookAccessError alloc] initWithCode:UNKNOWN_ERROR]);
-                        }
-                    });
-                });
-        } else
-#endif
-    {
-        // iOS 4 or 5 no checks needed
-        addressBook = ABAddressBookCreate();
-        workerBlock(addressBook, NULL);
-    }
-}
-
-@end

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/ubuntu/contacts.cpp
----------------------------------------------------------------------
diff --git a/src/ubuntu/contacts.cpp b/src/ubuntu/contacts.cpp
deleted file mode 100644
index 373a276..0000000
--- a/src/ubuntu/contacts.cpp
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-#include "contacts.h"
-
-#if defined QTCONTACTS_USE_NAMESPACE
-QTCONTACTS_USE_NAMESPACE
-#endif
-
-Contacts::Contacts(Cordova *cordova): CPlugin(cordova) {
-    m_fieldNamePairs.clear();
-
-    m_fieldNamePairs["displayName"] = QContactDetail::TypeDisplayLabel;
-    m_fieldNamePairs["name"] = QContactDetail::TypeName;
-    m_fieldNamePairs["nickname"] = QContactDetail::TypeNickname;
-    m_fieldNamePairs["phoneNumbers"] = QContactDetail::TypePhoneNumber;
-    m_fieldNamePairs["emails"] = QContactDetail::TypeEmailAddress;
-    m_fieldNamePairs["addresses"] = QContactDetail::TypeAddress;
-    m_fieldNamePairs["ims"] = QContactDetail::TypeOnlineAccount;
-    m_fieldNamePairs["organizations"] = QContactDetail::TypeOrganization;
-    m_fieldNamePairs["birthday"] = QContactDetail::TypeBirthday;
-    m_fieldNamePairs["note"] = QContactDetail::TypeNote;
-    m_fieldNamePairs["photos"] = QContactDetail::TypeAvatar;
-    m_fieldNamePairs["urls"] = QContactDetail::TypeUrl;
-
-    m_notSupportedFields.clear();
-    m_notSupportedFields << "categories";
-    m_manager.clear();
-    m_manager = QSharedPointer<QContactManager>(new QContactManager());
-}
-
-void Contacts::save(int scId, int ecId, const QVariantMap &params) {
-    QContact result;
-    QList<QContactDetail *> detailsToDelete;
-
-    if (params.find("id") != params.end()) {
-        QString id = params.find("id")->toString();
-        if (!id.isEmpty()) {
-            result = m_manager->contact(QContactId::fromString(id));
-            result.clearDetails();
-        }
-    }
-
-    foreach (QString field, params.keys()) {
-        QContactDetail::DetailType qtDefinition = cordovaFieldNameToQtDefinition(field);
-        if (qtDefinition == QContactDetail::TypeUndefined)
-            continue;
-
-        if (field == "nickname") {
-            QContactNickname *detail = new QContactNickname;
-            detail->setNickname(params[field].toString());
-            detailsToDelete << detail;
-            result.saveDetail(detail);
-        } else if (field == "note") {
-            QContactNote *detail = new QContactNote;
-            detail->setNote(params[field].toString());
-            detailsToDelete << detail;
-            result.saveDetail(detail);
-        } else if (field == "phoneNumbers") {
-            if (params[field].type() != QVariant::List)
-                continue;
-            QVariantList phonesList = params[field].toList();
-            foreach (const QVariant &phoneDesc, phonesList) {
-                if (phoneDesc.type() != QVariant::Map)
-                    continue;
-                QContactPhoneNumber *detail = new QContactPhoneNumber;
-                detail->setNumber(phoneDesc.toMap()["value"].toString());
-                if (!phoneDesc.toMap()["type"].toString().isEmpty() &&
-                        phoneDesc.toMap()["type"].toString() != "phone")
-                    detail->setSubTypes(QList<int>() <<
-                                        subTypePhoneFromString(phoneDesc.toMap()["type"].toString()));
-                detailsToDelete << detail;
-                result.saveDetail(detail);
-            }
-        } else if (field == "emails") {
-            if (params[field].type() != QVariant::List)
-                continue;
-            QVariantList emailsList = params[field].toList();
-            foreach (const QVariant &emailDesc, emailsList) {
-                if (emailDesc.type() != QVariant::Map)
-                    continue;
-                if (emailDesc.toMap()["value"].toString().isEmpty())
-                    continue;
-                QContactEmailAddress *detail = new QContactEmailAddress;
-                detail->setEmailAddress(emailDesc.toMap()["value"].toString());
-                detailsToDelete << detail;
-                result.saveDetail(detail);
-            }
-        } else if (field == "ims") {
-            if (params[field].type() != QVariant::List)
-                continue;
-            QVariantList imsList = params[field].toList();
-            foreach (const QVariant &imDesc, imsList) {
-                if (imDesc.type() != QVariant::Map)
-                    continue;
-                QContactOnlineAccount *detail = new QContactOnlineAccount;
-                detail->setAccountUri(imDesc.toMap()["value"].toString());
-                if (!imDesc.toMap()["type"].toString().isEmpty())
-                    detail->setSubTypes(QList<int>() <<
-                                        subTypeOnlineAccountFromString(imDesc.toMap()["type"].toString()));
-                detailsToDelete << detail;
-                result.saveDetail(detail);
-            }
-        } else if (field == "photos") {
-            if (params[field].type() != QVariant::List)
-                continue;
-            QVariantList photosList = params[field].toList();
-            foreach (const QVariant &photoDesc, photosList) {
-                if (photoDesc.type() != QVariant::Map)
-                    continue;
-                //TODO: we need to decide should we support base64 images or not
-                if (photoDesc.toMap()["type"].toString() != "url")
-                    continue;
-                QContactAvatar *detail = new QContactAvatar;
-                detail->setImageUrl(QUrl(photoDesc.toMap()["value"].toString()));
-                detailsToDelete << detail;
-                result.saveDetail(detail);
-            }
-        } else if (field == "urls") {
-            if (params[field].type() != QVariant::List)
-                continue;
-            QVariantList urlsList = params[field].toList();
-            foreach (const QVariant &urlDesc, urlsList) {
-                if (urlDesc.type() != QVariant::Map)
-                    continue;
-                QContactUrl *detail = new QContactUrl;
-                detail->setUrl(urlDesc.toMap()["value"].toString());
-                if (!urlDesc.toMap()["type"].toString().isEmpty())
-                    detail->setSubType((QContactUrl::SubType) subTypeUrlFromString(urlDesc.toMap()["type"].toString()));
-                detailsToDelete << detail;
-                result.saveDetail(detail);
-            }
-        } else if (field == "birthday") {
-            QDateTime birthday;
-            birthday.setTime_t(params[field].toLongLong() / 1000);
-
-            QContactBirthday *detail = new QContactBirthday;
-            detail->setDateTime(birthday);
-            detailsToDelete << detail;
-            result.saveDetail(detail);
-        } else if (field == "organizations") {
-
-            if (params[field].type() != QVariant::List)
-                continue;
-            QVariantList organizationsList = params[field].toList();
-            foreach (const QVariant &organizationDesc, organizationsList) {
-                if (organizationDesc.type() != QVariant::Map)
-                    continue;
-                QContactOrganization *detail = new QContactOrganization;
-                detail->setName(organizationDesc.toMap()["name"].toString());
-                detail->setDepartment(QStringList() << organizationDesc.toMap()["department"].toString());
-                detail->setRole(organizationDesc.toMap()["title"].toString());
-                detailsToDelete << detail;
-                result.saveDetail(detail);
-            }
-
-        } else if (field == "name") {
-            QContactName *detail = new QContactName;
-            QVariantMap nameMap = params[field].toMap();
-            detail->setLastName(nameMap["familyName"].toString());
-            detail->setFirstName(nameMap["givenName"].toString());
-            detail->setMiddleName(nameMap["middleName"].toString());
-            detail->setPrefix(nameMap["honorificPrefix"].toString());
-            detail->setSuffix(nameMap["honorificSuffix"].toString());
-            detailsToDelete << detail;
-            result.saveDetail(detail);
-        }
-
-    }
-    if (!m_manager->saveContact(&result)) {
-        switch (m_manager->error()) {
-        case QContactManager::DoesNotExistError:
-        case QContactManager::AlreadyExistsError:
-        case QContactManager::InvalidDetailError:
-        case QContactManager::InvalidRelationshipError:
-        case QContactManager::BadArgumentError:
-        case QContactManager::InvalidContactTypeError:
-            callback(ecId, "ContactError.INVALID_ARGUMENT_ERROR");
-            break;
-        case QContactManager::DetailAccessError:
-        case QContactManager::PermissionsError:
-            callback(ecId, "ContactError.PERMISSION_DENIED_ERROR");
-            break;
-        case QContactManager::NotSupportedError:
-            callback(ecId, "ContactError.NOT_SUPPORTED_ERROR");
-            break;
-        case QContactManager::TimeoutError:
-            callback(ecId, "ContactError.TIMEOUT_ERROR");
-            break;
-        case QContactManager::UnspecifiedError:
-        case QContactManager::LockedError:
-        case QContactManager::OutOfMemoryError:
-        case QContactManager::VersionMismatchError:
-        case QContactManager::LimitReachedError:
-        case QContactManager::NoError:
-        default:
-            callback(ecId, "ContactError.UNKNOWN_ERROR");
-            break;
-        }
-    } else {
-        callback(scId, jsonedContact(result));
-    }
-    qDeleteAll(detailsToDelete);
-}
-
-void Contacts::remove(int scId, int ecId, const QString &localId) {
-    QContactId id = QContactId::fromString(localId);
-
-    if (!m_manager->removeContact(id)) {
-        switch (m_manager->error()) {
-        case QContactManager::AlreadyExistsError:
-        case QContactManager::InvalidDetailError:
-        case QContactManager::InvalidRelationshipError:
-        case QContactManager::BadArgumentError:
-        case QContactManager::InvalidContactTypeError:
-            callback(ecId, "ContactError.INVALID_ARGUMENT_ERROR");
-            break;
-        case QContactManager::DetailAccessError:
-        case QContactManager::PermissionsError:
-            callback(ecId, "ContactError.PERMISSION_DENIED_ERROR");
-            break;
-        case QContactManager::NotSupportedError:
-            callback(ecId, "ContactError.NOT_SUPPORTED_ERROR");
-            break;
-        case QContactManager::TimeoutError:
-            callback(ecId, "ContactError.TIMEOUT_ERROR");
-            break;
-        case QContactManager::UnspecifiedError:
-        case QContactManager::LockedError:
-        case QContactManager::OutOfMemoryError:
-        case QContactManager::VersionMismatchError:
-        case QContactManager::LimitReachedError:
-        case QContactManager::NoError:
-        case QContactManager::DoesNotExistError:
-        default:
-            callback(ecId, "ContactError.UNKNOWN_ERROR");
-            break;
-        }
-
-    } else {
-        cb(scId);
-    }
-}
-
-void Contacts::search(int scId, int ecId, const QStringList &fields, const QVariantMap &params) {
-    QString filter;
-    bool multiple = true;
-
-    if (params.find("filter") != params.end()) {
-        filter = params["filter"].toString();
-    }
-    if (params.find("multiple") != params.end()) {
-        multiple = params["multiple"].toBool();
-    }
-
-    findContacts(scId, ecId, fields, filter, multiple);
-}
-
-void Contacts::findContacts(int scId, int ecId, const QStringList &fields, const QString &filter, bool multiple) {
-    if (fields.length() <= 0){
-        callback(ecId, "new ContactError(ContactError.INVALID_ARGUMENT_ERROR)");
-    }
-
-    QContactUnionFilter unionFilter;
-
-    QMap<QContactDetail::DetailType, QList<int> > fieldNames;
-    fieldNames[QContactDetail::TypeDisplayLabel] << QContactDisplayLabel::FieldLabel;
-    fieldNames[QContactDetail::TypeName] << QContactName::FieldFirstName << QContactName::FieldLastName << QContactName::FieldMiddleName << QContactName::FieldPrefix << QContactName::FieldSuffix;
-    fieldNames[QContactDetail::TypeNickname] << QContactNickname::FieldNickname;
-    fieldNames[QContactDetail::TypePhoneNumber] << QContactPhoneNumber::FieldNumber;
-    fieldNames[QContactDetail::TypeEmailAddress] << QContactEmailAddress::FieldEmailAddress;
-    fieldNames[QContactDetail::TypeAddress] << QContactAddress::FieldCountry << QContactAddress::FieldLocality << QContactAddress::FieldPostcode << QContactAddress::FieldPostOfficeBox << QContactAddress::FieldRegion << QContactAddress::FieldStreet;
-    fieldNames[QContactDetail::TypeOnlineAccount] << QContactOnlineAccount::FieldAccountUri;
-    fieldNames[QContactDetail::TypeOrganization] << QContactOrganization::FieldAssistantName << QContactOrganization::FieldDepartment << QContactOrganization::FieldLocation << QContactOrganization::FieldName << QContactOrganization::FieldRole << QContactOrganization::FieldTitle;
-    fieldNames[QContactDetail::TypeBirthday] << QContactBirthday::FieldBirthday;
-    fieldNames[QContactDetail::TypeNote] << QContactNote::FieldNote;
-    fieldNames[QContactDetail::TypeUrl] << QContactUrl::FieldUrl;
-
-    foreach (const QContactDetail::DetailType &defName, fieldNames.keys()) {
-        foreach(int fieldName, fieldNames[defName]) {
-            QContactDetailFilter subFilter;
-            subFilter.setDetailType(defName, fieldName);
-            subFilter.setValue(filter);
-            subFilter.setMatchFlags(QContactFilter::MatchContains);
-            unionFilter.append(subFilter);
-        }
-    }
-
-    QList<QContact> contacts = m_manager->contacts(unionFilter);
-    if (contacts.empty()) {
-        callback(scId, "[]");
-    } else {
-        QStringList stringifiedContacts;
-        foreach (const QContact &contact, contacts) {
-            stringifiedContacts << jsonedContact(contact, fields);
-
-            if (!multiple)
-                break;
-        }
-        callback(scId, QString("[%1]").arg(stringifiedContacts.join(", ")));
-    }
-}
-
-QContactDetail::DetailType Contacts::cordovaFieldNameToQtDefinition(const QString &cordovaFieldName) const {
-    if (m_fieldNamePairs.contains(cordovaFieldName))
-        return m_fieldNamePairs[cordovaFieldName];
-
-    return QContactDetail::TypeUndefined;
-}
-
-int Contacts::subTypePhoneFromString(const QString &cordovaSubType) const
-{
-    QString preparedSubType = cordovaSubType.toLower();
-    if (preparedSubType == "mobile")
-        return QContactPhoneNumber::SubTypeMobile;
-    else if (preparedSubType == "fax")
-        return QContactPhoneNumber::SubTypeFax;
-    else if (preparedSubType == "pager")
-        return QContactPhoneNumber::SubTypePager;
-    else if (preparedSubType == "voice")
-        return QContactPhoneNumber::SubTypeVoice;
-    else if (preparedSubType == "modem")
-        return QContactPhoneNumber::SubTypeModem;
-    else if (preparedSubType == "video")
-        return QContactPhoneNumber::SubTypeVideo;
-    else if (preparedSubType == "car")
-        return QContactPhoneNumber::SubTypeCar;
-    else if (preparedSubType == "assistant")
-        return QContactPhoneNumber::SubTypeAssistant;
-    return QContactPhoneNumber::SubTypeLandline;
-}
-
-int Contacts::subTypeOnlineAccountFromString(const QString &cordovaSubType) const {
-    QString preparedSubType = cordovaSubType.toLower();
-    if (preparedSubType == "aim")
-        return QContactOnlineAccount::ProtocolAim;
-    else if (preparedSubType == "icq")
-        return QContactOnlineAccount::ProtocolIcq;
-    else if (preparedSubType == "irc")
-        return QContactOnlineAccount::ProtocolIrc;
-    else if (preparedSubType == "jabber")
-        return QContactOnlineAccount::ProtocolJabber;
-    else if (preparedSubType == "msn")
-        return QContactOnlineAccount::ProtocolMsn;
-    else if (preparedSubType == "qq")
-        return QContactOnlineAccount::ProtocolQq;
-    else if (preparedSubType == "skype")
-        return QContactOnlineAccount::ProtocolSkype;
-    else if (preparedSubType == "yahoo")
-        return QContactOnlineAccount::ProtocolYahoo;
-    return QContactOnlineAccount::ProtocolUnknown;
-}
-
-int Contacts::subTypeUrlFromString(const QString &cordovaSubType) const {
-    QString preparedSubType = cordovaSubType.toLower();
-    if (preparedSubType == "blog")
-        return QContactUrl::SubTypeBlog;
-    else if (preparedSubType == "favourite")
-        return QContactUrl::SubTypeFavourite;
-    return QContactUrl::SubTypeHomePage;
-}
-
-QString Contacts::subTypePhoneToString(int qtSubType) const {
-    if (qtSubType == QContactPhoneNumber::SubTypeMobile)
-        return "mobile";
-    else if (qtSubType == QContactPhoneNumber::SubTypeFax)
-        return "fax";
-    else if (qtSubType == QContactPhoneNumber::SubTypePager)
-        return "pager";
-    else if (qtSubType == QContactPhoneNumber::SubTypeVoice)
-        return "voice";
-    else if (qtSubType == QContactPhoneNumber::SubTypeModem)
-        return "modem";
-    else if (qtSubType == QContactPhoneNumber::SubTypeVideo)
-        return "video";
-    else if (qtSubType == QContactPhoneNumber::SubTypeCar)
-        return "car";
-    else if (qtSubType == QContactPhoneNumber::SubTypeAssistant)
-        return "assistant";
-    return "home";
-}
-
-QString Contacts::subTypeOnlineAccountToString(int qtSubType) const {
-    if (qtSubType == QContactOnlineAccount::ProtocolAim)
-        return "aim";
-    else if (qtSubType == QContactOnlineAccount::ProtocolIcq)
-        return "icq";
-    else if (qtSubType == QContactOnlineAccount::ProtocolIrc)
-        return "irc";
-    else if (qtSubType == QContactOnlineAccount::ProtocolJabber)
-        return "jabber";
-    else if (qtSubType == QContactOnlineAccount::ProtocolMsn)
-        return "msn";
-    else if (qtSubType == QContactOnlineAccount::ProtocolQq)
-        return "qq";
-    else if (qtSubType == QContactOnlineAccount::ProtocolSkype)
-        return "skype";
-    else if (qtSubType == QContactOnlineAccount::ProtocolYahoo)
-        return "yahoo";
-    return "unknown";
-}
-
-QString Contacts::subTypeUrlToString(int qtSubType) const {
-    if (qtSubType == QContactUrl::SubTypeBlog)
-        return "blog";
-    else if (qtSubType == QContactUrl::SubTypeFavourite)
-        return "favourite";
-    return "homepage";
-}
-
-QString Contacts::jsonedContact(const QContact &contact, const QStringList &fields) const {
-    QStringList resultingFields = fields;
-    if (resultingFields.empty())
-        resultingFields.append(m_fieldNamePairs.keys());
-    if (!resultingFields.contains("id"))
-        resultingFields << "id";
-    QStringList fieldValuesList;
-    foreach (const QString &field, resultingFields) {
-        QContactDetail::DetailType qtDefinitionName = cordovaFieldNameToQtDefinition(field);
-        if (field == "id") {
-            fieldValuesList << QString("%1: \"%2\"")
-                               .arg(field)
-                               .arg(contact.id().toString());
-        } else if (field == "displayName") {
-            QContactDisplayLabel detail = contact.detail(qtDefinitionName);
-            fieldValuesList << QString("%1: \"%2\"")
-                               .arg(field)
-                               .arg(detail.label());
-        } else if (field == "nickname") {
-            QContactNickname detail = contact.detail(qtDefinitionName);
-            fieldValuesList << QString("%1: \"%2\"")
-                               .arg(field)
-                               .arg(detail.nickname());
-        } else if (field == "note") {
-            QContactNote detail = contact.detail(qtDefinitionName);
-            fieldValuesList << QString("%1: \"%2\"")
-                               .arg(field)
-                               .arg(detail.note());
-        } else if (field == "phoneNumbers") {
-            QStringList fieldValues;
-            QList<QContactDetail> details = contact.details(qtDefinitionName);
-            foreach (const QContactDetail &detail, details) {
-                QContactPhoneNumber castedDetail = detail;
-                QStringList subTypes;
-                foreach (int subType, castedDetail.subTypes())
-                    subTypes << subTypePhoneToString(subType);
-
-                if (subTypes.isEmpty())
-                    subTypes << "phone";
-                foreach(const QString &subType, subTypes) {
-                    fieldValues << QString("{type: \"%1\", value: \"%2\", pref: %3}")
-                                   .arg(subType)
-                                   .arg(castedDetail.number())
-                                   .arg("false");
-                }
-            }
-            fieldValuesList << QString("%1: [%2]")
-                               .arg(field)
-                               .arg(fieldValues.join(", "));
-        } else if (field == "emails") {
-            QStringList fieldValues;
-            QList<QContactDetail> details = contact.details(qtDefinitionName);
-            foreach (const QContactDetail &detail, details) {
-                QContactEmailAddress castedDetail = detail;
-                fieldValues << QString("{type: \"%1\", value: \"%2\", pref: %3}")
-                               .arg("email")
-                               .arg(castedDetail.emailAddress())
-                               .arg("false");
-            }
-            fieldValuesList << QString("%1: [%2]")
-                               .arg(field)
-                               .arg(fieldValues.join(", "));
-        } else if (field == "ims") {
-            QStringList fieldValues;
-            QList<QContactDetail> details = contact.details(qtDefinitionName);
-            foreach (const QContactDetail &detail, details) {
-                QContactOnlineAccount castedDetail = detail;
-                QStringList subTypes;
-                foreach (int subType, castedDetail.subTypes())
-                    subTypes << subTypeOnlineAccountToString(subType);
-
-                if (subTypes.isEmpty())
-                    subTypes << "IM";
-                foreach(const QString &subType, subTypes) {
-                    fieldValues << QString("{type: \"%1\", value: \"%2\", pref: %3}")
-                                   .arg(subType)
-                                   .arg(castedDetail.accountUri())
-                                   .arg("false");
-                }
-            }
-            fieldValuesList << QString("%1: [%2]")
-                               .arg(field)
-                               .arg(fieldValues.join(", "));
-        } else if (field == "photos") {
-            QStringList fieldValues;
-            QList<QContactDetail> details = contact.details(qtDefinitionName);
-            foreach (const QContactDetail &detail, details) {
-                QContactAvatar castedDetail = detail;
-                fieldValues << QString("{type: \"%1\", value: \"%2\", pref: %3}")
-                               .arg("url")
-                               .arg(castedDetail.imageUrl().toString())
-                               .arg("false");
-            }
-            fieldValuesList << QString("%1: [%2]")
-                               .arg(field)
-                               .arg(fieldValues.join(", "));
-        } else if (field == "urls") {
-            QStringList fieldValues;
-            QList<QContactDetail> details = contact.details(qtDefinitionName);
-
-            foreach (const QContactDetail &detail, details) {
-                QContactUrl castedDetail = detail;
-                QString subType = subTypeUrlToString(castedDetail.subType());
-
-                fieldValues << QString("{type: \"%1\", value: \"%2\", pref: %3}")
-                               .arg(subType)
-                               .arg(castedDetail.url())
-                               .arg("false");
-            }
-            fieldValuesList << QString("%1: [%2]")
-                               .arg(field)
-                               .arg(fieldValues.join(", "));
-        } else if (field == "birthday") {
-            QContactBirthday detail = contact.detail(qtDefinitionName);
-            fieldValuesList << QString("%1: %2")
-                               .arg(field)
-                               .arg(detail.dateTime().toMSecsSinceEpoch());
-        } else if (field == "organizations") {
-            QStringList fieldValues;
-            QList<QContactDetail> details = contact.details(qtDefinitionName);
-            foreach (const QContactDetail &detail, details) {
-                QContactOrganization castedDetail = detail;
-                fieldValues << QString("{type: \"%1\", name: \"%2\", department: \"%3\", title: \"%4\", pref: %5}")
-                               .arg("organization")
-                               .arg(castedDetail.name())
-                               .arg(castedDetail.department().join(" "))
-                               .arg(castedDetail.role())
-                               .arg("false");
-            }
-            fieldValuesList << QString("%1: [%2]")
-                               .arg(field)
-                               .arg(fieldValues.join(", "));
-        } else if (field == "name") {
-            QContactName detail = contact.detail(qtDefinitionName);
-            fieldValuesList <<  QString("%1: {familyName: \"%2\", givenName: \"%3\", middleName: \"%4\", honorificPrefix: \"%5\", honorificSuffix: \"%6\"}")
-                                .arg(field)
-                                .arg(detail.lastName())
-                                .arg(detail.firstName())
-                                .arg(detail.middleName())
-                                .arg(detail.prefix())
-                                .arg(detail.suffix());
-        }
-
-
-    }
-
-    return QString("{%1}").arg(fieldValuesList.join(", "));
-}

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/ubuntu/contacts.h
----------------------------------------------------------------------
diff --git a/src/ubuntu/contacts.h b/src/ubuntu/contacts.h
deleted file mode 100644
index 4c1343b..0000000
--- a/src/ubuntu/contacts.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-#ifndef CONTACTS_H_SSSSSSS
-#define CONTACTS_H_SSSSSSS
-
-#include <cplugin.h>
-
-#include <QtContacts>
-#include <QtCore>
-
-QTCONTACTS_USE_NAMESPACE
-
-class Contacts : public CPlugin {
-    Q_OBJECT
-public:
-    explicit Contacts(Cordova *cordova);
-
-    virtual const QString fullName() override {
-        return Contacts::fullID();
-    }
-
-    virtual const QString shortName() override {
-        return "Contacts";
-    }
-
-    static const QString fullID() {
-        return "Contacts";
-    }
-
-public slots:
-    void save(int scId, int ecId, const QVariantMap &params);
-    void remove(int scId, int ecId, const QString &localId);
-    void search(int scId, int ecId, const QStringList &fields, const QVariantMap &params);
-
-private:
-    void findContacts(int scId, int ecId, const QStringList &fields, const QString &filter, bool multiple);
-    QContactDetail::DetailType cordovaFieldNameToQtDefinition(const QString &cordovaFieldName) const;
-    int subTypePhoneFromString(const QString &cordovaSubType) const;
-    int subTypeOnlineAccountFromString(const QString &cordovaSubType) const;
-    int subTypeUrlFromString(const QString &cordovaSubType) const;
-    QString subTypePhoneToString(int qtSubType) const;
-    QString subTypeOnlineAccountToString(int qtSubType) const;
-    QString subTypeUrlToString(int qtSubType) const;
-    QString jsonedContact(const QContact &contact, const QStringList &fields = QStringList()) const;
-
-    QHash<QString, QContactDetail::DetailType> m_fieldNamePairs;
-    QSet<QString> m_notSupportedFields;
-    QSharedPointer<QContactManager> m_manager;
-};
-
-#endif

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/windows8/ContactProxy.js
----------------------------------------------------------------------
diff --git a/src/windows8/ContactProxy.js b/src/windows8/ContactProxy.js
deleted file mode 100644
index 10f9402..0000000
--- a/src/windows8/ContactProxy.js
+++ /dev/null
@@ -1,151 +0,0 @@
-//cordova.define("org.apache.cordova.contacts.ContactProxy", function (require, exports, module) {
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-
-module.exports = {
-    search:function(win,fail,args){
-        var fields = args[0]; // ignored, always returns entire object
-        var options = args[1];
-
-        var filter = options.filter;   // ignored
-        var multiple = true;//options.multiple;
-
-        var picker = new Windows.ApplicationModel.Contacts.ContactPicker();
-        picker.selectionMode = Windows.ApplicationModel.Contacts.ContactSelectionMode.contacts;   // select entire contact
-        if (picker.pickContactAsync) {
-            // TODO: 8.1 has better contact support via the 'Contact' object
-        }
-        else {
-            // 8.0 use the ContactInformation class
-            // decide which function we will call
-            var pickerFunkName = multiple ? 'pickMultipleContactsAsync' : 'pickSingleContactAsync';
-            picker[pickerFunkName]().done(function (res) {
-                if (!res) {
-                    fail && setTimeout(function () {
-                        fail(new Error("User did not pick a contact."));
-                    }, 0);
-                    return;
-                }
-
-                var contactResults = [];
-
-                for (var i = 0; i < res.length; i++) {
-
-
-                    var index,
-                        contactResult = res[i],
-                        contact = {
-                            id: "",
-                            name: { formatted: contactResult.name },  // ContactName
-                            displayName: contactResult.name,          // DOMString
-                            nickname: contactResult.name,             // DOMString
-                            phoneNumbers: contactResult.phoneNumbers, // ContactField[]
-                            addresses: contactResult.locations,       // ContactAddress[]
-                            emails: [],                               // ContactField
-                            ims: contactResult.instantMessages,       // ContactField[]
-                            organizations: [],              // ContactOrganization[]
-                            birthday: null,                 // Date
-                            note: "",                       // DOMString
-                            photos: [],                     // ContactField[]
-                            categories: [],                 // ContactField[]
-                            urls: []                        // ContactField[]
-                        };
-
-                    // Win8-ContactField is {category, name, type, value};
-                    // Cordova ContactField is {type,value, pref:bool };
-                    // Win8 type means 'email' cordova type means 'work|home|...' so we convert them
-                    if (contact.emails && contact.emails.length) {
-                        contact.emails[0].pref = true; // add a preferred prop 
-                        for (index = 0; index < contacts.emails.length; index++) {
-                            contact.emails[index].type = contact.emails[index].category;
-                        }
-                    }
-
-                    if (contact.phoneNumbers && contact.phoneNumbers.length) {
-                        contact.phoneNumbers[0].pref = true; // cordova contact field needs a 'prefered' property on  a contact
-                        // change the meaning of type from 'telephonenumber' to 'work|home|...'
-                        for (index = 0; index < contact.phoneNumbers.length; index++) {
-                            contact.phoneNumbers[index].type = contact.phoneNumbers[index].category;
-                        }
-                    }
-
-                    if (contact.addresses && contact.addresses.length) {
-
-                        // convert addresses/locations to Cordova.ContactAddresses                    
-                        // constr: ContactAddress(pref, type, formatted, streetAddress, locality, region, postalCode, country)
-                        var address, formatted;
-                        for (index = 0; index < contact.addresses.length; index++) {
-                            address = contact.addresses[index];   // make an alias
-                            var formattedArray = [];
-                            // get rid of the empty fields.
-                            var fields = [address.street, address.city, address.region, address.country, address.postalCode];
-                            for (var n = 0; n < fields.length; n++) {
-                                if (fields[n].length > 0) {
-                                    formattedArray.push(fields[n]);
-                                }
-                            }
-                            formattedAddress = formattedArray.join(", ");
-                            console.log(contact.name.formatted + " formatted looks like " + formattedAddress);
-                            contact.addresses[index] = new ContactAddress(false,
-                                                                          address.name,
-                                                                          formattedAddress,
-                                                                          address.street,
-                                                                          address.city,
-                                                                          address.region,
-                                                                          address.postalCode,
-                                                                          address.country);
-                        }
-
-                    }
-
-                    // convert ims to ContactField
-                    if (contact.ims && contact.ims.length) {
-                        // MS ContactInstantMessageField has : displayText, launchUri, service, userName, category, type
-                        contact.ims[0].pref = true;
-                        for (index = 0; index < contact.ims.length; index++) {
-                            contact.ims[index] = new ContactField(contact.ims[index].type, contact.ims[index].value, false);
-                        }
-                    }
-
-                    contactResults.push(contact);
-
-                }
-                // send em back
-                win(contactResults);
-
-            });
-        }
-    },
-
-    save:function(win,fail,args){
-        console && console.error && console.error("Error : Windows 8 does not support creating/saving contacts");
-        fail && setTimeout(function () {
-            fail(new Error("Contact create/save not supported on Windows 8"));
-        }, 0);
-
-    }
-
-
-}
-
-require("cordova/exec/proxy").add("Contacts", module.exports);
-// });


[4/6] CB-6521: Remove development branch

Posted by ia...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/android/ContactManager.java
----------------------------------------------------------------------
diff --git a/src/android/ContactManager.java b/src/android/ContactManager.java
deleted file mode 100644
index a50d799..0000000
--- a/src/android/ContactManager.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
-       Licensed to the Apache Software Foundation (ASF) under one
-       or more contributor license agreements.  See the NOTICE file
-       distributed with this work for additional information
-       regarding copyright ownership.  The ASF licenses this file
-       to you under the Apache License, Version 2.0 (the
-       "License"); you may not use this file except in compliance
-       with the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing,
-       software distributed under the License is distributed on an
-       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-       KIND, either express or implied.  See the License for the
-       specific language governing permissions and limitations
-       under the License.
-*/
-package org.apache.cordova.contacts;
-
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.PluginResult;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import android.util.Log;
-
-public class ContactManager extends CordovaPlugin {
-
-    private ContactAccessor contactAccessor;
-    private static final String LOG_TAG = "Contact Query";
-
-    public static final int UNKNOWN_ERROR = 0;
-    public static final int INVALID_ARGUMENT_ERROR = 1;
-    public static final int TIMEOUT_ERROR = 2;
-    public static final int PENDING_OPERATION_ERROR = 3;
-    public static final int IO_ERROR = 4;
-    public static final int NOT_SUPPORTED_ERROR = 5;
-    public static final int PERMISSION_DENIED_ERROR = 20;
-
-    /**
-     * Constructor.
-     */
-    public ContactManager() {
-    }
-
-    /**
-     * Executes the request and returns PluginResult.
-     *
-     * @param action            The action to execute.
-     * @param args              JSONArray of arguments for the plugin.
-     * @param callbackContext   The callback context used when calling back into JavaScript.
-     * @return                  True if the action was valid, false otherwise.
-     */
-    public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
-        /**
-         * Check to see if we are on an Android 1.X device.  If we are return an error as we
-         * do not support this as of Cordova 1.0.
-         */
-        if (android.os.Build.VERSION.RELEASE.startsWith("1.")) {
-            callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, ContactManager.NOT_SUPPORTED_ERROR));
-            return true;
-        }
-
-        /**
-         * Only create the contactAccessor after we check the Android version or the program will crash
-         * older phones.
-         */
-        if (this.contactAccessor == null) {
-            this.contactAccessor = new ContactAccessorSdk5(this.cordova);
-        }
-
-        if (action.equals("search")) {
-            final JSONArray filter = args.getJSONArray(0);
-            final JSONObject options = args.getJSONObject(1);
-            this.cordova.getThreadPool().execute(new Runnable() {
-                public void run() {
-                    JSONArray res = contactAccessor.search(filter, options);
-                    callbackContext.success(res);
-                }
-            });
-        }
-        else if (action.equals("save")) {
-            final JSONObject contact = args.getJSONObject(0);
-            this.cordova.getThreadPool().execute(new Runnable() {
-                public void run() {
-                    JSONObject res = null;
-                    String id = contactAccessor.save(contact);
-                    if (id != null) {
-                        try {
-                            res = contactAccessor.getContactById(id);
-                        } catch (JSONException e) {
-                            Log.e(LOG_TAG, "JSON fail.", e);
-                        }
-                    }
-                    if (res != null) {
-                        callbackContext.success(res);
-                    } else {
-                        callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, UNKNOWN_ERROR));
-                    }
-                }
-            });
-        }
-        else if (action.equals("remove")) {
-            final String contactId = args.getString(0);
-            this.cordova.getThreadPool().execute(new Runnable() {
-                public void run() {
-                    if (contactAccessor.remove(contactId)) {
-                        callbackContext.success();
-                    } else {
-                        callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, UNKNOWN_ERROR));
-                    }
-                }
-            });
-        }
-        else {
-            return false;
-        }
-        return true;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/blackberry10/ContactActivity.js
----------------------------------------------------------------------
diff --git a/src/blackberry10/ContactActivity.js b/src/blackberry10/ContactActivity.js
deleted file mode 100644
index 0205194..0000000
--- a/src/blackberry10/ContactActivity.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-var ContactActivity = function (args) {
-    this.direction = args.direction || null;
-    this.description = args.description || "";
-    this.mimeType = args.mimeType || "";
-    this.timestamp = new Date(parseInt(args.timestamp, 10)) || null;
-};
-
-Object.defineProperty(ContactActivity, "INCOMING", {"value": true});
-Object.defineProperty(ContactActivity, "OUTGOING", {"value": false});
-
-module.exports = ContactActivity;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/blackberry10/ContactAddress.js
----------------------------------------------------------------------
diff --git a/src/blackberry10/ContactAddress.js b/src/blackberry10/ContactAddress.js
deleted file mode 100644
index 30e9cbd..0000000
--- a/src/blackberry10/ContactAddress.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-var ContactAddress = function (properties) {
-    this.type = properties && properties.type ? properties.type : "";
-    this.streetAddress = properties && properties.streetAddress ? properties.streetAddress : "";
-    this.streetOther = properties && properties.streetOther ? properties.streetOther : "";
-    this.locality = properties && properties.locality ? properties.locality : "";
-    this.region = properties && properties.region ? properties.region : "";
-    this.postalCode = properties && properties.postalCode ? properties.postalCode : "";
-    this.country = properties && properties.country ? properties.country : "";
-};
-
-Object.defineProperty(ContactAddress, "HOME", {"value": "home"});
-Object.defineProperty(ContactAddress, "WORK", {"value": "work"});
-Object.defineProperty(ContactAddress, "OTHER", {"value": "other"});
-
-module.exports = ContactAddress;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/blackberry10/ContactError.js
----------------------------------------------------------------------
diff --git a/src/blackberry10/ContactError.js b/src/blackberry10/ContactError.js
deleted file mode 100644
index a44a546..0000000
--- a/src/blackberry10/ContactError.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-var ContactError = function (code, msg) {
-    this.code = code;
-    this.message = msg;
-};
-
-Object.defineProperty(ContactError, "UNKNOWN_ERROR", { "value": 0 });
-Object.defineProperty(ContactError, "INVALID_ARGUMENT_ERROR", { "value": 1 });
-Object.defineProperty(ContactError, "TIMEOUT_ERROR", { "value": 2 });
-Object.defineProperty(ContactError, "PENDING_OPERATION_ERROR", { "value": 3 });
-Object.defineProperty(ContactError, "IO_ERROR", { "value": 4 });
-Object.defineProperty(ContactError, "NOT_SUPPORTED_ERROR", { "value": 5 });
-Object.defineProperty(ContactError, "PERMISSION_DENIED_ERROR", { "value": 20 });
-
-module.exports = ContactError;
-

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/blackberry10/ContactField.js
----------------------------------------------------------------------
diff --git a/src/blackberry10/ContactField.js b/src/blackberry10/ContactField.js
deleted file mode 100644
index 9651700..0000000
--- a/src/blackberry10/ContactField.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-var ContactField = function (type, value) {
-    this.type = type || "";
-    this.value = value || "";
-};
-
-Object.defineProperty(ContactField, "HOME", {"value": "home"});
-Object.defineProperty(ContactField, "WORK", {"value": "work"});
-Object.defineProperty(ContactField, "OTHER", {"value": "other"});
-Object.defineProperty(ContactField, "MOBILE", {"value": "mobile"});
-Object.defineProperty(ContactField, "DIRECT", {"value": "direct"});
-
-module.exports = ContactField;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/blackberry10/ContactFindOptions.js
----------------------------------------------------------------------
diff --git a/src/blackberry10/ContactFindOptions.js b/src/blackberry10/ContactFindOptions.js
deleted file mode 100644
index 6f8ccfe..0000000
--- a/src/blackberry10/ContactFindOptions.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
- * ContactFindOptions.
- * @constructor
- * @param filter search fields
- * @param sort sort fields and order
- * @param limit max number of contacts to return
- * @param favorite if set, only favorite contacts will be returned
- */
-
-var ContactFindOptions = function (filter, sort, limit, favorite) {
-    this.filter = filter || null;
-    this.sort = sort || null;
-    this.limit = limit || -1; // -1 for returning all results
-    this.favorite = favorite || false;
-    this.includeAccounts = [];
-    this.excludeAccounts = [];
-};
-
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_GIVEN_NAME", { "value": 0 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_FAMILY_NAME", { "value": 1 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_ORGANIZATION_NAME", { "value": 2 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_PHONE", { "value": 3 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_EMAIL", { "value": 4 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_BBMPIN", { "value": 5 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_LINKEDIN", { "value": 6 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_TWITTER", { "value": 7 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_VIDEO_CHAT", { "value": 8 });
-
-Object.defineProperty(ContactFindOptions, "SORT_FIELD_GIVEN_NAME", { "value": 0 });
-Object.defineProperty(ContactFindOptions, "SORT_FIELD_FAMILY_NAME", { "value": 1 });
-Object.defineProperty(ContactFindOptions, "SORT_FIELD_ORGANIZATION_NAME", { "value": 2 });
-
-module.exports = ContactFindOptions;
-

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/blackberry10/ContactName.js
----------------------------------------------------------------------
diff --git a/src/blackberry10/ContactName.js b/src/blackberry10/ContactName.js
deleted file mode 100644
index 80136c9..0000000
--- a/src/blackberry10/ContactName.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-function toFormattedName(properties) {
-    var formatted = "";
-    if (properties && properties.givenName) {
-        formatted = properties.givenName;
-        if (properties && properties.familyName) {
-            formatted += " " + properties.familyName;
-        }
-    }
-    return formatted;
-}
-
-var ContactName = function (properties) {
-    this.familyName = properties && properties.familyName ? properties.familyName : "";
-    this.givenName = properties && properties.givenName ? properties.givenName : "";
-    this.formatted = toFormattedName(properties);
-    this.middleName = properties && properties.middleName ? properties.middleName : "";
-    this.honorificPrefix = properties && properties.honorificPrefix ? properties.honorificPrefix : "";
-    this.honorificSuffix = properties && properties.honorificSuffix ? properties.honorificSuffix : "";
-    this.phoneticFamilyName = properties && properties.phoneticFamilyName ? properties.phoneticFamilyName : "";
-    this.phoneticGivenName = properties && properties.phoneticGivenName ? properties.phoneticGivenName : "";
-};
-
-module.exports = ContactName;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/blackberry10/ContactNews.js
----------------------------------------------------------------------
diff --git a/src/blackberry10/ContactNews.js b/src/blackberry10/ContactNews.js
deleted file mode 100644
index e47a4cd..0000000
--- a/src/blackberry10/ContactNews.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-var ContactNews = function (args) {
-    this.title = args.title || "";
-    this.body = args.body || "";
-    this.articleSource = args.articleSource || "";
-    this.companies = args.companies || [];
-    this.publishedAt = new Date(parseInt(args.publishedAt, 10)) || null;
-    this.uri = args.uri || "";
-    this.type = args.type || "";
-};
-
-module.exports = ContactNews;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/blackberry10/ContactOrganization.js
----------------------------------------------------------------------
diff --git a/src/blackberry10/ContactOrganization.js b/src/blackberry10/ContactOrganization.js
deleted file mode 100644
index fc953f2..0000000
--- a/src/blackberry10/ContactOrganization.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-var ContactOrganization = function (properties) {
-    this.name = properties && properties.name ? properties.name : "";
-    this.department = properties && properties.department ? properties.department : "";
-    this.title = properties && properties.title ? properties.title : "";
-};
-
-module.exports = ContactOrganization;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/blackberry10/ContactPhoto.js
----------------------------------------------------------------------
diff --git a/src/blackberry10/ContactPhoto.js b/src/blackberry10/ContactPhoto.js
deleted file mode 100644
index 4604710..0000000
--- a/src/blackberry10/ContactPhoto.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-var ContactPhoto = function (originalFilePath, pref) {
-    this.originalFilePath = originalFilePath || "";
-    this.pref = pref || false;
-    this.largeFilePath = "";
-    this.smallFilePath = "";
-};
-
-module.exports = ContactPhoto;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/blackberry10/contactConsts.js
----------------------------------------------------------------------
diff --git a/src/blackberry10/contactConsts.js b/src/blackberry10/contactConsts.js
deleted file mode 100644
index ef25206..0000000
--- a/src/blackberry10/contactConsts.js
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
-* Copyright 2012 Research In Motion Limited.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-var ATTRIBUTE_KIND,
-    ATTRIBUTE_SUBKIND,
-    kindAttributeMap = {},
-    subKindAttributeMap = {},
-    _TITLE = 26,
-    _START_DATE = 43,
-    _END_DATE = 44;
-
-function populateKindAttributeMap() {
-    ATTRIBUTE_KIND = {
-        Invalid: 0,
-        Phone: 1,
-        Fax: 2,
-        Pager: 3,
-        Email: 4,
-        Website: 5,
-        Feed: 6,
-        Profile: 7,
-        Family: 8,
-        Person: 9,
-        Date: 10,
-        Group: 11,
-        Name: 12,
-        StockSymbol: 13,
-        Ranking: 14,
-        OrganizationAffiliation: 15,
-        Education: 16,
-        Note: 17,
-        InstantMessaging: 18,
-        VideoChat: 19,
-        ConnectionCount: 20,
-        Hidden: 21,
-        Biography: 22,
-        Sound: 23,
-        Notification: 24,
-        MessageSound: 25,
-        MessageNotification: 26
-    };
-
-    kindAttributeMap[ATTRIBUTE_KIND.Phone] = "phoneNumbers";
-    kindAttributeMap[ATTRIBUTE_KIND.Fax] = "faxNumbers";
-    kindAttributeMap[ATTRIBUTE_KIND.Pager] = "pagerNumber";
-    kindAttributeMap[ATTRIBUTE_KIND.Email] = "emails";
-    kindAttributeMap[ATTRIBUTE_KIND.Website] = "urls";
-    kindAttributeMap[ATTRIBUTE_KIND.Profile] = "socialNetworks";
-    kindAttributeMap[ATTRIBUTE_KIND.OrganizationAffiliation] = "organizations";
-    kindAttributeMap[ATTRIBUTE_KIND.Education] = "education";
-    kindAttributeMap[ATTRIBUTE_KIND.Note] = "note";
-    kindAttributeMap[ATTRIBUTE_KIND.InstantMessaging] = "ims";
-    kindAttributeMap[ATTRIBUTE_KIND.VideoChat] = "videoChat";
-    kindAttributeMap[ATTRIBUTE_KIND.Sound] = "ringtone";
-}
-
-function populateSubKindAttributeMap() {
-    ATTRIBUTE_SUBKIND = {
-        Invalid: 0,
-        Other: 1,
-        Home: 2,
-        Work: 3,
-        PhoneMobile: 4,
-        FaxDirect: 5,
-        Blog: 6,
-        WebsiteResume: 7,
-        WebsitePortfolio: 8,
-        WebsitePersonal: 9,
-        WebsiteCompany: 10,
-        ProfileFacebook: 11,
-        ProfileTwitter: 12,
-        ProfileLinkedIn: 13,
-        ProfileGist: 14,
-        ProfileTungle: 15,
-        FamilySpouse: 16,
-        FamilyChild: 17,
-        FamilyParent: 18,
-        PersonManager: 19,
-        PersonAssistant: 20,
-        DateBirthday: 21,
-        DateAnniversary: 22,
-        GroupDepartment: 23,
-        NameGiven: 24,
-        NameSurname: 25,
-        Title: _TITLE,
-        NameSuffix: 27,
-        NameMiddle: 28,
-        NameNickname: 29,
-        NameAlias: 30,
-        NameDisplayName: 31,
-        NamePhoneticGiven: 32,
-        NamePhoneticSurname: 33,
-        StockSymbolNyse: 34,
-        StockSymbolNasdaq: 35,
-        StockSymbolTse: 36,
-        StockSymbolLse: 37,
-        StockSymbolTsx: 38,
-        RankingKlout: 39,
-        RankingTrstRank: 40,
-        OrganizationAffiliationName: 41,
-        OrganizationAffiliationPhoneticName: 42,
-        OrganizationAffiliationTitle: _TITLE,
-        StartDate: _START_DATE,
-        EndDate: _END_DATE,
-        OrganizationAffiliationDetails: 45,
-        EducationInstitutionName: 46,
-        EducationStartDate: _START_DATE,
-        EducationEndDate: _END_DATE,
-        EducationDegree: 47,
-        EducationConcentration: 48,
-        EducationActivities: 49,
-        EducationNotes: 50,
-        InstantMessagingBbmPin: 51,
-        InstantMessagingAim: 52,
-        InstantMessagingAliwangwang: 53,
-        InstantMessagingGoogleTalk: 54,
-        InstantMessagingSametime: 55,
-        InstantMessagingIcq: 56,
-        InstantMessagingIrc: 57,
-        InstantMessagingJabber: 58,
-        InstantMessagingMsLcs: 59,
-        InstantMessagingMsn: 60,
-        InstantMessagingQq: 61,
-        InstantMessagingSkype: 62,
-        InstantMessagingYahooMessenger: 63,
-        InstantMessagingYahooMessengerJapan: 64,
-        VideoChatBbPlaybook: 65,
-        HiddenLinkedIn: 66,
-        HiddenFacebook: 67,
-        HiddenTwitter: 68,
-        ConnectionCountLinkedIn: 69,
-        ConnectionCountFacebook: 70,
-        ConnectionCountTwitter: 71,
-        HiddenChecksum: 72,
-        HiddenSpeedDial: 73,
-        BiographyFacebook: 74,
-        BiographyTwitter: 75,
-        BiographyLinkedIn: 76,
-        SoundRingtone: 77,
-        SimContactType: 78,
-        EcoID: 79,
-        Personal: 80,
-        StockSymbolAll: 81,
-        NotificationVibration: 82,
-        NotificationLED: 83,
-        MessageNotificationVibration: 84,
-        MessageNotificationLED: 85,
-        MessageNotificationDuringCall: 86,
-        VideoChatPin: 87
-    };
-
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.Other] = "other";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.Home] = "home";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.Work] = "work";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.PhoneMobile] = "mobile";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.FaxDirect] = "direct";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.Blog] = "blog";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.WebsiteResume] = "resume";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.WebsitePortfolio] = "portfolio";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.WebsitePersonal] = "personal";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.WebsiteCompany] = "company";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.ProfileFacebook] = "facebook";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.ProfileTwitter] = "twitter";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.ProfileLinkedIn] = "linkedin";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.ProfileGist] = "gist";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.ProfileTungle] = "tungle";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.DateBirthday] = "birthday";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.DateAnniversary] = "anniversary";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.NameGiven] = "givenName";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.NameSurname] = "familyName";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.Title] = "honorificPrefix";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.NameSuffix] = "honorificSuffix";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.NameMiddle] = "middleName";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.NamePhoneticGiven] = "phoneticGivenName";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.NamePhoneticSurname] = "phoneticFamilyName";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.NameNickname] = "nickname";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.NameDisplayName] = "displayName";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.OrganizationAffiliationName] = "name";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.OrganizationAffiliationDetails] = "department";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.Title] = "title";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingBbmPin] = "BbmPin";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingAim] = "Aim";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingAliwangwang] = "Aliwangwang";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingGoogleTalk] = "GoogleTalk";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingSametime] = "Sametime";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingIcq] = "Icq";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingJabber] = "Jabber";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingMsLcs] = "MsLcs";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingSkype] = "Skype";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingYahooMessenger] = "YahooMessenger";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingYahooMessengerJapan] = "YahooMessegerJapan";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.VideoChatBbPlaybook] = "BbPlaybook";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.SoundRingtone] = "ringtone";
-    subKindAttributeMap[ATTRIBUTE_SUBKIND.Personal] = "personal";
-}
-
-module.exports = {
-    getKindAttributeMap: function () {
-        if (!ATTRIBUTE_KIND) {
-            populateKindAttributeMap();
-        }
-
-        return kindAttributeMap;
-    },
-    getSubKindAttributeMap: function () {
-        if (!ATTRIBUTE_SUBKIND) {
-            populateSubKindAttributeMap();
-        }
-
-        return subKindAttributeMap;
-    }
-};

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/blackberry10/contactUtils.js
----------------------------------------------------------------------
diff --git a/src/blackberry10/contactUtils.js b/src/blackberry10/contactUtils.js
deleted file mode 100644
index e1f7d67..0000000
--- a/src/blackberry10/contactUtils.js
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
- 
-var self,
-    ContactFindOptions = require("./ContactFindOptions"),
-    ContactError = require("./ContactError"),
-    ContactName = require("./ContactName"),
-    ContactOrganization = require("./ContactOrganization"),
-    ContactAddress = require("./ContactAddress"),
-    ContactField = require("./ContactField"),
-    contactConsts = require("./contactConsts"),
-    ContactPhoto = require("./ContactPhoto"),
-    ContactNews = require("./ContactNews"),
-    ContactActivity = require("./ContactActivity");
-
-function populateFieldArray(contactProps, field, ClassName) {
-    if (contactProps[field]) {
-        var list = [],
-        obj;
-
-        contactProps[field].forEach(function (args) {
-            if (ClassName === ContactField) {
-                list.push(new ClassName(args.type, args.value));
-            } else if (ClassName === ContactPhoto) {
-                obj = new ContactPhoto(args.originalFilePath, args.pref);
-                obj.largeFilePath = args.largeFilePath;
-                obj.smallFilePath = args.smallFilePath;
-                list.push(obj);
-            } else if (ClassName === ContactNews) {
-                obj = new ContactNews(args);
-                list.push(obj);
-            } else if (ClassName === ContactActivity) {
-                obj = new ContactActivity(args);
-                list.push(obj);
-            } else {
-                list.push(new ClassName(args));
-            }
-        });
-        contactProps[field] = list;
-    }
-}
-
-function populateDate(contactProps, field) {
-    if (contactProps[field]) {
-        contactProps[field] = new Date(contactProps[field]);
-    }
-}
-
-function validateFindArguments(findOptions) {
-    var error = false;
-    
-    // findOptions is mandatory
-    if (!findOptions) {
-        error = true;
-    } else {
-        // findOptions.filter is optional
-        if (findOptions.filter) {
-            findOptions.filter.forEach(function (f) {
-                switch (f.fieldName) {
-                case ContactFindOptions.SEARCH_FIELD_GIVEN_NAME:
-                case ContactFindOptions.SEARCH_FIELD_FAMILY_NAME:
-                case ContactFindOptions.SEARCH_FIELD_ORGANIZATION_NAME:
-                case ContactFindOptions.SEARCH_FIELD_PHONE:
-                case ContactFindOptions.SEARCH_FIELD_EMAIL:
-                case ContactFindOptions.SEARCH_FIELD_BBMPIN:
-                case ContactFindOptions.SEARCH_FIELD_LINKEDIN:
-                case ContactFindOptions.SEARCH_FIELD_TWITTER:
-                case ContactFindOptions.SEARCH_FIELD_VIDEO_CHAT:
-                    break;
-                default:
-                    error = true;
-                }
-
-                if (!f.fieldValue) {
-                    error = true;
-                }
-            });
-        } 
-
-        //findOptions.limit is optional
-        if (findOptions.limit) {
-            if (typeof findOptions.limit !== "number") {
-                error = true;
-            } 
-        } 
-
-        //findOptions.favorite is optional
-        if (findOptions.favorite) {
-            if (typeof findOptions.favorite !== "boolean") {
-                error = true;
-            }
-        }
-
-        // findOptions.sort is optional
-        if (!error && findOptions.sort && Array.isArray(findOptions.sort)) {
-            findOptions.sort.forEach(function (s) {
-                switch (s.fieldName) {
-                case ContactFindOptions.SORT_FIELD_GIVEN_NAME:
-                case ContactFindOptions.SORT_FIELD_FAMILY_NAME:
-                case ContactFindOptions.SORT_FIELD_ORGANIZATION_NAME:
-                    break;
-                default:
-                    error = true;
-                }
-
-                if (s.desc === undefined || typeof s.desc !== "boolean") {
-                    error = true;
-                }
-            });
-        }
-
-        if (!error && findOptions.includeAccounts) {
-            if (!Array.isArray(findOptions.includeAccounts)) {
-                error = true;
-            } else {
-                findOptions.includeAccounts.forEach(function (acct) {
-                    if (!error && (!acct.id || window.isNaN(window.parseInt(acct.id, 10)))) {
-                        error = true;
-                    }
-                });
-            }
-        }
-
-        if (!error && findOptions.excludeAccounts) {
-            if (!Array.isArray(findOptions.excludeAccounts)) {
-                error = true;
-            } else {
-                findOptions.excludeAccounts.forEach(function (acct) {
-                    if (!error && (!acct.id || window.isNaN(window.parseInt(acct.id, 10)))) {
-                        error = true;
-                    }
-                });
-            }
-        }
-    }
-    return !error;
-}
-
-function validateContactsPickerFilter(filter) {
-    var isValid = true,
-        availableFields = {};
-
-    if (typeof(filter) === "undefined") {
-        isValid = false;
-    } else {
-        if (filter && Array.isArray(filter)) {
-            availableFields = contactConsts.getKindAttributeMap();
-            filter.forEach(function (e) {
-                isValid = isValid && Object.getOwnPropertyNames(availableFields).reduce(
-                    function (found, key) {
-                        return found || availableFields[key] === e;
-                    }, false);
-            });
-        }
-    }
-
-    return isValid;
-}
-
-function validateContactsPickerOptions(options) {
-    var isValid = false,
-        mode = options.mode;
-
-    if (typeof(options) === "undefined") {
-        isValid = false;
-    } else {
-        isValid = mode === ContactPickerOptions.MODE_SINGLE || mode === ContactPickerOptions.MODE_MULTIPLE || mode === ContactPickerOptions.MODE_ATTRIBUTE;
-
-        // if mode is attribute, fields must be defined
-        if (mode === ContactPickerOptions.MODE_ATTRIBUTE && !validateContactsPickerFilter(options.fields)) {
-            isValid = false;
-        }
-    }
-
-    return isValid;
-}
-
-self = module.exports = {
-    populateContact: function (contact) {
-        if (contact.name) {
-            contact.name = new ContactName(contact.name);
-        }
-
-        populateFieldArray(contact, "addresses", ContactAddress);
-        populateFieldArray(contact, "organizations", ContactOrganization);
-        populateFieldArray(contact, "emails", ContactField);
-        populateFieldArray(contact, "phoneNumbers", ContactField);
-        populateFieldArray(contact, "faxNumbers", ContactField);
-        populateFieldArray(contact, "pagerNumbers", ContactField);
-        populateFieldArray(contact, "ims", ContactField);
-        populateFieldArray(contact, "socialNetworks", ContactField);
-        populateFieldArray(contact, "urls", ContactField);
-        populateFieldArray(contact, "photos", ContactPhoto);
-        populateFieldArray(contact, "news", ContactNews);
-        populateFieldArray(contact, "activities", ContactActivity);
-        // TODO categories
-
-        populateDate(contact, "birthday");
-        populateDate(contact, "anniversary");
-    },
-    invokeErrorCallback: function (errorCallback, code) {
-        if (errorCallback) {
-            errorCallback(new ContactError(code));
-        }
-    },
-    validateFindArguments: validateFindArguments,
-    validateContactsPickerFilter: validateContactsPickerFilter,
-    validateContactsPickerOptions: validateContactsPickerOptions
-};
-

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/blackberry10/index.js
----------------------------------------------------------------------
diff --git a/src/blackberry10/index.js b/src/blackberry10/index.js
deleted file mode 100644
index 09a4bd2..0000000
--- a/src/blackberry10/index.js
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Copyright 2013 Research In Motion Limited.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-var pimContacts,
-    contactUtils = require("./contactUtils"),
-    contactConsts = require("./contactConsts"),
-    ContactError = require("./ContactError"),
-    ContactName = require("./ContactName"),
-    ContactFindOptions = require("./ContactFindOptions"),
-    noop = function () {};
-
-function getAccountFilters(options) {
-    if (options.includeAccounts) {
-        options.includeAccounts = options.includeAccounts.map(function (acct) {
-            return acct.id.toString();
-        });
-    }
-
-    if (options.excludeAccounts) {
-        options.excludeAccounts = options.excludeAccounts.map(function (acct) {
-            return acct.id.toString();
-        });
-    }
-}
-
-function populateSearchFields(fields) {
-    var i,
-        l,
-        key,
-        searchFieldsObject = {},
-        searchFields = [];
-
-    for (i = 0, l = fields.length; i < l; i++) {
-        if (fields[i] === "*") {
-            searchFieldsObject[ContactFindOptions.SEARCH_FIELD_GIVEN_NAME] = true;
-            searchFieldsObject[ContactFindOptions.SEARCH_FIELD_FAMILY_NAME] = true;
-            searchFieldsObject[ContactFindOptions.SEARCH_FIELD_PHONE] = true;
-            searchFieldsObject[ContactFindOptions.SEARCH_FIELD_EMAIL] = true;
-            searchFieldsObject[ContactFindOptions.SEARCH_FIELD_ORGANIZATION_NAME] = true;
-        } else if (fields[i] === "displayName" || fields[i] === "name") {
-            searchFieldsObject[ContactFindOptions.SEARCH_FIELD_GIVEN_NAME] = true;
-            searchFieldsObject[ContactFindOptions.SEARCH_FIELD_FAMILY_NAME] = true;
-        } else if (fields[i] === "nickname") {
-            // not supported by Cascades
-        } else if (fields[i] === "phoneNumbers") {
-            searchFieldsObject[ContactFindOptions.SEARCH_FIELD_PHONE] = true;
-        } else if (fields[i] === "emails") {
-            searchFieldsObject[ContactFindOptions.SEARCH_FIELD_EMAIL] = true;
-        } else if (field === "addresses") {
-            // not supported by Cascades
-        } else if (field === "ims") {
-            // not supported by Cascades
-        } else if (field === "organizations") {
-            searchFieldsObject[ContactFindOptions.SEARCH_FIELD_ORGANIZATION_NAME] = true;
-        } else if (field === "birthday") {
-            // not supported by Cascades
-        } else if (field === "note") {
-            // not supported by Cascades
-        } else if (field === "photos") {
-            // not supported by Cascades
-        } else if (field === "categories") {
-            // not supported by Cascades
-        } else if (field === "urls") {
-            // not supported by Cascades
-        }
-    }
-
-    for (key in searchFieldsObject) {
-        if (searchFieldsObject.hasOwnProperty(key)) {
-            searchFields.push(window.parseInt(key));
-        }
-    }
-
-    return searchFields;
-}
-
-function convertBirthday(birthday) {
-    //Convert date string from native to milliseconds since epoch for cordova-js
-    var birthdayInfo;
-    if (birthday) {
-        birthdayInfo = birthday.split("-");
-        return new Date(birthdayInfo[0], birthdayInfo[1] - 1, birthdayInfo[2]).getTime();
-    } else {
-        return null;
-    }
-}
-
-function processJnextSaveData(result, JnextData) {
-    var data = JnextData,
-        birthdayInfo;
-
-    if (data._success === true) {
-        data.birthday = convertBirthday(data.birthday);
-        result.callbackOk(data, false);
-    } else {
-        result.callbackError(data.code, false);
-    }
-}
-
-function processJnextRemoveData(result, JnextData) {
-    var data = JnextData;
-
-    if (data._success === true) {
-        result.callbackOk(data);
-    } else {
-        result.callbackError(ContactError.UNKNOWN_ERROR, false);
-    }
-}
-
-function processJnextFindData(eventId, eventHandler, JnextData) {
-    var data = JnextData,
-        i,
-        l,
-        more = false,
-        resultsObject = {},
-        birthdayInfo;
-
-    if (data.contacts) {
-        for (i = 0, l = data.contacts.length; i < l; i++) {
-            data.contacts[i].birthday = convertBirthday(data.contacts[i].birthday);
-            data.contacts[i].name = new ContactName(data.contacts[i].name);
-        }
-    } else {
-        data.contacts = []; // if JnextData.contacts return null, return an empty array
-    }
-
-    if (data._success === true) {
-        eventHandler.error = false;
-    }
-
-    if (eventHandler.multiple) {
-        // Concatenate results; do not add the same contacts
-        for (i = 0, l = eventHandler.searchResult.length; i < l; i++) {
-            resultsObject[eventHandler.searchResult[i].id] = true;
-        }
-
-        for (i = 0, l = data.contacts.length; i < l; i++) {
-            if (resultsObject[data.contacts[i].id]) {
-                // Already existing
-            } else {
-                eventHandler.searchResult.push(data.contacts[i]);
-            }
-        }
-
-        // check if more search is required
-        eventHandler.searchFieldIndex++;
-        if (eventHandler.searchFieldIndex < eventHandler.searchFields.length) {
-            more = true;
-        }
-    } else {
-        eventHandler.searchResult = data.contacts;
-    }
-
-    if (more) {
-        pimContacts.getInstance().invokeJnextSearch(eventId);
-    } else {
-        if (eventHandler.error) {
-            eventHandler.result.callbackError(data.code, false);
-        } else {
-            eventHandler.result.callbackOk(eventHandler.searchResult, false);
-        }
-    }
-}
-
-module.exports = {
-    search: function (successCb, failCb, args, env) {
-        var cordovaFindOptions = {},
-            result = new PluginResult(args, env),
-            key;
-
-        for (key in args) {
-            if (args.hasOwnProperty(key)) {
-                cordovaFindOptions[key] = JSON.parse(decodeURIComponent(args[key]));
-            }
-        }
-
-        pimContacts.getInstance().find(cordovaFindOptions, result, processJnextFindData);
-        result.noResult(true);
-    },
-    save: function (successCb, failCb, args, env) {
-        var attributes = {},
-            result = new PluginResult(args, env),
-            key,
-            nativeEmails = [];
-
-        attributes = JSON.parse(decodeURIComponent(args[0]));
-
-        //convert birthday format for our native .so file
-        if (attributes.birthday) {
-            attributes.birthday = new Date(attributes.birthday).toDateString();
-        }
-
-        if (attributes.emails) {
-            attributes.emails.forEach(function (email) {
-                if (email.value) {
-                    if (email.type) {
-                        nativeEmails.push({ "type" : email.type, "value" : email.value });
-                    } else {
-                        nativeEmails.push({ "type" : "home", "value" : email.value });
-                    }
-                }
-            });
-            attributes.emails = nativeEmails;
-        }
-
-        if (attributes.id !== null) {
-            attributes.id = window.parseInt(attributes.id);
-        }
-
-        attributes._eventId = result.callbackId;
-        pimContacts.getInstance().save(attributes, result, processJnextSaveData);
-        result.noResult(true);
-    },
-    remove: function (successCb, failCb, args, env) {
-        var result = new PluginResult(args, env),
-            attributes = {
-                "contactId": window.parseInt(JSON.parse(decodeURIComponent(args[0]))),
-                "_eventId": result.callbackId
-            };
-
-        if (!window.isNaN(attributes.contactId)) {
-            pimContacts.getInstance().remove(attributes, result, processJnextRemoveData);
-            result.noResult(true);
-        } else {
-            result.error(ContactError.UNKNOWN_ERROR);
-            result.noResult(false);
-        }
-    }
-};
-
-///////////////////////////////////////////////////////////////////
-// JavaScript wrapper for JNEXT plugin
-///////////////////////////////////////////////////////////////////
-
-JNEXT.PimContacts = function ()
-{
-    var self = this,
-        hasInstance = false;
-
-    self.find = function (cordovaFindOptions, pluginResult, handler) {
-        //register find eventHandler for when JNEXT onEvent fires
-        self.eventHandlers[cordovaFindOptions.callbackId] = {
-            "result" : pluginResult,
-            "action" : "find",
-            "multiple" : cordovaFindOptions[1].filter ? true : false,
-            "fields" : cordovaFindOptions[0],
-            "searchFilter" : cordovaFindOptions[1].filter,
-            "searchFields" : cordovaFindOptions[1].filter ? populateSearchFields(cordovaFindOptions[0]) : null,
-            "searchFieldIndex" : 0,
-            "searchResult" : [],
-            "handler" : handler,
-            "error" : true
-        };
-
-        self.invokeJnextSearch(cordovaFindOptions.callbackId);
-        return "";
-    };
-
-    self.invokeJnextSearch = function(eventId) {
-        var jnextArgs = {},
-            findHandler = self.eventHandlers[eventId];
-
-        jnextArgs._eventId = eventId;
-        jnextArgs.fields = findHandler.fields;
-        jnextArgs.options = {};
-        jnextArgs.options.filter = [];
-
-        if (findHandler.multiple) {
-            jnextArgs.options.filter.push({
-                "fieldName" : findHandler.searchFields[findHandler.searchFieldIndex],
-                "fieldValue" : findHandler.searchFilter
-            });
-            //findHandler.searchFieldIndex++;
-        }
-
-        JNEXT.invoke(self.m_id, "find " + JSON.stringify(jnextArgs));
-    }
-
-    self.getContact = function (args) {
-        return JSON.parse(JNEXT.invoke(self.m_id, "getContact " + JSON.stringify(args)));
-    };
-
-    self.save = function (args, pluginResult, handler) {
-        //register save eventHandler for when JNEXT onEvent fires
-        self.eventHandlers[args._eventId] = {
-            "result" : pluginResult,
-            "action" : "save",
-            "handler" : handler
-        };
-        JNEXT.invoke(self.m_id, "save " + JSON.stringify(args));
-        return "";
-    };
-
-    self.remove = function (args, pluginResult, handler) {
-        //register remove eventHandler for when JNEXT onEvent fires
-        self.eventHandlers[args._eventId] = {
-            "result" : pluginResult,
-            "action" : "remove",
-            "handler" : handler
-        };
-        JNEXT.invoke(self.m_id, "remove " + JSON.stringify(args));
-        return "";
-    };
-
-    self.getId = function () {
-        return self.m_id;
-    };
-
-    self.getContactAccounts = function () {
-        var value = JNEXT.invoke(self.m_id, "getContactAccounts");
-        return JSON.parse(value);
-    };
-
-    self.init = function () {
-        if (!JNEXT.require("libpimcontacts")) {
-            return false;
-        }
-
-        self.m_id = JNEXT.createObject("libpimcontacts.PimContacts");
-
-        if (self.m_id === "") {
-            return false;
-        }
-
-        JNEXT.registerEvents(self);
-    };
-
-    // Handle data coming back from JNEXT native layer. Each async function registers a handler and a PluginResult object.
-    // When JNEXT fires onEvent we parse the result string  back into JSON and trigger the appropriate handler (eventHandlers map
-    // uses callbackId as key), along with the actual data coming back from the native layer. Each function may have its own way of
-    // processing native data so we do not do any processing here.
-
-    self.onEvent = function (strData) {
-        var arData = strData.split(" "),
-            strEventDesc = arData[0],
-            eventHandler,
-            args = {};
-
-        if (strEventDesc === "result") {
-            args.result = escape(strData.split(" ").slice(2).join(" "));
-            eventHandler = self.eventHandlers[arData[1]];
-            if (eventHandler.action === "save" || eventHandler.action === "remove") {
-                eventHandler.handler(eventHandler.result, JSON.parse(decodeURIComponent(args.result)));
-            } else if (eventHandler.action === "find") {
-                eventHandler.handler(arData[1], eventHandler, JSON.parse(decodeURIComponent(args.result)));
-            }
-        }
-    };
-
-    self.m_id = "";
-    self.eventHandlers = {};
-
-    self.getInstance = function () {
-        if (!hasInstance) {
-            self.init();
-            hasInstance = true;
-        }
-        return self;
-    };
-};
-
-pimContacts = new JNEXT.PimContacts();

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/firefoxos/ContactsProxy.js
----------------------------------------------------------------------
diff --git a/src/firefoxos/ContactsProxy.js b/src/firefoxos/ContactsProxy.js
deleted file mode 100644
index a5b6667..0000000
--- a/src/firefoxos/ContactsProxy.js
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/ 
-
-// Cordova contact definition: 
-// http://cordova.apache.org/docs/en/2.5.0/cordova_contacts_contacts.md.html#Contact
-// FxOS contact definition:
-// https://developer.mozilla.org/en-US/docs/Web/API/mozContact
-
-
-var Contact = require('./Contact');
-var ContactField = require('./ContactField');
-var ContactAddress = require('./ContactAddress');
-var ContactName = require('./ContactName');
-
-// XXX: a hack to check if id is "empty". Cordova inserts a
-// string "this string is supposed to be a unique identifier that will 
-// never show up on a device" if id is empty
-function _hasId(id) {
-    if (!id || id.indexOf(' ') >= 0) {
-        return false;
-    }
-    return true;
-}
-
-// Extend mozContact prototype to provide update from Cordova
-function updateFromCordova(contact, fromContact) {
-
-    function exportContactFieldArray(contactFieldArray, key) {
-        if (!key) {
-            key = 'value';
-        }                 
-        var arr = [];
-        for (var i=0; i < contactFieldArray.length; i++) {
-            arr.push(contactFieldArray[i][key]);
-        };                                       
-        return arr;
-    }              
-
-    function exportAddress(addresses) {
-        // TODO: check moz address format
-        var arr = [];
-        
-        for (var i=0; i < addresses.length; i++) {
-            var addr = {};
-            for (var key in addresses[i]) {
-                if (key == 'formatted' || key == 'id') {
-                    continue;
-                } else if (key == 'type') {
-                    addr[key] = [addresses[i][key]];
-                } else if (key == 'country') {
-                    addr['countryName'] = addresses[i][key];
-                } else {
-                    addr[key] = addresses[i][key];    
-                }
-            } 
-            arr.push(addr);
-        }                                 
-        return arr;
-    } 
-
-    function exportContactField(data) {
-        var contactFields = [];
-        for (var i=0; i < data.length; i++) {
-            var item = data[i];
-            if (item.value) {
-                var itemData = {value: item.value};
-                if (item.type) {
-                    itemData.type = [item.type];
-                }
-                if (item.pref) {
-                    itemData.pref = item.pref;
-                }
-                contactFields.push(itemData);
-            }
-        }
-        return contactFields;
-    }
-    // adding simple fields [contactField, eventualMozContactField]
-    var nameFields = [['givenName'], ['familyName'],  
-                      ['honorificPrefix'], ['honorificSuffix'],
-                      ['middleName', 'additionalName']];
-    var baseArrayFields = [['displayName', 'name'], ['nickname']];
-    var baseStringFields = [];
-    var j = 0; while(field = nameFields[j++]) {
-      if (fromContact.name[field[0]]) {
-        contact[field[1] || field[0]] = fromContact.name[field[0]].split(' ');
-      }
-    }
-    j = 0; while(field = baseArrayFields[j++]) {
-      if (fromContact[field[0]]) {
-        contact[field[1] || field[0]] = fromContact[field[0]].split(' ');
-      }
-    }
-    j = 0; while(field = baseStringFields[j++]) {
-      if (fromContact[field[0]]) {
-        contact[field[1] || field[0]] = fromContact[field[0]];
-      }
-    }
-    if (fromContact.birthday) {
-      contact.bday = new Date(fromContact.birthday);
-    }
-    if (fromContact.emails) {
-        var emails = exportContactField(fromContact.emails)
-        contact.email = emails;
-    }
-    if (fromContact.categories) {
-        contact.category = exportContactFieldArray(fromContact.categories);
-    }
-    if (fromContact.addresses) {
-        contact.adr = exportAddress(fromContact.addresses);
-    }
-    if (fromContact.phoneNumbers) {
-        contact.tel = exportContactField(fromContact.phoneNumbers);
-    }
-    if (fromContact.organizations) {
-        // XXX: organizations are saved in 2 arrays - org and jobTitle
-        //      depending on the usecase it might generate issues
-        //      where wrong title will be added to an organization
-        contact.org = exportContactFieldArray(fromContact.organizations, 'name');
-        contact.jobTitle = exportContactFieldArray(fromContact.organizations, 'title');
-    }
-    if (fromContact.note) {
-        contact.note = [fromContact.note];
-    }
-}
-
-
-// Extend Cordova Contact prototype to provide update from FFOS contact
-Contact.prototype.updateFromMozilla = function(moz) {
-    function exportContactField(data) {
-        var contactFields = [];
-        for (var i=0; i < data.length; i++) {
-            var item = data[i];
-            var itemData = new ContactField(item.type, item.value, item.pref);
-            contactFields.push(itemData);
-        }
-        return contactFields;
-    }
-
-    function makeContactFieldFromArray(data) {
-        var contactFields = [];
-        for (var i=0; i < data.length; i++) {
-            var itemData = new ContactField(null, data[i]);
-            contactFields.push(itemData);
-        }
-        return contactFields;
-    }
-
-    function exportAddresses(addresses) {
-        // TODO: check moz address format
-        var arr = [];
-        
-        for (var i=0; i < addresses.length; i++) {
-            var addr = {};
-            for (var key in addresses[i]) {
-                if (key == 'countryName') {
-                    addr['country'] = addresses[i][key];
-                } else if (key == 'type') {
-                    addr[key] = addresses[i][key].join(' ');
-                } else {
-                    addr[key] = addresses[i][key];    
-                }
-            } 
-            arr.push(addr);
-        }
-        return arr;
-    } 
-
-    function createOrganizations(orgs, jobs) {
-        orgs = (orgs) ? orgs : [];
-        jobs = (jobs) ? jobs : [];
-        var max_length = Math.max(orgs.length, jobs.length);
-        var organizations = [];
-        for (var i=0; i < max_length; i++) {
-            organizations.push(new ContactOrganization(
-                  null, null, orgs[i] || null, null, jobs[i] || null));
-        }
-        return organizations;
-    }
-
-    function createFormatted(name) {
-        var fields = ['honorificPrefix', 'givenName', 'middleName', 
-                      'familyName', 'honorificSuffix'];
-        var f = '';
-        for (var i = 0; i < fields.length; i++) {
-            if (name[fields[i]]) {
-                if (f) {
-                    f += ' ';
-                }
-                f += name[fields[i]];
-            }
-        }
-        return f;
-    }
-
-
-    if (moz.id) {
-        this.id = moz.id;
-    }
-    var nameFields = [['givenName'], ['familyName'], 
-                       ['honorificPrefix'], ['honorificSuffix'],
-                       ['additionalName', 'middleName']];
-    var baseArrayFields = [['name', 'displayName'], 'nickname', ['note']];
-    var baseStringFields = [];
-    var name = new ContactName();
-    var j = 0; while(field = nameFields[j++]) {
-        if (moz[field[0]]) {
-            name[field[1] || field[0]] = moz[field[0]].join(' ');
-        }
-    }
-    this.name = name;
-    j = 0; while(field = baseArrayFields[j++]) {
-        if (moz[field[0]]) {
-            this[field[1] || field[0]] = moz[field[0]].join(' ');
-        }
-    }
-    j = 0; while(field = baseStringFields[j++]) {
-        if (moz[field[0]]) {
-            this[field[1] || field[0]] = moz[field[0]];
-        }
-    }
-    // emails
-    if (moz.email) {
-        this.emails = exportContactField(moz.email);
-    }
-    // categories
-    if (moz.category) {
-        this.categories = makeContactFieldFromArray(moz.category);
-    }
-
-    // addresses
-    if (moz.adr) {
-        this.addresses = exportAddresses(moz.adr);
-    }
-
-    // phoneNumbers
-    if (moz.tel) {
-        this.phoneNumbers = exportContactField(moz.tel);
-    }
-    // birthday
-    if (moz.bday) {
-      this.birthday = Date.parse(moz.bday);
-    }
-    // organizations
-    if (moz.org || moz.jobTitle) {
-        // XXX: organizations array is created from org and jobTitle
-        this.organizations = createOrganizations(moz.org, moz.jobTitle);
-    }
-    // construct a read-only formatted value
-    this.name.formatted = createFormatted(this.name);
-
-    /*  Find out how to translate these parameters
-        // photo: Blob
-        // url: Array with metadata (?)
-        // impp: exportIM(contact.ims), TODO: find the moz impp definition
-        // anniversary
-        // sex
-        // genderIdentity
-        // key
-    */
-}
-
-
-function createMozillaFromCordova(successCB, errorCB, contact) {
-    var moz;
-    // get contact if exists
-    if (_hasId(contact.id)) {
-      var search = navigator.mozContacts.find({
-        filterBy: ['id'], filterValue: contact.id, filterOp: 'equals'});
-      search.onsuccess = function() {
-        moz = search.result[0];
-        updateFromCordova(moz, contact);
-        successCB(moz);
-      };
-      search.onerror = errorCB;
-      return;
-    }
-
-    // create empty contact
-    moz = new mozContact();
-    // if ('init' in moz) {
-      // 1.2 and below compatibility
-      // moz.init();
-    // }
-    updateFromCordova(moz, contact);
-    successCB(moz);
-}
-
-
-function createCordovaFromMozilla(moz) {
-    var contact = new Contact();
-    contact.updateFromMozilla(moz);
-    return contact;
-}
-
-
-// However API requires the ability to save multiple contacts, it is 
-// used to save only one element array
-function saveContacts(successCB, errorCB, contacts) {
-    // a closure which is holding the right moz contact
-    function makeSaveSuccessCB(moz) {
-        return function(result) {
-            // create contact from FXOS contact (might be different than
-            // the original one due to differences in API)
-            var contact = createCordovaFromMozilla(moz);
-            // call callback
-            successCB(contact);
-        }
-    }
-    var i=0;
-    var contact;
-    while(contact = contacts[i++]){
-        var moz = createMozillaFromCordova(function(moz) {
-          var request = navigator.mozContacts.save(moz);
-          // success and/or fail will be called every time a contact is saved
-          request.onsuccess = makeSaveSuccessCB(moz);
-          request.onerror = errorCB;                
-        }, function() {}, contact);
-    }
-}   
-
-
-// API provides a list of ids to be removed
-function remove(successCB, errorCB, ids) {
-    var i=0;
-    var id;
-    for (var i=0; i < ids.length; i++){
-        // throw an error if no id provided
-        if (!_hasId(ids[i])) {
-            console.error('FFOS: Attempt to remove unsaved contact');
-            errorCB(0);
-            return;
-        }
-        // check if provided id actually exists 
-        var search = navigator.mozContacts.find({
-            filterBy: ['id'], filterValue: ids[i], filterOp: 'equals'});
-        search.onsuccess = function() {
-            if (search.result.length === 0) {
-                console.error('FFOS: Attempt to remove a non existing contact');
-                errorCB(0);
-                return;
-            }
-            var moz = search.result[0];
-            var request = navigator.mozContacts.remove(moz);
-            request.onsuccess = successCB;
-            request.onerror = errorCB;
-        };
-        search.onerror = errorCB;
-    }
-}
-
-
-var mozContactSearchFields = [['name', 'displayName'], ['givenName'], 
-    ['familyName'], ['email'], ['tel'], ['jobTitle'], ['note'], 
-    ['tel', 'phoneNumbers'], ['email', 'emails']]; 
-// Searching by nickname and additionalName is forbidden in  1.3 and below
-// Searching by name is forbidden in 1.2 and below
-
-// finds if a key is allowed and returns FFOS name if different
-function getMozSearchField(key) {
-    if (mozContactSearchFields.indexOf([key]) >= 0) {
-        return key;
-    }
-    for (var i=0; i < mozContactSearchFields.length; i++) {
-        if (mozContactSearchFields[i].length > 1) {
-            if (mozContactSearchFields[i][1] === key) {
-                return mozContactSearchFields[i][0];
-            }
-        }
-    }
-    return false;
-}
-
-
-function _getAll(successCB, errorCB, params) {
-    // [contactField, eventualMozContactField]
-    var getall = navigator.mozContacts.getAll({});
-    var contacts = [];
-
-    getall.onsuccess = function() {
-        if (getall.result) {
-            contacts.push(createCordovaFromMozilla(getall.result));
-            getall.continue();
-        } else {
-            successCB(contacts);
-        }
-    };
-    getall.onerror = errorCB;
-}
-
-
-function search(successCB, errorCB, params) {
-    var options = params[1] || {}; 
-    if (!options.filter) {
-        return _getAll(successCB, errorCB, params);
-    }
-    var filterBy = [];
-    // filter and translate fields
-    for (var i=0; i < params[0].length; i++) {
-        var searchField = params[0][i];
-        var mozField = getMozSearchField(searchField);
-        if (searchField === 'name') {
-            // Cordova uses name for search by all name fields.
-            filterBy.push('givenName');
-            filterBy.push('familyName');
-            continue;
-        } 
-        if (searchField === 'displayName' && 'init' in new mozContact()) {
-            // ``init`` in ``mozContact`` indicates FFOS version 1.2 or below
-            // Searching by name (in moz) is then forbidden
-            console.log('FFOS ContactProxy: Unable to search by displayName on FFOS 1.2');
-            continue;
-        } 
-        if (mozField) {
-            filterBy.push(mozField);
-        } else {
-            console.log('FXOS ContactProxy: inallowed field passed to search filtered out: ' + searchField);
-        }
-    }
-
-    var mozOptions = {filterBy: filterBy, filterOp: 'startsWith'};
-    if (!options.multiple) {
-        mozOptions.filterLimit = 1;
-    }
-    mozOptions.filterValue = options.filter;
-    var request = navigator.mozContacts.find(mozOptions);
-    request.onsuccess = function() {
-        var contacts = [];
-        var mozContacts = request.result;
-        var moz = mozContacts[0];
-        for (var i=0; i < mozContacts.length; i++) {
-            contacts.push(createCordovaFromMozilla(mozContacts[i]));
-        }
-        successCB(contacts);
-    };
-    request.onerror = errorCB;
-}
-
-
-module.exports = {
-    save: saveContacts,
-    remove: remove,
-    search: search
-};    
-    
-require("cordova/firefoxos/commandProxy").add("Contacts", module.exports);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/ios/CDVContact.h
----------------------------------------------------------------------
diff --git a/src/ios/CDVContact.h b/src/ios/CDVContact.h
deleted file mode 100644
index 5187efc..0000000
--- a/src/ios/CDVContact.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
-#import <Foundation/Foundation.h>
-#import <AddressBook/ABAddressBook.h>
-#import <AddressBookUI/AddressBookUI.h>
-
-enum CDVContactError {
-    UNKNOWN_ERROR = 0,
-    INVALID_ARGUMENT_ERROR = 1,
-    TIMEOUT_ERROR = 2,
-    PENDING_OPERATION_ERROR = 3,
-    IO_ERROR = 4,
-    NOT_SUPPORTED_ERROR = 5,
-    PERMISSION_DENIED_ERROR = 20
-};
-typedef NSUInteger CDVContactError;
-
-@interface CDVContact : NSObject {
-    ABRecordRef record;         // the ABRecord associated with this contact
-    NSDictionary* returnFields; // dictionary of fields to return when performing search
-}
-
-@property (nonatomic, assign) ABRecordRef record;
-@property (nonatomic, strong) NSDictionary* returnFields;
-
-+ (NSDictionary*)defaultABtoW3C;
-+ (NSDictionary*)defaultW3CtoAB;
-+ (NSSet*)defaultW3CtoNull;
-+ (NSDictionary*)defaultObjectAndProperties;
-+ (NSDictionary*)defaultFields;
-
-+ (NSDictionary*)calcReturnFields:(NSArray*)fields;
-- (id)init;
-- (id)initFromABRecord:(ABRecordRef)aRecord;
-- (bool)setFromContactDict:(NSDictionary*)aContact asUpdate:(BOOL)bUpdate;
-
-+ (BOOL)needsConversion:(NSString*)W3Label;
-+ (CFStringRef)convertContactTypeToPropertyLabel:(NSString*)label;
-+ (NSString*)convertPropertyLabelToContactType:(NSString*)label;
-+ (BOOL)isValidW3ContactType:(NSString*)label;
-- (bool)setValue:(id)aValue forProperty:(ABPropertyID)aProperty inRecord:(ABRecordRef)aRecord asUpdate:(BOOL)bUpdate;
-
-- (NSDictionary*)toDictionary:(NSDictionary*)withFields;
-- (NSNumber*)getDateAsNumber:(ABPropertyID)datePropId;
-- (NSObject*)extractName;
-- (NSObject*)extractMultiValue:(NSString*)propertyId;
-- (NSObject*)extractAddresses;
-- (NSObject*)extractIms;
-- (NSObject*)extractOrganizations;
-- (NSObject*)extractPhotos;
-
-- (NSMutableDictionary*)translateW3Dict:(NSDictionary*)dict forProperty:(ABPropertyID)prop;
-- (bool)setMultiValueStrings:(NSArray*)fieldArray forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person asUpdate:(BOOL)bUpdate;
-- (bool)setMultiValueDictionary:(NSArray*)array forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person asUpdate:(BOOL)bUpdate;
-- (ABMultiValueRef)allocStringMultiValueFromArray:array;
-- (ABMultiValueRef)allocDictMultiValueFromArray:array forProperty:(ABPropertyID)prop;
-- (BOOL)foundValue:(NSString*)testValue inFields:(NSDictionary*)searchFields;
-- (BOOL)testStringValue:(NSString*)testValue forW3CProperty:(NSString*)property;
-- (BOOL)testDateValue:(NSString*)testValue forW3CProperty:(NSString*)property;
-- (BOOL)searchContactFields:(NSArray*)fields forMVStringProperty:(ABPropertyID)propId withValue:testValue;
-- (BOOL)testMultiValueStrings:(NSString*)testValue forProperty:(ABPropertyID)propId ofType:(NSString*)type;
-- (NSArray*)valuesForProperty:(ABPropertyID)propId inRecord:(ABRecordRef)aRecord;
-- (NSArray*)labelsForProperty:(ABPropertyID)propId inRecord:(ABRecordRef)aRecord;
-- (BOOL)searchContactFields:(NSArray*)fields forMVDictionaryProperty:(ABPropertyID)propId withValue:(NSString*)testValue;
-
-@end
-
-// generic ContactField types
-#define kW3ContactFieldType @"type"
-#define kW3ContactFieldValue @"value"
-#define kW3ContactFieldPrimary @"pref"
-// Various labels for ContactField types
-#define kW3ContactWorkLabel @"work"
-#define kW3ContactHomeLabel @"home"
-#define kW3ContactOtherLabel @"other"
-#define kW3ContactPhoneFaxLabel @"fax"
-#define kW3ContactPhoneMobileLabel @"mobile"
-#define kW3ContactPhonePagerLabel @"pager"
-#define kW3ContactUrlBlog @"blog"
-#define kW3ContactUrlProfile @"profile"
-#define kW3ContactImAIMLabel @"aim"
-#define kW3ContactImICQLabel @"icq"
-#define kW3ContactImMSNLabel @"msn"
-#define kW3ContactImYahooLabel @"yahoo"
-#define kW3ContactFieldId @"id"
-// special translation for IM field value and type
-#define kW3ContactImType @"type"
-#define kW3ContactImValue @"value"
-
-// Contact object
-#define kW3ContactId @"id"
-#define kW3ContactName @"name"
-#define kW3ContactFormattedName @"formatted"
-#define kW3ContactGivenName @"givenName"
-#define kW3ContactFamilyName @"familyName"
-#define kW3ContactMiddleName @"middleName"
-#define kW3ContactHonorificPrefix @"honorificPrefix"
-#define kW3ContactHonorificSuffix @"honorificSuffix"
-#define kW3ContactDisplayName @"displayName"
-#define kW3ContactNickname @"nickname"
-#define kW3ContactPhoneNumbers @"phoneNumbers"
-#define kW3ContactAddresses @"addresses"
-#define kW3ContactAddressFormatted @"formatted"
-#define kW3ContactStreetAddress @"streetAddress"
-#define kW3ContactLocality @"locality"
-#define kW3ContactRegion @"region"
-#define kW3ContactPostalCode @"postalCode"
-#define kW3ContactCountry @"country"
-#define kW3ContactEmails @"emails"
-#define kW3ContactIms @"ims"
-#define kW3ContactOrganizations @"organizations"
-#define kW3ContactOrganizationName @"name"
-#define kW3ContactTitle @"title"
-#define kW3ContactDepartment @"department"
-#define kW3ContactBirthday @"birthday"
-#define kW3ContactNote @"note"
-#define kW3ContactPhotos @"photos"
-#define kW3ContactCategories @"categories"
-#define kW3ContactUrls @"urls"


[3/6] CB-6521: Remove development branch

Posted by ia...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/ios/CDVContact.m
----------------------------------------------------------------------
diff --git a/src/ios/CDVContact.m b/src/ios/CDVContact.m
deleted file mode 100644
index 5bf9f3c..0000000
--- a/src/ios/CDVContact.m
+++ /dev/null
@@ -1,1752 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
-#import "CDVContact.h"
-#import <Cordova/NSDictionary+Extensions.h>
-
-#define DATE_OR_NULL(dateObj) ((aDate != nil) ? (id)([aDate descriptionWithLocale:[NSLocale currentLocale]]) : (id)([NSNull null]))
-#define IS_VALID_VALUE(value) ((value != nil) && (![value isKindOfClass:[NSNull class]]))
-
-static NSDictionary* org_apache_cordova_contacts_W3CtoAB = nil;
-static NSDictionary* org_apache_cordova_contacts_ABtoW3C = nil;
-static NSSet* org_apache_cordova_contacts_W3CtoNull = nil;
-static NSDictionary* org_apache_cordova_contacts_objectAndProperties = nil;
-static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
-
-@implementation CDVContact : NSObject
-
-                             @synthesize returnFields;
-
-- (id)init
-{
-    if ((self = [super init]) != nil) {
-        ABRecordRef rec = ABPersonCreate();
-        self.record = rec;
-        if (rec) {
-            CFRelease(rec);
-        }
-    }
-    return self;
-}
-
-- (id)initFromABRecord:(ABRecordRef)aRecord
-{
-    if ((self = [super init]) != nil) {
-        self.record = aRecord;
-    }
-    return self;
-}
-
-/* synthesize 'record' ourselves to have retain properties for CF types */
-
-- (void)setRecord:(ABRecordRef)aRecord
-{
-    if (record != NULL) {
-        CFRelease(record);
-    }
-    if (aRecord != NULL) {
-        record = CFRetain(aRecord);
-    }
-}
-
-- (ABRecordRef)record
-{
-    return record;
-}
-
-/* Rather than creating getters and setters for each AddressBook (AB) Property, generic methods are used to deal with
- * simple properties,  MultiValue properties( phone numbers and emails) and MultiValueDictionary properties (Ims and addresses).
- * The dictionaries below are used to translate between the W3C identifiers and the AB properties.   Using the dictionaries,
- * allows looping through sets of properties to extract from or set into the W3C dictionary to/from the ABRecord.
- */
-
-/* The two following dictionaries translate between W3C properties and AB properties.  It currently mixes both
- * Properties (kABPersonAddressProperty for example) and Strings (kABPersonAddressStreetKey) so users should be aware of
- * what types of values are expected.
- * a bit.
-*/
-+ (NSDictionary*)defaultABtoW3C
-{
-    if (org_apache_cordova_contacts_ABtoW3C == nil) {
-        org_apache_cordova_contacts_ABtoW3C = [NSDictionary dictionaryWithObjectsAndKeys:
-            kW3ContactNickname, [NSNumber numberWithInt:kABPersonNicknameProperty],
-            kW3ContactGivenName, [NSNumber numberWithInt:kABPersonFirstNameProperty],
-            kW3ContactFamilyName, [NSNumber numberWithInt:kABPersonLastNameProperty],
-            kW3ContactMiddleName, [NSNumber numberWithInt:kABPersonMiddleNameProperty],
-            kW3ContactHonorificPrefix, [NSNumber numberWithInt:kABPersonPrefixProperty],
-            kW3ContactHonorificSuffix, [NSNumber numberWithInt:kABPersonSuffixProperty],
-            kW3ContactPhoneNumbers, [NSNumber numberWithInt:kABPersonPhoneProperty],
-            kW3ContactAddresses, [NSNumber numberWithInt:kABPersonAddressProperty],
-            kW3ContactStreetAddress, kABPersonAddressStreetKey,
-            kW3ContactLocality, kABPersonAddressCityKey,
-            kW3ContactRegion, kABPersonAddressStateKey,
-            kW3ContactPostalCode, kABPersonAddressZIPKey,
-            kW3ContactCountry, kABPersonAddressCountryKey,
-            kW3ContactEmails, [NSNumber numberWithInt:kABPersonEmailProperty],
-            kW3ContactIms, [NSNumber numberWithInt:kABPersonInstantMessageProperty],
-            kW3ContactOrganizations, [NSNumber numberWithInt:kABPersonOrganizationProperty],
-            kW3ContactOrganizationName, [NSNumber numberWithInt:kABPersonOrganizationProperty],
-            kW3ContactTitle, [NSNumber numberWithInt:kABPersonJobTitleProperty],
-            kW3ContactDepartment, [NSNumber numberWithInt:kABPersonDepartmentProperty],
-            kW3ContactBirthday, [NSNumber numberWithInt:kABPersonBirthdayProperty],
-            kW3ContactUrls, [NSNumber numberWithInt:kABPersonURLProperty],
-            kW3ContactNote, [NSNumber numberWithInt:kABPersonNoteProperty],
-            nil];
-    }
-
-    return org_apache_cordova_contacts_ABtoW3C;
-}
-
-+ (NSDictionary*)defaultW3CtoAB
-{
-    if (org_apache_cordova_contacts_W3CtoAB == nil) {
-        org_apache_cordova_contacts_W3CtoAB = [NSDictionary dictionaryWithObjectsAndKeys:
-            [NSNumber numberWithInt:kABPersonNicknameProperty], kW3ContactNickname,
-            [NSNumber numberWithInt:kABPersonFirstNameProperty], kW3ContactGivenName,
-            [NSNumber numberWithInt:kABPersonLastNameProperty], kW3ContactFamilyName,
-            [NSNumber numberWithInt:kABPersonMiddleNameProperty], kW3ContactMiddleName,
-            [NSNumber numberWithInt:kABPersonPrefixProperty], kW3ContactHonorificPrefix,
-            [NSNumber numberWithInt:kABPersonSuffixProperty], kW3ContactHonorificSuffix,
-            [NSNumber numberWithInt:kABPersonPhoneProperty], kW3ContactPhoneNumbers,
-            [NSNumber numberWithInt:kABPersonAddressProperty], kW3ContactAddresses,
-            kABPersonAddressStreetKey, kW3ContactStreetAddress,
-            kABPersonAddressCityKey, kW3ContactLocality,
-            kABPersonAddressStateKey, kW3ContactRegion,
-            kABPersonAddressZIPKey, kW3ContactPostalCode,
-            kABPersonAddressCountryKey, kW3ContactCountry,
-            [NSNumber numberWithInt:kABPersonEmailProperty], kW3ContactEmails,
-            [NSNumber numberWithInt:kABPersonInstantMessageProperty], kW3ContactIms,
-            [NSNumber numberWithInt:kABPersonOrganizationProperty], kW3ContactOrganizations,
-            [NSNumber numberWithInt:kABPersonJobTitleProperty], kW3ContactTitle,
-            [NSNumber numberWithInt:kABPersonDepartmentProperty], kW3ContactDepartment,
-            [NSNumber numberWithInt:kABPersonBirthdayProperty], kW3ContactBirthday,
-            [NSNumber numberWithInt:kABPersonNoteProperty], kW3ContactNote,
-            [NSNumber numberWithInt:kABPersonURLProperty], kW3ContactUrls,
-            kABPersonInstantMessageUsernameKey, kW3ContactImValue,
-            kABPersonInstantMessageServiceKey, kW3ContactImType,
-            [NSNull null], kW3ContactFieldType,     /* include entries in dictionary to indicate ContactField properties */
-            [NSNull null], kW3ContactFieldValue,
-            [NSNull null], kW3ContactFieldPrimary,
-            [NSNull null], kW3ContactFieldId,
-            [NSNumber numberWithInt:kABPersonOrganizationProperty], kW3ContactOrganizationName,      /* careful, name is used multiple times*/
-            nil];
-    }
-    return org_apache_cordova_contacts_W3CtoAB;
-}
-
-+ (NSSet*)defaultW3CtoNull
-{
-    // these are values that have no AddressBook Equivalent OR have not been implemented yet
-    if (org_apache_cordova_contacts_W3CtoNull == nil) {
-        org_apache_cordova_contacts_W3CtoNull = [NSSet setWithObjects:kW3ContactDisplayName,
-            kW3ContactCategories, kW3ContactFormattedName, nil];
-    }
-    return org_apache_cordova_contacts_W3CtoNull;
-}
-
-/*
- *	The objectAndProperties dictionary contains the all of the properties of the W3C Contact Objects specified by the key
- *	Used in calcReturnFields, and various extract<Property> methods
- */
-+ (NSDictionary*)defaultObjectAndProperties
-{
-    if (org_apache_cordova_contacts_objectAndProperties == nil) {
-        org_apache_cordova_contacts_objectAndProperties = [NSDictionary dictionaryWithObjectsAndKeys:
-            [NSArray arrayWithObjects:kW3ContactGivenName, kW3ContactFamilyName,
-            kW3ContactMiddleName, kW3ContactHonorificPrefix, kW3ContactHonorificSuffix, kW3ContactFormattedName, nil], kW3ContactName,
-            [NSArray arrayWithObjects:kW3ContactStreetAddress, kW3ContactLocality, kW3ContactRegion,
-            kW3ContactPostalCode, kW3ContactCountry, /*kW3ContactAddressFormatted,*/ nil], kW3ContactAddresses,
-            [NSArray arrayWithObjects:kW3ContactOrganizationName, kW3ContactTitle, kW3ContactDepartment, nil], kW3ContactOrganizations,
-            [NSArray arrayWithObjects:kW3ContactFieldType, kW3ContactFieldValue, kW3ContactFieldPrimary, nil], kW3ContactPhoneNumbers,
-            [NSArray arrayWithObjects:kW3ContactFieldType, kW3ContactFieldValue, kW3ContactFieldPrimary, nil], kW3ContactEmails,
-            [NSArray arrayWithObjects:kW3ContactFieldType, kW3ContactFieldValue, kW3ContactFieldPrimary, nil], kW3ContactPhotos,
-            [NSArray arrayWithObjects:kW3ContactFieldType, kW3ContactFieldValue, kW3ContactFieldPrimary, nil], kW3ContactUrls,
-            [NSArray arrayWithObjects:kW3ContactImValue, kW3ContactImType, nil], kW3ContactIms,
-            nil];
-    }
-    return org_apache_cordova_contacts_objectAndProperties;
-}
-
-+ (NSDictionary*)defaultFields
-{
-    if (org_apache_cordova_contacts_defaultFields == nil) {
-        org_apache_cordova_contacts_defaultFields = [NSDictionary dictionaryWithObjectsAndKeys:
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactName], kW3ContactName,
-            [NSNull null], kW3ContactNickname,
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactAddresses], kW3ContactAddresses,
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactOrganizations], kW3ContactOrganizations,
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactPhoneNumbers], kW3ContactPhoneNumbers,
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactEmails], kW3ContactEmails,
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactIms], kW3ContactIms,
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactPhotos], kW3ContactPhotos,
-            [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactUrls], kW3ContactUrls,
-            [NSNull null], kW3ContactBirthday,
-            [NSNull null], kW3ContactNote,
-            nil];
-    }
-    return org_apache_cordova_contacts_defaultFields;
-}
-
-/*  Translate W3C Contact data into ABRecordRef
- *
- *	New contact information comes in as a NSMutableDictionary.  All Null entries in Contact object are set
- *	as [NSNull null] in the dictionary when translating from the JSON input string of Contact data. However, if
- *  user did not set a value within a Contact object or sub-object (by not using the object constructor) some data
- *	may not exist.
- *  bUpdate = YES indicates this is a save of an existing record
- */
-- (bool)setFromContactDict:(NSDictionary*)aContact asUpdate:(BOOL)bUpdate
-{
-    if (![aContact isKindOfClass:[NSDictionary class]]) {
-        return FALSE; // can't do anything if no dictionary!
-    }
-
-    ABRecordRef person = self.record;
-    bool bSuccess = TRUE;
-    CFErrorRef error;
-
-    // set name info
-    // iOS doesn't have displayName - might have to pull parts from it to create name
-    bool bName = false;
-    NSDictionary* dict = [aContact valueForKey:kW3ContactName];
-    if ([dict isKindOfClass:[NSDictionary class]]) {
-        bName = true;
-        NSArray* propArray = [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactName];
-
-        for (id i in propArray) {
-            if (![(NSString*)i isEqualToString : kW3ContactFormattedName]) { // kW3ContactFormattedName is generated from ABRecordCopyCompositeName() and can't be set
-                [self setValue:[dict valueForKey:i] forProperty:(ABPropertyID)[(NSNumber*)[[CDVContact defaultW3CtoAB] objectForKey:i] intValue]
-                      inRecord:person asUpdate:bUpdate];
-            }
-        }
-    }
-
-    id nn = [aContact valueForKey:kW3ContactNickname];
-    if (![nn isKindOfClass:[NSNull class]]) {
-        bName = true;
-        [self setValue:nn forProperty:kABPersonNicknameProperty inRecord:person asUpdate:bUpdate];
-    }
-    if (!bName) {
-        // if no name or nickname - try and use displayName as W3Contact must have displayName or ContactName
-        [self setValue:[aContact valueForKey:kW3ContactDisplayName] forProperty:kABPersonNicknameProperty
-              inRecord:person asUpdate:bUpdate];
-    }
-
-    // set phoneNumbers
-    // NSLog(@"setting phoneNumbers");
-    NSArray* array = [aContact valueForKey:kW3ContactPhoneNumbers];
-    if ([array isKindOfClass:[NSArray class]]) {
-        [self setMultiValueStrings:array forProperty:kABPersonPhoneProperty inRecord:person asUpdate:bUpdate];
-    }
-    // set Emails
-    // NSLog(@"setting emails");
-    array = [aContact valueForKey:kW3ContactEmails];
-    if ([array isKindOfClass:[NSArray class]]) {
-        [self setMultiValueStrings:array forProperty:kABPersonEmailProperty inRecord:person asUpdate:bUpdate];
-    }
-    // set Urls
-    // NSLog(@"setting urls");
-    array = [aContact valueForKey:kW3ContactUrls];
-    if ([array isKindOfClass:[NSArray class]]) {
-        [self setMultiValueStrings:array forProperty:kABPersonURLProperty inRecord:person asUpdate:bUpdate];
-    }
-
-    // set multivalue dictionary properties
-    // set addresses:  streetAddress, locality, region, postalCode, country
-    // set ims:  value = username, type = servicetype
-    // iOS addresses and im are a MultiValue Properties with label, value=dictionary of  info, and id
-    // NSLog(@"setting addresses");
-    error = nil;
-    array = [aContact valueForKey:kW3ContactAddresses];
-    if ([array isKindOfClass:[NSArray class]]) {
-        [self setMultiValueDictionary:array forProperty:kABPersonAddressProperty inRecord:person asUpdate:bUpdate];
-    }
-    // ims
-    // NSLog(@"setting ims");
-    array = [aContact valueForKey:kW3ContactIms];
-    if ([array isKindOfClass:[NSArray class]]) {
-        [self setMultiValueDictionary:array forProperty:kABPersonInstantMessageProperty inRecord:person asUpdate:bUpdate];
-    }
-
-    // organizations
-    // W3C ContactOrganization has pref, type, name, title, department
-    // iOS only supports name, title, department
-    // NSLog(@"setting organizations");
-    // TODO this may need work - should Organization information be removed when array is empty??
-    array = [aContact valueForKey:kW3ContactOrganizations];  // iOS only supports one organization - use first one
-    if ([array isKindOfClass:[NSArray class]]) {
-        BOOL bRemove = NO;
-        NSDictionary* dict = nil;
-        if ([array count] > 0) {
-            dict = [array objectAtIndex:0];
-        } else {
-            // remove the organization info entirely
-            bRemove = YES;
-        }
-        if ([dict isKindOfClass:[NSDictionary class]] || (bRemove == YES)) {
-            [self setValue:(bRemove ? @"" : [dict valueForKey:@"name"]) forProperty:kABPersonOrganizationProperty inRecord:person asUpdate:bUpdate];
-            [self setValue:(bRemove ? @"" : [dict valueForKey:kW3ContactTitle]) forProperty:kABPersonJobTitleProperty inRecord:person asUpdate:bUpdate];
-            [self setValue:(bRemove ? @"" : [dict valueForKey:kW3ContactDepartment]) forProperty:kABPersonDepartmentProperty inRecord:person asUpdate:bUpdate];
-        }
-    }
-    // add dates
-    // Dates come in as milliseconds in NSNumber Object
-    id ms = [aContact valueForKey:kW3ContactBirthday];
-    NSDate* aDate = nil;
-    if (ms && [ms isKindOfClass:[NSNumber class]]) {
-        double msValue = [ms doubleValue];
-        msValue = msValue / 1000;
-        aDate = [NSDate dateWithTimeIntervalSince1970:msValue];
-    }
-    if ((aDate != nil) || [ms isKindOfClass:[NSString class]]) {
-        [self setValue:aDate != nil ? aDate:ms forProperty:kABPersonBirthdayProperty inRecord:person asUpdate:bUpdate];
-    }
-    // don't update creation date
-    // modification date will get updated when save
-    // anniversary is removed from W3C Contact api Dec 9, 2010 spec - don't waste time on it yet
-
-    // kABPersonDateProperty
-
-    // kABPersonAnniversaryLabel
-
-    // iOS doesn't have gender - ignore
-    // note
-    [self setValue:[aContact valueForKey:kW3ContactNote] forProperty:kABPersonNoteProperty inRecord:person asUpdate:bUpdate];
-
-    // iOS doesn't have preferredName- ignore
-
-    // photo
-    array = [aContact valueForKey:kW3ContactPhotos];
-    if ([array isKindOfClass:[NSArray class]]) {
-        if (bUpdate && ([array count] == 0)) {
-            // remove photo
-            bSuccess = ABPersonRemoveImageData(person, &error);
-        } else if ([array count] > 0) {
-            NSDictionary* dict = [array objectAtIndex:0]; // currently only support one photo
-            if ([dict isKindOfClass:[NSDictionary class]]) {
-                id value = [dict objectForKey:kW3ContactFieldValue];
-                if ([value isKindOfClass:[NSString class]]) {
-                    if (bUpdate && ([value length] == 0)) {
-                        // remove the current image
-                        bSuccess = ABPersonRemoveImageData(person, &error);
-                    } else {
-                        // use this image
-                        // don't know if string is encoded or not so first unencode it then encode it again
-                        NSString* cleanPath = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
-                        NSURL* photoUrl = [NSURL URLWithString:[cleanPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
-                        // caller is responsible for checking for a connection, if no connection this will fail
-                        NSError* err = nil;
-                        NSData* data = nil;
-                        if (photoUrl) {
-                            data = [NSData dataWithContentsOfURL:photoUrl options:NSDataReadingUncached error:&err];
-                        }
-                        if (data && ([data length] > 0)) {
-                            bSuccess = ABPersonSetImageData(person, (__bridge CFDataRef)data, &error);
-                        }
-                        if (!data || !bSuccess) {
-                            NSLog(@"error setting contact image: %@", (err != nil ? [err localizedDescription] : @""));
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    // TODO WebURLs
-
-    // TODO timezone
-
-    return bSuccess;
-}
-
-/* Set item into an AddressBook Record for the specified property.
- * aValue - the value to set into the address book (code checks for null or [NSNull null]
- * aProperty - AddressBook property ID
- * aRecord - the record to update
- * bUpdate - whether this is a possible update vs a new entry
- * RETURN
- *	true - property was set (or input value as null)
- *	false - property was not set
- */
-- (bool)setValue:(id)aValue forProperty:(ABPropertyID)aProperty inRecord:(ABRecordRef)aRecord asUpdate:(BOOL)bUpdate
-{
-    bool bSuccess = true;  // if property was null, just ignore and return success
-    CFErrorRef error;
-
-    if (aValue && ![aValue isKindOfClass:[NSNull class]]) {
-        if (bUpdate && ([aValue isKindOfClass:[NSString class]] && ([aValue length] == 0))) { // if updating, empty string means to delete
-            aValue = NULL;
-        } // really only need to set if different - more efficient to just update value or compare and only set if necessary???
-        bSuccess = ABRecordSetValue(aRecord, aProperty, (__bridge CFTypeRef)aValue, &error);
-        if (!bSuccess) {
-            NSLog(@"error setting %d property", aProperty);
-        }
-    }
-
-    return bSuccess;
-}
-
-- (bool)removeProperty:(ABPropertyID)aProperty inRecord:(ABRecordRef)aRecord
-{
-    CFErrorRef err;
-    bool bSuccess = ABRecordRemoveValue(aRecord, aProperty, &err);
-
-    if (!bSuccess) {
-        CFStringRef errDescription = CFErrorCopyDescription(err);
-        NSLog(@"Unable to remove property %d: %@", aProperty, errDescription);
-        CFRelease(errDescription);
-    }
-    return bSuccess;
-}
-
-- (bool)addToMultiValue:(ABMultiValueRef)multi fromDictionary:dict
-{
-    bool bSuccess = FALSE;
-    id value = [dict valueForKey:kW3ContactFieldValue];
-
-    if (IS_VALID_VALUE(value)) {
-        CFStringRef label = [CDVContact convertContactTypeToPropertyLabel:[dict valueForKey:kW3ContactFieldType]];
-        bSuccess = ABMultiValueAddValueAndLabel(multi, (__bridge CFTypeRef)value, label, NULL);
-        if (!bSuccess) {
-            NSLog(@"Error setting Value: %@ and label: %@", value, label);
-        }
-    }
-    return bSuccess;
-}
-
-- (ABMultiValueRef)allocStringMultiValueFromArray:array
-{
-    ABMutableMultiValueRef multi = ABMultiValueCreateMutable(kABMultiStringPropertyType);
-
-    for (NSDictionary* dict in array) {
-        [self addToMultiValue:multi fromDictionary:dict];
-    }
-
-    return multi;  // caller is responsible for releasing multi
-}
-
-- (bool)setValue:(CFTypeRef)value forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person
-{
-    CFErrorRef error;
-    bool bSuccess = ABRecordSetValue(person, prop, value, &error);
-
-    if (!bSuccess) {
-        NSLog(@"Error setting value for property: %d", prop);
-    }
-    return bSuccess;
-}
-
-/* Set MultiValue string properties into Address Book Record.
- * NSArray* fieldArray - array of dictionaries containing W3C properties to be set into record
- * ABPropertyID prop - the property to be set (generally used for phones and emails)
- * ABRecordRef  person - the record to set values into
- * BOOL bUpdate - whether or not to update date or set as new.
- *	When updating:
- *	  empty array indicates to remove entire property
- *	  empty string indicates to remove
- *    [NSNull null] do not modify (keep existing record value)
- * RETURNS
- * bool false indicates error
- *
- * used for phones and emails
- */
-- (bool)setMultiValueStrings:(NSArray*)fieldArray forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person asUpdate:(BOOL)bUpdate
-{
-    bool bSuccess = TRUE;
-    ABMutableMultiValueRef multi = nil;
-
-    if (!bUpdate) {
-        multi = [self allocStringMultiValueFromArray:fieldArray];
-        bSuccess = [self setValue:multi forProperty:prop inRecord:person];
-    } else if (bUpdate && ([fieldArray count] == 0)) {
-        // remove entire property
-        bSuccess = [self removeProperty:prop inRecord:person];
-    } else { // check for and apply changes
-        ABMultiValueRef copy = ABRecordCopyValue(person, prop);
-        if (copy != nil) {
-            multi = ABMultiValueCreateMutableCopy(copy);
-            CFRelease(copy);
-
-            for (NSDictionary* dict in fieldArray) {
-                id val;
-                NSString* label = nil;
-                val = [dict valueForKey:kW3ContactFieldValue];
-                label = (__bridge NSString*)[CDVContact convertContactTypeToPropertyLabel:[dict valueForKey:kW3ContactFieldType]];
-                if (IS_VALID_VALUE(val)) {
-                    // is an update,  find index of entry with matching id, if values are different, update.
-                    id idValue = [dict valueForKey:kW3ContactFieldId];
-                    int identifier = [idValue isKindOfClass:[NSNumber class]] ? [idValue intValue] : -1;
-                    CFIndex i = identifier >= 0 ? ABMultiValueGetIndexForIdentifier(multi, identifier) : kCFNotFound;
-                    if (i != kCFNotFound) {
-                        if ([val length] == 0) {
-                            // remove both value and label
-                            ABMultiValueRemoveValueAndLabelAtIndex(multi, i);
-                        } else {
-                            NSString* valueAB = (__bridge_transfer NSString*)ABMultiValueCopyValueAtIndex(multi, i);
-                            NSString* labelAB = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, i);
-                            if ((valueAB == nil) || ![val isEqualToString:valueAB]) {
-                                ABMultiValueReplaceValueAtIndex(multi, (__bridge CFTypeRef)val, i);
-                            }
-                            if ((labelAB == nil) || ![label isEqualToString:labelAB]) {
-                                ABMultiValueReplaceLabelAtIndex(multi, (__bridge CFStringRef)label, i);
-                            }
-                        }
-                    } else {
-                        // is a new value - insert
-                        [self addToMultiValue:multi fromDictionary:dict];
-                    }
-                } // end of if value
-            } // end of for
-        } else { // adding all new value(s)
-            multi = [self allocStringMultiValueFromArray:fieldArray];
-        }
-        // set the (updated) copy as the new value
-        bSuccess = [self setValue:multi forProperty:prop inRecord:person];
-    }
-
-    if (multi) {
-        CFRelease(multi);
-    }
-
-    return bSuccess;
-}
-
-// used for ims and addresses
-- (ABMultiValueRef)allocDictMultiValueFromArray:array forProperty:(ABPropertyID)prop
-{
-    ABMutableMultiValueRef multi = ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);
-    NSMutableDictionary* newDict;
-    NSMutableDictionary* addDict;
-
-    for (NSDictionary* dict in array) {
-        newDict = [self translateW3Dict:dict forProperty:prop];
-        addDict = [NSMutableDictionary dictionaryWithCapacity:2];
-        if (newDict) { // create a new dictionary with a Label and Value, value is the dictionary previously created
-            // June, 2011 W3C Contact spec adds type into ContactAddress book
-            // get the type out of the original dictionary for address
-            NSString* addrType = (NSString*)[dict valueForKey:kW3ContactFieldType];
-            if (!addrType) {
-                addrType = (NSString*)kABOtherLabel;
-            }
-            NSObject* typeValue = ((prop == kABPersonInstantMessageProperty) ? (NSObject*)kABOtherLabel : addrType);
-            // NSLog(@"typeValue: %@", typeValue);
-            [addDict setObject:typeValue forKey:kW3ContactFieldType];    //  im labels will be set as Other and address labels as type from dictionary
-            [addDict setObject:newDict forKey:kW3ContactFieldValue];
-            [self addToMultiValue:multi fromDictionary:addDict];
-        }
-    }
-
-    return multi; // caller is responsible for releasing
-}
-
-// used for ims and addresses to convert W3 dictionary of values to AB Dictionary
-// got messier when June, 2011 W3C Contact spec added type field into ContactAddress
-- (NSMutableDictionary*)translateW3Dict:(NSDictionary*)dict forProperty:(ABPropertyID)prop
-{
-    NSArray* propArray = [[CDVContact defaultObjectAndProperties] valueForKey:[[CDVContact defaultABtoW3C] objectForKey:[NSNumber numberWithInt:prop]]];
-
-    NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:1];
-    id value;
-
-    for (NSString* key in propArray) { // for each W3 Contact key get the value
-        if (((value = [dict valueForKey:key]) != nil) && ![value isKindOfClass:[NSNull class]]) {
-            // if necessary convert the W3 value to AB Property label
-            NSString* setValue = value;
-            if ([CDVContact needsConversion:key]) { // IM types must be converted
-                setValue = (NSString*)[CDVContact convertContactTypeToPropertyLabel:value];
-                // IMs must have a valid AB value!
-                if ((prop == kABPersonInstantMessageProperty) && [setValue isEqualToString:(NSString*)kABOtherLabel]) {
-                    setValue = @""; // try empty string
-                }
-            }
-            // set the AB value into the dictionary
-            [newDict setObject:setValue forKey:(NSString*)[[CDVContact defaultW3CtoAB] valueForKey:(NSString*)key]];
-        }
-    }
-
-    if ([newDict count] == 0) {
-        newDict = nil; // no items added
-    }
-    return newDict;
-}
-
-/* set multivalue dictionary properties into an AddressBook Record
- * NSArray* array - array of dictionaries containing the W3C properties to set into the record
- * ABPropertyID prop - the property id for the multivalue dictionary (addresses and ims)
- * ABRecordRef person - the record to set the values into
- * BOOL bUpdate - YES if this is an update to an existing record
- *	When updating:
- *	  empty array indicates to remove entire property
- *	  value/label == "" indicates to remove
- *    value/label == [NSNull null] do not modify (keep existing record value)
- * RETURN
- *   bool false indicates fatal error
- *
- *  iOS addresses and im are a MultiValue Properties with label, value=dictionary of  info, and id
- *  set addresses:  streetAddress, locality, region, postalCode, country
- *  set ims:  value = username, type = servicetype
- *  there are some special cases in here for ims - needs cleanup / simplification
- *
- */
-- (bool)setMultiValueDictionary:(NSArray*)array forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person asUpdate:(BOOL)bUpdate
-{
-    bool bSuccess = FALSE;
-    ABMutableMultiValueRef multi = nil;
-
-    if (!bUpdate) {
-        multi = [self allocDictMultiValueFromArray:array forProperty:prop];
-        bSuccess = [self setValue:multi forProperty:prop inRecord:person];
-    } else if (bUpdate && ([array count] == 0)) {
-        // remove property
-        bSuccess = [self removeProperty:prop inRecord:person];
-    } else { // check for and apply changes
-        ABMultiValueRef copy = ABRecordCopyValue(person, prop);
-        if (copy) {
-            multi = ABMultiValueCreateMutableCopy(copy);
-            CFRelease(copy);
-            // get the W3C values for this property
-            NSArray* propArray = [[CDVContact defaultObjectAndProperties] valueForKey:[[CDVContact defaultABtoW3C] objectForKey:[NSNumber numberWithInt:prop]]];
-            id value;
-            id valueAB;
-
-            for (NSDictionary* field in array) {
-                NSMutableDictionary* dict;
-                // find the index for the current property
-                id idValue = [field valueForKey:kW3ContactFieldId];
-                int identifier = [idValue isKindOfClass:[NSNumber class]] ? [idValue intValue] : -1;
-                CFIndex idx = identifier >= 0 ? ABMultiValueGetIndexForIdentifier(multi, identifier) : kCFNotFound;
-                BOOL bUpdateLabel = NO;
-                if (idx != kCFNotFound) {
-                    dict = [NSMutableDictionary dictionaryWithCapacity:1];
-                    // NSDictionary* existingDictionary = (NSDictionary*)ABMultiValueCopyValueAtIndex(multi, idx);
-                    CFTypeRef existingDictionary = ABMultiValueCopyValueAtIndex(multi, idx);
-                    NSString* existingABLabel = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, idx);
-                    NSString* testLabel = [field valueForKey:kW3ContactFieldType];
-                    // fixes cb-143 where setting empty label could cause address to not be removed
-                    //   (because empty label would become 'other'  in convertContactTypeToPropertyLabel
-                    //   which may not have matched existing label thus resulting in an incorrect updating of the label
-                    //   and the address not getting removed at the end of the for loop)
-                    if (testLabel && [testLabel isKindOfClass:[NSString class]] && ([testLabel length] > 0)) {
-                        CFStringRef w3cLabel = [CDVContact convertContactTypeToPropertyLabel:testLabel];
-                        if (w3cLabel && ![existingABLabel isEqualToString:(__bridge NSString*)w3cLabel]) {
-                            // replace the label
-                            ABMultiValueReplaceLabelAtIndex(multi, w3cLabel, idx);
-                            bUpdateLabel = YES;
-                        }
-                    } // else was invalid or empty label string so do not update
-
-                    for (id k in propArray) {
-                        value = [field valueForKey:k];
-                        bool bSet = (value != nil && ![value isKindOfClass:[NSNull class]] && ([value isKindOfClass:[NSString class]] && [value length] > 0));
-                        // if there is a contact value, put it into dictionary
-                        if (bSet) {
-                            NSString* setValue = [CDVContact needsConversion:(NSString*)k] ? (NSString*)[CDVContact convertContactTypeToPropertyLabel:value] : value;
-                            [dict setObject:setValue forKey:(NSString*)[[CDVContact defaultW3CtoAB] valueForKey:(NSString*)k]];
-                        } else if ((value == nil) || ([value isKindOfClass:[NSString class]] && ([value length] != 0))) {
-                            // value not provided in contact dictionary - if prop exists in AB dictionary, preserve it
-                            valueAB = [(__bridge NSDictionary*)existingDictionary valueForKey : [[CDVContact defaultW3CtoAB] valueForKey:k]];
-                            if (valueAB != nil) {
-                                [dict setValue:valueAB forKey:[[CDVContact defaultW3CtoAB] valueForKey:k]];
-                            }
-                        } // else if value == "" it will not be added into updated dict and thus removed
-                    } // end of for loop (moving here fixes cb-143, need to end for loop before replacing or removing multivalue)
-
-                    if ([dict count] > 0) {
-                        // something was added into new dict,
-                        ABMultiValueReplaceValueAtIndex(multi, (__bridge CFTypeRef)dict, idx);
-                    } else if (!bUpdateLabel) {
-                        // nothing added into new dict and no label change so remove this property entry
-                        ABMultiValueRemoveValueAndLabelAtIndex(multi, idx);
-                    }
-
-                    CFRelease(existingDictionary);
-                } else {
-                    // not found in multivalue so add it
-                    dict = [self translateW3Dict:field forProperty:prop];
-                    if (dict) {
-                        NSMutableDictionary* addDict = [NSMutableDictionary dictionaryWithCapacity:2];
-                        // get the type out of the original dictionary for address
-                        NSObject* typeValue = ((prop == kABPersonInstantMessageProperty) ? (NSObject*)kABOtherLabel : (NSString*)[field valueForKey:kW3ContactFieldType]);
-                        // NSLog(@"typeValue: %@", typeValue);
-                        [addDict setObject:typeValue forKey:kW3ContactFieldType];        //  im labels will be set as Other and address labels as type from dictionary
-                        [addDict setObject:dict forKey:kW3ContactFieldValue];
-                        [self addToMultiValue:multi fromDictionary:addDict];
-                    }
-                }
-            } // end of looping through dictionaries
-
-            // set the (updated) copy as the new value
-            bSuccess = [self setValue:multi forProperty:prop inRecord:person];
-        }
-    } // end of copy and apply changes
-    if (multi) {
-        CFRelease(multi);
-    }
-
-    return bSuccess;
-}
-
-/* Determine which W3C labels need to be converted
- */
-+ (BOOL)needsConversion:(NSString*)W3Label
-{
-    BOOL bConvert = NO;
-
-    if ([W3Label isEqualToString:kW3ContactFieldType] || [W3Label isEqualToString:kW3ContactImType]) {
-        bConvert = YES;
-    }
-    return bConvert;
-}
-
-/* Translation of property type labels  contact API ---> iPhone
- *
- *	phone:  work, home, other, mobile, fax, pager -->
- *		kABWorkLabel, kABHomeLabel, kABOtherLabel, kABPersonPhoneMobileLabel, kABPersonHomeFAXLabel || kABPersonHomeFAXLabel, kABPersonPhonePagerLabel
- *	emails:  work, home, other ---> kABWorkLabel, kABHomeLabel, kABOtherLabel
- *	ims: aim, gtalk, icq, xmpp, msn, skype, qq, yahoo --> kABPersonInstantMessageService + (AIM, ICG, MSN, Yahoo).  No support for gtalk, xmpp, skype, qq
- * addresses: work, home, other --> kABWorkLabel, kABHomeLabel, kABOtherLabel
- *
- *
- */
-+ (CFStringRef)convertContactTypeToPropertyLabel:(NSString*)label
-{
-    CFStringRef type;
-
-    if ([label isKindOfClass:[NSNull class]] || ![label isKindOfClass:[NSString class]]) {
-        type = NULL; // no label
-    } else if ([label caseInsensitiveCompare:kW3ContactWorkLabel] == NSOrderedSame) {
-        type = kABWorkLabel;
-    } else if ([label caseInsensitiveCompare:kW3ContactHomeLabel] == NSOrderedSame) {
-        type = kABHomeLabel;
-    } else if ([label caseInsensitiveCompare:kW3ContactOtherLabel] == NSOrderedSame) {
-        type = kABOtherLabel;
-    } else if ([label caseInsensitiveCompare:kW3ContactPhoneMobileLabel] == NSOrderedSame) {
-        type = kABPersonPhoneMobileLabel;
-    } else if ([label caseInsensitiveCompare:kW3ContactPhonePagerLabel] == NSOrderedSame) {
-        type = kABPersonPhonePagerLabel;
-    } else if ([label caseInsensitiveCompare:kW3ContactImAIMLabel] == NSOrderedSame) {
-        type = kABPersonInstantMessageServiceAIM;
-    } else if ([label caseInsensitiveCompare:kW3ContactImICQLabel] == NSOrderedSame) {
-        type = kABPersonInstantMessageServiceICQ;
-    } else if ([label caseInsensitiveCompare:kW3ContactImMSNLabel] == NSOrderedSame) {
-        type = kABPersonInstantMessageServiceMSN;
-    } else if ([label caseInsensitiveCompare:kW3ContactImYahooLabel] == NSOrderedSame) {
-        type = kABPersonInstantMessageServiceYahoo;
-    } else if ([label caseInsensitiveCompare:kW3ContactUrlProfile] == NSOrderedSame) {
-        type = kABPersonHomePageLabel;
-    } else {
-        type = kABOtherLabel;
-    }
-
-    return type;
-}
-
-+ (NSString*)convertPropertyLabelToContactType:(NSString*)label
-{
-    NSString* type = nil;
-
-    if (label != nil) { // improve efficiency......
-        if ([label isEqualToString:(NSString*)kABPersonPhoneMobileLabel]) {
-            type = kW3ContactPhoneMobileLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonPhoneHomeFAXLabel] ||
-            [label isEqualToString:(NSString*)kABPersonPhoneWorkFAXLabel]) {
-            type = kW3ContactPhoneFaxLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonPhonePagerLabel]) {
-            type = kW3ContactPhonePagerLabel;
-        } else if ([label isEqualToString:(NSString*)kABHomeLabel]) {
-            type = kW3ContactHomeLabel;
-        } else if ([label isEqualToString:(NSString*)kABWorkLabel]) {
-            type = kW3ContactWorkLabel;
-        } else if ([label isEqualToString:(NSString*)kABOtherLabel]) {
-            type = kW3ContactOtherLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceAIM]) {
-            type = kW3ContactImAIMLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceICQ]) {
-            type = kW3ContactImICQLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceJabber]) {
-            type = kW3ContactOtherLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceMSN]) {
-            type = kW3ContactImMSNLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceYahoo]) {
-            type = kW3ContactImYahooLabel;
-        } else if ([label isEqualToString:(NSString*)kABPersonHomePageLabel]) {
-            type = kW3ContactUrlProfile;
-        } else {
-            type = kW3ContactOtherLabel;
-        }
-    }
-    return type;
-}
-
-/* Check if the input label is a valid W3C ContactField.type. This is used when searching,
- * only search field types if the search string is a valid type.  If we converted any search
- * string to a ABPropertyLabel it could convert to kABOtherLabel which is probably not want
- * the user wanted to search for and could skew the results.
- */
-+ (BOOL)isValidW3ContactType:(NSString*)label
-{
-    BOOL isValid = NO;
-
-    if ([label isKindOfClass:[NSNull class]] || ![label isKindOfClass:[NSString class]]) {
-        isValid = NO; // no label
-    } else if ([label caseInsensitiveCompare:kW3ContactWorkLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactHomeLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactOtherLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactPhoneMobileLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactPhonePagerLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactImAIMLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactImICQLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactImMSNLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else if ([label caseInsensitiveCompare:kW3ContactImYahooLabel] == NSOrderedSame) {
-        isValid = YES;
-    } else {
-        isValid = NO;
-    }
-
-    return isValid;
-}
-
-/* Create a new Contact Dictionary object from an ABRecordRef that contains information in a format such that
- * it can be returned to JavaScript callback as JSON object string.
- * Uses:
- * ABRecordRef set into Contact Object
- * NSDictionary withFields indicates which fields to return from the AddressBook Record
- *
- * JavaScript Contact:
- * @param {DOMString} id unique identifier
- * @param {DOMString} displayName
- * @param {ContactName} name
- * @param {DOMString} nickname
- * @param {ContactField[]} phoneNumbers array of phone numbers
- * @param {ContactField[]} emails array of email addresses
- * @param {ContactAddress[]} addresses array of addresses
- * @param {ContactField[]} ims instant messaging user ids
- * @param {ContactOrganization[]} organizations
- * @param {DOMString} published date contact was first created
- * @param {DOMString} updated date contact was last updated
- * @param {DOMString} birthday contact's birthday
- * @param (DOMString} anniversary contact's anniversary
- * @param {DOMString} gender contact's gender
- * @param {DOMString} note user notes about contact
- * @param {DOMString} preferredUsername
- * @param {ContactField[]} photos
- * @param {ContactField[]} tags
- * @param {ContactField[]} relationships
- * @param {ContactField[]} urls contact's web sites
- * @param {ContactAccounts[]} accounts contact's online accounts
- * @param {DOMString} timezone UTC time zone offset
- * @param {DOMString} connected
- */
-
-- (NSDictionary*)toDictionary:(NSDictionary*)withFields
-{
-    // if not a person type record bail out for now
-    if (ABRecordGetRecordType(self.record) != kABPersonType) {
-        return NULL;
-    }
-    id value = nil;
-    self.returnFields = withFields;
-
-    NSMutableDictionary* nc = [NSMutableDictionary dictionaryWithCapacity:1];  // new contact dictionary to fill in from ABRecordRef
-    // id
-    [nc setObject:[NSNumber numberWithInt:ABRecordGetRecordID(self.record)] forKey:kW3ContactId];
-    if (self.returnFields == nil) {
-        // if no returnFields specified, W3C says to return empty contact (but Cordova will at least return id)
-        return nc;
-    }
-    if ([self.returnFields objectForKey:kW3ContactDisplayName]) {
-        // displayname requested -  iOS doesn't have so return null
-        [nc setObject:[NSNull null] forKey:kW3ContactDisplayName];
-        // may overwrite below if requested ContactName and there are no values
-    }
-    // nickname
-    if ([self.returnFields valueForKey:kW3ContactNickname]) {
-        value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, kABPersonNicknameProperty);
-        [nc setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactNickname];
-    }
-
-    // name dictionary
-    // NSLog(@"getting name info");
-    NSObject* data = [self extractName];
-    if (data != nil) {
-        [nc setObject:data forKey:kW3ContactName];
-    }
-    if ([self.returnFields objectForKey:kW3ContactDisplayName] && ((data == nil) || ([(NSDictionary*)data objectForKey : kW3ContactFormattedName] == [NSNull null]))) {
-        // user asked for displayName which iOS doesn't support but there is no other name data being returned
-        // try and use Composite Name so some name is returned
-        id tryName = (__bridge_transfer NSString*)ABRecordCopyCompositeName(self.record);
-        if (tryName != nil) {
-            [nc setObject:tryName forKey:kW3ContactDisplayName];
-        } else {
-            // use nickname or empty string
-            value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, kABPersonNicknameProperty);
-            [nc setObject:(value != nil) ? value:@"" forKey:kW3ContactDisplayName];
-        }
-    }
-    // phoneNumbers array
-    // NSLog(@"getting phoneNumbers");
-    value = [self extractMultiValue:kW3ContactPhoneNumbers];
-    if (value != nil) {
-        [nc setObject:value forKey:kW3ContactPhoneNumbers];
-    }
-    // emails array
-    // NSLog(@"getting emails");
-    value = [self extractMultiValue:kW3ContactEmails];
-    if (value != nil) {
-        [nc setObject:value forKey:kW3ContactEmails];
-    }
-    // urls array
-    value = [self extractMultiValue:kW3ContactUrls];
-    if (value != nil) {
-        [nc setObject:value forKey:kW3ContactUrls];
-    }
-    // addresses array
-    // NSLog(@"getting addresses");
-    value = [self extractAddresses];
-    if (value != nil) {
-        [nc setObject:value forKey:kW3ContactAddresses];
-    }
-    // im array
-    // NSLog(@"getting ims");
-    value = [self extractIms];
-    if (value != nil) {
-        [nc setObject:value forKey:kW3ContactIms];
-    }
-    // organization array (only info for one organization in iOS)
-    // NSLog(@"getting organizations");
-    value = [self extractOrganizations];
-    if (value != nil) {
-        [nc setObject:value forKey:kW3ContactOrganizations];
-    }
-
-    // for simple properties, could make this a bit more efficient by storing all simple properties in a single
-    // array in the returnFields dictionary and setting them via a for loop through the array
-
-    // add dates
-    // NSLog(@"getting dates");
-    NSNumber* ms;
-
-    /** Contact Revision field removed from June 16, 2011 version of specification
-
-    if ([self.returnFields valueForKey:kW3ContactUpdated]){
-        ms = [self getDateAsNumber: kABPersonModificationDateProperty];
-        if (!ms){
-            // try and get published date
-            ms = [self getDateAsNumber: kABPersonCreationDateProperty];
-        }
-        if (ms){
-            [nc setObject:  ms forKey:kW3ContactUpdated];
-        }
-
-    }
-    */
-
-    if ([self.returnFields valueForKey:kW3ContactBirthday]) {
-        ms = [self getDateAsNumber:kABPersonBirthdayProperty];
-        if (ms) {
-            [nc setObject:ms forKey:kW3ContactBirthday];
-        }
-    }
-
-    /*  Anniversary removed from 12-09-2010 W3C Contacts api spec
-     if ([self.returnFields valueForKey:kW3ContactAnniversary]){
-        // Anniversary date is stored in a multivalue property
-        ABMultiValueRef multi = ABRecordCopyValue(self.record, kABPersonDateProperty);
-        if (multi){
-            CFStringRef label = nil;
-            CFIndex count = ABMultiValueGetCount(multi);
-            // see if contains an Anniversary date
-            for(CFIndex i=0; i<count; i++){
-                label = ABMultiValueCopyLabelAtIndex(multi, i);
-                if(label && [(NSString*)label isEqualToString:(NSString*)kABPersonAnniversaryLabel]){
-                    CFDateRef aDate = ABMultiValueCopyValueAtIndex(multi, i);
-                    if(aDate){
-                        [nc setObject: (NSString*)aDate forKey: kW3ContactAnniversary];
-                        CFRelease(aDate);
-                    }
-                    CFRelease(label);
-                    break;
-                }
-            }
-            CFRelease(multi);
-        }
-    }*/
-
-    if ([self.returnFields valueForKey:kW3ContactNote]) {
-        // note
-        value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, kABPersonNoteProperty);
-        [nc setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactNote];
-    }
-
-    if ([self.returnFields valueForKey:kW3ContactPhotos]) {
-        value = [self extractPhotos];
-        [nc setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactPhotos];
-    }
-
-    /* TimeZone removed from June 16, 2011 Contacts spec
-     *
-    if ([self.returnFields valueForKey:kW3ContactTimezone]){
-        [NSTimeZone resetSystemTimeZone];
-        NSTimeZone* currentTZ = [NSTimeZone localTimeZone];
-        NSInteger seconds = [currentTZ secondsFromGMT];
-        NSString* tz = [NSString stringWithFormat:@"%2d:%02u",  seconds/3600, seconds % 3600 ];
-        [nc setObject:tz forKey:kW3ContactTimezone];
-    }
-    */
-    // TODO WebURLs
-    // [nc setObject:[NSNull null] forKey:kW3ContactUrls];
-    // online accounts - not available on iOS
-
-    return nc;
-}
-
-- (NSNumber*)getDateAsNumber:(ABPropertyID)datePropId
-{
-    NSNumber* msDate = nil;
-    NSDate* aDate = nil;
-    CFTypeRef cfDate = ABRecordCopyValue(self.record, datePropId);
-
-    if (cfDate) {
-        aDate = (__bridge NSDate*)cfDate;
-        msDate = [NSNumber numberWithDouble:([aDate timeIntervalSince1970] * 1000)];
-        CFRelease(cfDate);
-    }
-    return msDate;
-}
-
-/* Create Dictionary to match JavaScript ContactName object:
- *	formatted - ABRecordCopyCompositeName
- *	familyName
- *	givenName
- *	middleName
- *	honorificPrefix
- *	honorificSuffix
-*/
-
-- (NSObject*)extractName
-{
-    NSArray* fields = [self.returnFields objectForKey:kW3ContactName];
-
-    if (fields == nil) { // no name fields requested
-        return nil;
-    }
-
-    NSMutableDictionary* newName = [NSMutableDictionary dictionaryWithCapacity:6];
-    id value;
-
-    for (NSString* i in fields) {
-        if ([i isEqualToString:kW3ContactFormattedName]) {
-            value = (__bridge_transfer NSString*)ABRecordCopyCompositeName(self.record);
-            [newName setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactFormattedName];
-        } else {
-            // W3CtoAB returns NSNumber for AB name properties, get intValue and cast to ABPropertyID)
-            value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, (ABPropertyID)[[[CDVContact defaultW3CtoAB] valueForKey:i] intValue]);
-            [newName setObject:(value != nil) ? value:[NSNull null] forKey:(NSString*)i];
-        }
-    }
-
-    return newName;
-}
-
-/* Create array of Dictionaries to match JavaScript ContactField object for simple multiValue properties phoneNumbers, emails
- * Input: (NSString*) W3Contact Property name
- * type
- *		for phoneNumbers type is one of (work,home,other, mobile, fax, pager)
- *		for emails type is one of (work,home, other)
- * value - phone number or email address
- * (bool) primary (not supported on iphone)
- * id
-*/
-- (NSObject*)extractMultiValue:(NSString*)propertyId
-{
-    NSArray* fields = [self.returnFields objectForKey:propertyId];
-
-    if (fields == nil) {
-        return nil;
-    }
-    ABMultiValueRef multi = nil;
-    NSObject* valuesArray = nil;
-    NSNumber* propNumber = [[CDVContact defaultW3CtoAB] valueForKey:propertyId];
-    ABPropertyID propId = [propNumber intValue];
-    multi = ABRecordCopyValue(self.record, propId);
-    // multi = ABRecordCopyValue(self.record, (ABPropertyID)[[[Contact defaultW3CtoAB] valueForKey:propertyId] intValue]);
-    CFIndex count = multi != nil ? ABMultiValueGetCount(multi) : 0;
-    id value;
-    if (count) {
-        valuesArray = [NSMutableArray arrayWithCapacity:count];
-
-        for (CFIndex i = 0; i < count; i++) {
-            NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:4];
-            if ([fields containsObject:kW3ContactFieldType]) {
-                NSString* label = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, i);
-                value = [CDVContact convertPropertyLabelToContactType:label];
-                [newDict setObject:(value != nil) ? value:[NSNull null]   forKey:kW3ContactFieldType];
-            }
-            if ([fields containsObject:kW3ContactFieldValue]) {
-                value = (__bridge_transfer NSString*)ABMultiValueCopyValueAtIndex(multi, i);
-                [newDict setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactFieldValue];
-            }
-            if ([fields containsObject:kW3ContactFieldPrimary]) {
-                [newDict setObject:[NSNumber numberWithBool:(BOOL)NO] forKey:kW3ContactFieldPrimary];   // iOS doesn't support primary so set all to false
-            }
-            // always set id
-            value = [NSNumber numberWithUnsignedInt:ABMultiValueGetIdentifierAtIndex(multi, i)];
-            [newDict setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactFieldId];
-            [(NSMutableArray*)valuesArray addObject : newDict];
-        }
-    } else {
-        valuesArray = [NSNull null];
-    }
-    if (multi) {
-        CFRelease(multi);
-    }
-
-    return valuesArray;
-}
-
-/* Create array of Dictionaries to match JavaScript ContactAddress object for addresses
- *  pref - not supported
- *  type - address type
- *	formatted  - formatted for mailing label (what about localization?)
- *	streetAddress
- *	locality
- *	region;
- *	postalCode
- *	country
- *	id
- *
- *	iOS addresses are a MultiValue Properties with label, value=dictionary of address info, and id
- */
-- (NSObject*)extractAddresses
-{
-    NSArray* fields = [self.returnFields objectForKey:kW3ContactAddresses];
-
-    if (fields == nil) { // no name fields requested
-        return nil;
-    }
-    CFStringRef value;
-    NSObject* addresses;
-    ABMultiValueRef multi = ABRecordCopyValue(self.record, kABPersonAddressProperty);
-    CFIndex count = multi ? ABMultiValueGetCount(multi) : 0;
-    if (count) {
-        addresses = [NSMutableArray arrayWithCapacity:count];
-
-        for (CFIndex i = 0; i < count; i++) {
-            NSMutableDictionary* newAddress = [NSMutableDictionary dictionaryWithCapacity:7];
-            // if we got this far, at least some address info is being requested.
-
-            // Always set id
-            id identifier = [NSNumber numberWithUnsignedInt:ABMultiValueGetIdentifierAtIndex(multi, i)];
-            [newAddress setObject:(identifier != nil) ? identifier:[NSNull null] forKey:kW3ContactFieldId];
-            // set the type label
-            NSString* label = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, i);
-
-            [newAddress setObject:(label != nil) ? (NSObject*)[[CDVContact class] convertPropertyLabelToContactType:label]:[NSNull null] forKey:kW3ContactFieldType];
-            // set the pref - iOS doesn't support so set to default of false
-            [newAddress setObject:@"false" forKey:kW3ContactFieldPrimary];
-            // get dictionary of values for this address
-            CFDictionaryRef dict = (CFDictionaryRef)ABMultiValueCopyValueAtIndex(multi, i);
-
-            for (id k in fields) {
-                bool bFound;
-                id key = [[CDVContact defaultW3CtoAB] valueForKey:k];
-                if (key && ![k isKindOfClass:[NSNull class]]) {
-                    bFound = CFDictionaryGetValueIfPresent(dict, (__bridge const void*)key, (void*)&value);
-                    if (bFound && (value != NULL)) {
-                        CFRetain(value);
-                        [newAddress setObject:(__bridge id)value forKey:k];
-                        CFRelease(value);
-                    } else {
-                        [newAddress setObject:[NSNull null] forKey:k];
-                    }
-                } else {
-                    // was a property that iPhone doesn't support
-                    [newAddress setObject:[NSNull null] forKey:k];
-                }
-            }
-
-            if ([newAddress count] > 0) { // ?? this will always be true since we set id,label,primary field??
-                [(NSMutableArray*)addresses addObject : newAddress];
-            }
-            CFRelease(dict);
-        } // end of loop through addresses
-    } else {
-        addresses = [NSNull null];
-    }
-    if (multi) {
-        CFRelease(multi);
-    }
-
-    return addresses;
-}
-
-/* Create array of Dictionaries to match JavaScript ContactField object for ims
- * type one of [aim, gtalk, icq, xmpp, msn, skype, qq, yahoo] needs other as well
- * value
- * (bool) primary
- * id
- *
- *	iOS IMs are a MultiValue Properties with label, value=dictionary of IM details (service, username), and id
- */
-- (NSObject*)extractIms
-{
-    NSArray* fields = [self.returnFields objectForKey:kW3ContactIms];
-
-    if (fields == nil) { // no name fields requested
-        return nil;
-    }
-    NSObject* imArray;
-    ABMultiValueRef multi = ABRecordCopyValue(self.record, kABPersonInstantMessageProperty);
-    CFIndex count = multi ? ABMultiValueGetCount(multi) : 0;
-    if (count) {
-        imArray = [NSMutableArray arrayWithCapacity:count];
-
-        for (CFIndex i = 0; i < ABMultiValueGetCount(multi); i++) {
-            NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:3];
-            // iOS has label property (work, home, other) for each IM but W3C contact API doesn't use
-            CFDictionaryRef dict = (CFDictionaryRef)ABMultiValueCopyValueAtIndex(multi, i);
-            CFStringRef value;  // all values should be CFStringRefs / NSString*
-            bool bFound;
-            if ([fields containsObject:kW3ContactFieldValue]) {
-                // value = user name
-                bFound = CFDictionaryGetValueIfPresent(dict, kABPersonInstantMessageUsernameKey, (void*)&value);
-                if (bFound && (value != NULL)) {
-                    CFRetain(value);
-                    [newDict setObject:(__bridge id)value forKey:kW3ContactFieldValue];
-                    CFRelease(value);
-                } else {
-                    [newDict setObject:[NSNull null] forKey:kW3ContactFieldValue];
-                }
-            }
-            if ([fields containsObject:kW3ContactFieldType]) {
-                bFound = CFDictionaryGetValueIfPresent(dict, kABPersonInstantMessageServiceKey, (void*)&value);
-                if (bFound && (value != NULL)) {
-                    CFRetain(value);
-                    [newDict setObject:(id)[[CDVContact class] convertPropertyLabelToContactType : (__bridge NSString*)value] forKey:kW3ContactFieldType];
-                    CFRelease(value);
-                } else {
-                    [newDict setObject:[NSNull null] forKey:kW3ContactFieldType];
-                }
-            }
-            // always set ID
-            id identifier = [NSNumber numberWithUnsignedInt:ABMultiValueGetIdentifierAtIndex(multi, i)];
-            [newDict setObject:(identifier != nil) ? identifier:[NSNull null] forKey:kW3ContactFieldId];
-
-            [(NSMutableArray*)imArray addObject : newDict];
-            CFRelease(dict);
-        }
-    } else {
-        imArray = [NSNull null];
-    }
-
-    if (multi) {
-        CFRelease(multi);
-    }
-    return imArray;
-}
-
-/* Create array of Dictionaries to match JavaScript ContactOrganization object
- *	pref - not supported in iOS
- *  type - not supported in iOS
- *  name
- *	department
- *	title
- */
-
-- (NSObject*)extractOrganizations
-{
-    NSArray* fields = [self.returnFields objectForKey:kW3ContactOrganizations];
-
-    if (fields == nil) { // no name fields requested
-        return nil;
-    }
-    NSObject* array = nil;
-    NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:5];
-    id value;
-    int validValueCount = 0;
-
-    for (id i in fields) {
-        id key = [[CDVContact defaultW3CtoAB] valueForKey:i];
-        if (key && [key isKindOfClass:[NSNumber class]]) {
-            value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, (ABPropertyID)[[[CDVContact defaultW3CtoAB] valueForKey:i] intValue]);
-            if (value != nil) {
-                // if there are no organization values we should return null for organization
-                // this counter keeps indicates if any organization values have been set
-                validValueCount++;
-            }
-            [newDict setObject:(value != nil) ? value:[NSNull null] forKey:i];
-        } else { // not a key iOS supports, set to null
-            [newDict setObject:[NSNull null] forKey:i];
-        }
-    }
-
-    if (([newDict count] > 0) && (validValueCount > 0)) {
-        // add pref and type
-        // they are not supported by iOS and thus these values never change
-        [newDict setObject:@"false" forKey:kW3ContactFieldPrimary];
-        [newDict setObject:[NSNull null] forKey:kW3ContactFieldType];
-        array = [NSMutableArray arrayWithCapacity:1];
-        [(NSMutableArray*)array addObject : newDict];
-    } else {
-        array = [NSNull null];
-    }
-    return array;
-}
-
-// W3C Contacts expects an array of photos.  Can return photos in more than one format, currently
-// just returning the default format
-// Save the photo data into tmp directory and return FileURI - temp directory is deleted upon application exit
-- (NSObject*)extractPhotos
-{
-    NSMutableArray* photos = nil;
-
-    if (ABPersonHasImageData(self.record)) {
-        CFDataRef photoData = ABPersonCopyImageData(self.record);
-        NSData* data = (__bridge NSData*)photoData;
-        // write to temp directory and store URI in photos array
-        // get the temp directory path
-        NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
-        NSError* err = nil;
-        NSString* filePath = [NSString stringWithFormat:@"%@/photo_XXXXX", docsPath];
-        char template[filePath.length + 1];
-        strcpy(template, [filePath cStringUsingEncoding:NSASCIIStringEncoding]);
-        mkstemp(template);
-        filePath = [[NSFileManager defaultManager]
-            stringWithFileSystemRepresentation:template
-                                        length:strlen(template)];
-
-        // save file
-        if ([data writeToFile:filePath options:NSAtomicWrite error:&err]) {
-            photos = [NSMutableArray arrayWithCapacity:1];
-            NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:2];
-            [newDict setObject:filePath forKey:kW3ContactFieldValue];
-            [newDict setObject:@"url" forKey:kW3ContactFieldType];
-            [newDict setObject:@"false" forKey:kW3ContactFieldPrimary];
-            [photos addObject:newDict];
-        }
-
-        CFRelease(photoData);
-    }
-    return photos;
-}
-
-/**
- *	given an array of W3C Contact field names, create a dictionary of field names to extract
- *	if field name represents an object, return all properties for that object:  "name" - returns all properties in ContactName
- *	if field name is an explicit property, return only those properties:  "name.givenName - returns a ContactName with only ContactName.givenName
- *  if field contains ONLY ["*"] return all fields
- *	dictionary format:
- *	key is W3Contact #define
- *		value is NSMutableArray* for complex keys:  name,addresses,organizations, phone, emails, ims
- *		value is [NSNull null] for simple keys
-*/
-+ (NSDictionary*)calcReturnFields:(NSArray*)fieldsArray // NSLog(@"getting self.returnFields");
-{
-    NSMutableDictionary* d = [NSMutableDictionary dictionaryWithCapacity:1];
-
-    if ((fieldsArray != nil) && [fieldsArray isKindOfClass:[NSArray class]]) {
-        if (([fieldsArray count] == 1) && [[fieldsArray objectAtIndex:0] isEqualToString:@"*"]) {
-            return [CDVContact defaultFields];  // return all fields
-        }
-
-        for (id i in fieldsArray) {
-            NSMutableArray* keys = nil;
-            NSString* fieldStr = nil;
-            if ([i isKindOfClass:[NSNumber class]]) {
-                fieldStr = [i stringValue];
-            } else {
-                fieldStr = i;
-            }
-
-            // see if this is specific property request in object - object.property
-            NSArray* parts = [fieldStr componentsSeparatedByString:@"."]; // returns original string if no separator found
-            NSString* name = [parts objectAtIndex:0];
-            NSString* property = nil;
-            if ([parts count] > 1) {
-                property = [parts objectAtIndex:1];
-            }
-            // see if this is a complex field by looking for its array of properties in objectAndProperties dictionary
-            id fields = [[CDVContact defaultObjectAndProperties] objectForKey:name];
-
-            // if find complex name (name,addresses,organizations, phone, emails, ims) in fields, add name as key
-            // with array of associated properties as the value
-            if ((fields != nil) && (property == nil)) { // request was for full object
-                keys = [NSMutableArray arrayWithArray:fields];
-                if (keys != nil) {
-                    [d setObject:keys forKey:name]; // will replace if prop array already exists
-                }
-            } else if ((fields != nil) && (property != nil)) {
-                // found an individual property request  in form of name.property
-                // verify is real property name by using it as key in W3CtoAB
-                id abEquiv = [[CDVContact defaultW3CtoAB] objectForKey:property];
-                if (abEquiv || [[CDVContact defaultW3CtoNull] containsObject:property]) {
-                    // if existing array add to it
-                    if ((keys = [d objectForKey:name]) != nil) {
-                        [keys addObject:property];
-                    } else {
-                        keys = [NSMutableArray arrayWithObject:property];
-                        [d setObject:keys forKey:name];
-                    }
-                } else {
-                    NSLog(@"Contacts.find -- request for invalid property ignored: %@.%@", name, property);
-                }
-            } else { // is an individual property, verify is real property name by using it as key in W3CtoAB
-                id valid = [[CDVContact defaultW3CtoAB] objectForKey:name];
-                if (valid || [[CDVContact defaultW3CtoNull] containsObject:name]) {
-                    [d setObject:[NSNull null] forKey:name];
-                }
-            }
-        }
-    }
-    if ([d count] == 0) {
-        // no array or nothing in the array. W3C spec says to return nothing
-        return nil;   // [Contact defaultFields];
-    }
-    return d;
-}
-
-/*
- * Search for the specified value in each of the fields specified in the searchFields dictionary.
- * NSString* value - the string value to search for (need clarification from W3C on how to search for dates)
- * NSDictionary* searchFields - a dictionary created via calcReturnFields where the key is the top level W3C
- *	object and the object is the array of specific fields within that object or null if it is a single property
- * RETURNS
- *	YES as soon as a match is found in any of the fields
- *	NO - the specified value does not exist in any of the fields in this contact
- *
- *  Note: I'm not a fan of returning in the middle of methods but have done it some in this method in order to
- *    keep the code simpler. bgibson
- */
-- (BOOL)foundValue:(NSString*)testValue inFields:(NSDictionary*)searchFields
-{
-    BOOL bFound = NO;
-
-    if ((testValue == nil) || ![testValue isKindOfClass:[NSString class]] || ([testValue length] == 0)) {
-        // nothing to find so return NO
-        return NO;
-    }
-    NSInteger valueAsInt = [testValue integerValue];
-
-    // per W3C spec, always include id in search
-    int recordId = ABRecordGetRecordID(self.record);
-    if (valueAsInt && (recordId == valueAsInt)) {
-        return YES;
-    }
-
-    if (searchFields == nil) {
-        // no fields to search
-        return NO;
-    }
-
-    if ([searchFields valueForKey:kW3ContactNickname]) {
-        bFound = [self testStringValue:testValue forW3CProperty:kW3ContactNickname];
-        if (bFound == YES) {
-            return bFound;
-        }
-    }
-
-    if ([searchFields valueForKeyIsArray:kW3ContactName]) {
-        // test name fields.  All are string properties obtained via ABRecordCopyValue except kW3ContactFormattedName
-        NSArray* fields = [searchFields valueForKey:kW3ContactName];
-
-        for (NSString* testItem in fields) {
-            if ([testItem isEqualToString:kW3ContactFormattedName]) {
-                NSString* propValue = (__bridge_transfer NSString*)ABRecordCopyCompositeName(self.record);
-                if ((propValue != nil) && ([propValue length] > 0)) {
-                    NSRange range = [propValue rangeOfString:testValue options:NSCaseInsensitiveSearch];
-                    bFound = (range.location != NSNotFound);
-                    propValue = nil;
-                }
-            } else {
-                bFound = [self testStringValue:testValue forW3CProperty:testItem];
-            }
-
-            if (bFound) {
-                break;
-            }
-        }
-    }
-    if (!bFound && [searchFields valueForKeyIsArray:kW3ContactPhoneNumbers]) {
-        bFound = [self searchContactFields:(NSArray*)[searchFields valueForKey:kW3ContactPhoneNumbers]
-                       forMVStringProperty:kABPersonPhoneProperty withValue:testValue];
-    }
-    if (!bFound && [searchFields valueForKeyIsArray:kW3ContactEmails]) {
-        bFound = [self searchContactFields:(NSArray*)[searchFields valueForKey:kW3ContactEmails]
-                       forMVStringProperty:kABPersonEmailProperty withValue:testValue];
-    }
-
-    if (!bFound && [searchFields valueForKeyIsArray:kW3ContactAddresses]) {
-        bFound = [self searchContactFields:[searchFields valueForKey:kW3ContactAddresses]
-                   forMVDictionaryProperty:kABPersonAddressProperty withValue:testValue];
-    }
-
-    if (!bFound && [searchFields valueForKeyIsArray:kW3ContactIms]) {
-        bFound = [self searchContactFields:[searchFields valueForKey:kW3ContactIms]
-                   forMVDictionaryProperty:kABPersonInstantMessageProperty withValue:testValue];
-    }
-
-    if (!bFound && [searchFields valueForKeyIsArray:kW3ContactOrganizations]) {
-        NSArray* fields = [searchFields valueForKey:kW3ContactOrganizations];
-
-        for (NSString* testItem in fields) {
-            bFound = [self testStringValue:testValue forW3CProperty:testItem];
-            if (bFound == YES) {
-                break;
-            }
-        }
-    }
-    if (!bFound && [searchFields valueForKey:kW3ContactNote]) {
-        bFound = [self testStringValue:testValue forW3CProperty:kW3ContactNote];
-    }
-
-    // if searching for a date field is requested, get the date field as a localized string then look for match against testValue in date string
-    // searching for photos is not supported
-    if (!bFound && [searchFields valueForKey:kW3ContactBirthday]) {
-        bFound = [self testDateValue:testValue forW3CProperty:kW3ContactBirthday];
-    }
-    if (!bFound && [searchFields valueForKeyIsArray:kW3ContactUrls]) {
-        bFound = [self searchContactFields:(NSArray*)[searchFields valueForKey:kW3ContactUrls]
-                       forMVStringProperty:kABPersonURLProperty withValue:testValue];
-    }
-
-    return bFound;
-}
-
-/*
- * Test for the existence of a given string within the value of a ABPersonRecord string property based on the W3c property name.
- *
- * IN:
- *	NSString* testValue - the value to find - search is case insensitive
- *  NSString* property - the W3c property string
- * OUT:
- * BOOL YES if the given string was found within the property value
- *		NO if the testValue was not found, W3C property string was invalid or the AddressBook property was not a string
- */
-- (BOOL)testStringValue:(NSString*)testValue forW3CProperty:(NSString*)property
-{
-    BOOL bFound = NO;
-
-    if ([[CDVContact defaultW3CtoAB] valueForKeyIsNumber:property]) {
-        ABPropertyID propId = [[[CDVContact defaultW3CtoAB] objectForKey:property] intValue];
-        if (ABPersonGetTypeOfProperty(propId) == kABStringPropertyType) {
-            NSString* propValue = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, propId);
-            if ((propValue != nil) && ([propValue length] > 0)) {
-                NSPredicate* containPred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", testValue];
-                bFound = [containPred evaluateWithObject:propValue];
-                // NSRange range = [propValue rangeOfString:testValue options: NSCaseInsensitiveSearch];
-                // bFound = (range.location != NSNotFound);
-            }
-        }
-    }
-    return bFound;
-}
-
-/*
- * Test for the existence of a given Date string within the value of a ABPersonRecord datetime property based on the W3c property name.
- *
- * IN:
- *	NSString* testValue - the value to find - search is case insensitive
- *  NSString* property - the W3c property string
- * OUT:
- * BOOL YES if the given string was found within the localized date string value
- *		NO if the testValue was not found, W3C property string was invalid or the AddressBook property was not a DateTime
- */
-- (BOOL)testDateValue:(NSString*)testValue forW3CProperty:(NSString*)property
-{
-    BOOL bFound = NO;
-
-    if ([[CDVContact defaultW3CtoAB] valueForKeyIsNumber:property]) {
-        ABPropertyID propId = [[[CDVContact defaultW3CtoAB] objectForKey:property] intValue];
-        if (ABPersonGetTypeOfProperty(propId) == kABDateTimePropertyType) {
-            NSDate* date = (__bridge_transfer NSDate*)ABRecordCopyValue(self.record, propId);
-            if (date != nil) {
-                NSString* dateString = [date descriptionWithLocale:[NSLocale currentLocale]];
-                NSPredicate* containPred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", testValue];
-                bFound = [containPred evaluateWithObject:dateString];
-            }
-        }
-    }
-    return bFound;
-}
-
-/*
- * Search the specified fields within an AddressBook multivalue string property for the specified test value.
- * Used for phoneNumbers, emails and urls.
- * IN:
- *	NSArray* fields - the fields to search for within the multistring property (value and/or type)
- *	ABPropertyID - the property to search
- *	NSString* testValue - the value to search for. Will convert between W3C types and AB types.  Will only
- *		search for types if the testValue is a valid ContactField type.
- * OUT:
- *	YES if the test value was found in one of the specified fields
- *	NO if the test value was not found
- */
-- (BOOL)searchContactFields:(NSArray*)fields forMVStringProperty:(ABPropertyID)propId withValue:testValue
-{
-    BOOL bFound = NO;
-
-    for (NSString* type in fields) {
-        NSString* testString = nil;
-        if ([type isEqualToString:kW3ContactFieldType]) {
-            if ([CDVContact isValidW3ContactType:testValue]) {
-                // only search types if the filter string is a valid ContactField.type
-                testString = (NSString*)[CDVContact convertContactTypeToPropertyLabel:testValue];
-            }
-        } else {
-            testString = testValue;
-        }
-
-        if (testString != nil) {
-            bFound = [self testMultiValueStrings:testString forProperty:propId ofType:type];
-        }
-        if (bFound == YES) {
-            break;
-        }
-    }
-
-    return bFound;
-}
-
-/*
- * Searches a multiString value of the specified type for the specified test value.
- *
- * IN:
- *	NSString* testValue - the value to test for
- *	ABPropertyID propId - the property id of the multivalue property to search
- *	NSString* type - the W3C contact type to search for (value or type)
- * OUT:
- * YES is the test value was found
- * NO if the test value was not found
- */
-- (BOOL)testMultiValueStrings:(NSString*)testValue forProperty:(ABPropertyID)propId ofType:(NSString*)type
-{
-    BOOL bFound = NO;
-
-    if (ABPersonGetTypeOfProperty(propId) == kABMultiStringPropertyType) {
-        NSArray* valueArray = nil;
-        if ([type isEqualToString:kW3ContactFieldType]) {
-            valueArray = [self labelsForProperty:propId inRecord:self.record];
-        } else if ([type isEqualToString:kW3ContactFieldValue]) {
-            valueArray = [self valuesForProperty:propId inRecord:self.record];
-        }
-        if (valueArray) {
-            NSString* valuesAsString = [valueArray componentsJoinedByString:@" "];
-            NSPredicate* containPred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", testValue];
-            bFound = [containPred evaluateWithObject:valuesAsString];
-        }
-    }
-    return bFound;
-}
-
-/*
- * Returns the array of values for a multivalue string property of the specified property id
- */
-- (__autoreleasing NSArray*)valuesForProperty:(ABPropertyID)propId inRecord:(ABRecordRef)aRecord
-{
-    ABMultiValueRef multi = ABRecordCopyValue(aRecord, propId);
-    NSArray* values = (__bridge_transfer NSArray*)ABMultiValueCopyArrayOfAllValues(multi);
-
-    CFRelease(multi);
-    return values;
-}
-
-/*
- * Returns the array of labels for a multivalue string property of the specified property id
- */
-- (NSArray*)labelsForProperty:(ABPropertyID)propId inRecord:(ABRecordRef)aRecord
-{
-    ABMultiValueRef multi = ABRecordCopyValue(aRecord, propId);
-    CFIndex count = ABMultiValueGetCount(multi);
-    NSMutableArray* labels = [NSMutableArray arrayWithCapacity:count];
-
-    for (int i = 0; i < count; i++) {
-        NSString* label = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, i);
-        if (label) {
-            [labels addObject:label];
-        }
-    }
-
-    CFRelease(multi);
-    return labels;
-}
-
-/* search for values within MultiValue Dictionary properties Address or IM property
- * IN:
- * (NSArray*) fields - the array of W3C field names to search within
- * (ABPropertyID) propId - the AddressBook property that returns a multivalue dictionary
- * (NSString*) testValue - the string to search for within the specified fields
- *
- */
-- (BOOL)searchContactFields:(NSArray*)fields forMVDictionaryProperty:(ABPropertyID)propId withValue:(NSString*)testValue
-{
-    BOOL bFound = NO;
-
-    NSArray* values = [self valuesForProperty:propId inRecord:self.record];  // array of dictionaries (as CFDictionaryRef)
-    NSUInteger dictCount = [values count];
-
-    // for ims dictionary contains with service (w3C type) and username (W3c value)
-    // for addresses dictionary contains street, city, state, zip, country
-    for (int i = 0; i < dictCount; i++) {
-        CFDictionaryRef dict = (__bridge CFDictionaryRef)[values objectAtIndex:i];
-
-        for (NSString* member in fields) {
-            NSString* abKey = [[CDVContact defaultW3CtoAB] valueForKey:member]; // im and address fields are all strings
-            CFStringRef abValue = nil;
-            if (abKey) {
-                NSString* testString = nil;
-                if ([member isEqualToString:kW3ContactImType]) {
-                    if ([CDVContact isValidW3ContactType:testValue]) {
-                        // only search service/types if the filter string is a valid ContactField.type
-                        testString = (NSString*)[CDVContact convertContactTypeToPropertyLabel:testValue];
-                    }
-                } else {
-                    testString = testValue;
-                }
-                if (testString != nil) {
-                    BOOL bExists = CFDictionaryGetValueIfPresent(dict, (__bridge const void*)abKey, (void*)&abValue);
-                    if (bExists) {
-                        CFRetain(abValue);
-                        NSPredicate* containPred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", testString];
-                        bFound = [containPred evaluateWithObject:(__bridge id)abValue];
-                        CFRelease(abValue);
-                    }
-                }
-            }
-            if (bFound == YES) {
-                break;
-            }
-        } // end of for each member in fields
-
-        if (bFound == YES) {
-            break;
-        }
-    } // end of for each dictionary
-
-    return bFound;
-}
-
-@end

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/ios/CDVContacts.h
----------------------------------------------------------------------
diff --git a/src/ios/CDVContacts.h b/src/ios/CDVContacts.h
deleted file mode 100644
index e3deb21..0000000
--- a/src/ios/CDVContacts.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
-#import <Foundation/Foundation.h>
-#import <AddressBook/ABAddressBook.h>
-#import <AddressBookUI/AddressBookUI.h>
-#import <Cordova/CDVPlugin.h>
-#import "CDVContact.h"
-
-@interface CDVContacts : CDVPlugin <ABNewPersonViewControllerDelegate,
-                         ABPersonViewControllerDelegate,
-                         ABPeoplePickerNavigationControllerDelegate
-                         >
-{
-    ABAddressBookRef addressBook;
-}
-
-/*
- * newContact - create a new contact via the GUI
- *
- * arguments:
- *	1: successCallback: this is the javascript function that will be called with the newly created contactId
- */
-- (void)newContact:(CDVInvokedUrlCommand*)command;
-
-/*
- * displayContact  - IN PROGRESS
- *
- * arguments:
- *	1: recordID of the contact to display in the iPhone contact display
- *	2: successCallback - currently not used
- *  3: error callback
- * options:
- *	allowsEditing: set to true to allow the user to edit the contact - currently not supported
- */
-- (void)displayContact:(CDVInvokedUrlCommand*)command;
-
-/*
- * chooseContact
- *
- * arguments:
- *	1: this is the javascript function that will be called with the contact data as a JSON object (as the first param)
- * options:
- *	allowsEditing: set to true to not choose the contact, but to edit it in the iPhone contact editor
- */
-- (void)chooseContact:(CDVInvokedUrlCommand*)command;
-
-- (void)newPersonViewController:(ABNewPersonViewController*)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person;
-- (BOOL)personViewController:(ABPersonViewController*)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person
-                    property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue;
-
-/*
- * search - searches for contacts.  Only person records are currently supported.
- *
- * arguments:
- *  1: successcallback - this is the javascript function that will be called with the array of found contacts
- *  2:  errorCallback - optional javascript function to be called in the event of an error with an error code.
- * options:  dictionary containing ContactFields and ContactFindOptions
- *	fields - ContactFields array
- *  findOptions - ContactFindOptions object as dictionary
- *
- */
-- (void)search:(CDVInvokedUrlCommand*)command;
-
-/*
- * save - saves a new contact or updates and existing contact
- *
- * arguments:
- *  1: success callback - this is the javascript function that will be called with the JSON representation of the saved contact
- *		search calls a fixed navigator.service.contacts._findCallback which then calls the success callback stored before making the call into obj-c
- */
-- (void)save:(CDVInvokedUrlCommand*)command;
-
-/*
- * remove - removes a contact from the address book
- *
- * arguments:
- *  1:  1: successcallback - this is the javascript function that will be called with a (now) empty contact object
- *
- * options:  dictionary containing Contact object to remove
- *	contact - Contact object as dictionary
- */
-- (void)remove:(CDVInvokedUrlCommand*)command;
-
-// - (void) dealloc;
-
-@end
-
-@interface CDVContactsPicker : ABPeoplePickerNavigationController
-{
-    BOOL allowsEditing;
-    NSString* callbackId;
-    NSDictionary* options;
-    NSDictionary* pickedContactDictionary;
-}
-
-@property BOOL allowsEditing;
-@property (copy) NSString* callbackId;
-@property (nonatomic, strong) NSDictionary* options;
-@property (nonatomic, strong) NSDictionary* pickedContactDictionary;
-
-@end
-
-@interface CDVNewContactsController : ABNewPersonViewController
-{
-    NSString* callbackId;
-}
-@property (copy) NSString* callbackId;
-@end
-
-/* ABPersonViewController does not have any UI to dismiss.  Adding navigationItems to it does not work properly,  the navigationItems are lost when the app goes into the background.
-    The solution was to create an empty NavController in front of the ABPersonViewController. This
-    causes the ABPersonViewController to have a back button. By subclassing the ABPersonViewController,
-    we can override viewWillDisappear and take down the entire NavigationController at that time.
- */
-@interface CDVDisplayContactViewController : ABPersonViewController
-{}
-@property (nonatomic, strong) CDVPlugin* contactsPlugin;
-
-@end
-@interface CDVAddressBookAccessError : NSObject
-{}
-@property (assign) CDVContactError errorCode;
-- (CDVAddressBookAccessError*)initWithCode:(CDVContactError)code;
-@end
-
-typedef void (^ CDVAddressBookWorkerBlock)(
-    ABAddressBookRef         addressBook,
-    CDVAddressBookAccessError* error
-    );
-@interface CDVAddressBookHelper : NSObject
-{}
-
-- (void)createAddressBook:(CDVAddressBookWorkerBlock)workerBlock;
-@end


[5/6] CB-6521: Remove development branch

Posted by ia...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/android/ContactAccessorSdk5.java
----------------------------------------------------------------------
diff --git a/src/android/ContactAccessorSdk5.java b/src/android/ContactAccessorSdk5.java
deleted file mode 100644
index d8b9592..0000000
--- a/src/android/ContactAccessorSdk5.java
+++ /dev/null
@@ -1,2181 +0,0 @@
-/*
-       Licensed to the Apache Software Foundation (ASF) under one
-       or more contributor license agreements.  See the NOTICE file
-       distributed with this work for additional information
-       regarding copyright ownership.  The ASF licenses this file
-       to you under the Apache License, Version 2.0 (the
-       "License"); you may not use this file except in compliance
-       with the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing,
-       software distributed under the License is distributed on an
-       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-       KIND, either express or implied.  See the License for the
-       specific language governing permissions and limitations
-       under the License.
-*/
-
-package org.apache.cordova.contacts;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.content.ContentProviderOperation;
-import android.content.ContentProviderResult;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.OperationApplicationException;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.RemoteException;
-import android.provider.ContactsContract;
-import android.util.Log;
-
-import org.apache.cordova.CordovaInterface;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-//import android.app.Activity;
-//import android.content.Context;
-
-/**
- * An implementation of {@link ContactAccessor} that uses current Contacts API.
- * This class should be used on Eclair or beyond, but would not work on any earlier
- * release of Android.  As a matter of fact, it could not even be loaded.
- * <p>
- * This implementation has several advantages:
- * <ul>
- * <li>It sees contacts from multiple accounts.
- * <li>It works with aggregated contacts. So for example, if the contact is the result
- * of aggregation of two raw contacts from different accounts, it may return the name from
- * one and the phone number from the other.
- * <li>It is efficient because it uses the more efficient current API.
- * <li>Not obvious in this particular example, but it has access to new kinds
- * of data available exclusively through the new APIs. Exercise for the reader: add support
- * for nickname (see {@link android.provider.ContactsContract.CommonDataKinds.Nickname}) or
- * social status updates (see {@link android.provider.ContactsContract.StatusUpdates}).
- * </ul>
- */
-
-public class ContactAccessorSdk5 extends ContactAccessor {
-
-    /**
-     * Keep the photo size under the 1 MB blog limit.
-     */
-    private static final long MAX_PHOTO_SIZE = 1048576;
-
-    private static final String EMAIL_REGEXP = ".+@.+\\.+.+"; /* <anything>@<anything>.<anything>*/
-
-    /**
-     * A static map that converts the JavaScript property name to Android database column name.
-     */
-    private static final Map<String, String> dbMap = new HashMap<String, String>();
-    static {
-        dbMap.put("id", ContactsContract.Data.CONTACT_ID);
-        dbMap.put("displayName", ContactsContract.Contacts.DISPLAY_NAME);
-        dbMap.put("name", ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
-        dbMap.put("name.formatted", ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
-        dbMap.put("name.familyName", ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
-        dbMap.put("name.givenName", ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
-        dbMap.put("name.middleName", ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME);
-        dbMap.put("name.honorificPrefix", ContactsContract.CommonDataKinds.StructuredName.PREFIX);
-        dbMap.put("name.honorificSuffix", ContactsContract.CommonDataKinds.StructuredName.SUFFIX);
-        dbMap.put("nickname", ContactsContract.CommonDataKinds.Nickname.NAME);
-        dbMap.put("phoneNumbers", ContactsContract.CommonDataKinds.Phone.NUMBER);
-        dbMap.put("phoneNumbers.value", ContactsContract.CommonDataKinds.Phone.NUMBER);
-        dbMap.put("emails", ContactsContract.CommonDataKinds.Email.DATA);
-        dbMap.put("emails.value", ContactsContract.CommonDataKinds.Email.DATA);
-        dbMap.put("addresses", ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS);
-        dbMap.put("addresses.formatted", ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS);
-        dbMap.put("addresses.streetAddress", ContactsContract.CommonDataKinds.StructuredPostal.STREET);
-        dbMap.put("addresses.locality", ContactsContract.CommonDataKinds.StructuredPostal.CITY);
-        dbMap.put("addresses.region", ContactsContract.CommonDataKinds.StructuredPostal.REGION);
-        dbMap.put("addresses.postalCode", ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE);
-        dbMap.put("addresses.country", ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY);
-        dbMap.put("ims", ContactsContract.CommonDataKinds.Im.DATA);
-        dbMap.put("ims.value", ContactsContract.CommonDataKinds.Im.DATA);
-        dbMap.put("organizations", ContactsContract.CommonDataKinds.Organization.COMPANY);
-        dbMap.put("organizations.name", ContactsContract.CommonDataKinds.Organization.COMPANY);
-        dbMap.put("organizations.department", ContactsContract.CommonDataKinds.Organization.DEPARTMENT);
-        dbMap.put("organizations.title", ContactsContract.CommonDataKinds.Organization.TITLE);
-        dbMap.put("birthday", ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE);
-        dbMap.put("note", ContactsContract.CommonDataKinds.Note.NOTE);
-        dbMap.put("photos.value", ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
-        //dbMap.put("categories.value", null);
-        dbMap.put("urls", ContactsContract.CommonDataKinds.Website.URL);
-        dbMap.put("urls.value", ContactsContract.CommonDataKinds.Website.URL);
-    }
-
-    /**
-     * Create an contact accessor.
-     */
-    public ContactAccessorSdk5(CordovaInterface context) {
-        mApp = context;
-    }
-
-    /**
-     * This method takes the fields required and search options in order to produce an
-     * array of contacts that matches the criteria provided.
-     * @param fields an array of items to be used as search criteria
-     * @param options that can be applied to contact searching
-     * @return an array of contacts
-     */
-    @Override
-    public JSONArray search(JSONArray fields, JSONObject options) {
-        // Get the find options
-        String searchTerm = "";
-        int limit = Integer.MAX_VALUE;
-        boolean multiple = true;
-
-        if (options != null) {
-            searchTerm = options.optString("filter");
-            if (searchTerm.length() == 0) {
-                searchTerm = "%";
-            }
-            else {
-                searchTerm = "%" + searchTerm + "%";
-            }
-            
-            try {
-                multiple = options.getBoolean("multiple");
-                if (!multiple) {
-                    limit = 1;
-                }
-            } catch (JSONException e) {
-                // Multiple was not specified so we assume the default is true.
-            }
-        }
-        else {
-            searchTerm = "%";
-        }
-        
-
-        //Log.d(LOG_TAG, "Search Term = " + searchTerm);
-        //Log.d(LOG_TAG, "Field Length = " + fields.length());
-        //Log.d(LOG_TAG, "Fields = " + fields.toString());
-
-        // Loop through the fields the user provided to see what data should be returned.
-        HashMap<String, Boolean> populate = buildPopulationSet(fields);
-
-        // Build the ugly where clause and where arguments for one big query.
-        WhereOptions whereOptions = buildWhereClause(fields, searchTerm);
-
-        // Get all the id's where the search term matches the fields passed in.
-        Cursor idCursor = mApp.getActivity().getContentResolver().query(ContactsContract.Data.CONTENT_URI,
-                new String[] { ContactsContract.Data.CONTACT_ID },
-                whereOptions.getWhere(),
-                whereOptions.getWhereArgs(),
-                ContactsContract.Data.CONTACT_ID + " ASC");
-
-        // Create a set of unique ids
-        Set<String> contactIds = new HashSet<String>();
-        int idColumn = -1;
-        while (idCursor.moveToNext()) {
-            if (idColumn < 0) {
-                idColumn = idCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
-            }
-            contactIds.add(idCursor.getString(idColumn));
-        }
-        idCursor.close();
-
-        // Build a query that only looks at ids
-        WhereOptions idOptions = buildIdClause(contactIds, searchTerm);
-
-        // Determine which columns we should be fetching.
-        HashSet<String> columnsToFetch = new HashSet<String>();
-        columnsToFetch.add(ContactsContract.Data.CONTACT_ID);
-        columnsToFetch.add(ContactsContract.Data.RAW_CONTACT_ID);
-        columnsToFetch.add(ContactsContract.Data.MIMETYPE);
-        
-        if (isRequired("displayName", populate)) {
-            columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);            
-        }
-        if (isRequired("name", populate)) {
-            columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredName.PREFIX);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredName.SUFFIX);
-        }
-        if (isRequired("phoneNumbers", populate)) {
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Phone._ID);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Phone.NUMBER);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Phone.TYPE);
-        }
-        if (isRequired("emails", populate)) {
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Email._ID);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Email.DATA);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Email.TYPE);
-        }
-        if (isRequired("addresses", populate)) {
-            columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredPostal._ID);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Organization.TYPE);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredPostal.STREET);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredPostal.CITY);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredPostal.REGION);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY);
-        }
-        if (isRequired("organizations", populate)) {
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Organization._ID);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Organization.TYPE);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Organization.DEPARTMENT);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Organization.COMPANY);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Organization.TITLE);
-        }
-        if (isRequired("ims", populate)) {
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Im._ID);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Im.DATA);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Im.TYPE);
-        }
-        if (isRequired("note", populate)) {
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Note.NOTE);
-        }
-        if (isRequired("nickname", populate)) {
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Nickname.NAME);
-        }
-        if (isRequired("urls", populate)) {
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Website._ID);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Website.URL);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Website.TYPE);
-        }
-        if (isRequired("birthday", populate)) {
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Event.START_DATE);
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Event.TYPE);
-        }
-        if (isRequired("photos", populate)) {
-            columnsToFetch.add(ContactsContract.CommonDataKinds.Photo._ID);
-        }
-        
-        // Do the id query
-        Cursor c = mApp.getActivity().getContentResolver().query(ContactsContract.Data.CONTENT_URI,
-                columnsToFetch.toArray(new String[] {}),
-                idOptions.getWhere(),
-                idOptions.getWhereArgs(),
-                ContactsContract.Data.CONTACT_ID + " ASC");
-
-        JSONArray contacts = populateContactArray(limit, populate, c);
-        return contacts;
-    }
-
-    /**
-     * A special search that finds one contact by id
-     *
-     * @param id   contact to find by id
-     * @return     a JSONObject representing the contact
-     * @throws JSONException
-     */
-    public JSONObject getContactById(String id) throws JSONException {
-        // Do the id query
-        Cursor c = mApp.getActivity().getContentResolver().query(ContactsContract.Data.CONTENT_URI,
-                null,
-                ContactsContract.Data.RAW_CONTACT_ID + " = ? ",
-                new String[] { id },
-                ContactsContract.Data.RAW_CONTACT_ID + " ASC");
-
-        JSONArray fields = new JSONArray();
-        fields.put("*");
-
-        HashMap<String, Boolean> populate = buildPopulationSet(fields);
-
-        JSONArray contacts = populateContactArray(1, populate, c);
-
-        if (contacts.length() == 1) {
-            return contacts.getJSONObject(0);
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Creates an array of contacts from the cursor you pass in
-     *
-     * @param limit        max number of contacts for the array
-     * @param populate     whether or not you should populate a certain value
-     * @param c            the cursor
-     * @return             a JSONArray of contacts
-     */
-    private JSONArray populateContactArray(int limit,
-            HashMap<String, Boolean> populate, Cursor c) {
-
-        String contactId = "";
-        String rawId = "";
-        String oldContactId = "";
-        boolean newContact = true;
-        String mimetype = "";
-
-        JSONArray contacts = new JSONArray();
-        JSONObject contact = new JSONObject();
-        JSONArray organizations = new JSONArray();
-        JSONArray addresses = new JSONArray();
-        JSONArray phones = new JSONArray();
-        JSONArray emails = new JSONArray();
-        JSONArray ims = new JSONArray();
-        JSONArray websites = new JSONArray();
-        JSONArray photos = new JSONArray();
-
-        // Column indices
-        int colContactId = c.getColumnIndex(ContactsContract.Data.CONTACT_ID);
-        int colRawContactId = c.getColumnIndex(ContactsContract.Data.RAW_CONTACT_ID);
-        int colMimetype = c.getColumnIndex(ContactsContract.Data.MIMETYPE);
-        int colDisplayName = c.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
-        int colNote = c.getColumnIndex(ContactsContract.CommonDataKinds.Note.NOTE);
-        int colNickname = c.getColumnIndex(ContactsContract.CommonDataKinds.Nickname.NAME);
-        int colBirthday = c.getColumnIndex(ContactsContract.CommonDataKinds.Event.START_DATE);
-        int colEventType = c.getColumnIndex(ContactsContract.CommonDataKinds.Event.TYPE);
-
-        if (c.getCount() > 0) {
-            while (c.moveToNext() && (contacts.length() <= (limit - 1))) {
-                try {
-                    contactId = c.getString(colContactId);
-                    rawId = c.getString(colRawContactId);
-
-                    // If we are in the first row set the oldContactId
-                    if (c.getPosition() == 0) {
-                        oldContactId = contactId;
-                    }
-
-                    // When the contact ID changes we need to push the Contact object
-                    // to the array of contacts and create new objects.
-                    if (!oldContactId.equals(contactId)) {
-                        // Populate the Contact object with it's arrays
-                        // and push the contact into the contacts array
-                        contacts.put(populateContact(contact, organizations, addresses, phones,
-                                emails, ims, websites, photos));
-
-                        // Clean up the objects
-                        contact = new JSONObject();
-                        organizations = new JSONArray();
-                        addresses = new JSONArray();
-                        phones = new JSONArray();
-                        emails = new JSONArray();
-                        ims = new JSONArray();
-                        websites = new JSONArray();
-                        photos = new JSONArray();
-
-                        // Set newContact to true as we are starting to populate a new contact
-                        newContact = true;
-                    }
-
-                    // When we detect a new contact set the ID and display name.
-                    // These fields are available in every row in the result set returned.
-                    if (newContact) {
-                        newContact = false;
-                        contact.put("id", contactId);
-                        contact.put("rawId", rawId);
-                    }
-
-                    // Grab the mimetype of the current row as it will be used in a lot of comparisons
-                    mimetype = c.getString(colMimetype);
-                    
-                    if (mimetype.equals(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)) {
-                        contact.put("displayName", c.getString(colDisplayName));
-                    }
-
-                    if (mimetype.equals(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
-                            && isRequired("name", populate)) {
-                        contact.put("name", nameQuery(c));
-                    }
-                    else if (mimetype.equals(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
-                            && isRequired("phoneNumbers", populate)) {
-                        phones.put(phoneQuery(c));
-                    }
-                    else if (mimetype.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
-                            && isRequired("emails", populate)) {
-                        emails.put(emailQuery(c));
-                    }
-                    else if (mimetype.equals(ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE)
-                            && isRequired("addresses", populate)) {
-                        addresses.put(addressQuery(c));
-                    }
-                    else if (mimetype.equals(ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE)
-                            && isRequired("organizations", populate)) {
-                        organizations.put(organizationQuery(c));
-                    }
-                    else if (mimetype.equals(ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
-                            && isRequired("ims", populate)) {
-                        ims.put(imQuery(c));
-                    }
-                    else if (mimetype.equals(ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE)
-                            && isRequired("note", populate)) {
-                        contact.put("note", c.getString(colNote));
-                    }
-                    else if (mimetype.equals(ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE)
-                            && isRequired("nickname", populate)) {
-                        contact.put("nickname", c.getString(colNickname));
-                    }
-                    else if (mimetype.equals(ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE)
-                            && isRequired("urls", populate)) {
-                        websites.put(websiteQuery(c));
-                    }
-                    else if (mimetype.equals(ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE)) {
-                        if (isRequired("birthday", populate) &&
-                                ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY == c.getInt(colEventType)) {
-                            contact.put("birthday", c.getString(colBirthday));
-                        }
-                    }
-                    else if (mimetype.equals(ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
-                            && isRequired("photos", populate)) {
-                        photos.put(photoQuery(c, contactId));
-                    }
-                } catch (JSONException e) {
-                    Log.e(LOG_TAG, e.getMessage(), e);
-                }
-
-                // Set the old contact ID
-                oldContactId = contactId;
-
-            }
-            
-            // Push the last contact into the contacts array
-            if (contacts.length() < limit) {
-                contacts.put(populateContact(contact, organizations, addresses, phones,
-                        emails, ims, websites, photos));
-            }
-        }
-        c.close();
-        return contacts;
-    }
-
-    /**
-     * Builds a where clause all all the ids passed into the method
-     * @param contactIds a set of unique contact ids
-     * @param searchTerm what to search for
-     * @return an object containing the selection and selection args
-     */
-    private WhereOptions buildIdClause(Set<String> contactIds, String searchTerm) {
-        WhereOptions options = new WhereOptions();
-
-        // If the user is searching for every contact then short circuit the method
-        // and return a shorter where clause to be searched.
-        if (searchTerm.equals("%")) {
-            options.setWhere("(" + ContactsContract.Data.CONTACT_ID + " LIKE ? )");
-            options.setWhereArgs(new String[] { searchTerm });
-            return options;
-        }
-
-        // This clause means that there are specific ID's to be populated
-        Iterator<String> it = contactIds.iterator();
-        StringBuffer buffer = new StringBuffer("(");
-
-        while (it.hasNext()) {
-            buffer.append("'" + it.next() + "'");
-            if (it.hasNext()) {
-                buffer.append(",");
-            }
-        }
-        buffer.append(")");
-
-        options.setWhere(ContactsContract.Data.CONTACT_ID + " IN " + buffer.toString());
-        options.setWhereArgs(null);
-
-        return options;
-    }
-
-    /**
-     * Create a new contact using a JSONObject to hold all the data.
-     * @param contact
-     * @param organizations array of organizations
-     * @param addresses array of addresses
-     * @param phones array of phones
-     * @param emails array of emails
-     * @param ims array of instant messenger addresses
-     * @param websites array of websites
-     * @param photos
-     * @return
-     */
-    private JSONObject populateContact(JSONObject contact, JSONArray organizations,
-            JSONArray addresses, JSONArray phones, JSONArray emails,
-            JSONArray ims, JSONArray websites, JSONArray photos) {
-        try {
-            // Only return the array if it has at least one entry
-            if (organizations.length() > 0) {
-                contact.put("organizations", organizations);
-            }
-            if (addresses.length() > 0) {
-                contact.put("addresses", addresses);
-            }
-            if (phones.length() > 0) {
-                contact.put("phoneNumbers", phones);
-            }
-            if (emails.length() > 0) {
-                contact.put("emails", emails);
-            }
-            if (ims.length() > 0) {
-                contact.put("ims", ims);
-            }
-            if (websites.length() > 0) {
-                contact.put("urls", websites);
-            }
-            if (photos.length() > 0) {
-                contact.put("photos", photos);
-            }
-        } catch (JSONException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-        }
-        return contact;
-    }
-
-  /**
-   * Take the search criteria passed into the method and create a SQL WHERE clause.
-   * @param fields the properties to search against
-   * @param searchTerm the string to search for
-   * @return an object containing the selection and selection args
-   */
-  private WhereOptions buildWhereClause(JSONArray fields, String searchTerm) {
-
-    ArrayList<String> where = new ArrayList<String>();
-    ArrayList<String> whereArgs = new ArrayList<String>();
-
-    WhereOptions options = new WhereOptions();
-
-        /*
-         * Special case where the user wants all fields returned
-         */
-        if (isWildCardSearch(fields)) {
-            // Get all contacts with all properties
-            if ("%".equals(searchTerm)) {
-                options.setWhere("(" + ContactsContract.Contacts.DISPLAY_NAME + " LIKE ? )");
-                options.setWhereArgs(new String[] { searchTerm });
-                return options;
-            } else {
-                // Get all contacts that match the filter but return all properties
-                where.add("(" + dbMap.get("displayName") + " LIKE ? )");
-                whereArgs.add(searchTerm);
-                where.add("(" + dbMap.get("name") + " LIKE ? AND "
-                        + ContactsContract.Data.MIMETYPE + " = ? )");
-                whereArgs.add(searchTerm);
-                whereArgs.add(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
-                where.add("(" + dbMap.get("nickname") + " LIKE ? AND "
-                        + ContactsContract.Data.MIMETYPE + " = ? )");
-                whereArgs.add(searchTerm);
-                whereArgs.add(ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE);
-                where.add("(" + dbMap.get("phoneNumbers") + " LIKE ? AND "
-                        + ContactsContract.Data.MIMETYPE + " = ? )");
-                whereArgs.add(searchTerm);
-                whereArgs.add(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
-                where.add("(" + dbMap.get("emails") + " LIKE ? AND "
-                        + ContactsContract.Data.MIMETYPE + " = ? )");
-                whereArgs.add(searchTerm);
-                whereArgs.add(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
-                where.add("(" + dbMap.get("addresses") + " LIKE ? AND "
-                        + ContactsContract.Data.MIMETYPE + " = ? )");
-                whereArgs.add(searchTerm);
-                whereArgs.add(ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE);
-                where.add("(" + dbMap.get("ims") + " LIKE ? AND "
-                        + ContactsContract.Data.MIMETYPE + " = ? )");
-                whereArgs.add(searchTerm);
-                whereArgs.add(ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE);
-                where.add("(" + dbMap.get("organizations") + " LIKE ? AND "
-                        + ContactsContract.Data.MIMETYPE + " = ? )");
-                whereArgs.add(searchTerm);
-                whereArgs.add(ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
-                where.add("(" + dbMap.get("note") + " LIKE ? AND "
-                        + ContactsContract.Data.MIMETYPE + " = ? )");
-                whereArgs.add(searchTerm);
-                whereArgs.add(ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE);
-                where.add("(" + dbMap.get("urls") + " LIKE ? AND "
-                        + ContactsContract.Data.MIMETYPE + " = ? )");
-                whereArgs.add(searchTerm);
-                whereArgs.add(ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE);
-            }
-        }
-
-        /*
-         * Special case for when the user wants all the contacts but
-         */
-        if ("%".equals(searchTerm)) {
-            options.setWhere("(" + ContactsContract.Contacts.DISPLAY_NAME + " LIKE ? )");
-            options.setWhereArgs(new String[] { searchTerm });
-            return options;
-        }
-
-        String key;
-        try {
-            //Log.d(LOG_TAG, "How many fields do we have = " + fields.length());
-            for (int i = 0; i < fields.length(); i++) {
-                key = fields.getString(i);
-
-                if (key.equals("id")) {
-                    where.add("(" + dbMap.get(key) + " = ? )");
-                    whereArgs.add(searchTerm.substring(1, searchTerm.length() - 1));
-                }
-                else if (key.startsWith("displayName")) {
-                    where.add("(" + dbMap.get(key) + " LIKE ? )");
-                    whereArgs.add(searchTerm);
-                }
-                else if (key.startsWith("name")) {
-                    where.add("(" + dbMap.get(key) + " LIKE ? AND "
-                            + ContactsContract.Data.MIMETYPE + " = ? )");
-                    whereArgs.add(searchTerm);
-                    whereArgs.add(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
-                }
-                else if (key.startsWith("nickname")) {
-                    where.add("(" + dbMap.get(key) + " LIKE ? AND "
-                            + ContactsContract.Data.MIMETYPE + " = ? )");
-                    whereArgs.add(searchTerm);
-                    whereArgs.add(ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE);
-                }
-                else if (key.startsWith("phoneNumbers")) {
-                    where.add("(" + dbMap.get(key) + " LIKE ? AND "
-                            + ContactsContract.Data.MIMETYPE + " = ? )");
-                    whereArgs.add(searchTerm);
-                    whereArgs.add(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
-                }
-                else if (key.startsWith("emails")) {
-                    where.add("(" + dbMap.get(key) + " LIKE ? AND "
-                            + ContactsContract.Data.MIMETYPE + " = ? )");
-                    whereArgs.add(searchTerm);
-                    whereArgs.add(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
-                }
-                else if (key.startsWith("addresses")) {
-                    where.add("(" + dbMap.get(key) + " LIKE ? AND "
-                            + ContactsContract.Data.MIMETYPE + " = ? )");
-                    whereArgs.add(searchTerm);
-                    whereArgs.add(ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE);
-                }
-                else if (key.startsWith("ims")) {
-                    where.add("(" + dbMap.get(key) + " LIKE ? AND "
-                            + ContactsContract.Data.MIMETYPE + " = ? )");
-                    whereArgs.add(searchTerm);
-                    whereArgs.add(ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE);
-                }
-                else if (key.startsWith("organizations")) {
-                    where.add("(" + dbMap.get(key) + " LIKE ? AND "
-                            + ContactsContract.Data.MIMETYPE + " = ? )");
-                    whereArgs.add(searchTerm);
-                    whereArgs.add(ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
-                }
-                //        else if (key.startsWith("birthday")) {
-//          where.add("(" + dbMap.get(key) + " LIKE ? AND "
-//              + ContactsContract.Data.MIMETYPE + " = ? )");
-//        }
-                else if (key.startsWith("note")) {
-                    where.add("(" + dbMap.get(key) + " LIKE ? AND "
-                            + ContactsContract.Data.MIMETYPE + " = ? )");
-                    whereArgs.add(searchTerm);
-                    whereArgs.add(ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE);
-                }
-                else if (key.startsWith("urls")) {
-                    where.add("(" + dbMap.get(key) + " LIKE ? AND "
-                            + ContactsContract.Data.MIMETYPE + " = ? )");
-                    whereArgs.add(searchTerm);
-                    whereArgs.add(ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE);
-                }
-            }
-        } catch (JSONException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-        }
-
-        // Creating the where string
-        StringBuffer selection = new StringBuffer();
-        for (int i = 0; i < where.size(); i++) {
-            selection.append(where.get(i));
-            if (i != (where.size() - 1)) {
-                selection.append(" OR ");
-            }
-        }
-        options.setWhere(selection.toString());
-
-        // Creating the where args array
-        String[] selectionArgs = new String[whereArgs.size()];
-        for (int i = 0; i < whereArgs.size(); i++) {
-            selectionArgs[i] = whereArgs.get(i);
-        }
-        options.setWhereArgs(selectionArgs);
-
-        return options;
-    }
-
-    /**
-     * If the user passes in the '*' wildcard character for search then they want all fields for each contact
-     *
-     * @param fields
-     * @return true if wildcard search requested, false otherwise
-     */
-    private boolean isWildCardSearch(JSONArray fields) {
-        // Only do a wildcard search if we are passed ["*"]
-        if (fields.length() == 1) {
-            try {
-                if ("*".equals(fields.getString(0))) {
-                    return true;
-                }
-            } catch (JSONException e) {
-                return false;
-            }
-        }
-        return false;
-    }
-
-    /**
-    * Create a ContactOrganization JSONObject
-    * @param cursor the current database row
-    * @return a JSONObject representing a ContactOrganization
-    */
-    private JSONObject organizationQuery(Cursor cursor) {
-        JSONObject organization = new JSONObject();
-        try {
-            organization.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization._ID)));
-            organization.put("pref", false); // Android does not store pref attribute
-            organization.put("type", getOrgType(cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TYPE))));
-            organization.put("department", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.DEPARTMENT)));
-            organization.put("name", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.COMPANY)));
-            organization.put("title", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TITLE)));
-        } catch (JSONException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-        }
-        return organization;
-    }
-
-    /**
-     * Create a ContactAddress JSONObject
-     * @param cursor the current database row
-     * @return a JSONObject representing a ContactAddress
-     */
-    private JSONObject addressQuery(Cursor cursor) {
-        JSONObject address = new JSONObject();
-        try {
-            address.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal._ID)));
-            address.put("pref", false); // Android does not store pref attribute
-            address.put("type", getAddressType(cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TYPE))));
-            address.put("formatted", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS)));
-            address.put("streetAddress", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET)));
-            address.put("locality", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY)));
-            address.put("region", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION)));
-            address.put("postalCode", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE)));
-            address.put("country", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY)));
-        } catch (JSONException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-        }
-        return address;
-    }
-
-    /**
-     * Create a ContactName JSONObject
-     * @param cursor the current database row
-     * @return a JSONObject representing a ContactName
-     */
-    private JSONObject nameQuery(Cursor cursor) {
-        JSONObject contactName = new JSONObject();
-        try {
-            String familyName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
-            String givenName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
-            String middleName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME));
-            String honorificPrefix = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.PREFIX));
-            String honorificSuffix = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.SUFFIX));
-
-            // Create the formatted name
-            StringBuffer formatted = new StringBuffer("");
-            if (honorificPrefix != null) {
-                formatted.append(honorificPrefix + " ");
-            }
-            if (givenName != null) {
-                formatted.append(givenName + " ");
-            }
-            if (middleName != null) {
-                formatted.append(middleName + " ");
-            }
-            if (familyName != null) {
-                formatted.append(familyName);
-            }
-            if (honorificSuffix != null) {
-                formatted.append(" " + honorificSuffix);
-            }
-
-            contactName.put("familyName", familyName);
-            contactName.put("givenName", givenName);
-            contactName.put("middleName", middleName);
-            contactName.put("honorificPrefix", honorificPrefix);
-            contactName.put("honorificSuffix", honorificSuffix);
-            contactName.put("formatted", formatted);
-        } catch (JSONException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-        }
-        return contactName;
-    }
-
-    /**
-     * Create a ContactField JSONObject
-     * @param cursor the current database row
-     * @return a JSONObject representing a ContactField
-     */
-    private JSONObject phoneQuery(Cursor cursor) {
-        JSONObject phoneNumber = new JSONObject();
-        try {
-            phoneNumber.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID)));
-            phoneNumber.put("pref", false); // Android does not store pref attribute
-            phoneNumber.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
-            phoneNumber.put("type", getPhoneType(cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE))));
-        } catch (JSONException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-        } catch (Exception excp) {
-            Log.e(LOG_TAG, excp.getMessage(), excp);
-        }
-        return phoneNumber;
-    }
-
-    /**
-     * Create a ContactField JSONObject
-     * @param cursor the current database row
-     * @return a JSONObject representing a ContactField
-     */
-    private JSONObject emailQuery(Cursor cursor) {
-        JSONObject email = new JSONObject();
-        try {
-            email.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email._ID)));
-            email.put("pref", false); // Android does not store pref attribute
-            email.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)));
-            email.put("type", getContactType(cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE))));
-        } catch (JSONException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-        }
-        return email;
-    }
-
-    /**
-     * Create a ContactField JSONObject
-     * @param cursor the current database row
-     * @return a JSONObject representing a ContactField
-     */
-    private JSONObject imQuery(Cursor cursor) {
-        JSONObject im = new JSONObject();
-        try {
-            im.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im._ID)));
-            im.put("pref", false); // Android does not store pref attribute
-            im.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA)));
-            im.put("type", getImType(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im.PROTOCOL))));
-        } catch (JSONException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-        }
-        return im;
-    }
-
-    /**
-     * Create a ContactField JSONObject
-     * @param cursor the current database row
-     * @return a JSONObject representing a ContactField
-     */
-    private JSONObject websiteQuery(Cursor cursor) {
-        JSONObject website = new JSONObject();
-        try {
-            website.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Website._ID)));
-            website.put("pref", false); // Android does not store pref attribute
-            website.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Website.URL)));
-            website.put("type", getContactType(cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Website.TYPE))));
-        } catch (JSONException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-        }
-        return website;
-    }
-
-    /**
-     * Create a ContactField JSONObject
-     * @param contactId
-     * @return a JSONObject representing a ContactField
-     */
-    private JSONObject photoQuery(Cursor cursor, String contactId) {
-        JSONObject photo = new JSONObject();
-        try {
-            photo.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Photo._ID)));
-            photo.put("pref", false);
-            photo.put("type", "url");
-            Uri person = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, (new Long(contactId)));
-            Uri photoUri = Uri.withAppendedPath(person, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
-            photo.put("value", photoUri.toString());
-        } catch (JSONException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-        }
-        return photo;
-    }
-
-    @Override
-    /**
-     * This method will save a contact object into the devices contacts database.
-     *
-     * @param contact the contact to be saved.
-     * @returns the id if the contact is successfully saved, null otherwise.
-     */
-    public String save(JSONObject contact) {
-        AccountManager mgr = AccountManager.get(mApp.getActivity());
-        Account[] accounts = mgr.getAccounts();
-        String accountName = null;
-        String accountType = null;
-
-        if (accounts.length == 1) {
-            accountName = accounts[0].name;
-            accountType = accounts[0].type;
-        }
-        else if (accounts.length > 1) {
-            for (Account a : accounts) {
-                if (a.type.contains("eas") && a.name.matches(EMAIL_REGEXP)) /*Exchange ActiveSync*/{
-                    accountName = a.name;
-                    accountType = a.type;
-                    break;
-                }
-            }
-            if (accountName == null) {
-                for (Account a : accounts) {
-                    if (a.type.contains("com.google") && a.name.matches(EMAIL_REGEXP)) /*Google sync provider*/{
-                        accountName = a.name;
-                        accountType = a.type;
-                        break;
-                    }
-                }
-            }
-            if (accountName == null) {
-                for (Account a : accounts) {
-                    if (a.name.matches(EMAIL_REGEXP)) /*Last resort, just look for an email address...*/{
-                        accountName = a.name;
-                        accountType = a.type;
-                        break;
-                    }
-                }
-            }
-        }
-
-        String id = getJsonString(contact, "id");
-        if (id == null) {
-            // Create new contact
-            return createNewContact(contact, accountType, accountName);
-        } else {
-            // Modify existing contact
-            return modifyContact(id, contact, accountType, accountName);
-        }
-    }
-
-    /**
-     * Creates a new contact and stores it in the database
-     *
-     * @param id the raw contact id which is required for linking items to the contact
-     * @param contact the contact to be saved
-     * @param account the account to be saved under
-     */
-    private String modifyContact(String id, JSONObject contact, String accountType, String accountName) {
-        // Get the RAW_CONTACT_ID which is needed to insert new values in an already existing contact.
-        // But not needed to update existing values.
-        int rawId = (new Integer(getJsonString(contact, "rawId"))).intValue();
-
-        // Create a list of attributes to add to the contact database
-        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
-
-        //Add contact type
-        ops.add(ContentProviderOperation.newUpdate(ContactsContract.RawContacts.CONTENT_URI)
-                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
-                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
-                .build());
-
-        // Modify name
-        JSONObject name;
-        try {
-            String displayName = getJsonString(contact, "displayName");
-            name = contact.getJSONObject("name");
-            if (displayName != null || name != null) {
-                ContentProviderOperation.Builder builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
-                        .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " +
-                                ContactsContract.Data.MIMETYPE + "=?",
-                                new String[] { id, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE });
-
-                if (displayName != null) {
-                    builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName);
-                }
-
-                String familyName = getJsonString(name, "familyName");
-                if (familyName != null) {
-                    builder.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, familyName);
-                }
-                String middleName = getJsonString(name, "middleName");
-                if (middleName != null) {
-                    builder.withValue(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME, middleName);
-                }
-                String givenName = getJsonString(name, "givenName");
-                if (givenName != null) {
-                    builder.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, givenName);
-                }
-                String honorificPrefix = getJsonString(name, "honorificPrefix");
-                if (honorificPrefix != null) {
-                    builder.withValue(ContactsContract.CommonDataKinds.StructuredName.PREFIX, honorificPrefix);
-                }
-                String honorificSuffix = getJsonString(name, "honorificSuffix");
-                if (honorificSuffix != null) {
-                    builder.withValue(ContactsContract.CommonDataKinds.StructuredName.SUFFIX, honorificSuffix);
-                }
-
-                ops.add(builder.build());
-            }
-        } catch (JSONException e1) {
-            Log.d(LOG_TAG, "Could not get name");
-        }
-
-        // Modify phone numbers
-        JSONArray phones = null;
-        try {
-            phones = contact.getJSONArray("phoneNumbers");
-            if (phones != null) {
-                // Delete all the phones
-                if (phones.length() == 0) {
-                    ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
-                            .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
-                                    ContactsContract.Data.MIMETYPE + "=?",
-                                    new String[] { "" + rawId, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE })
-                            .build());
-                }
-                // Modify or add a phone
-                else {
-                    for (int i = 0; i < phones.length(); i++) {
-                        JSONObject phone = (JSONObject) phones.get(i);
-                        String phoneId = getJsonString(phone, "id");
-                        // This is a new phone so do a DB insert
-                        if (phoneId == null) {
-                            ContentValues contentValues = new ContentValues();
-                            contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
-                            contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
-                            contentValues.put(ContactsContract.CommonDataKinds.Phone.NUMBER, getJsonString(phone, "value"));
-                            contentValues.put(ContactsContract.CommonDataKinds.Phone.TYPE, getPhoneType(getJsonString(phone, "type")));
-
-                            ops.add(ContentProviderOperation.newInsert(
-                                    ContactsContract.Data.CONTENT_URI).withValues(contentValues).build());
-                        }
-                        // This is an existing phone so do a DB update
-                        else {
-                            ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
-                                    .withSelection(ContactsContract.CommonDataKinds.Phone._ID + "=? AND " +
-                                            ContactsContract.Data.MIMETYPE + "=?",
-                                            new String[] { phoneId, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE })
-                                    .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, getJsonString(phone, "value"))
-                                    .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, getPhoneType(getJsonString(phone, "type")))
-                                    .build());
-                        }
-                    }
-                }
-            }
-        } catch (JSONException e) {
-            Log.d(LOG_TAG, "Could not get phone numbers");
-        }
-
-        // Modify emails
-        JSONArray emails = null;
-        try {
-            emails = contact.getJSONArray("emails");
-            if (emails != null) {
-                // Delete all the emails
-                if (emails.length() == 0) {
-                    ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
-                            .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
-                                    ContactsContract.Data.MIMETYPE + "=?",
-                                    new String[] { "" + rawId, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE })
-                            .build());
-                }
-                // Modify or add a email
-                else {
-                    for (int i = 0; i < emails.length(); i++) {
-                        JSONObject email = (JSONObject) emails.get(i);
-                        String emailId = getJsonString(email, "id");
-                        // This is a new email so do a DB insert
-                        if (emailId == null) {
-                            ContentValues contentValues = new ContentValues();
-                            contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
-                            contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
-                            contentValues.put(ContactsContract.CommonDataKinds.Email.DATA, getJsonString(email, "value"));
-                            contentValues.put(ContactsContract.CommonDataKinds.Email.TYPE, getContactType(getJsonString(email, "type")));
-
-                            ops.add(ContentProviderOperation.newInsert(
-                                    ContactsContract.Data.CONTENT_URI).withValues(contentValues).build());
-                        }
-                        // This is an existing email so do a DB update
-                        else {
-                        	String emailValue=getJsonString(email, "value");
-                        	if(!emailValue.isEmpty()) {
-                                ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
-                                    .withSelection(ContactsContract.CommonDataKinds.Email._ID + "=? AND " +
-                                            ContactsContract.Data.MIMETYPE + "=?",
-                                            new String[] { emailId, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE })
-                                    .withValue(ContactsContract.CommonDataKinds.Email.DATA, getJsonString(email, "value"))
-                                    .withValue(ContactsContract.CommonDataKinds.Email.TYPE, getContactType(getJsonString(email, "type")))
-                                    .build());
-                        	} else {
-                                ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
-                                        .withSelection(ContactsContract.CommonDataKinds.Email._ID + "=? AND " +
-                                                ContactsContract.Data.MIMETYPE + "=?",
-                                                new String[] { emailId, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE })
-                                        .build());
-                        	}
-                        }
-                    }
-                }
-            }
-        } catch (JSONException e) {
-            Log.d(LOG_TAG, "Could not get emails");
-        }
-
-        // Modify addresses
-        JSONArray addresses = null;
-        try {
-            addresses = contact.getJSONArray("addresses");
-            if (addresses != null) {
-                // Delete all the addresses
-                if (addresses.length() == 0) {
-                    ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
-                            .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
-                                    ContactsContract.Data.MIMETYPE + "=?",
-                                    new String[] { "" + rawId, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE })
-                            .build());
-                }
-                // Modify or add a address
-                else {
-                    for (int i = 0; i < addresses.length(); i++) {
-                        JSONObject address = (JSONObject) addresses.get(i);
-                        String addressId = getJsonString(address, "id");
-                        // This is a new address so do a DB insert
-                        if (addressId == null) {
-                            ContentValues contentValues = new ContentValues();
-                            contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
-                            contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE);
-                            contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.TYPE, getAddressType(getJsonString(address, "type")));
-                            contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS, getJsonString(address, "formatted"));
-                            contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.STREET, getJsonString(address, "streetAddress"));
-                            contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.CITY, getJsonString(address, "locality"));
-                            contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.REGION, getJsonString(address, "region"));
-                            contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE, getJsonString(address, "postalCode"));
-                            contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY, getJsonString(address, "country"));
-
-                            ops.add(ContentProviderOperation.newInsert(
-                                    ContactsContract.Data.CONTENT_URI).withValues(contentValues).build());
-                        }
-                        // This is an existing address so do a DB update
-                        else {
-                            ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
-                                    .withSelection(ContactsContract.CommonDataKinds.StructuredPostal._ID + "=? AND " +
-                                            ContactsContract.Data.MIMETYPE + "=?",
-                                            new String[] { addressId, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE })
-                                    .withValue(ContactsContract.CommonDataKinds.StructuredPostal.TYPE, getAddressType(getJsonString(address, "type")))
-                                    .withValue(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS, getJsonString(address, "formatted"))
-                                    .withValue(ContactsContract.CommonDataKinds.StructuredPostal.STREET, getJsonString(address, "streetAddress"))
-                                    .withValue(ContactsContract.CommonDataKinds.StructuredPostal.CITY, getJsonString(address, "locality"))
-                                    .withValue(ContactsContract.CommonDataKinds.StructuredPostal.REGION, getJsonString(address, "region"))
-                                    .withValue(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE, getJsonString(address, "postalCode"))
-                                    .withValue(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY, getJsonString(address, "country"))
-                                    .build());
-                        }
-                    }
-                }
-            }
-        } catch (JSONException e) {
-            Log.d(LOG_TAG, "Could not get addresses");
-        }
-
-        // Modify organizations
-        JSONArray organizations = null;
-        try {
-            organizations = contact.getJSONArray("organizations");
-            if (organizations != null) {
-                // Delete all the organizations
-                if (organizations.length() == 0) {
-                    ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
-                            .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
-                                    ContactsContract.Data.MIMETYPE + "=?",
-                                    new String[] { "" + rawId, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE })
-                            .build());
-                }
-                // Modify or add a organization
-                else {
-                    for (int i = 0; i < organizations.length(); i++) {
-                        JSONObject org = (JSONObject) organizations.get(i);
-                        String orgId = getJsonString(org, "id");
-                        // This is a new organization so do a DB insert
-                        if (orgId == null) {
-                            ContentValues contentValues = new ContentValues();
-                            contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
-                            contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
-                            contentValues.put(ContactsContract.CommonDataKinds.Organization.TYPE, getOrgType(getJsonString(org, "type")));
-                            contentValues.put(ContactsContract.CommonDataKinds.Organization.DEPARTMENT, getJsonString(org, "department"));
-                            contentValues.put(ContactsContract.CommonDataKinds.Organization.COMPANY, getJsonString(org, "name"));
-                            contentValues.put(ContactsContract.CommonDataKinds.Organization.TITLE, getJsonString(org, "title"));
-
-                            ops.add(ContentProviderOperation.newInsert(
-                                    ContactsContract.Data.CONTENT_URI).withValues(contentValues).build());
-                        }
-                        // This is an existing organization so do a DB update
-                        else {
-                            ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
-                                    .withSelection(ContactsContract.CommonDataKinds.Organization._ID + "=? AND " +
-                                            ContactsContract.Data.MIMETYPE + "=?",
-                                            new String[] { orgId, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE })
-                                    .withValue(ContactsContract.CommonDataKinds.Organization.TYPE, getOrgType(getJsonString(org, "type")))
-                                    .withValue(ContactsContract.CommonDataKinds.Organization.DEPARTMENT, getJsonString(org, "department"))
-                                    .withValue(ContactsContract.CommonDataKinds.Organization.COMPANY, getJsonString(org, "name"))
-                                    .withValue(ContactsContract.CommonDataKinds.Organization.TITLE, getJsonString(org, "title"))
-                                    .build());
-                        }
-                    }
-                }
-            }
-        } catch (JSONException e) {
-            Log.d(LOG_TAG, "Could not get organizations");
-        }
-
-        // Modify IMs
-        JSONArray ims = null;
-        try {
-            ims = contact.getJSONArray("ims");
-            if (ims != null) {
-                // Delete all the ims
-                if (ims.length() == 0) {
-                    ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
-                            .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
-                                    ContactsContract.Data.MIMETYPE + "=?",
-                                    new String[] { "" + rawId, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE })
-                            .build());
-                }
-                // Modify or add a im
-                else {
-                    for (int i = 0; i < ims.length(); i++) {
-                        JSONObject im = (JSONObject) ims.get(i);
-                        String imId = getJsonString(im, "id");
-                        // This is a new IM so do a DB insert
-                        if (imId == null) {
-                            ContentValues contentValues = new ContentValues();
-                            contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
-                            contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE);
-                            contentValues.put(ContactsContract.CommonDataKinds.Im.DATA, getJsonString(im, "value"));
-                            contentValues.put(ContactsContract.CommonDataKinds.Im.TYPE, getImType(getJsonString(im, "type")));
-
-                            ops.add(ContentProviderOperation.newInsert(
-                                    ContactsContract.Data.CONTENT_URI).withValues(contentValues).build());
-                        }
-                        // This is an existing IM so do a DB update
-                        else {
-                            ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
-                                    .withSelection(ContactsContract.CommonDataKinds.Im._ID + "=? AND " +
-                                            ContactsContract.Data.MIMETYPE + "=?",
-                                            new String[] { imId, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE })
-                                    .withValue(ContactsContract.CommonDataKinds.Im.DATA, getJsonString(im, "value"))
-                                    .withValue(ContactsContract.CommonDataKinds.Im.TYPE, getContactType(getJsonString(im, "type")))
-                                    .build());
-                        }
-                    }
-                }
-            }
-        } catch (JSONException e) {
-            Log.d(LOG_TAG, "Could not get emails");
-        }
-
-        // Modify note
-        String note = getJsonString(contact, "note");
-        ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
-                .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " +
-                        ContactsContract.Data.MIMETYPE + "=?",
-                        new String[] { id, ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE })
-                .withValue(ContactsContract.CommonDataKinds.Note.NOTE, note)
-                .build());
-
-        // Modify nickname
-        String nickname = getJsonString(contact, "nickname");
-        if (nickname != null) {
-            ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
-                    .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " +
-                            ContactsContract.Data.MIMETYPE + "=?",
-                            new String[] { id, ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE })
-                    .withValue(ContactsContract.CommonDataKinds.Nickname.NAME, nickname)
-                    .build());
-        }
-
-        // Modify urls
-        JSONArray websites = null;
-        try {
-            websites = contact.getJSONArray("urls");
-            if (websites != null) {
-                // Delete all the websites
-                if (websites.length() == 0) {
-                    Log.d(LOG_TAG, "This means we should be deleting all the phone numbers.");
-                    ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
-                            .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
-                                    ContactsContract.Data.MIMETYPE + "=?",
-                                    new String[] { "" + rawId, ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE })
-                            .build());
-                }
-                // Modify or add a website
-                else {
-                    for (int i = 0; i < websites.length(); i++) {
-                        JSONObject website = (JSONObject) websites.get(i);
-                        String websiteId = getJsonString(website, "id");
-                        // This is a new website so do a DB insert
-                        if (websiteId == null) {
-                            ContentValues contentValues = new ContentValues();
-                            contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
-                            contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE);
-                            contentValues.put(ContactsContract.CommonDataKinds.Website.DATA, getJsonString(website, "value"));
-                            contentValues.put(ContactsContract.CommonDataKinds.Website.TYPE, getContactType(getJsonString(website, "type")));
-
-                            ops.add(ContentProviderOperation.newInsert(
-                                    ContactsContract.Data.CONTENT_URI).withValues(contentValues).build());
-                        }
-                        // This is an existing website so do a DB update
-                        else {
-                            ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
-                                    .withSelection(ContactsContract.CommonDataKinds.Website._ID + "=? AND " +
-                                            ContactsContract.Data.MIMETYPE + "=?",
-                                            new String[] { websiteId, ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE })
-                                    .withValue(ContactsContract.CommonDataKinds.Website.DATA, getJsonString(website, "value"))
-                                    .withValue(ContactsContract.CommonDataKinds.Website.TYPE, getContactType(getJsonString(website, "type")))
-                                    .build());
-                        }
-                    }
-                }
-            }
-        } catch (JSONException e) {
-            Log.d(LOG_TAG, "Could not get websites");
-        }
-
-        // Modify birthday
-        String birthday = getJsonString(contact, "birthday");
-        if (birthday != null) {
-            ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
-                    .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " +
-                            ContactsContract.Data.MIMETYPE + "=? AND " +
-                            ContactsContract.CommonDataKinds.Event.TYPE + "=?",
-                            new String[] { id, ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE, new String("" + ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY) })
-                    .withValue(ContactsContract.CommonDataKinds.Event.TYPE, ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY)
-                    .withValue(ContactsContract.CommonDataKinds.Event.START_DATE, birthday)
-                    .build());
-        }
-
-        // Modify photos
-        JSONArray photos = null;
-        try {
-            photos = contact.getJSONArray("photos");
-            if (photos != null) {
-                // Delete all the photos
-                if (photos.length() == 0) {
-                    ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
-                            .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
-                                    ContactsContract.Data.MIMETYPE + "=?",
-                                    new String[] { "" + rawId, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE })
-                            .build());
-                }
-                // Modify or add a photo
-                else {
-                    for (int i = 0; i < photos.length(); i++) {
-                        JSONObject photo = (JSONObject) photos.get(i);
-                        String photoId = getJsonString(photo, "id");
-                        byte[] bytes = getPhotoBytes(getJsonString(photo, "value"));
-                        // This is a new photo so do a DB insert
-                        if (photoId == null) {
-                            ContentValues contentValues = new ContentValues();
-                            contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
-                            contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
-                            contentValues.put(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
-                            contentValues.put(ContactsContract.CommonDataKinds.Photo.PHOTO, bytes);
-
-                            ops.add(ContentProviderOperation.newInsert(
-                                    ContactsContract.Data.CONTENT_URI).withValues(contentValues).build());
-                        }
-                        // This is an existing photo so do a DB update
-                        else {
-                            ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
-                                    .withSelection(ContactsContract.CommonDataKinds.Photo._ID + "=? AND " +
-                                            ContactsContract.Data.MIMETYPE + "=?",
-                                            new String[] { photoId, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE })
-                                    .withValue(ContactsContract.Data.IS_SUPER_PRIMARY, 1)
-                                    .withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, bytes)
-                                    .build());
-                        }
-                    }
-                }
-            }
-        } catch (JSONException e) {
-            Log.d(LOG_TAG, "Could not get photos");
-        }
-
-        boolean retVal = true;
-
-        //Modify contact
-        try {
-            mApp.getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
-        } catch (RemoteException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-            Log.e(LOG_TAG, Log.getStackTraceString(e), e);
-            retVal = false;
-        } catch (OperationApplicationException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-            Log.e(LOG_TAG, Log.getStackTraceString(e), e);
-            retVal = false;
-        }
-
-        // if the save was a success return the contact ID
-        if (retVal) {
-            return id;
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Add a website to a list of database actions to be performed
-     *
-     * @param ops the list of database actions
-     * @param website the item to be inserted
-     */
-    private void insertWebsite(ArrayList<ContentProviderOperation> ops,
-            JSONObject website) {
-        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
-                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
-                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE)
-                .withValue(ContactsContract.CommonDataKinds.Website.DATA, getJsonString(website, "value"))
-                .withValue(ContactsContract.CommonDataKinds.Website.TYPE, getContactType(getJsonString(website, "type")))
-                .build());
-    }
-
-    /**
-     * Add an im to a list of database actions to be performed
-     *
-     * @param ops the list of database actions
-     * @param im the item to be inserted
-     */
-    private void insertIm(ArrayList<ContentProviderOperation> ops, JSONObject im) {
-        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
-                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
-                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
-                .withValue(ContactsContract.CommonDataKinds.Im.DATA, getJsonString(im, "value"))
-                .withValue(ContactsContract.CommonDataKinds.Im.TYPE, getImType(getJsonString(im, "type")))
-                .build());
-    }
-
-    /**
-     * Add an organization to a list of database actions to be performed
-     *
-     * @param ops the list of database actions
-     * @param org the item to be inserted
-     */
-    private void insertOrganization(ArrayList<ContentProviderOperation> ops,
-            JSONObject org) {
-        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
-                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
-                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE)
-                .withValue(ContactsContract.CommonDataKinds.Organization.TYPE, getOrgType(getJsonString(org, "type")))
-                .withValue(ContactsContract.CommonDataKinds.Organization.DEPARTMENT, getJsonString(org, "department"))
-                .withValue(ContactsContract.CommonDataKinds.Organization.COMPANY, getJsonString(org, "name"))
-                .withValue(ContactsContract.CommonDataKinds.Organization.TITLE, getJsonString(org, "title"))
-                .build());
-    }
-
-    /**
-     * Add an address to a list of database actions to be performed
-     *
-     * @param ops the list of database actions
-     * @param address the item to be inserted
-     */
-    private void insertAddress(ArrayList<ContentProviderOperation> ops,
-            JSONObject address) {
-        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
-                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
-                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE)
-                .withValue(ContactsContract.CommonDataKinds.StructuredPostal.TYPE, getAddressType(getJsonString(address, "type")))
-                .withValue(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS, getJsonString(address, "formatted"))
-                .withValue(ContactsContract.CommonDataKinds.StructuredPostal.STREET, getJsonString(address, "streetAddress"))
-                .withValue(ContactsContract.CommonDataKinds.StructuredPostal.CITY, getJsonString(address, "locality"))
-                .withValue(ContactsContract.CommonDataKinds.StructuredPostal.REGION, getJsonString(address, "region"))
-                .withValue(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE, getJsonString(address, "postalCode"))
-                .withValue(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY, getJsonString(address, "country"))
-                .build());
-    }
-
-    /**
-     * Add an email to a list of database actions to be performed
-     *
-     * @param ops the list of database actions
-     * @param email the item to be inserted
-     */
-    private void insertEmail(ArrayList<ContentProviderOperation> ops,
-            JSONObject email) {
-        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
-                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
-                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
-                .withValue(ContactsContract.CommonDataKinds.Email.DATA, getJsonString(email, "value"))
-                .withValue(ContactsContract.CommonDataKinds.Email.TYPE, getContactType(getJsonString(email, "type")))
-                .build());
-    }
-
-    /**
-     * Add a phone to a list of database actions to be performed
-     *
-     * @param ops the list of database actions
-     * @param phone the item to be inserted
-     */
-    private void insertPhone(ArrayList<ContentProviderOperation> ops,
-            JSONObject phone) {
-        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
-                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
-                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
-                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, getJsonString(phone, "value"))
-                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, getPhoneType(getJsonString(phone, "type")))
-                .build());
-    }
-
-    /**
-     * Add a phone to a list of database actions to be performed
-     *
-     * @param ops the list of database actions
-     * @param phone the item to be inserted
-     */
-    private void insertPhoto(ArrayList<ContentProviderOperation> ops,
-            JSONObject photo) {
-        byte[] bytes = getPhotoBytes(getJsonString(photo, "value"));
-        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
-                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
-                .withValue(ContactsContract.Data.IS_SUPER_PRIMARY, 1)
-                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
-                .withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, bytes)
-                .build());
-    }
-
-    /**
-     * Gets the raw bytes from the supplied filename
-     *
-     * @param filename the file to read the bytes from
-     * @return a byte array
-     * @throws IOException
-     */
-    private byte[] getPhotoBytes(String filename) {
-        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-        try {
-            int bytesRead = 0;
-            long totalBytesRead = 0;
-            byte[] data = new byte[8192];
-            InputStream in = getPathFromUri(filename);
-
-            while ((bytesRead = in.read(data, 0, data.length)) != -1 && totalBytesRead <= MAX_PHOTO_SIZE) {
-                buffer.write(data, 0, bytesRead);
-                totalBytesRead += bytesRead;
-            }
-
-            in.close();
-            buffer.flush();
-        } catch (FileNotFoundException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-        } catch (IOException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-        }
-        return buffer.toByteArray();
-    }
-
-    /**
-       * Get an input stream based on file path or uri content://, http://, file://
-       *
-       * @param path
-       * @return an input stream
-     * @throws IOException
-       */
-    private InputStream getPathFromUri(String path) throws IOException {
-        if (path.startsWith("content:")) {
-            Uri uri = Uri.parse(path);
-            return mApp.getActivity().getContentResolver().openInputStream(uri);
-        }
-        if (path.startsWith("http:") || path.startsWith("https:") || path.startsWith("file:")) {
-            URL url = new URL(path);
-            return url.openStream();
-        }
-        else {
-            return new FileInputStream(path);
-        }
-    }
-
-    /**
-     * Creates a new contact and stores it in the database
-     *
-     * @param contact the contact to be saved
-     * @param account the account to be saved under
-     */
-    private String createNewContact(JSONObject contact, String accountType, String accountName) {
-        // Create a list of attributes to add to the contact database
-        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
-
-        //Add contact type
-        ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
-                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
-                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
-                .build());
-
-        // Add name
-        try {
-            JSONObject name = contact.optJSONObject("name");
-            String displayName = contact.getString("displayName");
-            if (displayName != null || name != null) {
-                ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
-                        .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
-                        .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
-                        .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName)
-                        .withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, getJsonString(name, "familyName"))
-                        .withValue(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME, getJsonString(name, "middleName"))
-                        .withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, getJsonString(name, "givenName"))
-                        .withValue(ContactsContract.CommonDataKinds.StructuredName.PREFIX, getJsonString(name, "honorificPrefix"))
-                        .withValue(ContactsContract.CommonDataKinds.StructuredName.SUFFIX, getJsonString(name, "honorificSuffix"))
-                        .build());
-            }
-        } catch (JSONException e) {
-            Log.d(LOG_TAG, "Could not get name object");
-        }
-
-        //Add phone numbers
-        JSONArray phones = null;
-        try {
-            phones = contact.getJSONArray("phoneNumbers");
-            if (phones != null) {
-                for (int i = 0; i < phones.length(); i++) {
-                    JSONObject phone = (JSONObject) phones.get(i);
-                    insertPhone(ops, phone);
-                }
-            }
-        } catch (JSONException e) {
-            Log.d(LOG_TAG, "Could not get phone numbers");
-        }
-
-        // Add emails
-        JSONArray emails = null;
-        try {
-            emails = contact.getJSONArray("emails");
-            if (emails != null) {
-                for (int i = 0; i < emails.length(); i++) {
-                    JSONObject email = (JSONObject) emails.get(i);
-                    insertEmail(ops, email);
-                }
-            }
-        } catch (JSONException e) {
-            Log.d(LOG_TAG, "Could not get emails");
-        }
-
-        // Add addresses
-        JSONArray addresses = null;
-        try {
-            addresses = contact.getJSONArray("addresses");
-            if (addresses != null) {
-                for (int i = 0; i < addresses.length(); i++) {
-                    JSONObject address = (JSONObject) addresses.get(i);
-                    insertAddress(ops, address);
-                }
-            }
-        } catch (JSONException e) {
-            Log.d(LOG_TAG, "Could not get addresses");
-        }
-
-        // Add organizations
-        JSONArray organizations = null;
-        try {
-            organizations = contact.getJSONArray("organizations");
-            if (organizations != null) {
-                for (int i = 0; i < organizations.length(); i++) {
-                    JSONObject org = (JSONObject) organizations.get(i);
-                    insertOrganization(ops, org);
-                }
-            }
-        } catch (JSONException e) {
-            Log.d(LOG_TAG, "Could not get organizations");
-        }
-
-        // Add IMs
-        JSONArray ims = null;
-        try {
-            ims = contact.getJSONArray("ims");
-            if (ims != null) {
-                for (int i = 0; i < ims.length(); i++) {
-                    JSONObject im = (JSONObject) ims.get(i);
-                    insertIm(ops, im);
-                }
-            }
-        } catch (JSONException e) {
-            Log.d(LOG_TAG, "Could not get emails");
-        }
-
-        // Add note
-        String note = getJsonString(contact, "note");
-        if (note != null) {
-            ops.add(ContentP

<TRUNCATED>

[6/6] git commit: CB-6521: Remove development branch

Posted by ia...@apache.org.
CB-6521: Remove development branch


Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/commit/fc255252
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/tree/fc255252
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/diff/fc255252

Branch: refs/heads/dev
Commit: fc2552522b6465301b1787dfe0d4730f83bddd73
Parents: 55ba3f2
Author: Ian Clelland <ic...@chromium.org>
Authored: Fri Apr 25 14:09:46 2014 -0400
Committer: Ian Clelland <ic...@chromium.org>
Committed: Fri Apr 25 14:09:46 2014 -0400

----------------------------------------------------------------------
 LICENSE                                 |  202 ---
 NOTICE                                  |    5 -
 README.md                               |    2 +
 RELEASENOTES.md                         |   84 -
 doc/index.md                            |  687 --------
 plugin.xml                              |  215 ---
 src/android/ContactAccessor.java        |  196 ---
 src/android/ContactAccessorSdk5.java    | 2181 --------------------------
 src/android/ContactManager.java         |  122 --
 src/blackberry10/ContactActivity.js     |   31 -
 src/blackberry10/ContactAddress.js      |   35 -
 src/blackberry10/ContactError.js        |   35 -
 src/blackberry10/ContactField.js        |   32 -
 src/blackberry10/ContactFindOptions.js  |   55 -
 src/blackberry10/ContactName.js         |   44 -
 src/blackberry10/ContactNews.js         |   31 -
 src/blackberry10/ContactOrganization.js |   27 -
 src/blackberry10/ContactPhoto.js        |   28 -
 src/blackberry10/contactConsts.js       |  225 ---
 src/blackberry10/contactUtils.js        |  228 ---
 src/blackberry10/index.js               |  374 -----
 src/firefoxos/ContactsProxy.js          |  464 ------
 src/ios/CDVContact.h                    |  136 --
 src/ios/CDVContact.m                    | 1752 ---------------------
 src/ios/CDVContacts.h                   |  151 --
 src/ios/CDVContacts.m                   |  604 -------
 src/ubuntu/contacts.cpp                 |  576 -------
 src/ubuntu/contacts.h                   |   70 -
 src/windows8/ContactProxy.js            |  151 --
 src/wp/Contacts.cs                      |  693 --------
 www/Contact.js                          |  177 ---
 www/ContactAddress.js                   |   46 -
 www/ContactError.js                     |   42 -
 www/ContactField.js                     |   37 -
 www/ContactFindOptions.js               |   34 -
 www/ContactName.js                      |   41 -
 www/ContactOrganization.js              |   44 -
 www/contacts.js                         |   76 -
 www/ios/Contact.js                      |   51 -
 www/ios/contacts.js                     |   62 -
 40 files changed, 2 insertions(+), 10044 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 7a4a3ea..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/NOTICE
----------------------------------------------------------------------
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index 8ec56a5..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,5 +0,0 @@
-Apache Cordova
-Copyright 2012 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 5b74138..07daee6 100644
--- a/README.md
+++ b/README.md
@@ -20,3 +20,5 @@
 # org.apache.cordova.contacts
 
 Plugin documentation: [doc/index.md](doc/index.md)
+
+This is `dev` - the deprecated development branch of this plugin; development of this plugin has moved to the `master` branch

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/RELEASENOTES.md
----------------------------------------------------------------------
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
deleted file mode 100644
index 30f2c2f..0000000
--- a/RELEASENOTES.md
+++ /dev/null
@@ -1,84 +0,0 @@
-<!--
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-# 
-# http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#  KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
--->
-# Release Notes
-
-### 0.2.1 (Sept 5, 2013)
-* [CB-4580] Fixed up duplicate definitions of module id
-* [CB-4432] Copyright notice change
-
-### 0.2.3 (Sept 25, 2013)
-* CB-4889 bumping&resetting version
-* [BlackBerry10] removed uneeded permission tags in plugin.xml
-* [BlackBerry10] removed uneeded permission tags in plugin.xml
-* CB-4889 renaming blackberry10 reference in plugin.xml
-* CB-4888 renaming org.apache.cordova.core.contacts to org.apache.cordova.contacts
-* added contacts api for firefoxos
-* Rename CHANGELOG.md -> RELEASENOTES.md
-* [CB-4824] Fix XCode 5 contacts plugin warnings
-* [CB-4752] Incremented plugin version on dev branch.
-
-### 0.2.4 (Oct 9, 2013)
-* [CB-4950] Remove the dependence on concrete component android.webkit.WebView.
-* [CB-4915] Incremented plugin version on dev branch.
-
- ### 0.2.5 (Oct 28, 2013)
-* CB-5128: added repo + issue tags for contacts
-* [CB-5010] Incremented plugin version on dev branch.
-
-### 0.2.6 (Dec 4, 2013)
-* Fix bad commit/merge
-* CB-3035 Fix issue with windows new line char \n\r
-* wrong example given
-* docs added
-* FxOS name fields are arrays hackedSearch refactored search based on find commented out
-* search hacked via getAll
-* search added - no idea if this is working
-* createMozillaFromCordova and vice versa are used to translate contact objects from one API to another.
-* add/remove working
-* save is working
-* attempt to save is failing trying to limit the translated contact fields to name and familyName, but still failing
-* save is linked with the proxy contact.name doesn't exist www/Contact.js#Contact.prototype.save check on which side is the error
-* CB-5214 Make mobile spec tests on WP8 to run w/o user interaction + Sync with cordova-mobile-spec
-* CB-5525 WP8. Contacts Api fails in case of there is special character in contact field
-* fixed ubuntu policy error
-* [ubuntu] specify policy_group
-* add ubuntu platform
-* CB-3035 Fix issue with windows new line char \n\r
-* 1. Added amazon-fireos platform. 2. Change to use amazon-fireos as the platform if user agent string contains 'cordova-amazon-fireos'.
-* CB-5198 [BlackBerry10] Update dependencies to point to registry
-* handle null filter when fields are specified. ( long standing pull-req from @kevfromireland )
-
-### 0.2.7 (Jan 02, 2014)
-* B-5658 Add doc/index.md for Contacts plugin
-
-### 0.2.8 (Feb 05, 2014)
-* [CB-3208] FFOS docs updated
-* CB-4590 - chooseContact in CDVContacts crashes app
-
-### 0.2.9 (Feb 26, 2014)
-* CB-6086 Fix typo in ffos part of plugin.xml: Camera -> Contacts
-* CB-5994 Switch Contact ID lookup to use Raw contact id.
-
-### 0.2.10 (Apr 17, 2014)
-* CB-6126: [BlackBerry10] Update docs quirks section for fields which are supported
-* CB-6212: [iOS] fix warnings compiled under arm64 64-bit
-* CB-6460: Update license headers
-* Add NOTICE file

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/doc/index.md
----------------------------------------------------------------------
diff --git a/doc/index.md b/doc/index.md
deleted file mode 100644
index 83f5a30..0000000
--- a/doc/index.md
+++ /dev/null
@@ -1,687 +0,0 @@
-<!---
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing,
-    software distributed under the License is distributed on an
-    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-    KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
--->
-
-# org.apache.cordova.contacts
-
-Provides access to the device contacts database.
-
-__WARNING__: Collection and use of contact data raises
-important privacy issues.  Your app's privacy policy should discuss
-how the app uses contact data and whether it is shared with any other
-parties.  Contact information is considered sensitive because it
-reveals the people with whom a person communicates.  Therefore, in
-addition to the app's privacy policy, you should strongly consider
-providing a just-in-time notice before the app accesses or uses
-contact data, if the device operating system doesn't do so
-already. That notice should provide the same information noted above,
-as well as obtaining the user's permission (e.g., by presenting
-choices for __OK__ and __No Thanks__).  Note that some app
-marketplaces may require the app to provide a just-in-time notice and
-obtain the user's permission before accessing contact data.  A
-clear and easy-to-understand user experience surrounding the use of
-contact data helps avoid user confusion and perceived misuse of
-contact data.  For more information, please see the Privacy Guide.
-
-## Installation
-
-    cordova plugin add org.apache.cordova.contacts
-
-### Firefox OS Quirks
-
-Create __www/manifest.webapp__ as described in 
-[Manifest Docs](https://developer.mozilla.org/en-US/Apps/Developing/Manifest).
-Add relevant permisions.
-There is also a need to change the webapp type to "privileged"  - [Manifest Docs](https://developer.mozilla.org/en-US/Apps/Developing/Manifest#type).
-__WARNING__: All privileged apps enforce [Content Security Policy](https://developer.mozilla.org/en-US/Apps/CSP) which forbids inline script. Initialize your application in another way.
-
-	"type": "privileged",
-	"permissions": {
-		"contacts": {
-			"access": "readwrite",
-			"description": "Describe why there is a need for such permission"
-		}
-	}
-
-## navigator.contacts
-
-### Methods
-
-- navigator.contacts.create
-- navigator.contacts.find
-
-### Objects
-
-- Contact
-- ContactName
-- ContactField
-- ContactAddress
-- ContactOrganization
-- ContactFindOptions
-- ContactError
-
-## navigator.contacts.create
-
-The `navigator.contacts.create` method is synchronous, and returns a new `Contact` object.
-
-This method does not retain the Contact object in the device contacts
-database, for which you need to invoke the `Contact.save` method.
-
-### Supported Platforms
-
-- Android
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Windows Phone 7 and 8
-- Windows 8 ( Note: Windows 8 Contacts are readonly via the Cordova API
-Contacts are not queryable/searchable, you should inform the user to pick a contact as a call to contacts.find will open the 'People' app where the user must choose a contact.
-Any contacts returned are readonly, so your application cannot modify them. )
-
-### Example
-
-    var myContact = navigator.contacts.create({"displayName": "Test User"});
-
-## navigator.contacts.find
-
-The `navigator.contacts.find` method executes asynchronously, querying the
-device contacts database and returning an array of `Contact` objects.
-The resulting objects are passed to the `contactSuccess` callback
-function specified by the __contactSuccess__ parameter.
-
-The __contactFields__ parameter specifies the fields to be used as a
-search qualifier, and only those results are passed to the
-__contactSuccess__ callback function.  A zero-length __contactFields__
-parameter is invalid and results in
-`ContactError.INVALID_ARGUMENT_ERROR`. A __contactFields__ value of
-`"*"` returns all contact fields.
-
-The __contactFindOptions.filter__ string can be used as a search
-filter when querying the contacts database.  If provided, a
-case-insensitive, partial value match is applied to each field
-specified in the __contactFields__ parameter.  If there's a match for
-_any_ of the specified fields, the contact is returned.
-
-### Parameters
-
-- __contactFields__: Contact fields to use as a search qualifier. The resulting `Contact` object only features values for these fields. _(DOMString[])_ [Required]
-
-- __contactSuccess__: Success callback function invoked with the array of Contact objects returned from the database. [Required]
-
-- __contactError__: Error callback function, invoked when an error occurs. [Optional]
-
-- __contactFindOptions__: Search options to filter navigator.contacts. [Optional] Keys include:
-
-- __filter__: The search string used to find navigator.contacts. _(DOMString)_ (Default: `""`)
-
-- __multiple__: Determines if the find operation returns multiple navigator.contacts. _(Boolean)_ (Default: `false`)
-
-### Supported Platforms
-
-- Android
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Windows Phone 7 and 8
-- Windows 8 ( read-only support, search requires user interaction, contactFields are ignored, only contactFindOptions.multiple is used to enable the user to select 1 or many contacts. )
-
-### Example
-
-    function onSuccess(contacts) {
-        alert('Found ' + contacts.length + ' contacts.');
-    };
-
-    function onError(contactError) {
-        alert('onError!');
-    };
-
-    // find all contacts with 'Bob' in any name field
-    var options      = new ContactFindOptions();
-    options.filter   = "Bob";
-    options.multiple = true;
-    var fields       = ["displayName", "name"];
-    navigator.contacts.find(fields, onSuccess, onError, options);
-
-
-## Contact
-
-The `Contact` object represents a user's contact.  Contacts can be
-created, stored, or removed from the device contacts database.
-Contacts can also be retrieved (individually or in bulk) from the
-database by invoking the `navigator.contacts.find` method.
-
-__NOTE__: Not all of the contact fields listed above are supported on
-every device platform.  Please check each platform's _Quirks_ section
-for details.
-
-
-### Properties
-
-- __id__: A globally unique identifier. _(DOMString)_
-
-- __displayName__: The name of this Contact, suitable for display to end users. _(DOMString)_
-
-- __name__: An object containing all components of a persons name. _(ContactName)_
-
-- __nickname__: A casual name by which to address the contact. _(DOMString)_
-
-- __phoneNumbers__: An array of all the contact's phone numbers. _(ContactField[])_
-
-- __emails__: An array of all the contact's email addresses. _(ContactField[])_
-
-- __addresses__: An array of all the contact's addresses. _(ContactAddress[])_
-
-- __ims__: An array of all the contact's IM addresses. _(ContactField[])_
-
-- __organizations__: An array of all the contact's organizations. _(ContactOrganization[])_
-
-- __birthday__: The birthday of the contact. _(Date)_
-
-- __note__: A note about the contact. _(DOMString)_
-
-- __photos__: An array of the contact's photos. _(ContactField[])_
-
-- __categories__:  An array of all the user-defined categories associated with the contact. _(ContactField[])_
-
-- __urls__:  An array of web pages associated with the contact. _(ContactField[])_
-
-### Methods
-
-- __clone__: Returns a new `Contact` object that is a deep copy of the calling object, with the `id` property set to `null`.
-
-- __remove__: Removes the contact from the device contacts database, otherwise executes an error callback with a `ContactError` object.
-
-- __save__: Saves a new contact to the device contacts database, or updates an existing contact if a contact with the same __id__ already exists.
-
-### Supported Platforms
-
-- Amazon Fire OS
-- Android
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Windows Phone 7 and 8
-
-### Save Example
-
-    function onSuccess(contact) {
-        alert("Save Success");
-    };
-
-    function onError(contactError) {
-        alert("Error = " + contactError.code);
-    };
-
-    // create a new contact object
-    var contact = navigator.contacts.create();
-    contact.displayName = "Plumber";
-    contact.nickname = "Plumber";            // specify both to support all devices
-
-    // populate some fields
-    var name = new ContactName();
-    name.givenName = "Jane";
-    name.familyName = "Doe";
-    contact.name = name;
-
-    // save to device
-    contact.save(onSuccess,onError);
-
-### Clone Example
-
-        // clone the contact object
-        var clone = contact.clone();
-        clone.name.givenName = "John";
-        console.log("Original contact name = " + contact.name.givenName);
-        console.log("Cloned contact name = " + clone.name.givenName);
-
-### Remove Example
-
-    function onSuccess() {
-        alert("Removal Success");
-    };
-
-    function onError(contactError) {
-        alert("Error = " + contactError.code);
-    };
-
-    // remove the contact from the device
-    contact.remove(onSuccess,onError);
-
-
-### Android 2.X Quirks
-
-- __categories__:  Not supported on Android 2.X devices, returning `null`.
-
-### BlackBerry 10 Quirks
-
-- __id__: Assigned by the device when saving the contact.
-
-### FirefoxOS Quirks
-
-- __categories__: Partially supported. Fields __pref__ and __type__ are returning `null`
-
-- __ims__: Not supported
-
-- __photos__: Not supported
-
-
-### iOS Quirks
-
-- __displayName__: Not supported on iOS, returning `null` unless there is no `ContactName` specified, in which case it returns the composite name, __nickname__ or `""`, respectively.
-
-- __birthday__: Must be input as a JavaScript `Date` object, the same way it is returned.
-
-- __photos__: Returns a File URL to the image, which is stored in the application's temporary directory.  Contents of the temporary directory are removed when the application exits.
-
-- __categories__:  This property is currently not supported, returning `null`.
-
-### Windows Phone 7 and 8 Quirks
-
-- __displayName__: When creating a contact, the value provided for the display name parameter differs from the display name retrieved when finding the contact.
-
-- __urls__: When creating a contact, users can input and save more than one web address, but only one is available when searching the contact.
-
-- __phoneNumbers__: The _pref_ option is not supported. The _type_ is not supported in a _find_ operation. Only one `phoneNumber` is allowed for each _type_.
-
-- __emails__: The _pref_ option is not supported. Home and personal references same email entry. Only one entry is allowed for each _type_.
-
-- __addresses__: Supports only work, and home/personal _type_. The home and personal _type_ reference the same address entry. Only one entry is allowed for each _type_.
-
-- __organizations__: Only one is allowed, and does not support the _pref_, _type_, and _department_ attributes.
-
-- __note__: Not supported, returning `null`.
-
-- __ims__: Not supported, returning `null`.
-
-- __birthdays__: Not supported, returning `null`.
-
-- __categories__: Not supported, returning `null`.
-
-
-## ContactAddress
-
-The `ContactAddress` object stores the properties of a single address
-of a contact.  A `Contact` object may include more than one address in
-a `ContactAddress[]` array.
-
-
-### Properties
-
-- __pref__: Set to `true` if this `ContactAddress` contains the user's preferred value. _(boolean)_
-
-- __type__: A string indicating what type of field this is, _home_ for example. _(DOMString)_
-
-- __formatted__: The full address formatted for display. _(DOMString)_
-
-- __streetAddress__: The full street address. _(DOMString)_
-
-- __locality__: The city or locality. _(DOMString)_
-
-- __region__: The state or region. _(DOMString)_
-
-- __postalCode__: The zip code or postal code. _(DOMString)_
-
-- __country__: The country name. _(DOMString)_
-
-### Supported Platforms
-
-- Amazon Fire OS
-- Android
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Windows Phone 7 and 8
-- Windows 8
-
-### Example
-
-    // display the address information for all contacts
-
-    function onSuccess(contacts) {
-        for (var i = 0; i < contacts.length; i++) {
-            for (var j = 0; j < contacts[i].addresses.length; j++) {
-                alert("Pref: "         + contacts[i].addresses[j].pref          + "\n" +
-                    "Type: "           + contacts[i].addresses[j].type          + "\n" +
-                    "Formatted: "      + contacts[i].addresses[j].formatted     + "\n" +
-                    "Street Address: " + contacts[i].addresses[j].streetAddress + "\n" +
-                    "Locality: "       + contacts[i].addresses[j].locality      + "\n" +
-                    "Region: "         + contacts[i].addresses[j].region        + "\n" +
-                    "Postal Code: "    + contacts[i].addresses[j].postalCode    + "\n" +
-                    "Country: "        + contacts[i].addresses[j].country);
-            }
-        }
-    };
-
-    function onError(contactError) {
-        alert('onError!');
-    };
-
-    // find all contacts
-    var options = new ContactFindOptions();
-    options.filter = "";
-    var filter = ["displayName", "addresses"];
-    navigator.contacts.find(filter, onSuccess, onError, options);
-
-### Android 2.X Quirks
-
-- __pref__: Not supported, returning `false` on Android 2.X devices.
-
-### BlackBerry 10 Quirks
-
-- __pref__: Not supported on BlackBerry devices, returning `false`.
-
-- __type__: Partially supported.  Only one each of _Work_ and _Home_ type addresses can be stored per contact.
-
-- __formatted__: Partially supported.  Returns a concatenation of all BlackBerry address fields.
-
-- __streetAddress__: Supported.  Returns a concatenation of BlackBerry __address1__ and __address2__ address fields.
-
-- __locality__: Supported.  Stored in BlackBerry __city__ address field.
-
-- __region__: Supported.  Stored in BlackBerry __stateProvince__ address field.
-
-- __postalCode__: Supported.  Stored in BlackBerry __zipPostal__ address field.
-
-- __country__: Supported.
-
-### FirefoxOS Quirks
-
-- __formatted__: Currently not supported
-
-### iOS Quirks
-
-- __pref__: Not supported on iOS devices, returning `false`.
-
-- __formatted__: Currently not supported.
-
-### Windows 8 Quirks
-
-- __pref__: Not supported
-
-
-## ContactError
-
-The `ContactError` object is returned to the user through the
-`contactError` callback function when an error occurs.
-
-### Properties
-
-- __code__: One of the predefined error codes listed below.
-
-### Constants
-
-- `ContactError.UNKNOWN_ERROR`
-- `ContactError.INVALID_ARGUMENT_ERROR`
-- `ContactError.TIMEOUT_ERROR`
-- `ContactError.PENDING_OPERATION_ERROR`
-- `ContactError.IO_ERROR`
-- `ContactError.NOT_SUPPORTED_ERROR`
-- `ContactError.PERMISSION_DENIED_ERROR`
-
-
-## ContactField
-
-The `ContactField` object is a reusable component that represents
-contact fields generically.  Each `ContactField` object contains a
-`value`, `type`, and `pref` property.  A `Contact` object stores
-several properties in `ContactField[]` arrays, such as phone numbers
-and email addresses.
-
-In most instances, there are no pre-determined values for a
-`ContactField` object's __type__ attribute.  For example, a phone
-number can specify __type__ values of _home_, _work_, _mobile_,
-_iPhone_, or any other value that is supported by a particular device
-platform's contact database.  However, for the `Contact` __photos__
-field, the __type__ field indicates the format of the returned image:
-__url__ when the __value__ attribute contains a URL to the photo
-image, or _base64_ when the __value__ contains a base64-encoded image
-string.
-
-### Properties
-
-- __type__: A string that indicates what type of field this is, _home_ for example. _(DOMString)_
-
-- __value__: The value of the field, such as a phone number or email address. _(DOMString)_
-
-- __pref__: Set to `true` if this `ContactField` contains the user's preferred value. _(boolean)_
-
-### Supported Platforms
-
-- Amazon Fire OS
-- Android
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Windows Phone 7 and 8
-- Windows 8
-
-### Example
-
-        // create a new contact
-        var contact = navigator.contacts.create();
-
-        // store contact phone numbers in ContactField[]
-        var phoneNumbers = [];
-        phoneNumbers[0] = new ContactField('work', '212-555-1234', false);
-        phoneNumbers[1] = new ContactField('mobile', '917-555-5432', true); // preferred number
-        phoneNumbers[2] = new ContactField('home', '203-555-7890', false);
-        contact.phoneNumbers = phoneNumbers;
-
-        // save the contact
-        contact.save();
-
-### Android Quirks
-
-- __pref__: Not supported, returning `false`.
-
-### BlackBerry 10 Quirks
-
-- __type__: Partially supported.  Used for phone numbers.
-
-- __value__: Supported.
-
-- __pref__: Not supported, returning `false`.
-
-### iOS Quirks
-
-- __pref__: Not supported, returning `false`.
-
-### Windows8 Quirks
-
-- __pref__: Not supported, returning `false`.
-
-
-## ContactName
-
-Contains different kinds of information about a `Contact` object's name.
-
-### Properties
-
-- __formatted__: The complete name of the contact. _(DOMString)_
-
-- __familyName__: The contact's family name. _(DOMString)_
-
-- __givenName__: The contact's given name. _(DOMString)_
-
-- __middleName__: The contact's middle name. _(DOMString)_
-
-- __honorificPrefix__: The contact's prefix (example _Mr._ or _Dr._) _(DOMString)_
-
-- __honorificSuffix__: The contact's suffix (example _Esq._). _(DOMString)_
-
-### Supported Platforms
-
-- Amazon Fire OS
-- Android 2.X
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Windows Phone 7 and 8
-- Windows 8
-
-### Example
-
-    function onSuccess(contacts) {
-        for (var i = 0; i < contacts.length; i++) {
-            alert("Formatted: "  + contacts[i].name.formatted       + "\n" +
-                "Family Name: "  + contacts[i].name.familyName      + "\n" +
-                "Given Name: "   + contacts[i].name.givenName       + "\n" +
-                "Middle Name: "  + contacts[i].name.middleName      + "\n" +
-                "Suffix: "       + contacts[i].name.honorificSuffix + "\n" +
-                "Prefix: "       + contacts[i].name.honorificSuffix);
-        }
-    };
-
-    function onError(contactError) {
-        alert('onError!');
-    };
-
-    var options = new ContactFindOptions();
-    options.filter = "";
-    filter = ["displayName", "name"];
-    navigator.contacts.find(filter, onSuccess, onError, options);
-
-### Android Quirks
-
-- __formatted__: Partially supported, and read-only.  Returns a concatenation of `honorificPrefix`, `givenName`, `middleName`, `familyName`, and `honorificSuffix`.
-
-### BlackBerry 10 Quirks
-
-- __formatted__: Partially supported.  Returns a concatenation of BlackBerry __firstName__ and __lastName__ fields.
-
-- __familyName__: Supported.  Stored in BlackBerry __lastName__ field.
-
-- __givenName__: Supported.  Stored in BlackBerry __firstName__ field.
-
-- __middleName__: Not supported, returning `null`.
-
-- __honorificPrefix__: Not supported, returning `null`.
-
-- __honorificSuffix__: Not supported, returning `null`.
-
-### FirefoxOS Quirks
-
-- __formatted__: Partially supported, and read-only.  Returns a concatenation of `honorificPrefix`, `givenName`, `middleName`, `familyName`, and `honorificSuffix`.
-
-
-### iOS Quirks
-
-- __formatted__: Partially supported.  Returns iOS Composite Name, but is read-only.
-
-### Windows 8 Quirks
-
-- __formatted__: This is the only name property, and is identical to `displayName`, and `nickname`
-
-- __familyName__: not supported
-
-- __givenName__: not supported
-
-- __middleName__: not supported
-
-- __honorificPrefix__: not supported
-
-- __honorificSuffix__: not supported
-
-
-## ContactOrganization
-
-The `ContactOrganization` object stores a contact's organization
-properties.  A `Contact` object stores one or more
-`ContactOrganization` objects in an array.
-
-### Properties
-
-- __pref__: Set to `true` if this `ContactOrganization` contains the user's preferred value. _(boolean)_
-
-- __type__: A string that indicates what type of field this is, _home_ for example. _(DOMString)
-
-- __name__: The name of the organization. _(DOMString)_
-
-- __department__: The department the contract works for. _(DOMString)_
-
-- __title__: The contact's title at the organization. _(DOMString)_
-
-
-### Supported Platforms
-
-- Android
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Windows Phone 7 and 8
-
-### Example
-
-    function onSuccess(contacts) {
-        for (var i = 0; i < contacts.length; i++) {
-            for (var j = 0; j < contacts[i].organizations.length; j++) {
-                alert("Pref: "      + contacts[i].organizations[j].pref       + "\n" +
-                    "Type: "        + contacts[i].organizations[j].type       + "\n" +
-                    "Name: "        + contacts[i].organizations[j].name       + "\n" +
-                    "Department: "  + contacts[i].organizations[j].department + "\n" +
-                    "Title: "       + contacts[i].organizations[j].title);
-            }
-        }
-    };
-
-    function onError(contactError) {
-        alert('onError!');
-    };
-
-    var options = new ContactFindOptions();
-    options.filter = "";
-    filter = ["displayName", "organizations"];
-    navigator.contacts.find(filter, onSuccess, onError, options);
-
-### Android 2.X Quirks
-
-- __pref__: Not supported by Android 2.X devices, returning `false`.
-
-### BlackBerry 10 Quirks
-
-- __pref__: Not supported by BlackBerry devices, returning `false`.
-
-- __type__: Not supported by BlackBerry devices, returning `null`.
-
-- __name__: Partially supported.  The first organization name is stored in the BlackBerry __company__ field.
-
-- __department__: Not supported, returning `null`.
-
-- __title__: Partially supported.  The first organization title is stored in the BlackBerry __jobTitle__ field.
-
-### Firefox OS Quirks
-
-- __pref__: Not supported
-
-- __type__: Not supported
-
-- __department__: Not supported
-
-- Fields __name__ and __title__ stored in __org__ and __jobTitle__.
-
-### iOS Quirks
-
-- __pref__: Not supported on iOS devices, returning `false`.
-
-- __type__: Not supported on iOS devices, returning `null`.
-
-- __name__: Partially supported.  The first organization name is stored in the iOS __kABPersonOrganizationProperty__ field.
-
-- __department__: Partially supported.  The first department name is stored in the iOS __kABPersonDepartmentProperty__ field.
-
-- __title__: Partially supported.  The first title is stored in the iOS __kABPersonJobTitleProperty__ field.

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/plugin.xml
----------------------------------------------------------------------
diff --git a/plugin.xml b/plugin.xml
deleted file mode 100644
index 676ffd5..0000000
--- a/plugin.xml
+++ /dev/null
@@ -1,215 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you under the Apache License, Version 2.0 (the
-  "License"); you may not use this file except in compliance
-  with the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing,
-  software distributed under the License is distributed on an
-  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  KIND, either express or implied.  See the License for the
-  specific language governing permissions and limitations
-  under the License.
--->
-
-<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
-    xmlns:rim="http://www.blackberry.com/ns/widgets"
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    id="org.apache.cordova.contacts"
-    version="0.2.11-dev">
-
-    <name>Contacts</name>
-    <description>Cordova Contacts Plugin</description>
-    <license>Apache 2.0</license>
-    <keywords>cordova,contacts</keywords>
-    <repo>https://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts.git</repo>
-    <issue>https://issues.apache.org/jira/browse/CB/component/12320652</issue>
-
-    <js-module src="www/contacts.js" name="contacts">
-        <clobbers target="navigator.contacts" />
-    </js-module>
-
-    <js-module src="www/Contact.js" name="Contact">
-        <clobbers target="Contact" />
-    </js-module>
-
-    <js-module src="www/ContactAddress.js" name="ContactAddress">
-        <clobbers target="ContactAddress" />
-    </js-module>
-
-    <js-module src="www/ContactError.js" name="ContactError">
-        <clobbers target="ContactError" />
-    </js-module>
-
-    <js-module src="www/ContactField.js" name="ContactField">
-        <clobbers target="ContactField" />
-    </js-module>
-
-    <js-module src="www/ContactFindOptions.js" name="ContactFindOptions">
-        <clobbers target="ContactFindOptions" />
-    </js-module>
-
-    <js-module src="www/ContactName.js" name="ContactName">
-        <clobbers target="ContactName" />
-    </js-module>
-
-    <js-module src="www/ContactOrganization.js" name="ContactOrganization">
-        <clobbers target="ContactOrganization" />
-    </js-module>
-
-
-
-
-    <!-- android -->
-    <platform name="android">
-        <config-file target="res/xml/config.xml" parent="/*">
-            <feature name="Contacts">
-                <param name="android-package" value="org.apache.cordova.contacts.ContactManager"/>
-            </feature>
-        </config-file>
-
-        <config-file target="AndroidManifest.xml" parent="/*">
-            <uses-permission android:name="android.permission.READ_CONTACTS" />
-            <uses-permission android:name="android.permission.WRITE_CONTACTS" />
-            <uses-permission android:name="android.permission.GET_ACCOUNTS" />
-        </config-file>
-
-        <source-file src="src/android/ContactAccessor.java" target-dir="src/org/apache/cordova/contacts" />
-        <source-file src="src/android/ContactAccessorSdk5.java" target-dir="src/org/apache/cordova/contacts" />
-        <source-file src="src/android/ContactManager.java" target-dir="src/org/apache/cordova/contacts" />
-    </platform>
-
-    <!-- amazon-fireos -->
-    <platform name="amazon-fireos">
-        <config-file target="res/xml/config.xml" parent="/*">
-            <feature name="Contacts">
-                <param name="android-package" value="org.apache.cordova.contacts.ContactManager"/>
-            </feature>
-        </config-file>
-
-        <config-file target="AndroidManifest.xml" parent="/*">
-            <uses-permission android:name="android.permission.READ_CONTACTS" />
-            <uses-permission android:name="android.permission.WRITE_CONTACTS" />
-            <uses-permission android:name="android.permission.GET_ACCOUNTS" />
-        </config-file>
-
-        <source-file src="src/android/ContactAccessor.java" target-dir="src/org/apache/cordova/contacts" />
-        <source-file src="src/android/ContactAccessorSdk5.java" target-dir="src/org/apache/cordova/contacts" />
-        <source-file src="src/android/ContactManager.java" target-dir="src/org/apache/cordova/contacts" />
-    </platform>
-    
-    <!-- ubuntu -->
-    <platform name="ubuntu">
-        <config-file target="config.xml" parent="/*">
-            <feature name="Contacts">
-                <param policy_group="contacts" policy_version="1" />
-            </feature>
-        </config-file>
-        <header-file src="src/ubuntu/contacts.h" />
-        <source-file src="src/ubuntu/contacts.cpp" />
-    </platform>
-
-    <!-- ios -->
-    <platform name="ios">
-        <config-file target="config.xml" parent="/*">
-            <feature name="Contacts">
-                <param name="ios-package" value="CDVContacts"/>
-            </feature>
-        </config-file>
-
-        <js-module src="www/ios/contacts.js" name="contacts-ios">
-            <merges target="navigator.contacts" />
-        </js-module>
-
-        <js-module src="www/ios/Contact.js" name="Contact-iOS">
-            <merges target="Contact" />
-        </js-module>
-
-        <header-file src="src/ios/CDVContacts.h" />
-        <source-file src="src/ios/CDVContacts.m" />
-        <header-file src="src/ios/CDVContact.h" />
-        <source-file src="src/ios/CDVContact.m" />
-
-        <framework src="AddressBook.framework" weak="true" />
-        <framework src="AddressBookUI.framework" weak="true" />
-        <framework src="CoreGraphics.framework" />
-    </platform>
-
-    <!-- blackberry10 -->
-    <platform name="blackberry10">
-        <config-file target="www/config.xml" parent="/widget">
-            <feature name="Contacts" value="Contacts"/>
-        </config-file>
-        <config-file target="www/config.xml" parent="/widget/rim:permissions">
-            <rim:permit>access_pimdomain_contacts</rim:permit>
-        </config-file>
-        <source-file src="src/blackberry10/index.js" target-dir="Contacts"></source-file>
-        <source-file src="src/blackberry10/ContactActivity.js" target-dir="Contacts"></source-file>
-        <source-file src="src/blackberry10/ContactAddress.js" target-dir="Contacts"></source-file>
-        <source-file src="src/blackberry10/contactConsts.js" target-dir="Contacts"></source-file>
-        <source-file src="src/blackberry10/ContactError.js" target-dir="Contacts"></source-file>
-        <source-file src="src/blackberry10/ContactField.js" target-dir="Contacts"></source-file>
-        <source-file src="src/blackberry10/ContactFindOptions.js" target-dir="Contacts"></source-file>
-        <source-file src="src/blackberry10/ContactName.js" target-dir="Contacts"></source-file>
-        <source-file src="src/blackberry10/ContactNews.js" target-dir="Contacts"></source-file>
-        <source-file src="src/blackberry10/ContactOrganization.js" target-dir="Contacts"></source-file>
-        <source-file src="src/blackberry10/ContactPhoto.js" target-dir="Contacts"></source-file>
-        <source-file src="src/blackberry10/contactUtils.js" target-dir="Contacts"></source-file>
-        <dependency id="com.blackberry.utils" />
-        <dependency id="com.blackberry.pim.lib" />
-    </platform>
-
-    <!-- wp7 -->
-    <platform name="wp7">
-        <config-file target="config.xml" parent="/*">
-            <feature name="Contacts">
-                <param name="wp-package" value="Contacts"/>
-            </feature>
-        </config-file>
-
-        <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities">
-            <Capability Name="ID_CAP_CONTACTS" />
-        </config-file>
-
-        <source-file src="src/wp/Contacts.cs" />
-    </platform>
-
-    <!-- wp8 -->
-    <platform name="wp8">
-        <config-file target="config.xml" parent="/*">
-            <feature name="Contacts">
-                <param name="wp-package" value="Contacts"/>
-            </feature>
-        </config-file>
-
-        <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities">
-            <Capability Name="ID_CAP_CONTACTS" />
-        </config-file>
-
-        <source-file src="src/wp/Contacts.cs" />
-    </platform>
-    
-    <!-- firefoxos -->
-    <platform name="firefoxos">
-        <config-file target="config.xml" parent="/*">
-            <feature name="Contacts">
-                <param name="firefoxos-package" value="Contacts" />
-            </feature>
-        </config-file>                                         
-        <js-module src="src/firefoxos/ContactsProxy.js" name="ContactsProxy">
-            <runs />
-        </js-module>
-    </platform>  
-
-        <!-- wp8 -->
-    <js-module src="src/windows8/ContactProxy.js" name="ContactProxy">
-        <merges target="" />
-    </js-module>
-
-</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts/blob/fc255252/src/android/ContactAccessor.java
----------------------------------------------------------------------
diff --git a/src/android/ContactAccessor.java b/src/android/ContactAccessor.java
deleted file mode 100644
index bac243e..0000000
--- a/src/android/ContactAccessor.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.cordova.contacts;
-
-import java.util.HashMap;
-
-import android.util.Log;
-
-import org.apache.cordova.CordovaInterface;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * This abstract class defines SDK-independent API for communication with
- * Contacts Provider. The actual implementation used by the application depends
- * on the level of API available on the device. If the API level is Cupcake or
- * Donut, we want to use the {@link ContactAccessorSdk3_4} class. If it is
- * Eclair or higher, we want to use {@link ContactAccessorSdk5}.
- */
-public abstract class ContactAccessor {
-
-    protected final String LOG_TAG = "ContactsAccessor";
-    protected CordovaInterface mApp;
-
-    /**
-     * Check to see if the data associated with the key is required to
-     * be populated in the Contact object.
-     * @param key
-     * @param map created by running buildPopulationSet.
-     * @return true if the key data is required
-     */
-    protected boolean isRequired(String key, HashMap<String,Boolean> map) {
-        Boolean retVal = map.get(key);
-        return (retVal == null) ? false : retVal.booleanValue();
-    }
-
-    /**
-     * Create a hash map of what data needs to be populated in the Contact object
-     * @param fields the list of fields to populate
-     * @return the hash map of required data
-     */
-    protected HashMap<String,Boolean> buildPopulationSet(JSONArray fields) {
-        HashMap<String,Boolean> map = new HashMap<String,Boolean>();
-
-        String key;
-        try {
-            if (fields.length() == 1 && fields.getString(0).equals("*")) {
-                map.put("displayName", true);
-                map.put("name", true);
-                map.put("nickname", true);
-                map.put("phoneNumbers", true);
-                map.put("emails", true);
-                map.put("addresses", true);
-                map.put("ims", true);
-                map.put("organizations", true);
-                map.put("birthday", true);
-                map.put("note", true);
-                map.put("urls", true);
-                map.put("photos", true);
-                map.put("categories", true);
-           } 
-            else {
-                for (int i=0; i<fields.length(); i++) {
-                    key = fields.getString(i);
-                    if (key.startsWith("displayName")) {
-                        map.put("displayName", true);
-                    }
-                    else if (key.startsWith("name")) {
-                        map.put("displayName", true);
-                        map.put("name", true);
-                    }
-                    else if (key.startsWith("nickname")) {
-                        map.put("nickname", true);
-                    }
-                    else if (key.startsWith("phoneNumbers")) {
-                        map.put("phoneNumbers", true);
-                    }
-                    else if (key.startsWith("emails")) {
-                        map.put("emails", true);
-                    }
-                    else if (key.startsWith("addresses")) {
-                        map.put("addresses", true);
-                    }
-                    else if (key.startsWith("ims")) {
-                        map.put("ims", true);
-                    }
-                    else if (key.startsWith("organizations")) {
-                        map.put("organizations", true);
-                    }
-                    else if (key.startsWith("birthday")) {
-                        map.put("birthday", true);
-                    }
-                    else if (key.startsWith("note")) {
-                        map.put("note", true);
-                    }
-                    else if (key.startsWith("urls")) {
-                        map.put("urls", true);
-                    }
-                    else if (key.startsWith("photos")) {
-                        map.put("photos", true);
-                    }
-                    else if (key.startsWith("categories")) {
-                        map.put("categories", true);
-                    }
-                }
-            }
-       }
-        catch (JSONException e) {
-            Log.e(LOG_TAG, e.getMessage(), e);
-        }
-        return map;
-    }
-
-    /**
-     * Convenience method to get a string from a JSON object.  Saves a
-     * lot of try/catch writing.
-     * If the property is not found in the object null will be returned.
-     *
-     * @param obj contact object to search
-     * @param property to be looked up
-     * @return The value of the property
-     */
-    protected String getJsonString(JSONObject obj, String property) {
-        String value = null;
-        try {
-            if (obj != null) {
-                value = obj.getString(property);
-                if (value.equals("null")) {
-                    Log.d(LOG_TAG, property + " is string called 'null'");
-                    value = null;
-                }
-            }
-       }
-        catch (JSONException e) {
-            Log.d(LOG_TAG, "Could not get = " + e.getMessage());
-        }
-        return value;
-    }
-
-    /**
-     * Handles adding a JSON Contact object into the database.
-     * @return TODO
-     */
-    public abstract String save(JSONObject contact);
-
-    /**
-     * Handles searching through SDK-specific contacts API.
-     */
-    public abstract JSONArray search(JSONArray filter, JSONObject options);
-
-    /**
-     * Handles searching through SDK-specific contacts API.
-     * @throws JSONException
-     */
-    public abstract JSONObject getContactById(String id) throws JSONException;
-
-    /**
-     * Handles removing a contact from the database.
-     */
-    public abstract boolean remove(String id);
-
-   /**
-     * A class that represents the where clause to be used in the database query 
-     */
-    class WhereOptions {
-        private String where;
-        private String[] whereArgs;
-        public void setWhere(String where) {
-            this.where = where;
-        }
-        public String getWhere() {
-            return where;
-        }
-        public void setWhereArgs(String[] whereArgs) {
-            this.whereArgs = whereArgs;
-        }
-        public String[] getWhereArgs() {
-            return whereArgs;
-        }
-    }
-}