You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by lo...@apache.org on 2013/05/14 06:15:54 UTC

[47/50] [abbrv] webworks commit: Contacts core plugin

Contacts core plugin


Project: http://git-wip-us.apache.org/repos/asf/cordova-blackberry/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-blackberry/commit/1890c10c
Tree: http://git-wip-us.apache.org/repos/asf/cordova-blackberry/tree/1890c10c
Diff: http://git-wip-us.apache.org/repos/asf/cordova-blackberry/diff/1890c10c

Branch: refs/heads/master
Commit: 1890c10c2604ffa1a99a9b75bd76f1b3e2180185
Parents: 42b066f
Author: Hasan Ahmad <ha...@blackberry.com>
Authored: Thu Apr 11 16:28:42 2013 -0400
Committer: lorinbeer <lo...@adobe.com>
Committed: Mon May 13 13:12:40 2013 -0700

----------------------------------------------------------------------
 .../templates/project/plugins/Contacts/plugin.xml  |   29 +
 .../Contacts/src/blackberry10/ContactActivity.js   |   26 +
 .../Contacts/src/blackberry10/ContactAddress.js    |   30 +
 .../Contacts/src/blackberry10/ContactError.js      |   30 +
 .../Contacts/src/blackberry10/ContactField.js      |   27 +
 .../src/blackberry10/ContactFindOptions.js         |   50 +
 .../Contacts/src/blackberry10/ContactName.js       |   39 +
 .../Contacts/src/blackberry10/ContactNews.js       |   26 +
 .../src/blackberry10/ContactOrganization.js        |   22 +
 .../Contacts/src/blackberry10/ContactPhoto.js      |   23 +
 .../Contacts/src/blackberry10/contactConsts.js     |  225 ++
 .../Contacts/src/blackberry10/contactUtils.js      |  223 ++
 .../plugins/Contacts/src/blackberry10/index.js     |  374 ++++
 .../plugin.xml                                     |   23 +
 .../src/blackberry10/native/Makefile               |    8 +
 .../src/blackberry10/native/arm/Makefile           |    8 +
 .../src/blackberry10/native/arm/so.le-v7/Makefile  |    1 +
 .../native/arm/so.le-v7/libpimcontacts.so          |  Bin 0 -> 170350 bytes
 .../src/blackberry10/native/common.mk              |   18 +
 .../src/blackberry10/native/contact_account.cpp    |   74 +
 .../src/blackberry10/native/contact_account.hpp    |   54 +
 .../blackberry10/native/device/libpimcontacts.so   |  Bin 0 -> 170350 bytes
 .../src/blackberry10/native/pim_contacts_js.cpp    |  174 ++
 .../src/blackberry10/native/pim_contacts_js.hpp    |   45 +
 .../src/blackberry10/native/pim_contacts_qt.cpp    | 1611 +++++++++++++++
 .../src/blackberry10/native/pim_contacts_qt.hpp    |  148 ++
 .../native/simulator/libpimcontacts.so             |  Bin 0 -> 265964 bytes
 .../src/blackberry10/native/x86/Makefile           |    8 +
 .../src/blackberry10/native/x86/so/Makefile        |    1 +
 .../blackberry10/native/x86/so/libpimcontacts.so   |  Bin 0 -> 265964 bytes
 blackberry10/bin/test/plugins/Contacts/index.js    |  197 ++
 31 files changed, 3494 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/Contacts/plugin.xml
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/Contacts/plugin.xml b/blackberry10/bin/templates/project/plugins/Contacts/plugin.xml
new file mode 100644
index 0000000..6753d29
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/Contacts/plugin.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+
+-->
+
+<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
+    id="org.apache.cordova.core"
+    version="0.0.1">
+
+    <name>Contacts</name>
+
+    <platform name="blackberry10">
+        <config-file target="www/config.xml" parent="/widget">
+            <feature name="Contacts" value="Contacts"/>
+        </config-file>
+      </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactActivity.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactActivity.js b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactActivity.js
new file mode 100644
index 0000000..0794d23
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactActivity.js
@@ -0,0 +1,26 @@
+/*
+ * 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 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;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactAddress.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactAddress.js b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactAddress.js
new file mode 100644
index 0000000..1ba9fe4
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactAddress.js
@@ -0,0 +1,30 @@
+/*
+ * 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 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-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactError.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactError.js b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactError.js
new file mode 100644
index 0000000..f20f85e
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactError.js
@@ -0,0 +1,30 @@
+/*
+ * 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 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-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactField.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactField.js b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactField.js
new file mode 100644
index 0000000..aad735c
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactField.js
@@ -0,0 +1,27 @@
+/*
+ * 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 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-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactFindOptions.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactFindOptions.js b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactFindOptions.js
new file mode 100644
index 0000000..8be830d
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactFindOptions.js
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+/**
+ * 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-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactName.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactName.js b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactName.js
new file mode 100644
index 0000000..9b74753
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactName.js
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+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-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactNews.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactNews.js b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactNews.js
new file mode 100644
index 0000000..7aa9d8c
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactNews.js
@@ -0,0 +1,26 @@
+/*
+ * 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 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;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactOrganization.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactOrganization.js b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactOrganization.js
new file mode 100644
index 0000000..ecf5d0c
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactOrganization.js
@@ -0,0 +1,22 @@
+/*
+ * 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 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;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactPhoto.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactPhoto.js b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactPhoto.js
new file mode 100644
index 0000000..5b1c9d6
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/ContactPhoto.js
@@ -0,0 +1,23 @@
+/*
+ * 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 ContactPhoto = function (originalFilePath, pref) {
+    this.originalFilePath = originalFilePath || "";
+    this.pref = pref || false;
+    this.largeFilePath = "";
+    this.smallFilePath = "";
+};
+
+module.exports = ContactPhoto;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/contactConsts.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/contactConsts.js b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/contactConsts.js
new file mode 100644
index 0000000..ef25206
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/contactConsts.js
@@ -0,0 +1,225 @@
+/*
+* 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-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/contactUtils.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/contactUtils.js b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/contactUtils.js
new file mode 100644
index 0000000..cd022c4
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/contactUtils.js
@@ -0,0 +1,223 @@
+/*
+ * 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 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-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/index.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/index.js b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/index.js
new file mode 100644
index 0000000..09a4bd2
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/Contacts/src/blackberry10/index.js
@@ -0,0 +1,374 @@
+/*
+ * 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-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/plugin.xml
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/plugin.xml b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/plugin.xml
new file mode 100644
index 0000000..b35a83e
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/plugin.xml
@@ -0,0 +1,23 @@
+
+<!--
+ 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://www.phonegap.com/ns/plugins/1.0"
+    id="org.apache.cordova.blackberry10.pimlib"
+    version="1.0.0">
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/Makefile
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/Makefile b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/Makefile
new file mode 100644
index 0000000..0cc5eae
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/Makefile
@@ -0,0 +1,8 @@
+LIST=CPU
+ifndef QRECURSE
+QRECURSE=recurse.mk
+ifdef QCONFIG
+QRDIR=$(dir $(QCONFIG))
+endif
+endif
+include $(QRDIR)$(QRECURSE)

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/arm/Makefile
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/arm/Makefile b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/arm/Makefile
new file mode 100644
index 0000000..0e22650
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/arm/Makefile
@@ -0,0 +1,8 @@
+LIST=VARIANT
+ifndef QRECURSE
+QRECURSE=recurse.mk
+ifdef QCONFIG
+QRDIR=$(dir $(QCONFIG))
+endif
+endif
+include $(QRDIR)$(QRECURSE)

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/arm/so.le-v7/Makefile
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/arm/so.le-v7/Makefile b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/arm/so.le-v7/Makefile
new file mode 100644
index 0000000..2c76089
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/arm/so.le-v7/Makefile
@@ -0,0 +1 @@
+include ../../common.mk

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/arm/so.le-v7/libpimcontacts.so
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/arm/so.le-v7/libpimcontacts.so b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/arm/so.le-v7/libpimcontacts.so
new file mode 100755
index 0000000..f90047f
Binary files /dev/null and b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/arm/so.le-v7/libpimcontacts.so differ

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/common.mk
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/common.mk b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/common.mk
new file mode 100644
index 0000000..7bc06fb
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/common.mk
@@ -0,0 +1,18 @@
+ifndef QCONFIG
+QCONFIG=qconfig.mk
+endif
+include $(QCONFIG)
+
+NAME=pimcontacts
+PLUGIN=yes
+UTILS=yes
+
+include ../../../../../../meta.mk
+
+SRCS+=pim_contacts_qt.cpp \
+      pim_contacts_js.cpp \
+      contact_account.cpp
+
+include $(MKFILES_ROOT)/qtargets.mk
+
+LIBS+=bbpim bbcascadespickers QtCore img

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/contact_account.cpp
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/contact_account.cpp b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/contact_account.cpp
new file mode 100644
index 0000000..3476e70
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/contact_account.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+#include <webworks_utils.hpp>
+#include "contact_account.hpp"
+
+ContactAccount& ContactAccount::GetAccountInstance()
+{
+    static ContactAccount ca;
+    return ca;
+}
+
+ContactAccount::ContactAccount()
+{
+    fetchContactAccounts();
+}
+
+ContactAccount::~ContactAccount()
+{}
+
+QList<bb::pim::account::Account> ContactAccount::GetContactAccounts(bool fresh)
+{
+    if (fresh) {
+        fetchContactAccounts();
+    }
+    return _accounts;
+}
+
+bb::pim::account::Account ContactAccount::GetAccount(bb::pim::account::AccountKey id, bool fresh)
+{
+    if (fresh) {
+        fetchContactAccounts();
+    }
+    return _accountMap.value(id);
+}
+
+Json::Value ContactAccount::Account2Json(const bb::pim::account::Account& account)
+{
+    Json::Value jsonAccount;
+    jsonAccount["id"] = webworks::Utils::intToStr(account.id());
+    jsonAccount["name"] = account.displayName().isEmpty() ? account.provider().name().toStdString() : account.displayName().toStdString();
+    jsonAccount["enterprise"] = account.isEnterprise() == 1 ? true : false;
+
+    return jsonAccount;
+}
+
+void ContactAccount::fetchContactAccounts()
+{
+    QList<bb::pim::account::Account> accounts = _accountService.accounts(bb::pim::account::Service::Contacts);
+
+    _accounts.clear();
+    _accountMap.clear();
+    for (QList<bb::pim::account::Account>::const_iterator it = accounts.begin(); it != accounts.end(); ++it) {
+        if ((it->id() != ID_UNIFIED_ACCOUNT) && (it->id() != ID_ENHANCED_ACCOUNT)) {
+            _accounts.append(*it);
+            _accountMap.insert(it->id(), (bb::pim::account::Account)(*it));
+        }
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/contact_account.hpp
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/contact_account.hpp b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/contact_account.hpp
new file mode 100644
index 0000000..3910de8
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/contact_account.hpp
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#ifndef _CONTACT_ACCOUNT_HPP_
+#define _CONTACT_ACCOUNT_HPP_
+
+#include <bb/pim/account/Account>
+#include <bb/pim/account/AccountService>
+#include <bb/pim/account/Provider>
+
+#include <json/value.h>
+#include <QList>
+#include <QDebug>
+
+class ContactAccount
+{
+public:
+    static ContactAccount& GetAccountInstance();
+
+    // get all available accounts which provide contact service
+    QList<bb::pim::account::Account> GetContactAccounts(bool fresh = false);
+    // get the contact account with the specific id
+    bb::pim::account::Account GetAccount(bb::pim::account::AccountKey id, bool fresh = false);
+    // serialize account to json object
+    static Json::Value Account2Json(const bb::pim::account::Account& account);
+
+private:
+    ContactAccount();
+    ~ContactAccount();
+    explicit ContactAccount(ContactAccount const&);
+    void operator=(ContactAccount const&);
+    // Refresh the accounts list and map
+    void fetchContactAccounts();
+    QMap<bb::pim::account::AccountKey, bb::pim::account::Account> _accountMap;
+    QList<bb::pim::account::Account> _accounts;
+    bb::pim::account::AccountService _accountService;
+    static const int ID_UNIFIED_ACCOUNT = 4;
+    static const int ID_ENHANCED_ACCOUNT = 6;
+};
+
+#endif // end of _CONTACT_ACCOUNT_HPP_

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/device/libpimcontacts.so
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/device/libpimcontacts.so b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/device/libpimcontacts.so
new file mode 100644
index 0000000..f90047f
Binary files /dev/null and b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/device/libpimcontacts.so differ

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/pim_contacts_js.cpp
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/pim_contacts_js.cpp b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/pim_contacts_js.cpp
new file mode 100644
index 0000000..4788bd1
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/pim_contacts_js.cpp
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+#include <json/reader.h>
+#include <json/writer.h>
+#include <string>
+#include "pim_contacts_js.hpp"
+#include "pim_contacts_qt.hpp"
+
+PimContacts::PimContacts(const std::string& id) : m_id(id)
+{
+}
+
+char* onGetObjList()
+{
+    // Return list of classes in the object
+    static char name[] = "PimContacts";
+    return name;
+}
+
+JSExt* onCreateObject(const std::string& className, const std::string& id)
+{
+    // Make sure we are creating the right class
+    if (className != "PimContacts") {
+        return 0;
+    }
+
+    return new PimContacts(id);
+}
+
+std::string PimContacts::InvokeMethod(const std::string& command)
+{
+    unsigned int index = command.find_first_of(" ");
+
+    string strCommand;
+    string jsonObject;
+    Json::Value *obj;
+
+    if (index != std::string::npos) {
+        strCommand = command.substr(0, index);
+        jsonObject = command.substr(index + 1, command.length());
+
+        // Parse the JSON
+        obj = new Json::Value;
+        bool parse = Json::Reader().parse(jsonObject, *obj);
+
+        if (!parse) {
+            return "Cannot parse JSON object";
+        }
+    } else {
+        strCommand = command;
+        obj = NULL;
+    }
+
+    if (strCommand == "find") {
+        startThread(FindThread, obj);
+    } else if (strCommand == "save") {
+        startThread(SaveThread, obj);
+    } else if (strCommand == "remove") {
+        startThread(RemoveThread, obj);
+    } else if (strCommand == "getContact") {
+        std::string result = Json::FastWriter().write(webworks::PimContactsQt().GetContact(*obj));
+        delete obj;
+        return result;
+    } else if (strCommand == "invokePicker") {
+        Json::Value result = webworks::PimContactsQt::InvokePicker(*obj);
+        delete obj;
+
+        std::string event = Json::FastWriter().write(result);
+        NotifyEvent("invokeContactPicker.invokeEventId", event);
+    } else if (strCommand == "getContactAccounts") {
+        return Json::FastWriter().write(webworks::PimContactsQt::GetContactAccounts());
+    }
+
+    return "";
+}
+
+bool PimContacts::CanDelete()
+{
+    return true;
+}
+
+// Notifies JavaScript of an event
+void PimContacts::NotifyEvent(const std::string& eventId, const std::string& event)
+{
+    std::string eventString = m_id + " result ";
+    eventString.append(eventId);
+    eventString.append(" ");
+    eventString.append(event);
+    SendPluginEvent(eventString.c_str(), m_pContext);
+}
+
+bool PimContacts::startThread(ThreadFunc threadFunction, Json::Value *jsonObj) {
+    webworks::PimContactsThreadInfo *thread_info = new webworks::PimContactsThreadInfo;
+    thread_info->parent = this;
+    thread_info->jsonObj = jsonObj;
+    thread_info->eventId = jsonObj->removeMember("_eventId").asString();
+
+    pthread_attr_t thread_attr;
+    pthread_attr_init(&thread_attr);
+    pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
+
+    pthread_t thread;
+    pthread_create(&thread, &thread_attr, threadFunction, static_cast<void *>(thread_info));
+    pthread_attr_destroy(&thread_attr);
+
+    if (!thread) {
+        return false;
+    }
+
+    return true;
+}
+
+
+// Static functions:
+
+void* PimContacts::FindThread(void *args)
+{
+    webworks::PimContactsThreadInfo *thread_info = static_cast<webworks::PimContactsThreadInfo *>(args);
+
+    webworks::PimContactsQt pim_qt;
+    Json::Value result = pim_qt.Find(*(thread_info->jsonObj));
+    delete thread_info->jsonObj;
+
+    std::string event = Json::FastWriter().write(result);
+    thread_info->parent->NotifyEvent(thread_info->eventId, event);
+    delete thread_info;
+
+    return NULL;
+}
+
+void* PimContacts::SaveThread(void *args)
+{
+    webworks::PimContactsThreadInfo *thread_info = static_cast<webworks::PimContactsThreadInfo *>(args);
+
+    webworks::PimContactsQt pim_qt;
+    Json::Value result = pim_qt.Save(*(thread_info->jsonObj));
+    delete thread_info->jsonObj;
+
+    std::string event = Json::FastWriter().write(result);
+    thread_info->parent->NotifyEvent(thread_info->eventId, event);
+    delete thread_info;
+
+    return NULL;
+}
+
+void* PimContacts::RemoveThread(void *args)
+{
+    webworks::PimContactsThreadInfo *thread_info = static_cast<webworks::PimContactsThreadInfo *>(args);
+
+    webworks::PimContactsQt pim_qt;
+    Json::Value result = pim_qt.DeleteContact(*(thread_info->jsonObj));
+    delete thread_info->jsonObj;
+
+    std::string event = Json::FastWriter().write(result);
+    thread_info->parent->NotifyEvent(thread_info->eventId, event);
+    delete thread_info;
+
+    return NULL;
+}
+

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/1890c10c/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/pim_contacts_js.hpp
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/pim_contacts_js.hpp b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/pim_contacts_js.hpp
new file mode 100644
index 0000000..df8bbd7
--- /dev/null
+++ b/blackberry10/bin/templates/project/plugins/org.apache.cordova.blackberry10.pimlib/src/blackberry10/native/pim_contacts_js.hpp
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#ifndef PIM_CONTACTS_JS_H_
+#define PIM_CONTACTS_JS_H_
+
+#include <json/value.h>
+#include <pthread.h>
+#include <string>
+#include "../common/plugin.h"
+
+typedef void* ThreadFunc(void *args);
+
+class PimContacts : public JSExt
+{
+public:
+    explicit PimContacts(const std::string& id);
+    virtual ~PimContacts() {}
+    virtual std::string InvokeMethod(const std::string& command);
+    virtual bool CanDelete();
+    void NotifyEvent(const std::string& eventId, const std::string& event);
+
+    static void* FindThread(void *args);
+    static void* SaveThread(void *args);
+    static void* RemoveThread(void *args);
+private:
+    bool startThread(ThreadFunc threadFunction, Json::Value *jsonObj);
+
+    std::string m_id;
+};
+
+#endif // PIM_CONTACTS_JS_H_