[Contact] JS files renamed to match common convention
authorRafal Galka <r.galka@samsung.com>
Tue, 13 Jan 2015 12:09:27 +0000 (13:09 +0100)
committerRafal Galka <r.galka@samsung.com>
Tue, 13 Jan 2015 12:23:52 +0000 (21:23 +0900)
Change-Id: I9c82b5be3a09867ebed73ce9d67aff716b42b0e9
Signed-off-by: Rafal Galka <r.galka@samsung.com>
13 files changed:
src/contact/contact_api.js
src/contact/js/address_book.js [new file with mode: 0644]
src/contact/js/common.js [new file with mode: 0644]
src/contact/js/contact.js [new file with mode: 0644]
src/contact/js/contact_data_structures.js [new file with mode: 0644]
src/contact/js/contact_manager.js [new file with mode: 0644]
src/contact/js/person.js [new file with mode: 0644]
src/contact/js/tizen.contact.AddressBook.js [deleted file]
src/contact/js/tizen.contact.Common.js [deleted file]
src/contact/js/tizen.contact.Contact.js [deleted file]
src/contact/js/tizen.contact.ContactDataStructures.js [deleted file]
src/contact/js/tizen.contact.ContactManager.js [deleted file]
src/contact/js/tizen.contact.Person.js [deleted file]

index fc7ca6521d6162d300371db8ab4f66c9f93e3355..7b198bba4b12a664e9b0d44205cca177730ffd88 100644 (file)
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-//= require('tizen.contact.Common.js');
-//= require('tizen.contact.ContactDataStructures.js');
-//= require('tizen.contact.Contact.js');
-//= require('tizen.contact.AddressBook.js');
-//= require('tizen.contact.Person.js');
-//= require('tizen.contact.ContactManager.js');
+//= require('common.js');
+//= require('contact_data_structures.js');
+//= require('contact.js');
+//= require('address_book.js');
+//= require('person.js');
+//= require('contact_manager.js');
diff --git a/src/contact/js/address_book.js b/src/contact/js/address_book.js
new file mode 100644 (file)
index 0000000..12190ab
--- /dev/null
@@ -0,0 +1,696 @@
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var DEFAULT_ADDRESSBOOK_ID = '0';
+var UNIFIED_ADDRESSBOOK_ID = '-1';
+
+var _contactListenerRegistered = false;
+var _contactCallbackMap = {};
+
+var _filterById = function(array, id) {
+  var ret = [];
+  for (var i = 0; i < array.length; ++i) {
+    if (array[i].addressBookId === id) {
+      ret.push(_promote(array[i], Contact));
+    }
+  }
+  return ret;
+};
+
+var _contactChangeListener = function(result) {
+  var unifiedId = UNIFIED_ADDRESSBOOK_ID;
+  var watchId;
+  var i;
+
+  // Unified address book case
+  if (_contactCallbackMap.hasOwnProperty(unifiedId)) {
+    for (watchId in _contactCallbackMap[unifiedId]) {
+      if (_contactCallbackMap[unifiedId].hasOwnProperty(watchId)) {
+        var callback = _contactCallbackMap[unifiedId][watchId].successCallback;
+        if (result.added.length) {
+          native_.callIfPossible(callback.oncontactsadded, _promote(result.added, Contact));
+        }
+        if (result.updated.length) {
+          native_.callIfPossible(callback.oncontactsupdated, _promote(result.updated, Contact));
+        }
+        if (result.removed.length) {
+          var allRemoved = [];
+          for (i = 0; i < result.removed.length; ++i) {
+            allRemoved.push(result.removed[i].id);
+          }
+          native_.callIfPossible(callback.oncontactsremoved, result.allRemoved);
+        }
+      }
+    }
+  }
+
+  for (var callbackAddressbookId in _contactCallbackMap) {
+    if (callbackAddressbookId !== UNIFIED_ADDRESSBOOK_ID &&
+        _contactCallbackMap.hasOwnProperty(callbackAddressbookId)) {
+
+      var filteredAdded = [];
+      var filteredUpdated = [];
+      var filteredRemoved = [];
+
+      if (result.added.length) {
+        filteredAdded = _filterById(result.added, callbackAddressbookId);
+      }
+      if (result.updated.length) {
+        filteredUpdated = _filterById(result.updated, callbackAddressbookId);
+      }
+      if (result.removed.length) {
+        for (i = 0; i < result.removed.length; ++i) {
+          if (result.removed[i].addressBookId === callbackAddressbookId) {
+            filteredRemoved.push(result.removed[i].id);
+          }
+        }
+      }
+
+      for (watchId in _contactCallbackMap[callbackAddressbookId]) {
+        if (_contactCallbackMap[callbackAddressbookId].hasOwnProperty(watchId)) {
+          var callback = _contactCallbackMap[callbackAddressbookId][watchId].successCallback;
+          if (filteredAdded.length) {
+            native_.callIfPossible(callback.oncontactsadded, filteredAdded);
+          }
+          if (filteredUpdated.length) {
+            native_.callIfPossible(callback.oncontactsupdated, filteredUpdated);
+          }
+          if (filteredRemoved.length) {
+            native_.callIfPossible(callback.oncontactsremoved, filteredRemoved);
+          }
+        }
+      }
+    }
+  }
+};
+
+
+var AddressBook = function(accountId, name) {
+  AV.isConstructorCall(this, AddressBook);
+
+  var id_ = null;
+  var name_ = '';
+  var readOnly_ = false;
+  var accountId_ = null;
+
+  if (Type.isNumber(accountId)) {
+    accountId_ = accountId;
+  }
+  if (Type.isString(name)) {
+    name_ = name;
+  }
+
+  Object.defineProperties(this, {
+    id: {
+      get: function() {
+        return id_;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          id_ = Converter.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    accountId: {
+      get: function() {
+        return accountId_;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          accountId_ = Converter.toLong(v, true);
+        }
+      },
+      enumerable: true
+    },
+    name: {
+      get: function() {
+        return name_;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          name_ = Converter.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    readOnly: {
+      get: function() {
+        return readOnly_;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          readOnly_ = Converter.toBoolean(v, false);
+        }
+      },
+      enumerable: true
+    }
+  });
+};
+
+AddressBook.prototype.get = function() {
+  var args = AV.validateArgs(arguments, [{
+    name: 'id',
+    type: AV.Types.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(Converter.toLong(args.id)) !== args.id) {
+    // TCT: AddressBook_get_id_invalid
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('AddressBook_get', {
+    // TODO move to only sending the address book id (in all functions)
+    addressBook: this,
+    id: args.id
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return _editGuard.run(function() {
+    var contact = new Contact(native_.getResultObject(result));
+
+    if (contact.name instanceof ContactName) {
+      contact.name.displayName = '';
+      if (Type.isString(contact.name.firstName)) {
+        contact.name.displayName = contact.name.firstName;
+        if (Type.isString(contact.name.lastName)) {
+          contact.name.displayName += ' ' + contact.name.lastName;
+        }
+      } else if (Type.isArray(contact.name.nicknames) &&
+          Type.isString(contact.name.nicknames[0])) {
+        contact.name.displayName = contact.name.nicknames[0];
+      } else if (Type.isString(contact.name.nicknames)) {
+        contact.name.displayName = contact.name.nicknames;
+      }
+    }
+
+
+
+    return contact;
+  });
+};
+
+AddressBook.prototype.add = function() {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'contact',
+      type: AV.Types.PLATFORM_OBJECT,
+      values: Contact,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  var result = native_.callSync('AddressBook_add', {
+    // TODO move to only sending the address book id (in all functions)
+    addressBook: this,
+    contact: _toJsonObject(args.contact)
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var _updatedContact = native_.getResultObject(result);
+  _editGuard.run(function() {
+    for (var prop in _updatedContact) {
+      if (args.contact.hasOwnProperty(prop)) {
+        args.contact[prop] = _updatedContact[prop];
+      }
+    }
+
+    if (args.contact.name instanceof ContactName) {
+      args.contact.name.displayName = '';
+      if (Type.isString(args.contact.name.firstName)) {
+        args.contact.name.displayName = args.contact.name.firstName;
+        if (Type.isString(args.contact.name.lastName)) {
+          args.contact.name.displayName += ' ' + args.contact.name.lastName;
+        }
+      } else if (Type.isArray(args.contact.name.nicknames) &&
+          Type.isString(args.contact.name.nicknames[0])) {
+        args.contact.name.displayName = args.contact.name.nicknames[0];
+      } else if (Type.isString(args.contact.name.nicknames)) {
+        args.contact.name.displayName = args.contact.name.nicknames;
+      }
+    }
+  });
+};
+
+AddressBook.prototype.addBatch = function() {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'contacts',
+      type: AV.Types.ARRAY,
+      value: Contact,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    _editGuard.run(function() {
+      var _result = native_.getResultObject(result);
+      for (var i = 0; i < _result.length; ++i) {
+        for (var prop in _result[i]) {
+          if (args.contacts[i].hasOwnProperty(prop)) {
+            args.contacts[i][prop] = _result[i][prop];
+          }
+        }
+      }
+    });
+
+    native_.callIfPossible(args.successCallback, args.contacts);
+  };
+
+  native_.call('AddressBook_addBatch', {
+    addressBookId: this.id,
+    batchArgs: _toJsonObject(args.contacts)
+  }, callback);
+};
+
+AddressBook.prototype.update = function() {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'contact',
+      type: AV.Types.PLATFORM_OBJECT,
+      values: Contact,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  var result = native_.callSync('AddressBook_update', {
+    addressBook: this,
+    contact: _toJsonObject(args.contact)
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var _updatedContact = native_.getResultObject(result);
+  _editGuard.run(function() {
+    for (var prop in _updatedContact) {
+      if (args.contact.hasOwnProperty(prop)) {
+        args.contact[prop] = _updatedContact[prop];
+      }
+    }
+  });
+};
+
+AddressBook.prototype.updateBatch = function() {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'contacts',
+      type: AV.Types.ARRAY,
+      values: Contact,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    _editGuard.run(function() {
+      var _result = native_.getResultObject(result);
+      for (var i = 0; i < _result.length; ++i) {
+        for (var prop in _result[i].result) {
+          if (args.contacts[i].hasOwnProperty(prop)) {
+            args.contacts[i][prop] = _result[i].result[prop];
+          }
+        }
+      }
+    });
+
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('AddressBook_updateBatch', {
+    addressBook: this,
+    batchArgs: _toJsonObject(args.contacts)
+  }, callback);
+};
+
+AddressBook.prototype.remove = function() {
+  var args = AV.validateArgs(arguments, [{
+    name: 'id',
+    type: AV.Types.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(Converter.toLong(args.id)) !== args.id) {
+    // TCT: AddressBook_remove_id_invalid
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('AddressBook_remove', {
+    addressBook: this,
+    id: args.id
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+AddressBook.prototype.removeBatch = function(ids, successCallback, errorCallback) {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'ids',
+      type: AV.Types.ARRAY,
+      values: AV.Types.STRING,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('AddressBook_removeBatch', {
+    addressBook: this,
+    batchArgs: args.ids
+  }, callback);
+};
+
+AddressBook.prototype.find = function(successCallback, errorCallback, filter, sortMode) {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: AV.Types.FUNCTION,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'filter',
+      type: AV.Types.PLATFORM_OBJECT,
+      values: [
+        tizen.AttributeFilter,
+        tizen.AttributeRangeFilter,
+        tizen.CompositeFilter
+      ],
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'sortMode',
+      type: AV.Types.PLATFORM_OBJECT,
+      values: tizen.SortMode,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var self = this;
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+    }
+
+    var _contacts = [];
+    var _result = native_.getResultObject(result);
+    _result.forEach(function(data) {
+      try {
+        _contacts.push(self.get(String(data)));
+      } catch (e) {}
+    });
+
+    //TODO: Move filtering to native code
+    try {
+      _contacts = C.filter(_contacts, args.filter);
+    } catch (e) {
+      native_.callIfPossible(errorCallback, e);
+      return;
+    }
+
+    //TODO: Move sorting to native code
+    _contacts = C.sort(_contacts, args.sortMode);
+
+    native_.callIfPossible(successCallback, _contacts);
+  };
+
+  native_.call('AddressBook_find', {
+    addressBook: this,
+    filter: filter,
+    sortMode: sortMode
+  }, callback);
+};
+
+AddressBook.prototype.addChangeListener = function() {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: AV.Types.LISTENER,
+      values: ['oncontactsadded', 'oncontactsupdated', 'oncontactsremoved'],
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  if (Type.isEmptyObject(_contactCallbackMap)) {
+    var result = native_.callSync('AddressBook_startListening', {});
+
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+
+  if (!_contactListenerRegistered) {
+    native_.addListener('ContactChangeListener', _contactChangeListener);
+    _contactListenerRegistered = true;
+  }
+
+  if (!_contactCallbackMap.hasOwnProperty(this.id)) {
+    _contactCallbackMap[this.id] = {};
+  }
+
+  var currentWatchId = _getNextWatchId();
+
+  _contactCallbackMap[this.id][currentWatchId] = {
+    successCallback: args.successCallback,
+    errorCallback: args.errorCallback
+  };
+
+  return currentWatchId;
+};
+
+AddressBook.prototype.removeChangeListener = function(watchId) {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'watchId',
+      type: AV.Types.LONG,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  if (args.watchId === 0) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
+        'id is null or undefined');
+  }
+
+  if (args.watchId < 0) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
+        'Negative watch id');
+  }
+
+  if (!_contactCallbackMap.hasOwnProperty(this.id) ||
+      !_contactCallbackMap[this.id].hasOwnProperty(args.watchId)) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR,
+        'watch id not found for this address book');
+  }
+
+  delete _contactCallbackMap[this.id][args.watchId];
+
+  if (Type.isEmptyObject(_contactCallbackMap[this.id])) {
+    delete _contactCallbackMap[this.id];
+  }
+
+  if (Type.isEmptyObject(_contactCallbackMap)) {
+    native_.removeListener('ContactChangeListener', _contactChangeListener);
+    _contactListenerRegistered = false;
+
+    var result = native_.callSync('AddressBook_stopListening', {});
+
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+};
+
+AddressBook.prototype.getGroup = function() {
+  var args = AV.validateArgs(arguments, [{
+    name: 'groupId',
+    type: AV.Types.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(Converter.toLong(args.groupId)) !== args.groupId) {
+    // TCT: AddressBook_getGroup_groupId_invalid
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('AddressBook_getGroup', {
+    addressBook: this,
+    id: args.groupId
+  });
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return _editGuard.run(function() {
+    return new ContactGroup(native_.getResultObject(result));
+  });
+};
+
+AddressBook.prototype.addGroup = function() {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'group',
+      type: AV.Types.PLATFORM_OBJECT,
+      values: ContactGroup,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  var result = native_.callSync('AddressBook_addGroup',
+      {addressBookId: this.id, group: args.group});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  _editGuard.run(function() {
+    result = native_.getResultObject(result);
+    args.group.id = result.id;
+    args.group.addressBookId = result.addressBookId;
+  });
+};
+
+AddressBook.prototype.updateGroup = function() {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'group',
+      type: AV.Types.PLATFORM_OBJECT,
+      values: ContactGroup,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  var result = native_.callSync('AddressBook_updateGroup',
+      {addressBookId: this.id, group: args.group});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+AddressBook.prototype.removeGroup = function() {
+  var args = AV.validateArgs(arguments, [{
+    name: 'groupId',
+    type: AV.Types.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(Converter.toLong(args.groupId)) !== args.groupId) {
+    // TCT: AddressBook_removeGroup_groupId_invalid
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('AddressBook_removeGroup',
+      {addressBook: this, id: args.groupId});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+AddressBook.prototype.getGroups = function() {
+  var result = native_.callSync('AddressBook_getGroups', {addressBook: this});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  result = native_.getResultObject(result);
+  var _tab = [];
+  _editGuard.run(function() {
+    result.forEach(function(data) {
+      _tab.push(new ContactGroup(data));
+    });
+  });
+  return _tab;
+};
+
+// exports /////////////////////////////////////////////////////////////////
+tizen.AddressBook = AddressBook;
diff --git a/src/contact/js/common.js b/src/contact/js/common.js
new file mode 100644 (file)
index 0000000..ce1140d
--- /dev/null
@@ -0,0 +1,188 @@
+/* global xwalk, extension */
+
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var _common = xwalk.utils;
+var Type = _common.type;
+var Converter = _common.converter;
+var AV = _common.validator;
+
+var native_ = new _common.NativeManager(extension);
+
+var _currentWatchId = 1;
+
+var _getNextWatchId = function() {
+  return _currentWatchId++;
+};
+
+// Adjusts properties to have the correct format expected by the native side.
+// Currently only translates JS Date
+var _toJsonObject = function(obj) {
+  var ret;
+  if (Type.isDate(obj)) {
+    var year = ('0000' + obj.getFullYear()).slice(-4);
+    var month = ('00' + (obj.getMonth() + 1)).slice(-2);
+    var day = ('00' + obj.getDate()).slice(-2);
+    return Number(year + month + day);
+  }
+  if (Type.isArray(obj)) {
+    ret = [];
+    for (var i = 0; i < obj.length; ++i) {
+      ret[i] = _toJsonObject(obj[i]);
+    }
+    return ret;
+  }
+  if (obj instanceof Object) {
+    ret = {};
+    for (var prop in obj) {
+      if (obj.hasOwnProperty(prop)) {
+        ret[prop] = _toJsonObject(obj[prop]);
+      }
+    }
+    return ret;
+  }
+  return obj;
+};
+
+var _fromJsonDate = function(date) {
+  date = date + '';
+  var year = date.substr(0, 4);
+  var month = date.substr(4, 2);
+  var day = date.substr(6, 2);
+  return new Date(year, month - 1, day);
+};
+
+var _promote = function(val, type) {
+  return _editGuard.run(function() {
+    if (Type.isArray(val)) {
+      var ret = [];
+      for (var i = 0; i < val.length; ++i) {
+        ret.push(new type(val[i]));
+      }
+      return ret;
+    }
+    return new type(val);
+  });
+};
+
+function _checkError(result) {
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+}
+
+var TypeEnum = ['VCARD_30'];
+
+// Edit Guard //////////////////////////////////////////////////////////////
+// This flag is workaround. It is caused by specification
+// which tell to edit readonly fields.
+var _canEdit = 0;
+
+var EditGuard = function() {
+};
+
+EditGuard.prototype.run = function(callback) {
+  try {
+    this.enable();
+    var result = callback();
+    this.disable();
+    return result;
+  } catch (ex) {
+    this.disable();
+    throw ex;
+  }
+};
+
+EditGuard.prototype.enable = function() {
+  _canEdit++;
+};
+
+EditGuard.prototype.disable = function() {
+  _canEdit--;
+};
+
+EditGuard.prototype.isEditEnabled = function() {
+  return _canEdit > 0;
+};
+
+var _editGuard = new EditGuard();
+
+//TODO: Move sorting and filtering to native code
+var Common = function() {};
+Common.prototype.sort = function(arr, sortMode) {
+  var _getSortProperty = function(obj, props) {
+    for (var i = 0; i < props.length; ++i) {
+      if (!obj.hasOwnProperty(props[i])) {
+        return null;
+      }
+      obj = obj[props[i]];
+    }
+    return obj;
+  };
+
+  if (sortMode instanceof tizen.SortMode) {
+    var props = sortMode.attributeName.split('.');
+    arr.sort(function(a, b) {
+      var aValue = _getSortProperty(a, props);
+      var bValue = _getSortProperty(b, props);
+
+      if (sortMode.order === 'DESC') {
+        return aValue < bValue;
+      }
+      return bValue < aValue;
+    });
+  }
+  return arr;
+};
+
+Common.prototype.filter = function(arr, filter) {
+  if (Type.isNullOrUndefined(arr))
+    return arr;
+  if (filter instanceof tizen.AttributeFilter ||
+      filter instanceof tizen.AttributeRangeFilter ||
+      filter instanceof tizen.CompositeFilter) {
+    arr = arr.filter(function(element) {
+      return filter._filter(element);
+    });
+  }
+  return arr;
+};
+
+Common.prototype.repackFilter = function (filter) {
+  if (filter instanceof tizen.AttributeFilter) {
+    return {
+      filterType: 'AttributeFilter',
+      attributeName: filter.attributeName,
+      matchFlag: filter.matchFlag,
+      matchValue: filter.matchValue
+    };
+  }
+  if (filter instanceof tizen.AttributeRangeFilter) {
+    return {
+      filterType: 'AttributeRangeFilter',
+      attributeName: filter.attributeName,
+      initialValue: Type.isNullOrUndefined(filter.initialValue) ? null : filter.initialValue,
+      endValue: Type.isNullOrUndefined(filter.endValue) ? null : filter.endValue
+    };
+  }
+  if (filter instanceof tizen.CompositeFilter) {
+    var _f = [];
+    var filters = filter.filters;
+
+    for (var i = 0; i < filters.length; ++i) {
+      _f.push(this.repackFilter(filters[i]));
+    }
+
+    return {
+      filterType: 'CompositeFilter',
+      type: filter.type,
+      filters: _f
+    };
+  }
+
+  return null;
+};
+
+var C = new Common();
diff --git a/src/contact/js/contact.js b/src/contact/js/contact.js
new file mode 100644 (file)
index 0000000..cecc843
--- /dev/null
@@ -0,0 +1,585 @@
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var Contact = function(data) {
+  AV.isConstructorCall(this, Contact);
+
+  var _forceEditMode = false;
+  if (Type.isString(data)) {
+    var result = native_.callSync('ContactManager_importFromVCard', {
+      'contact': data
+    });
+    _checkError(result);
+
+    data = native_.getResultObject(result);
+    // These need to be forced to null as a contact created from a vcard is not added
+    // to any address book
+    data.id = null;
+    data.personId = null;
+    data.addressBookId = null;
+    data.lastUpdate = null;
+
+    // Force edit mode so that anonymous objects can be promoted to their correct types.
+    _forceEditMode = true;
+  } else if (Type.isObject(data) || Type.isFunction(data)) {
+    // It's a dictionary
+  } else {
+    // null or invalid types.
+    data = {};
+  }
+
+  var _id = null;
+  var _personId = null;
+  var _addressBookId = null;
+  var _lastUpdate = null;
+  var _isFavorite = false;
+  var _name = null;
+  var _addresses = [];
+  var _photoURI = null;
+  var _phoneNumbers = [];
+  var _emails = [];
+  var _messengers = [];
+  var _relationships = [];
+  var _birthday = null;
+  var _anniversaries = [];
+  var _organizations = [];
+  var _notes = [];
+  var _urls = [];
+  var _ringtoneURI = null;
+  var _messageAlertURI = null;
+  var _vibrationURI = null;
+  var _groupIds = [];
+
+  var _sanitizeArray = function(arr, type, previousValue) {
+    if (!Type.isArray(arr)) {
+      return previousValue;
+    }
+    for (var i = 0; i < arr.length; ++i) {
+      if (Type.isString(type)) {
+        if (!Type.isString(arr[i])) {
+          return previousValue;
+        }
+      } else if (_editGuard.isEditEnabled()) {
+        arr[i] = new type(arr[i]);
+      } else if (!(arr[i] instanceof type)) {
+        return previousValue;
+      }
+    }
+    return arr;
+  };
+
+  Object.defineProperties(this, {
+    id: {
+      get: function() {
+        return _id;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _id = Converter.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    personId: {
+      get: function() {
+        return _personId;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _personId = Converter.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    addressBookId: {
+      get: function() {
+        return _addressBookId;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _addressBookId = Converter.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    lastUpdated: {
+      get: function() {
+        return _lastUpdate;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          if (v instanceof Date || v === null) {
+            _lastUpdate = v;
+          } else if (Type.isString(v)) {
+            _lastUpdate = new Date(v);
+          } else {
+            _lastUpdate = _fromJsonDate(v);
+          }
+        }
+      },
+      enumerable: true
+    },
+    isFavorite: {
+      get: function() {
+        return _isFavorite;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _isFavorite = Converter.toBoolean(v, false);
+        }
+      },
+      enumerable: true
+    },
+    name: {
+      get: function() {
+        return _name;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _name = new ContactName(v);
+        } else {
+          _name = (v instanceof ContactName || v === null) ? v : _name;
+        }
+      },
+      enumerable: true
+    },
+    addresses: {
+      get: function() {
+        return _addresses;
+      },
+      set: function(v) {
+        _addresses = _sanitizeArray(v, ContactAddress, _addresses);
+      },
+      enumerable: true
+    },
+    photoURI: {
+      get: function() {
+        return _photoURI;
+      },
+      set: function(v) {
+        _photoURI = Converter.toString(v, true);
+      },
+      enumerable: true
+    },
+    phoneNumbers: {
+      get: function() {
+        return _phoneNumbers;
+      },
+      set: function(v) {
+        _phoneNumbers = _sanitizeArray(v, ContactPhoneNumber, _phoneNumbers);
+      },
+      enumerable: true
+    },
+    emails: {
+      get: function() {
+        return _emails;
+      },
+      set: function(v) {
+        _emails = _sanitizeArray(v, ContactEmailAddress, _emails);
+      },
+      enumerable: true
+    },
+    messengers: {
+      get: function() {
+        return _messengers;
+      },
+      set: function(v) {
+        _messengers = _sanitizeArray(v, ContactInstantMessenger, _messengers);
+      },
+      enumerable: true
+    },
+    relationships: {
+      get: function() {
+        return _relationships;
+      },
+      set: function(v) {
+        _relationships = _sanitizeArray(v, ContactRelationship, _relationships);
+      },
+      enumerable: true
+    },
+    birthday: {
+      get: function() {
+        return _birthday;
+      },
+      set: function(v) {
+        if (v instanceof Date || v === null) {
+          _birthday = v;
+        } else if (Type.isString(v)) {
+          _birthday = new Date(v);
+        } else if (_editGuard.isEditEnabled()) {
+          _birthday = _fromJsonDate(v);
+        }
+      },
+      enumerable: true
+    },
+    anniversaries: {
+      get: function() {
+        return _anniversaries;
+      },
+      set: function(v) {
+        _anniversaries = _sanitizeArray(v, ContactAnniversary, _anniversaries);
+      },
+      enumerable: true
+    },
+    organizations: {
+      get: function() {
+        return _organizations;
+      },
+      set: function(v) {
+        _organizations = _sanitizeArray(v, ContactOrganization, _organizations);
+      },
+      enumerable: true
+    },
+    notes: {
+      get: function() {
+        return _notes;
+      },
+      set: function(v) {
+        _notes = _sanitizeArray(v, '', _notes);
+      },
+      enumerable: true
+    },
+    urls: {
+      get: function() {
+        return _urls;
+      },
+      set: function(v) {
+        _urls = _sanitizeArray(v, ContactWebSite, _urls);
+      },
+      enumerable: true
+    },
+    ringtoneURI: {
+      get: function() {
+        return _ringtoneURI;
+      },
+      set: function(v) {
+        _ringtoneURI = Converter.toString(v, true);
+      },
+      enumerable: true
+    },
+    messageAlertURI: {
+      get: function() {
+        return _messageAlertURI;
+      },
+      set: function(v) {
+        _messageAlertURI = Converter.toString(v, true);
+      },
+      enumerable: true
+    },
+    vibrationURI: {
+      get: function() {
+        return _vibrationURI;
+      },
+      set: function(v) {
+        _vibrationURI = Converter.toString(v, true);
+      },
+      enumerable: true
+    },
+    groupIds: {
+      get: function() {
+        return _groupIds;
+      },
+      set: function(v) {
+        _groupIds = _sanitizeArray(v, '', _groupIds);
+      },
+      enumerable: true
+    }
+  });
+
+  var _this = this;
+  var _setProperties = function() {
+    for (var p in _this) {
+      if (data.hasOwnProperty(p)) {
+        _this[p] = data[p];
+      }
+    }
+  };
+
+  if (_forceEditMode) {
+    _editGuard.run(_setProperties);
+  } else {
+    _setProperties();
+  }
+
+};
+
+// Auxiliary functions /////////////////////////////////////////////////////
+
+// Convert address from Contact object to string
+var _contactAddressToString = function(obj) {
+  var str = '';
+  if (obj.addresses.length === 0) {
+    return '';
+  }
+  // Sorry for so many if statements, but the IDE makes me do it
+  for (var it in obj.addresses) {
+    if (!it instanceof ContactAddress) {
+      continue;
+    }
+    str += 'ADR;';
+    for (var addType in it.types) {
+      if (Type.isString(addType)) {
+        str += addType + ',';
+      }
+    }
+    if (str.charAt(str.length - 1) === ',') {
+      str[str.length - 1] = ':';
+    }
+    str += ';'; // because of we don't keep Post office addres
+    // which is part of vCard 3.0 standard
+    str += it.additionalInformation + ';';
+    str += it.streetAddress + ';';
+    str += it.city + ';';
+    str += it.region + ';';
+    str += it.postalCode + ';';
+    str += it.country + ';';
+    str += '\n';
+  }
+  return str;
+};
+
+// Convert email address from Contact object to string
+var _contactEmailToString = function(obj) {
+  if (!Type.isArray(obj.emails) || obj.emails.length === 0) {
+    console.log('Empty email list');
+    return '';
+  }
+  var str = '';
+  for (var mail in obj.emails) {
+    if (!mail instanceof ContactEmailAddress || !Type.isArray(mail.types) ||
+      mail.types.length === 0) {
+      console.log('Incorrect email type');
+      continue;
+    }
+    str += 'EMAIL;';
+    // set types
+    for (var type in mail.types) {
+      if (Type.isString(type)) {
+        str += type + ',';
+      }
+    }
+    if (str.charAt(str.length - 1) === ',') {
+      str[str.length - 1] = ':';
+    }
+    str += '=' + Converter.toString(mail.email) + '\n';
+  }
+  return str;
+};
+
+// Convert organizations info from Contact object to string
+var _contactOrganizationToString = function(obj) {
+  if (obj.organizations.length === 0 ||
+    !obj.organizations[0] instanceof ContactOrganization) {
+    return '';
+  }
+  var str = '';
+  for (var org in obj.organizations) {
+    if (!org instanceof ContactOrganization) {
+      continue;
+    }
+    str += 'ORG:';
+    str += org.name + ';' + org.department + ';' + org.title + '\n';
+  }
+  return str;
+};
+
+// Convert organizations roles from Contact object to string
+var _contactRoleToString = function(obj) {
+  if (obj.organizations.length === 0 ||
+    !obj.organizations[0] instanceof ContactOrganization) {
+    return '';
+  }
+  var str = '';
+  for (var org in obj.organizations) {
+    if (!org instanceof ContactOrganization) {
+      continue;
+    }
+    str += 'ROLE:';
+    str += org.name + ';' + org.role + '\n';
+  }
+  return str;
+};
+
+// Convert phone numbers from Contact object to string
+var _contactPhoneNumbersToString = function(obj) {
+  if (obj.phoneNumbers.length === 0 || !obj.phoneNumbers[0] instanceof ContactPhoneNumber) {
+    return '';
+  }
+  var str = '';
+  for (var phone in obj.phoneNumbers) {
+    if (!phone instanceof ContactPhoneNumber) {
+      continue;
+    }
+    str += 'TEL';
+    for (var type in phone.types) {
+      if (Type.isString(type)) {
+        str += ';' + type;
+      }
+    }
+    str += ':';
+    str += phone.number + '\n';
+  }
+  return str;
+};
+
+// Convert urls from Contact object to string
+var _contactURLToString = function(obj) {
+  if (obj.urls.length === 0 || !obj.urls[0] instanceof ContactWebSite) {
+    return '';
+  }
+  var str = '';
+  for (var url in obj.urls) {
+    if (url instanceof ContactWebSite) {
+      str += 'URL:' + url.url + '\n';
+    }
+  }
+  return str;
+};
+
+// Convert anniversaries to string
+var _contactAnniversaryToString = function(obj) {
+  if (obj.anniversaries.length === 0 || !obj.anniversaries[0] instanceof ContactAnniversary) {
+    return '';
+  }
+  var str = '';
+  for (var ann in obj.anniversaries) {
+    if (ann instanceof ContactAnniversary) {
+      str += 'X-ANNIVERSARY;' + ann.label + ':' + ann.date + ';' + '\n';
+    }
+  }
+  return str;
+};
+
+// Convert relationships to string
+var _contactRelationshipsToString = function(obj) {
+  if (obj.relationships.length === 0 ||
+    !obj.relationships[0] instanceof ContactRelationship) {
+    return '';
+  }
+  var str = '';
+  for (var rel in obj.relationships) {
+    if (rel instanceof ContactRelationship) {
+      str += 'X-RELATIONSHIP;' + rel.relativeName + ':' + rel.type +
+      ':' + rel.label + ';\n';
+    }
+  }
+  return str;
+};
+
+// Convert messengers to string
+var _contactInstantMessengeToString = function(obj) {
+  if (obj.messengers.length === 0 || !obj.messengers[0] instanceof ContactInstantMessenger) {
+    return '';
+  }
+  var str = '';
+  for (var messenger in obj.messengers) {
+    if (messenger instanceof ContactInstantMessenger) {
+      str += 'X-MESSANGER;' + messenger.imAddress + ':' + messenger.type +
+      ':' + messenger.label + ';\n';
+    }
+  }
+  return str;
+};
+
+// Auxiliary function, allows to parse JSON to Contact
+var _JSONToContactType = function(type, obj) {
+  var contact = new type();
+
+  for (var prop in obj) {
+    if (contact.hasOwnProperty(prop)) {
+      if (contact[prop] instanceof Date && Type.isNumber(obj[prop])) {
+        contact[prop] = new Date(1000 * obj[prop]);
+      } else {
+        contact[prop] = obj[prop];
+      }
+    }
+  }
+
+  return contact;
+};
+
+// Converts the Contact item to a string format.
+Contact.prototype.convertToString = function(format) {
+  format = format || TypeEnum[0];
+
+  if (!Type.isString(format)) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR, 'Invalid format');
+  }
+
+  if (TypeEnum.indexOf(format) < 0) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR, 'Invalid format');
+  }
+
+  if (this.id === '') {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR,
+      'Contact ID is empty.');
+  }
+
+  var str = 'BEGIN:VCARD\nVERSION:3.0\n';
+
+  // set contact name
+  str += 'N:' + this.name.lastName + ';' + this.name.firstName + ';' +
+  this.name.middleName + ';' + this.name.prefix + ';' + this.name.suffix + '\n';
+  str += 'FN' + this.name.displayName + '\n';
+
+  // set phonetic names
+  str += 'X-PHONETIC-FIRST-NAME' + this.name.phoneticFirstName + '\n' +
+  'X-PHONETIC-LAST-NAME' + this.name.phoneticLastName + '\n';
+
+  // set contact address
+  str += _contactAddressToString(this);
+
+  // set Birthday
+  if (this.birthday) {
+    str += 'BDAY:' + this.birthday.getYear() + '-' + this.birthday.getMonth() +
+    '-' + this.birthday.getDay() + '\n';
+  }
+
+  // set anniversary
+  str += _contactAnniversaryToString(this);
+
+  // set relationship
+  str += _contactRelationshipsToString(this);
+
+  // set emails
+  str += _contactEmailToString(this);
+
+  // set organization data
+  str += _contactOrganizationToString(this);
+
+  // set role
+  str += _contactRoleToString(this);
+
+  // set phone numbers
+  str += _contactPhoneNumbersToString(this);
+
+  // set user ID
+  str += 'UID:' + this.id + '\n';
+
+  // set isFavorite
+  str += 'X-IS-FAVORITE' + this.isFavorite + '\n';
+
+  // set URLs
+  str += _contactURLToString(this);
+
+  // set messengers
+  str += _contactInstantMessengeToString(this);
+
+  // set last revision
+  str += 'REV:' + this.lastUpdated.getYear() + '-' + this.lastUpdated.getMonth() +
+  '-' + this.lastUpdated.getDay() + 'T' + this.lastUpdated.getHours() + ':' +
+  this.lastUpdated.getMinutes() + ':' + this.lastUpdated.getSeconds() + 'Z\n';
+
+  str += 'END:VCARD\n';
+
+  return str;
+};
+
+// Creates a clone of the Contact object, detached from any address book
+Contact.prototype.clone = function() {
+  return new Contact(this);
+};
+
+// exports /////////////////////////////////////////////////////////////////
+tizen.Contact = Contact;
diff --git a/src/contact/js/contact_data_structures.js b/src/contact/js/contact_data_structures.js
new file mode 100644 (file)
index 0000000..eab6256
--- /dev/null
@@ -0,0 +1,743 @@
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// An enumerator that indicates the types for the relationships.
+var ContactRelationshipType = {
+  ASSISTANT: 'ASSISTANT',
+  BROTHER: 'BROTHER',
+  CHILD: 'CHILD',
+  DOMESTIC_PARTNER: 'DOMESTIC_PARTNER',
+  FATHER: 'FATHER',
+  FRIEND: 'FRIEND',
+  MANAGER: 'MANAGER',
+  MOTHER: 'MOTHER',
+  PARENT: 'PARENT',
+  PARTNER: 'PARTNER',
+  REFERRED_BY: 'REFERRED_BY',
+  RELATIVE: 'RELATIVE',
+  SISTER: 'SISTER',
+  SPOUSE: 'SPOUSE',
+  OTHER: 'OTHER',
+  CUSTOM: 'CUSTOM'
+};
+
+// An enumerator that indicates the types for instant messenger.
+var ContactInstantMessengerType = {
+  GOOGLE: 'GOOGLE',
+  WLM: 'WLM',
+  YAHOO: 'YAHOO',
+  FACEBOOK: 'FACEBOOK',
+  ICQ: 'ICQ',
+  AIM: 'AIM',
+  QQ: 'QQ',
+  JABBER: 'JABBER',
+  SKYPE: 'SKYPE',
+  IRC: 'IRC',
+  OTHER: 'OTHER',
+  CUSTOM: 'CUSTOM'
+};
+
+// class ContactRef ////////////////////////////////////////////////////////
+
+var ContactRef = function(data) {
+  AV.isConstructorCall(this, ContactRef);
+  var _contactId = '';
+  var _addressBookId = '';
+  Object.defineProperties(this, {
+    addressBookId: {
+      get: function() {
+        return _addressBookId;
+      },
+      set: function(v) {
+        _addressBookId = Converter.toString(v, false);
+      },
+      enumerable: true
+    },
+    contactId: {
+      get: function() {
+        return _contactId;
+      },
+      set: function(v) {
+        _contactId = Converter.toString(v, false);
+      },
+      enumerable: true
+    }
+  });
+
+  if (Type.isObject(data)) {
+    this.addressBookId = data.addressBookId;
+    this.contactId = data.contactId;
+  } else {
+    try {
+      var args = AV.validateArgs(arguments, [
+        {
+          name: 'addressBookId',
+          type: AV.Types.STRING,
+          optional: false,
+          nullable: false
+        },
+        {
+          name: 'contactId',
+          type: AV.Types.STRING,
+          optional: false,
+          nullable: false
+        }
+      ]);
+      _addressBookId = args.addressBookId;
+      _contactId = args.contactId;
+    } catch (x) {
+      // Constructors shouldn't throw
+    }
+  }
+};
+
+// class ContactGroup //////////////////////////////////////////////////
+
+var ContactGroup = function(name, ringtone, photo) {
+  AV.isConstructorCall(this, ContactGroup);
+
+  var _id = null;
+  var _address = null;
+  var _readOnly = false;
+  var _name = '';
+  var _ringtoneURI = null;
+  var _photoURI = null;
+
+  if (name && Type.isString(name)) {
+    _name = name.length ? name : '';
+  }
+
+  if (ringtone && Type.isString(ringtone)) {
+    _ringtoneURI = ringtone.length ? ringtone : null;
+  }
+
+  if (photo && Type.isString(photo)) {
+    _photoURI = photo.length ? photo : null;
+  }
+
+  Object.defineProperties(this, {
+    id: {
+      get: function() {
+        return _id;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _id = Converter.toString(v, true);
+        }
+      },
+      enumerable: true
+    },
+    addressBookId: {
+      get: function() {
+        return _address;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _address = Converter.toString(v, true);
+        }
+      },
+      enumerable: true
+    },
+    name: {
+      get: function() {
+        return _name;
+      },
+      set: function(v) {
+        _name = Converter.toString(v, false);
+      },
+      enumerable: true
+    },
+    ringtoneURI: {
+      get: function() {
+        return _ringtoneURI;
+      },
+      set: function(v) {
+        _ringtoneURI = Converter.toString(v, true);
+      },
+      enumerable: true
+    },
+    photoURI: {
+      get: function() {
+        return _photoURI;
+      },
+      set: function(v) {
+        _photoURI = Converter.toString(v, true);
+      },
+      enumerable: true
+    },
+    readOnly: {
+      get: function() {
+        return _readOnly;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _readOnly = Converter.toBoolean(v, false);
+        }
+      },
+      enumerable: true
+    }
+  });
+
+  if (_editGuard.isEditEnabled()) {
+    var data = arguments[0];
+    if (Type.isObject(data)) {
+      for (var prop in data) {
+        if (this.hasOwnProperty(prop)) {
+          this[prop] = data[prop];
+        }
+      }
+    }
+  }
+};
+
+// class ContactEmailAddress ///////////////////////////////////////////
+
+var ContactEmailAddress = function(address, types, isDefault) {
+  AV.isConstructorCall(this, ContactEmailAddress);
+
+  var _email = '';
+  var _label = null;
+  var _isDefault = false;
+  var _types = ['WORK'];
+
+  if (Type.isString(address) && address.indexOf('@') > 0 &&
+      address.indexOf('@') !== (address.length - 1)) {
+    _email = address;
+  }
+
+  if (Type.isBoolean(isDefault)) {
+    _isDefault = isDefault;
+  }
+
+  if (Type.isArray(types)) {
+    _types = [];
+    for (var i = 0; i < types.length; ++i) {
+      if (Type.isString(types[i])) {
+        _types.push(types[i]);
+      }
+    }
+  } else if (Type.isString(types)) {
+    _types = [];
+    _types.push(types);
+  }
+
+  Object.defineProperties(this, {
+    email: {
+      get: function() {
+        return _email;
+      },
+      set: function(v) {
+        if (Type.isString(v) && v.indexOf('@') > 0 &&
+            v.indexOf('@') !== (v.length - 1)) {
+          _email = v;
+        }
+      },
+      enumerable: true
+    },
+    isDefault: {
+      get: function() {
+        return _isDefault;
+      },
+      set: function(v) {
+        _isDefault = Converter.toBoolean(v, false);
+      },
+      enumerable: true
+    },
+    types: {
+      get: function() {
+        return _types;
+      },
+      set: function(v) {
+        if (Type.isArray(v)) {
+          _types = [];
+          for (var i = 0; i < v.length; ++i) {
+            if (Type.isString(v[i])) {
+              _types.push(v[i]);
+            }
+          }
+        } else if (Type.isString(v)) {
+          _types = [];
+          _types.push(v);
+        }
+      },
+      enumerable: true
+    },
+    label: {
+      get: function() {
+        return _label;
+      },
+      set: function(v) {
+        _label = Converter.toString(v, true);
+      },
+      enumerable: true
+    }
+  });
+
+  if (_editGuard.isEditEnabled()) {
+    for (var prop in arguments[0]) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = arguments[0][prop];
+      }
+    }
+  }
+};
+
+// class ContactPhoneNumber ////////////////////////////////////////////
+
+var ContactPhoneNumber = function(number, type, isDefault) {
+  AV.isConstructorCall(this, ContactPhoneNumber);
+
+  var _isDefault = false;
+  var _number = '';
+  var _types = ['VOICE'];
+
+  if (Type.isString(number)) {
+    _number = number;
+  }
+
+  if (Type.isArray(type)) {
+    _types = [];
+    for (var i = 0; i < type.length; ++i) {
+      _types.push(Converter.toString(type[i], false));
+    }
+  } else if (Type.isString(type)) {
+    _types = [];
+    _types.push(type, false);
+  }
+
+  if (Type.isBoolean(isDefault)) {
+    _isDefault = isDefault;
+  }
+
+  Object.defineProperties(this, {
+    number: {
+      get: function() {
+        return _number;
+      },
+      set: function(v) {
+        _number = Converter.toString(v, false);
+      },
+      enumerable: true
+    },
+    isDefault: {
+      get: function() {
+        return _isDefault;
+      },
+      set: function(v) {
+        _isDefault = Converter.toBoolean(v, false);
+      },
+      enumerable: true
+    },
+    types: {
+      get: function() {
+        return _types;
+      },
+      set: function(v) {
+        if (Type.isArray(v)) {
+          _types = [];
+          for (var i = 0; i < v.length; ++i) {
+            _types.push(Converter.toString(v[i], false));
+          }
+        } else if (Type.isString(v)) {
+          _types = [];
+          _types.push(v, false);
+        }
+      },
+      enumerable: true
+    },
+    label: {
+      value: null,
+      writable: true,
+      enumerable: true
+    }
+  });
+
+  if (_editGuard.isEditEnabled()) {
+    for (var prop in arguments[0]) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = arguments[0][prop];
+      }
+    }
+  }
+};
+
+// class ContactAddress ////////////////////////////////////////////////
+
+var ContactAddress = function(data) {
+  AV.isConstructorCall(this, ContactAddress);
+
+  var _isDefault = false;
+  var _types = ['HOME'];
+
+  Object.defineProperties(this, {
+    country: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    region: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    city: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    streetAddress: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    additionalInformation: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    postalCode: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    isDefault: {
+      get: function() {
+        return _isDefault;
+      },
+      set: function(v) {
+        _isDefault = Converter.toBoolean(v, false);
+      },
+      enumerable: true
+    },
+    types: {
+      get: function() {
+        return _types;
+      },
+      set: function(v) {
+        if (Type.isString(v)) {
+          _types = [];
+          _types.push(v);
+        } else if (Type.isArray(v)) {
+          _types = [];
+          for (var i = 0; i < v.length; ++i) {
+            if (Type.isString(v[i])) {
+              _types.push(v[i]);
+            }
+          }
+        }
+      },
+      enumerable: true
+    },
+    label: {
+      value: null,
+      writable: true,
+      enumerable: true
+    }
+  });
+
+  if (Type.isObject(data)) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+};
+
+// class ContactAnniversary ////////////////////////////////////////////////
+
+var ContactAnniversary = function(anniversary_date, anniversary_label) {
+  AV.isConstructorCall(this, ContactAnniversary);
+
+  var _anniversary_date = new Date();
+  var _anniversary_label = null;
+
+  Object.defineProperties(this, {
+    date: {
+      get: function() {
+        return _anniversary_date;
+      },
+      set: function(v) {
+        _anniversary_date = v instanceof Date ? v : new Date();
+      },
+      enumerable: true
+    },
+    label: {
+      get: function() {
+        return _anniversary_label;
+      },
+      set: function(v) {
+        _anniversary_label = Converter.toString(v, true);
+      },
+      enumerable: true
+    }
+  });
+
+  if (_editGuard.isEditEnabled()) {
+    _anniversary_date = _fromJsonDate(arguments[0].date);
+    _anniversary_label = arguments[0].label;
+  } else {
+    if (Type.isDate(anniversary_date)) {
+      _anniversary_date = anniversary_date;
+    }
+    if (Type.isString(anniversary_label)) {
+      _anniversary_label = anniversary_label;
+    }
+  }
+};
+
+// class ContactWebSite ////////////////////////////////////////////////////
+
+var ContactWebSite = function(contact_url, contact_type) {
+  AV.isConstructorCall(this, ContactWebSite);
+
+  var _url = '';
+  var _type = 'HOMEPAGE';
+
+  if (Type.isString(contact_url)) {
+    _url = contact_url;
+  }
+  if (Type.isString(contact_type)) {
+    _type = contact_type;
+  }
+
+  Object.defineProperties(this, {
+    url: {
+      get: function() {
+        return _url;
+      },
+      set: function(v) {
+        _url = Converter.toString(v, false);
+      },
+      enumerable: true
+    },
+    type: {
+      get: function() {
+        return _type;
+      },
+      set: function(v) {
+        _type = Converter.toString(v, false);
+      },
+      enumerable: true
+    }
+  });
+};
+
+// class ContactOrganization ///////////////////////////////////////////////
+
+var ContactOrganization = function(data) {
+  AV.isConstructorCall(this, ContactOrganization);
+  Object.defineProperties(this, {
+    name: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    department: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    title: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    role: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    logoURI: {
+      value: null,
+      writable: true,
+      enumerable: true
+    }
+  });
+
+  if (Type.isObject(data)) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+};
+
+// class ContactName ///////////////////////////////////////////////////////
+
+var ContactName = function(data) {
+  AV.isConstructorCall(this, ContactName);
+
+  var _displayName = null;
+  var _nicknames = [];
+
+  Object.defineProperties(this, {
+    prefix: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    suffix: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    firstName: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    middleName: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    lastName: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    nicknames: {
+      get: function() {
+        return _nicknames;
+      },
+      set: function(nicknames) {
+        if (Type.isArray(nicknames)) {
+          _nicknames = nicknames;
+        }
+      },
+      enumerable: true
+    },
+    phoneticFirstName: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    phoneticMiddleName: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    phoneticLastName: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    displayName: {
+      get: function() {
+        return _displayName;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _displayName = Converter.toString(v, true);
+        }
+      },
+      enumerable: true
+    }
+  });
+
+  if (Type.isObject(data)) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+};
+
+var ContactRelationship = function(relativeName, type) {
+  AV.isConstructorCall(this, ContactRelationship);
+
+  var _relativeName = Converter.toString(relativeName, false);
+  var _type = type ? Converter.toEnum(type, Object.keys(ContactRelationshipType), false)
+            : ContactRelationshipType.OTHER;
+  var _label = null;
+
+  Object.defineProperties(this, {
+    relativeName: {
+      get: function () {
+        return _relativeName;
+      },
+      set: function (v) {
+        _relativeName = Converter.toString(v, false);
+      },
+      enumerable: true
+    },
+    type: {
+      get: function () {
+        return _type;
+      },
+      set: function (v) {
+        _type = v ? Converter.toEnum(v, Object.keys(ContactRelationshipType), false)
+                  : _type;
+      },
+      enumerable: true
+    },
+    label: {
+      get: function () {
+        return _label;
+      },
+      set: function (v) {
+        _label = Converter.toString(v, true);
+      },
+      enumerable: true
+    }
+  });
+};
+
+var ContactInstantMessenger = function(imAddress, type) {
+  AV.isConstructorCall(this, ContactInstantMessenger);
+
+  var imAddress_ = '';
+  var type_ = 'OTHER';
+
+  Object.defineProperties(this, {
+    imAddress: {
+      get: function() {
+        return imAddress_;
+      },
+      set: function(v) {
+        if (Type.isNullOrUndefined(v)) {
+          return;
+        }
+        imAddress_ = Converter.toString(v, false);
+      },
+      enumerable: true
+    },
+    type: {
+      get: function() {
+        return type_;
+      },
+      set: function(v) {
+        if (Type.isNullOrUndefined(v)) {
+          return;
+        }
+        type_ = Converter.toEnum(v, Object.keys(ContactInstantMessengerType), false);
+      },
+      enumerable: true
+    },
+    label: {
+      value: null,
+      writable: true,
+      enumerable: true
+    }
+  });
+
+  this.imAddress = imAddress;
+  this.type = type;
+};
+
+// exports /////////////////////////////////////////////////////////////////
+tizen.ContactRef = ContactRef;
+tizen.ContactName = ContactName;
+tizen.ContactOrganization = ContactOrganization;
+tizen.ContactWebSite = ContactWebSite;
+tizen.ContactAnniversary = ContactAnniversary;
+tizen.ContactAddress = ContactAddress;
+tizen.ContactPhoneNumber = ContactPhoneNumber;
+tizen.ContactEmailAddress = ContactEmailAddress;
+tizen.ContactGroup = ContactGroup;
+tizen.ContactRelationship = ContactRelationship;
+tizen.ContactInstantMessenger = ContactInstantMessenger;
diff --git a/src/contact/js/contact_manager.js b/src/contact/js/contact_manager.js
new file mode 100644 (file)
index 0000000..c27b512
--- /dev/null
@@ -0,0 +1,467 @@
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+var _personListenerRegistered = false;
+var _personCallbackMap = {};
+var _personChangeListener = function(result) {
+  for (var key in _personCallbackMap) {
+    if (_personCallbackMap.hasOwnProperty(key)) {
+      if (result.added.length) {
+        native_.callIfPossible(_personCallbackMap[key].onpersonsadded,
+            _promote(result.added, Person));
+      }
+      if (result.updated.length) {
+        native_.callIfPossible(_personCallbackMap[key].onpersonsupdated,
+            _promote(result.updated, Person));
+      }
+      if (result.removed.length) {
+        native_.callIfPossible(_personCallbackMap[key].onpersonsremoved,
+            result.removed);
+      }
+    }
+  }
+};
+
+
+var ContactManager = function() {};
+
+// Gets the available address books
+ContactManager.prototype.getAddressBooks = function() {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: AV.Types.FUNCTION,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+    } else {
+      var books = native_.getResultObject(result);
+      var tmp = [];
+
+      books.forEach(function(data) {
+        return _editGuard.run(function() {
+          var addressBook = new AddressBook(result.accountId, result.name);
+          addressBook.id = data.id;
+          addressBook.readOnly = result.readOnly;
+
+          tmp.push(addressBook);
+        });
+      });
+
+      native_.callIfPossible(args.successCallback, tmp);
+    }
+  };
+
+  native_.call('ContactManager_getAddressBooks', {}, callback);
+};
+
+// Gets the aggregation of all address books.
+ContactManager.prototype.getUnifiedAddressBook = function() {
+  // TODO check privileges
+  //var result = native_.callSync('CheckReadPrivileges', {});
+  //if (native_.isFailure(result)) {
+  //  throw new tizen.WebAPIException(WebAPIException.SECURITY_ERR,
+  //      'You do not have privileges for this operation');
+  //}
+
+  return _editGuard.run(function() {
+    var addressBook = new AddressBook(0, 'Unified address book');
+    addressBook.id = UNIFIED_ADDRESSBOOK_ID;
+    addressBook.readOnly = false;
+
+    return addressBook;
+  });
+};
+
+// Gets the default address book.
+ContactManager.prototype.getDefaultAddressBook = function() {
+  //privileges are checked in getAddressBook function
+  return this.getAddressBook(DEFAULT_ADDRESSBOOK_ID);
+};
+
+// Gets the address book with the specified identifier.
+ContactManager.prototype.getAddressBook = function() {
+  var args = AV.validateArgs(arguments, [{
+    name: 'addressBookId',
+    type: AV.Types.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(Converter.toLong(args.addressBookId)) !== args.addressBookId) {
+    // TCT: ContactManager_getAddressBook_addressBookId_invalid
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
+  }
+
+  var result = native_.callSync('ContactManager_getAddressBook', {
+    addressBookId: args.addressBookId
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  result = native_.getResultObject(result);
+
+  return _editGuard.run(function() {
+    var addressBook = new AddressBook(result.accountId, result.name);
+    addressBook.id = args.addressBookId;
+    addressBook.readOnly = result.readOnly;
+
+    return addressBook;
+  });
+};
+
+ContactManager.prototype.addAddressBook = function() {
+  var args = AV.validateArgs(arguments, [{
+    name: 'addressBook',
+    type: AV.Types.PLATFORM_OBJECT,
+    values: tizen.AddressBook,
+    optional: false,
+    nullable: false
+  }]);
+
+  var result = native_.callSync('ContactManager_addAddressBook', {
+    addressBook: args.addressBook
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var data = native_.getResultObject(result);
+  _editGuard.run(function() {
+    for (var prop in data) {
+      if (args.addressBook.hasOwnProperty(prop)) {
+        args.addressBook[prop] = data[prop];
+      }
+    }
+  });
+};
+
+ContactManager.prototype.removeAddressBook = function() {
+  // TCT: ContactManager_removeAddressBook_misarg
+  if (Type.isNullOrUndefined(arguments[0])) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var args = AV.validateArgs(arguments, [{
+    name: 'addressBookId',
+    type: AV.Types.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (args.addressBookId === UNIFIED_ADDRESSBOOK_ID) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
+        'Unified address book can not be deleted');
+  }
+
+  if (args.addressBookId === DEFAULT_ADDRESSBOOK_ID) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
+        'Default address book can not be deleted');
+  }
+
+  var result = native_.callSync('ContactManager_removeAddressBook', {
+    addressBookId: args.addressBookId
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+// Gets the person with the specified identifier.
+ContactManager.prototype.get = function() {
+  // validation
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'personId',
+      type: AV.Types.STRING,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  if (String(Converter.toLong(args.personId)) !== args.personId) {
+    // TCT: ContactManager_get_personId_invalid
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('ContactManager_get', {
+    personId: args.personId
+  });
+  _checkError(result);
+
+  return _editGuard.run(function() {
+    return new Person(native_.getResultObject(result));
+  });
+};
+
+// Updates a person in the address book synchronously.
+ContactManager.prototype.update = function() {
+  // validation
+  var args = AV.validateArgs(arguments, [{
+    name: 'person',
+    type: AV.Types.PLATFORM_OBJECT,
+    values: Person,
+    optional: false,
+    nullable: false
+  }]);
+  var result = native_.callSync('ContactManager_update', { person: args.person });
+  _checkError(result);
+
+  result = native_.getResultObject(result);
+  for (var prop in result) {
+    if (args.person.hasOwnProperty(prop)) {
+      args.person[prop] = result[prop];
+    }
+  }
+};
+
+// Updates several existing persons in the contact DB asynchronously.
+ContactManager.prototype.updateBatch = function() {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'persons',
+      type: AV.Types.ARRAY,
+      values: Person,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('ContactManager_updateBatch', {
+    addressBook: {},
+    batchArgs: _toJsonObject(args.persons)
+  }, callback);
+};
+
+// Removes a person from the contact DB synchronously.
+ContactManager.prototype.remove = function() {
+  // validation
+  var args = AV.validateArgs(arguments, [{
+    name: 'personId',
+    type: AV.Types.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(Converter.toLong(args.personId)) !== args.personId) {
+    // TCT: ContactManager_remove_personId_invalid
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('ContactManager_remove', {personId: args.personId});
+  _checkError(result);
+};
+
+// Removes persons from contact DB asynchronously.
+ContactManager.prototype.removeBatch = function() {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'personIds',
+      type: AV.Types.ARRAY,
+      values: AV.Types.STRING,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('ContactManager_removeBatch', {
+    addressBook: {},
+    batchArgs: _toJsonObject(args.personIds)
+  }, callback);
+};
+
+// Gets an array of all Person objects from the contact DB or the ones that match the
+// optionally supplied filter.
+ContactManager.prototype.find = function() {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: AV.Types.FUNCTION,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'filter',
+      type: AV.Types.PLATFORM_OBJECT,
+      values: [tizen.AttributeFilter,
+        tizen.AttributeRangeFilter,
+        tizen.CompositeFilter],
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'sortMode',
+      type: AV.Types.PLATFORM_OBJECT,
+      values: tizen.SortMode,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  // TODO implement contact filtering/sorting.
+  var data = {
+    filter: C.repackFilter(args.filter),
+    sortMode: args.sortMode
+  };
+
+  var self = this;
+
+  var callback = function(result) {
+    if (native_.isSuccess(result)) {
+      var _result = native_.getResultObject(result);
+      var retval = [];
+      for (var i = 0; i < _result.length; ++i) {
+        retval.push(self.get(String(_result[i])));
+      }
+      //TODO: Move sorting to native code
+      retval = C.sort(retval, args.sortMode);
+      args.successCallback(retval);
+    } else {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+    }
+  };
+
+  native_.call('ContactManager_find', data, callback);
+};
+
+// Subscribes to receive notifications about persons' changes.
+ContactManager.prototype.addChangeListener = function() {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: AV.Types.LISTENER,
+      values: ['onpersonsadded', 'onpersonsupdated', 'onpersonsremoved'],
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  if (Type.isEmptyObject(_personCallbackMap)) {
+    var result = native_.callSync('ContactManager_startListening', {});
+
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+
+  if (!_personListenerRegistered) {
+    native_.addListener('ContactPersonChangeListener', _personChangeListener);
+    _personListenerRegistered = true;
+  }
+
+  var currentWatchId = _getNextWatchId();
+
+  _personCallbackMap[currentWatchId] = args.successCallback;
+
+  return currentWatchId;
+};
+
+// Unsubscribes a persons' changes watch operation.
+ContactManager.prototype.removeChangeListener = function() {
+  var args = AV.validateArgs(arguments, [
+    {
+      name: 'watchId',
+      type: AV.Types.LONG,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  // This makes UTC_contact_removeChangeListenerPerson_N_001 pass.
+  // watch id's start at 1
+  if (args.watchId === 0) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
+      'id is null or undefined');
+  }
+
+  if (args.watchId < 0) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
+        'Negative watch id');
+  }
+
+  if (!_personCallbackMap.hasOwnProperty(args.watchId)) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR,
+        'watch id not found');
+  }
+
+  delete _personCallbackMap[args.watchId];
+
+  if (Type.isEmptyObject(_personCallbackMap)) {
+    native_.removeListener('ContactPersonChangeListener', _personChangeListener);
+    _personListenerRegistered = false;
+
+    var result = native_.callSync('ContactManager_stopListening', {});
+
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+};
+
+// exports /////////////////////////////////////////////////////////////////
+exports = new ContactManager();
diff --git a/src/contact/js/person.js b/src/contact/js/person.js
new file mode 100644 (file)
index 0000000..d6c1ef5
--- /dev/null
@@ -0,0 +1,182 @@
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+var Person = function(data) {
+  AV.isConstructorCall(this, Person);
+
+  var _id = '';
+  var _displayName = '';
+  var _contactCount = 0;
+  var _hasPhoneNumber = false;
+  var _hasEmail = false;
+  var _isFavorite = false;
+  var _displayContactId = '';
+
+  if (data.hasOwnProperty('id') && Type.isString(data.id)) {
+    _id = data.id;
+  }
+  if (data.hasOwnProperty('displayName') && Type.isString(data.displayName)) {
+    _displayName = data.displayName;
+  }
+  if (data.hasOwnProperty('contactCount') && Type.isNumber(data.contactCount)) {
+    _contactCount = data.contactCount;
+  }
+  if (data.hasOwnProperty('hasPhoneNumber') && Type.isBoolean(data.hasPhoneNumber)) {
+    _hasPhoneNumber = data.hasPhoneNumber;
+  }
+  if (data.hasOwnProperty('hasEmail') && Type.isBoolean(data.hasEmail)) {
+    _hasEmail = data.hasEmail;
+  }
+  if (data.hasOwnProperty('displayContactId') && Type.isString(data.displayContactId)) {
+    _displayContactId = data.displayContactId;
+  }
+  if (data.hasOwnProperty('isFavorite') && Type.isBoolean(data.isFavorite)) {
+    _isFavorite = data.isFavorite;
+  }
+
+  Object.defineProperties(this, {
+    id: {
+      get: function() {
+        return _id;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _id = Converter.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    displayName: {
+      get: function() {
+        return _displayName;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _displayName = Converter.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    contactCount: {
+      get: function() {
+        return _contactCount;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _contactCount = Converter.toLong(v, false);
+        }
+      },
+      enumerable: true
+    },
+    hasPhoneNumber: {
+      get: function() {
+        return _hasPhoneNumber;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _hasPhoneNumber = Converter.toBoolean(v, false);
+        }
+      },
+      enumerable: true
+    },
+    hasEmail: {
+      get: function() {
+        return _hasEmail;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _hasEmail = Converter.toBoolean(v, false);
+        }
+      },
+      enumerable: true
+    },
+
+    isFavorite: {
+      get: function() {
+        return _isFavorite;
+      },
+      set: function(v) {
+        _isFavorite = Converter.toBoolean(v, false);
+      },
+      enumerable: true
+    },
+    photoURI: {
+      value: data.hasOwnProperty('photoURI') ? data.photoURI : null,
+      writable: true,
+      enumerable: true
+    },
+    ringtoneURI: {
+      value: data.hasOwnProperty('ringtoneURI') ? data.ringtoneURI : null,
+      writable: true,
+      enumerable: true
+    },
+    displayContactId: {
+      get: function() {
+        return _displayContactId;
+      },
+      set: function(v) {
+        _displayContactId = Converter.toString(v, false);
+      },
+      enumerable: true
+    }
+  });
+};
+
+// Aggregates another person to this person.
+Person.prototype.link = function() {
+  var args = AV.validateArgs(arguments, [{
+    name: 'personId',
+    type: AV.Types.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(Converter.toLong(args.personId)) !== args.personId) {
+    // TCT: Person_link_personId_invalid
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('Person_link', {
+    // TODO move to only sending the person id (in all functions)
+    person: this,
+    id: args.personId
+  });
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  var _this = this;
+  _editGuard.run(function() {
+    _this.contactCount = _this.contactCount + 1;
+  });
+};
+
+// Separates a contact from this person.
+Person.prototype.unlink = function(contactId) {
+  var args = AV.validateArgs(arguments, [{
+    name: 'contactId',
+    type: AV.Types.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(Converter.toLong(args.contactId)) !== args.contactId) {
+    // TCT: Person_unlink_contactId_invalid
+    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('Person_unlink', {
+    // TODO move to only sending the person id (in all functions)
+    person: this,
+    id: args.contactId
+  });
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  var _this = this;
+  return _editGuard.run(function() {
+    _this.contactCount = _this.contactCount - 1;
+    return new Person(native_.getResultObject(result));
+  });
+};
diff --git a/src/contact/js/tizen.contact.AddressBook.js b/src/contact/js/tizen.contact.AddressBook.js
deleted file mode 100644 (file)
index 12190ab..0000000
+++ /dev/null
@@ -1,696 +0,0 @@
-// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var DEFAULT_ADDRESSBOOK_ID = '0';
-var UNIFIED_ADDRESSBOOK_ID = '-1';
-
-var _contactListenerRegistered = false;
-var _contactCallbackMap = {};
-
-var _filterById = function(array, id) {
-  var ret = [];
-  for (var i = 0; i < array.length; ++i) {
-    if (array[i].addressBookId === id) {
-      ret.push(_promote(array[i], Contact));
-    }
-  }
-  return ret;
-};
-
-var _contactChangeListener = function(result) {
-  var unifiedId = UNIFIED_ADDRESSBOOK_ID;
-  var watchId;
-  var i;
-
-  // Unified address book case
-  if (_contactCallbackMap.hasOwnProperty(unifiedId)) {
-    for (watchId in _contactCallbackMap[unifiedId]) {
-      if (_contactCallbackMap[unifiedId].hasOwnProperty(watchId)) {
-        var callback = _contactCallbackMap[unifiedId][watchId].successCallback;
-        if (result.added.length) {
-          native_.callIfPossible(callback.oncontactsadded, _promote(result.added, Contact));
-        }
-        if (result.updated.length) {
-          native_.callIfPossible(callback.oncontactsupdated, _promote(result.updated, Contact));
-        }
-        if (result.removed.length) {
-          var allRemoved = [];
-          for (i = 0; i < result.removed.length; ++i) {
-            allRemoved.push(result.removed[i].id);
-          }
-          native_.callIfPossible(callback.oncontactsremoved, result.allRemoved);
-        }
-      }
-    }
-  }
-
-  for (var callbackAddressbookId in _contactCallbackMap) {
-    if (callbackAddressbookId !== UNIFIED_ADDRESSBOOK_ID &&
-        _contactCallbackMap.hasOwnProperty(callbackAddressbookId)) {
-
-      var filteredAdded = [];
-      var filteredUpdated = [];
-      var filteredRemoved = [];
-
-      if (result.added.length) {
-        filteredAdded = _filterById(result.added, callbackAddressbookId);
-      }
-      if (result.updated.length) {
-        filteredUpdated = _filterById(result.updated, callbackAddressbookId);
-      }
-      if (result.removed.length) {
-        for (i = 0; i < result.removed.length; ++i) {
-          if (result.removed[i].addressBookId === callbackAddressbookId) {
-            filteredRemoved.push(result.removed[i].id);
-          }
-        }
-      }
-
-      for (watchId in _contactCallbackMap[callbackAddressbookId]) {
-        if (_contactCallbackMap[callbackAddressbookId].hasOwnProperty(watchId)) {
-          var callback = _contactCallbackMap[callbackAddressbookId][watchId].successCallback;
-          if (filteredAdded.length) {
-            native_.callIfPossible(callback.oncontactsadded, filteredAdded);
-          }
-          if (filteredUpdated.length) {
-            native_.callIfPossible(callback.oncontactsupdated, filteredUpdated);
-          }
-          if (filteredRemoved.length) {
-            native_.callIfPossible(callback.oncontactsremoved, filteredRemoved);
-          }
-        }
-      }
-    }
-  }
-};
-
-
-var AddressBook = function(accountId, name) {
-  AV.isConstructorCall(this, AddressBook);
-
-  var id_ = null;
-  var name_ = '';
-  var readOnly_ = false;
-  var accountId_ = null;
-
-  if (Type.isNumber(accountId)) {
-    accountId_ = accountId;
-  }
-  if (Type.isString(name)) {
-    name_ = name;
-  }
-
-  Object.defineProperties(this, {
-    id: {
-      get: function() {
-        return id_;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          id_ = Converter.toString(v, false);
-        }
-      },
-      enumerable: true
-    },
-    accountId: {
-      get: function() {
-        return accountId_;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          accountId_ = Converter.toLong(v, true);
-        }
-      },
-      enumerable: true
-    },
-    name: {
-      get: function() {
-        return name_;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          name_ = Converter.toString(v, false);
-        }
-      },
-      enumerable: true
-    },
-    readOnly: {
-      get: function() {
-        return readOnly_;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          readOnly_ = Converter.toBoolean(v, false);
-        }
-      },
-      enumerable: true
-    }
-  });
-};
-
-AddressBook.prototype.get = function() {
-  var args = AV.validateArgs(arguments, [{
-    name: 'id',
-    type: AV.Types.STRING,
-    optional: false,
-    nullable: false
-  }]);
-
-  if (String(Converter.toLong(args.id)) !== args.id) {
-    // TCT: AddressBook_get_id_invalid
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
-  }
-
-  var result = native_.callSync('AddressBook_get', {
-    // TODO move to only sending the address book id (in all functions)
-    addressBook: this,
-    id: args.id
-  });
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-
-  return _editGuard.run(function() {
-    var contact = new Contact(native_.getResultObject(result));
-
-    if (contact.name instanceof ContactName) {
-      contact.name.displayName = '';
-      if (Type.isString(contact.name.firstName)) {
-        contact.name.displayName = contact.name.firstName;
-        if (Type.isString(contact.name.lastName)) {
-          contact.name.displayName += ' ' + contact.name.lastName;
-        }
-      } else if (Type.isArray(contact.name.nicknames) &&
-          Type.isString(contact.name.nicknames[0])) {
-        contact.name.displayName = contact.name.nicknames[0];
-      } else if (Type.isString(contact.name.nicknames)) {
-        contact.name.displayName = contact.name.nicknames;
-      }
-    }
-
-
-
-    return contact;
-  });
-};
-
-AddressBook.prototype.add = function() {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'contact',
-      type: AV.Types.PLATFORM_OBJECT,
-      values: Contact,
-      optional: false,
-      nullable: false
-    }
-  ]);
-
-  var result = native_.callSync('AddressBook_add', {
-    // TODO move to only sending the address book id (in all functions)
-    addressBook: this,
-    contact: _toJsonObject(args.contact)
-  });
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-
-  var _updatedContact = native_.getResultObject(result);
-  _editGuard.run(function() {
-    for (var prop in _updatedContact) {
-      if (args.contact.hasOwnProperty(prop)) {
-        args.contact[prop] = _updatedContact[prop];
-      }
-    }
-
-    if (args.contact.name instanceof ContactName) {
-      args.contact.name.displayName = '';
-      if (Type.isString(args.contact.name.firstName)) {
-        args.contact.name.displayName = args.contact.name.firstName;
-        if (Type.isString(args.contact.name.lastName)) {
-          args.contact.name.displayName += ' ' + args.contact.name.lastName;
-        }
-      } else if (Type.isArray(args.contact.name.nicknames) &&
-          Type.isString(args.contact.name.nicknames[0])) {
-        args.contact.name.displayName = args.contact.name.nicknames[0];
-      } else if (Type.isString(args.contact.name.nicknames)) {
-        args.contact.name.displayName = args.contact.name.nicknames;
-      }
-    }
-  });
-};
-
-AddressBook.prototype.addBatch = function() {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'contacts',
-      type: AV.Types.ARRAY,
-      value: Contact,
-      optional: false,
-      nullable: false
-    },
-    {
-      name: 'successCallback',
-      type: AV.Types.FUNCTION,
-      optional: true,
-      nullable: true
-    },
-    {
-      name: 'errorCallback',
-      type: AV.Types.FUNCTION,
-      optional: true,
-      nullable: true
-    }
-
-  ]);
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
-      return;
-    }
-
-    _editGuard.run(function() {
-      var _result = native_.getResultObject(result);
-      for (var i = 0; i < _result.length; ++i) {
-        for (var prop in _result[i]) {
-          if (args.contacts[i].hasOwnProperty(prop)) {
-            args.contacts[i][prop] = _result[i][prop];
-          }
-        }
-      }
-    });
-
-    native_.callIfPossible(args.successCallback, args.contacts);
-  };
-
-  native_.call('AddressBook_addBatch', {
-    addressBookId: this.id,
-    batchArgs: _toJsonObject(args.contacts)
-  }, callback);
-};
-
-AddressBook.prototype.update = function() {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'contact',
-      type: AV.Types.PLATFORM_OBJECT,
-      values: Contact,
-      optional: false,
-      nullable: false
-    }
-  ]);
-
-  var result = native_.callSync('AddressBook_update', {
-    addressBook: this,
-    contact: _toJsonObject(args.contact)
-  });
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-
-  var _updatedContact = native_.getResultObject(result);
-  _editGuard.run(function() {
-    for (var prop in _updatedContact) {
-      if (args.contact.hasOwnProperty(prop)) {
-        args.contact[prop] = _updatedContact[prop];
-      }
-    }
-  });
-};
-
-AddressBook.prototype.updateBatch = function() {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'contacts',
-      type: AV.Types.ARRAY,
-      values: Contact,
-      optional: false,
-      nullable: false
-    },
-    {
-      name: 'successCallback',
-      type: AV.Types.FUNCTION,
-      optional: true,
-      nullable: true
-    },
-    {
-      name: 'errorCallback',
-      type: AV.Types.FUNCTION,
-      optional: true,
-      nullable: true
-    }
-  ]);
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
-      return;
-    }
-
-    _editGuard.run(function() {
-      var _result = native_.getResultObject(result);
-      for (var i = 0; i < _result.length; ++i) {
-        for (var prop in _result[i].result) {
-          if (args.contacts[i].hasOwnProperty(prop)) {
-            args.contacts[i][prop] = _result[i].result[prop];
-          }
-        }
-      }
-    });
-
-    native_.callIfPossible(args.successCallback);
-  };
-
-  native_.call('AddressBook_updateBatch', {
-    addressBook: this,
-    batchArgs: _toJsonObject(args.contacts)
-  }, callback);
-};
-
-AddressBook.prototype.remove = function() {
-  var args = AV.validateArgs(arguments, [{
-    name: 'id',
-    type: AV.Types.STRING,
-    optional: false,
-    nullable: false
-  }]);
-
-  if (String(Converter.toLong(args.id)) !== args.id) {
-    // TCT: AddressBook_remove_id_invalid
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
-  }
-
-  var result = native_.callSync('AddressBook_remove', {
-    addressBook: this,
-    id: args.id
-  });
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-};
-
-AddressBook.prototype.removeBatch = function(ids, successCallback, errorCallback) {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'ids',
-      type: AV.Types.ARRAY,
-      values: AV.Types.STRING,
-      optional: false,
-      nullable: false
-    },
-    {
-      name: 'successCallback',
-      type: AV.Types.FUNCTION,
-      optional: true,
-      nullable: true
-    },
-    {
-      name: 'errorCallback',
-      type: AV.Types.FUNCTION,
-      optional: true,
-      nullable: true
-    }
-  ]);
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
-      return;
-    }
-
-    native_.callIfPossible(args.successCallback);
-  };
-
-  native_.call('AddressBook_removeBatch', {
-    addressBook: this,
-    batchArgs: args.ids
-  }, callback);
-};
-
-AddressBook.prototype.find = function(successCallback, errorCallback, filter, sortMode) {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'successCallback',
-      type: AV.Types.FUNCTION,
-      optional: false,
-      nullable: false
-    },
-    {
-      name: 'errorCallback',
-      type: AV.Types.FUNCTION,
-      optional: true,
-      nullable: true
-    },
-    {
-      name: 'filter',
-      type: AV.Types.PLATFORM_OBJECT,
-      values: [
-        tizen.AttributeFilter,
-        tizen.AttributeRangeFilter,
-        tizen.CompositeFilter
-      ],
-      optional: true,
-      nullable: true
-    },
-    {
-      name: 'sortMode',
-      type: AV.Types.PLATFORM_OBJECT,
-      values: tizen.SortMode,
-      optional: true,
-      nullable: true
-    }
-  ]);
-
-  var self = this;
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(errorCallback, native_.getErrorObject(result));
-    }
-
-    var _contacts = [];
-    var _result = native_.getResultObject(result);
-    _result.forEach(function(data) {
-      try {
-        _contacts.push(self.get(String(data)));
-      } catch (e) {}
-    });
-
-    //TODO: Move filtering to native code
-    try {
-      _contacts = C.filter(_contacts, args.filter);
-    } catch (e) {
-      native_.callIfPossible(errorCallback, e);
-      return;
-    }
-
-    //TODO: Move sorting to native code
-    _contacts = C.sort(_contacts, args.sortMode);
-
-    native_.callIfPossible(successCallback, _contacts);
-  };
-
-  native_.call('AddressBook_find', {
-    addressBook: this,
-    filter: filter,
-    sortMode: sortMode
-  }, callback);
-};
-
-AddressBook.prototype.addChangeListener = function() {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'successCallback',
-      type: AV.Types.LISTENER,
-      values: ['oncontactsadded', 'oncontactsupdated', 'oncontactsremoved'],
-      optional: false,
-      nullable: false
-    },
-    {
-      name: 'errorCallback',
-      type: AV.Types.FUNCTION,
-      optional: true,
-      nullable: true
-    }
-  ]);
-
-  if (Type.isEmptyObject(_contactCallbackMap)) {
-    var result = native_.callSync('AddressBook_startListening', {});
-
-    if (native_.isFailure(result)) {
-      throw native_.getErrorObject(result);
-    }
-  }
-
-  if (!_contactListenerRegistered) {
-    native_.addListener('ContactChangeListener', _contactChangeListener);
-    _contactListenerRegistered = true;
-  }
-
-  if (!_contactCallbackMap.hasOwnProperty(this.id)) {
-    _contactCallbackMap[this.id] = {};
-  }
-
-  var currentWatchId = _getNextWatchId();
-
-  _contactCallbackMap[this.id][currentWatchId] = {
-    successCallback: args.successCallback,
-    errorCallback: args.errorCallback
-  };
-
-  return currentWatchId;
-};
-
-AddressBook.prototype.removeChangeListener = function(watchId) {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'watchId',
-      type: AV.Types.LONG,
-      optional: false,
-      nullable: false
-    }
-  ]);
-
-  if (args.watchId === 0) {
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
-        'id is null or undefined');
-  }
-
-  if (args.watchId < 0) {
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
-        'Negative watch id');
-  }
-
-  if (!_contactCallbackMap.hasOwnProperty(this.id) ||
-      !_contactCallbackMap[this.id].hasOwnProperty(args.watchId)) {
-    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR,
-        'watch id not found for this address book');
-  }
-
-  delete _contactCallbackMap[this.id][args.watchId];
-
-  if (Type.isEmptyObject(_contactCallbackMap[this.id])) {
-    delete _contactCallbackMap[this.id];
-  }
-
-  if (Type.isEmptyObject(_contactCallbackMap)) {
-    native_.removeListener('ContactChangeListener', _contactChangeListener);
-    _contactListenerRegistered = false;
-
-    var result = native_.callSync('AddressBook_stopListening', {});
-
-    if (native_.isFailure(result)) {
-      throw native_.getErrorObject(result);
-    }
-  }
-};
-
-AddressBook.prototype.getGroup = function() {
-  var args = AV.validateArgs(arguments, [{
-    name: 'groupId',
-    type: AV.Types.STRING,
-    optional: false,
-    nullable: false
-  }]);
-
-  if (String(Converter.toLong(args.groupId)) !== args.groupId) {
-    // TCT: AddressBook_getGroup_groupId_invalid
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
-  }
-
-  var result = native_.callSync('AddressBook_getGroup', {
-    addressBook: this,
-    id: args.groupId
-  });
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-
-  return _editGuard.run(function() {
-    return new ContactGroup(native_.getResultObject(result));
-  });
-};
-
-AddressBook.prototype.addGroup = function() {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'group',
-      type: AV.Types.PLATFORM_OBJECT,
-      values: ContactGroup,
-      optional: false,
-      nullable: false
-    }
-  ]);
-
-  var result = native_.callSync('AddressBook_addGroup',
-      {addressBookId: this.id, group: args.group});
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-
-  _editGuard.run(function() {
-    result = native_.getResultObject(result);
-    args.group.id = result.id;
-    args.group.addressBookId = result.addressBookId;
-  });
-};
-
-AddressBook.prototype.updateGroup = function() {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'group',
-      type: AV.Types.PLATFORM_OBJECT,
-      values: ContactGroup,
-      optional: false,
-      nullable: false
-    }
-  ]);
-
-  var result = native_.callSync('AddressBook_updateGroup',
-      {addressBookId: this.id, group: args.group});
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-};
-
-AddressBook.prototype.removeGroup = function() {
-  var args = AV.validateArgs(arguments, [{
-    name: 'groupId',
-    type: AV.Types.STRING,
-    optional: false,
-    nullable: false
-  }]);
-
-  if (String(Converter.toLong(args.groupId)) !== args.groupId) {
-    // TCT: AddressBook_removeGroup_groupId_invalid
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
-  }
-
-  var result = native_.callSync('AddressBook_removeGroup',
-      {addressBook: this, id: args.groupId});
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-};
-
-AddressBook.prototype.getGroups = function() {
-  var result = native_.callSync('AddressBook_getGroups', {addressBook: this});
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-  result = native_.getResultObject(result);
-  var _tab = [];
-  _editGuard.run(function() {
-    result.forEach(function(data) {
-      _tab.push(new ContactGroup(data));
-    });
-  });
-  return _tab;
-};
-
-// exports /////////////////////////////////////////////////////////////////
-tizen.AddressBook = AddressBook;
diff --git a/src/contact/js/tizen.contact.Common.js b/src/contact/js/tizen.contact.Common.js
deleted file mode 100644 (file)
index ce1140d..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/* global xwalk, extension */
-
-// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var _common = xwalk.utils;
-var Type = _common.type;
-var Converter = _common.converter;
-var AV = _common.validator;
-
-var native_ = new _common.NativeManager(extension);
-
-var _currentWatchId = 1;
-
-var _getNextWatchId = function() {
-  return _currentWatchId++;
-};
-
-// Adjusts properties to have the correct format expected by the native side.
-// Currently only translates JS Date
-var _toJsonObject = function(obj) {
-  var ret;
-  if (Type.isDate(obj)) {
-    var year = ('0000' + obj.getFullYear()).slice(-4);
-    var month = ('00' + (obj.getMonth() + 1)).slice(-2);
-    var day = ('00' + obj.getDate()).slice(-2);
-    return Number(year + month + day);
-  }
-  if (Type.isArray(obj)) {
-    ret = [];
-    for (var i = 0; i < obj.length; ++i) {
-      ret[i] = _toJsonObject(obj[i]);
-    }
-    return ret;
-  }
-  if (obj instanceof Object) {
-    ret = {};
-    for (var prop in obj) {
-      if (obj.hasOwnProperty(prop)) {
-        ret[prop] = _toJsonObject(obj[prop]);
-      }
-    }
-    return ret;
-  }
-  return obj;
-};
-
-var _fromJsonDate = function(date) {
-  date = date + '';
-  var year = date.substr(0, 4);
-  var month = date.substr(4, 2);
-  var day = date.substr(6, 2);
-  return new Date(year, month - 1, day);
-};
-
-var _promote = function(val, type) {
-  return _editGuard.run(function() {
-    if (Type.isArray(val)) {
-      var ret = [];
-      for (var i = 0; i < val.length; ++i) {
-        ret.push(new type(val[i]));
-      }
-      return ret;
-    }
-    return new type(val);
-  });
-};
-
-function _checkError(result) {
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-}
-
-var TypeEnum = ['VCARD_30'];
-
-// Edit Guard //////////////////////////////////////////////////////////////
-// This flag is workaround. It is caused by specification
-// which tell to edit readonly fields.
-var _canEdit = 0;
-
-var EditGuard = function() {
-};
-
-EditGuard.prototype.run = function(callback) {
-  try {
-    this.enable();
-    var result = callback();
-    this.disable();
-    return result;
-  } catch (ex) {
-    this.disable();
-    throw ex;
-  }
-};
-
-EditGuard.prototype.enable = function() {
-  _canEdit++;
-};
-
-EditGuard.prototype.disable = function() {
-  _canEdit--;
-};
-
-EditGuard.prototype.isEditEnabled = function() {
-  return _canEdit > 0;
-};
-
-var _editGuard = new EditGuard();
-
-//TODO: Move sorting and filtering to native code
-var Common = function() {};
-Common.prototype.sort = function(arr, sortMode) {
-  var _getSortProperty = function(obj, props) {
-    for (var i = 0; i < props.length; ++i) {
-      if (!obj.hasOwnProperty(props[i])) {
-        return null;
-      }
-      obj = obj[props[i]];
-    }
-    return obj;
-  };
-
-  if (sortMode instanceof tizen.SortMode) {
-    var props = sortMode.attributeName.split('.');
-    arr.sort(function(a, b) {
-      var aValue = _getSortProperty(a, props);
-      var bValue = _getSortProperty(b, props);
-
-      if (sortMode.order === 'DESC') {
-        return aValue < bValue;
-      }
-      return bValue < aValue;
-    });
-  }
-  return arr;
-};
-
-Common.prototype.filter = function(arr, filter) {
-  if (Type.isNullOrUndefined(arr))
-    return arr;
-  if (filter instanceof tizen.AttributeFilter ||
-      filter instanceof tizen.AttributeRangeFilter ||
-      filter instanceof tizen.CompositeFilter) {
-    arr = arr.filter(function(element) {
-      return filter._filter(element);
-    });
-  }
-  return arr;
-};
-
-Common.prototype.repackFilter = function (filter) {
-  if (filter instanceof tizen.AttributeFilter) {
-    return {
-      filterType: 'AttributeFilter',
-      attributeName: filter.attributeName,
-      matchFlag: filter.matchFlag,
-      matchValue: filter.matchValue
-    };
-  }
-  if (filter instanceof tizen.AttributeRangeFilter) {
-    return {
-      filterType: 'AttributeRangeFilter',
-      attributeName: filter.attributeName,
-      initialValue: Type.isNullOrUndefined(filter.initialValue) ? null : filter.initialValue,
-      endValue: Type.isNullOrUndefined(filter.endValue) ? null : filter.endValue
-    };
-  }
-  if (filter instanceof tizen.CompositeFilter) {
-    var _f = [];
-    var filters = filter.filters;
-
-    for (var i = 0; i < filters.length; ++i) {
-      _f.push(this.repackFilter(filters[i]));
-    }
-
-    return {
-      filterType: 'CompositeFilter',
-      type: filter.type,
-      filters: _f
-    };
-  }
-
-  return null;
-};
-
-var C = new Common();
diff --git a/src/contact/js/tizen.contact.Contact.js b/src/contact/js/tizen.contact.Contact.js
deleted file mode 100644 (file)
index cecc843..0000000
+++ /dev/null
@@ -1,585 +0,0 @@
-// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var Contact = function(data) {
-  AV.isConstructorCall(this, Contact);
-
-  var _forceEditMode = false;
-  if (Type.isString(data)) {
-    var result = native_.callSync('ContactManager_importFromVCard', {
-      'contact': data
-    });
-    _checkError(result);
-
-    data = native_.getResultObject(result);
-    // These need to be forced to null as a contact created from a vcard is not added
-    // to any address book
-    data.id = null;
-    data.personId = null;
-    data.addressBookId = null;
-    data.lastUpdate = null;
-
-    // Force edit mode so that anonymous objects can be promoted to their correct types.
-    _forceEditMode = true;
-  } else if (Type.isObject(data) || Type.isFunction(data)) {
-    // It's a dictionary
-  } else {
-    // null or invalid types.
-    data = {};
-  }
-
-  var _id = null;
-  var _personId = null;
-  var _addressBookId = null;
-  var _lastUpdate = null;
-  var _isFavorite = false;
-  var _name = null;
-  var _addresses = [];
-  var _photoURI = null;
-  var _phoneNumbers = [];
-  var _emails = [];
-  var _messengers = [];
-  var _relationships = [];
-  var _birthday = null;
-  var _anniversaries = [];
-  var _organizations = [];
-  var _notes = [];
-  var _urls = [];
-  var _ringtoneURI = null;
-  var _messageAlertURI = null;
-  var _vibrationURI = null;
-  var _groupIds = [];
-
-  var _sanitizeArray = function(arr, type, previousValue) {
-    if (!Type.isArray(arr)) {
-      return previousValue;
-    }
-    for (var i = 0; i < arr.length; ++i) {
-      if (Type.isString(type)) {
-        if (!Type.isString(arr[i])) {
-          return previousValue;
-        }
-      } else if (_editGuard.isEditEnabled()) {
-        arr[i] = new type(arr[i]);
-      } else if (!(arr[i] instanceof type)) {
-        return previousValue;
-      }
-    }
-    return arr;
-  };
-
-  Object.defineProperties(this, {
-    id: {
-      get: function() {
-        return _id;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          _id = Converter.toString(v, false);
-        }
-      },
-      enumerable: true
-    },
-    personId: {
-      get: function() {
-        return _personId;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          _personId = Converter.toString(v, false);
-        }
-      },
-      enumerable: true
-    },
-    addressBookId: {
-      get: function() {
-        return _addressBookId;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          _addressBookId = Converter.toString(v, false);
-        }
-      },
-      enumerable: true
-    },
-    lastUpdated: {
-      get: function() {
-        return _lastUpdate;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          if (v instanceof Date || v === null) {
-            _lastUpdate = v;
-          } else if (Type.isString(v)) {
-            _lastUpdate = new Date(v);
-          } else {
-            _lastUpdate = _fromJsonDate(v);
-          }
-        }
-      },
-      enumerable: true
-    },
-    isFavorite: {
-      get: function() {
-        return _isFavorite;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          _isFavorite = Converter.toBoolean(v, false);
-        }
-      },
-      enumerable: true
-    },
-    name: {
-      get: function() {
-        return _name;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          _name = new ContactName(v);
-        } else {
-          _name = (v instanceof ContactName || v === null) ? v : _name;
-        }
-      },
-      enumerable: true
-    },
-    addresses: {
-      get: function() {
-        return _addresses;
-      },
-      set: function(v) {
-        _addresses = _sanitizeArray(v, ContactAddress, _addresses);
-      },
-      enumerable: true
-    },
-    photoURI: {
-      get: function() {
-        return _photoURI;
-      },
-      set: function(v) {
-        _photoURI = Converter.toString(v, true);
-      },
-      enumerable: true
-    },
-    phoneNumbers: {
-      get: function() {
-        return _phoneNumbers;
-      },
-      set: function(v) {
-        _phoneNumbers = _sanitizeArray(v, ContactPhoneNumber, _phoneNumbers);
-      },
-      enumerable: true
-    },
-    emails: {
-      get: function() {
-        return _emails;
-      },
-      set: function(v) {
-        _emails = _sanitizeArray(v, ContactEmailAddress, _emails);
-      },
-      enumerable: true
-    },
-    messengers: {
-      get: function() {
-        return _messengers;
-      },
-      set: function(v) {
-        _messengers = _sanitizeArray(v, ContactInstantMessenger, _messengers);
-      },
-      enumerable: true
-    },
-    relationships: {
-      get: function() {
-        return _relationships;
-      },
-      set: function(v) {
-        _relationships = _sanitizeArray(v, ContactRelationship, _relationships);
-      },
-      enumerable: true
-    },
-    birthday: {
-      get: function() {
-        return _birthday;
-      },
-      set: function(v) {
-        if (v instanceof Date || v === null) {
-          _birthday = v;
-        } else if (Type.isString(v)) {
-          _birthday = new Date(v);
-        } else if (_editGuard.isEditEnabled()) {
-          _birthday = _fromJsonDate(v);
-        }
-      },
-      enumerable: true
-    },
-    anniversaries: {
-      get: function() {
-        return _anniversaries;
-      },
-      set: function(v) {
-        _anniversaries = _sanitizeArray(v, ContactAnniversary, _anniversaries);
-      },
-      enumerable: true
-    },
-    organizations: {
-      get: function() {
-        return _organizations;
-      },
-      set: function(v) {
-        _organizations = _sanitizeArray(v, ContactOrganization, _organizations);
-      },
-      enumerable: true
-    },
-    notes: {
-      get: function() {
-        return _notes;
-      },
-      set: function(v) {
-        _notes = _sanitizeArray(v, '', _notes);
-      },
-      enumerable: true
-    },
-    urls: {
-      get: function() {
-        return _urls;
-      },
-      set: function(v) {
-        _urls = _sanitizeArray(v, ContactWebSite, _urls);
-      },
-      enumerable: true
-    },
-    ringtoneURI: {
-      get: function() {
-        return _ringtoneURI;
-      },
-      set: function(v) {
-        _ringtoneURI = Converter.toString(v, true);
-      },
-      enumerable: true
-    },
-    messageAlertURI: {
-      get: function() {
-        return _messageAlertURI;
-      },
-      set: function(v) {
-        _messageAlertURI = Converter.toString(v, true);
-      },
-      enumerable: true
-    },
-    vibrationURI: {
-      get: function() {
-        return _vibrationURI;
-      },
-      set: function(v) {
-        _vibrationURI = Converter.toString(v, true);
-      },
-      enumerable: true
-    },
-    groupIds: {
-      get: function() {
-        return _groupIds;
-      },
-      set: function(v) {
-        _groupIds = _sanitizeArray(v, '', _groupIds);
-      },
-      enumerable: true
-    }
-  });
-
-  var _this = this;
-  var _setProperties = function() {
-    for (var p in _this) {
-      if (data.hasOwnProperty(p)) {
-        _this[p] = data[p];
-      }
-    }
-  };
-
-  if (_forceEditMode) {
-    _editGuard.run(_setProperties);
-  } else {
-    _setProperties();
-  }
-
-};
-
-// Auxiliary functions /////////////////////////////////////////////////////
-
-// Convert address from Contact object to string
-var _contactAddressToString = function(obj) {
-  var str = '';
-  if (obj.addresses.length === 0) {
-    return '';
-  }
-  // Sorry for so many if statements, but the IDE makes me do it
-  for (var it in obj.addresses) {
-    if (!it instanceof ContactAddress) {
-      continue;
-    }
-    str += 'ADR;';
-    for (var addType in it.types) {
-      if (Type.isString(addType)) {
-        str += addType + ',';
-      }
-    }
-    if (str.charAt(str.length - 1) === ',') {
-      str[str.length - 1] = ':';
-    }
-    str += ';'; // because of we don't keep Post office addres
-    // which is part of vCard 3.0 standard
-    str += it.additionalInformation + ';';
-    str += it.streetAddress + ';';
-    str += it.city + ';';
-    str += it.region + ';';
-    str += it.postalCode + ';';
-    str += it.country + ';';
-    str += '\n';
-  }
-  return str;
-};
-
-// Convert email address from Contact object to string
-var _contactEmailToString = function(obj) {
-  if (!Type.isArray(obj.emails) || obj.emails.length === 0) {
-    console.log('Empty email list');
-    return '';
-  }
-  var str = '';
-  for (var mail in obj.emails) {
-    if (!mail instanceof ContactEmailAddress || !Type.isArray(mail.types) ||
-      mail.types.length === 0) {
-      console.log('Incorrect email type');
-      continue;
-    }
-    str += 'EMAIL;';
-    // set types
-    for (var type in mail.types) {
-      if (Type.isString(type)) {
-        str += type + ',';
-      }
-    }
-    if (str.charAt(str.length - 1) === ',') {
-      str[str.length - 1] = ':';
-    }
-    str += '=' + Converter.toString(mail.email) + '\n';
-  }
-  return str;
-};
-
-// Convert organizations info from Contact object to string
-var _contactOrganizationToString = function(obj) {
-  if (obj.organizations.length === 0 ||
-    !obj.organizations[0] instanceof ContactOrganization) {
-    return '';
-  }
-  var str = '';
-  for (var org in obj.organizations) {
-    if (!org instanceof ContactOrganization) {
-      continue;
-    }
-    str += 'ORG:';
-    str += org.name + ';' + org.department + ';' + org.title + '\n';
-  }
-  return str;
-};
-
-// Convert organizations roles from Contact object to string
-var _contactRoleToString = function(obj) {
-  if (obj.organizations.length === 0 ||
-    !obj.organizations[0] instanceof ContactOrganization) {
-    return '';
-  }
-  var str = '';
-  for (var org in obj.organizations) {
-    if (!org instanceof ContactOrganization) {
-      continue;
-    }
-    str += 'ROLE:';
-    str += org.name + ';' + org.role + '\n';
-  }
-  return str;
-};
-
-// Convert phone numbers from Contact object to string
-var _contactPhoneNumbersToString = function(obj) {
-  if (obj.phoneNumbers.length === 0 || !obj.phoneNumbers[0] instanceof ContactPhoneNumber) {
-    return '';
-  }
-  var str = '';
-  for (var phone in obj.phoneNumbers) {
-    if (!phone instanceof ContactPhoneNumber) {
-      continue;
-    }
-    str += 'TEL';
-    for (var type in phone.types) {
-      if (Type.isString(type)) {
-        str += ';' + type;
-      }
-    }
-    str += ':';
-    str += phone.number + '\n';
-  }
-  return str;
-};
-
-// Convert urls from Contact object to string
-var _contactURLToString = function(obj) {
-  if (obj.urls.length === 0 || !obj.urls[0] instanceof ContactWebSite) {
-    return '';
-  }
-  var str = '';
-  for (var url in obj.urls) {
-    if (url instanceof ContactWebSite) {
-      str += 'URL:' + url.url + '\n';
-    }
-  }
-  return str;
-};
-
-// Convert anniversaries to string
-var _contactAnniversaryToString = function(obj) {
-  if (obj.anniversaries.length === 0 || !obj.anniversaries[0] instanceof ContactAnniversary) {
-    return '';
-  }
-  var str = '';
-  for (var ann in obj.anniversaries) {
-    if (ann instanceof ContactAnniversary) {
-      str += 'X-ANNIVERSARY;' + ann.label + ':' + ann.date + ';' + '\n';
-    }
-  }
-  return str;
-};
-
-// Convert relationships to string
-var _contactRelationshipsToString = function(obj) {
-  if (obj.relationships.length === 0 ||
-    !obj.relationships[0] instanceof ContactRelationship) {
-    return '';
-  }
-  var str = '';
-  for (var rel in obj.relationships) {
-    if (rel instanceof ContactRelationship) {
-      str += 'X-RELATIONSHIP;' + rel.relativeName + ':' + rel.type +
-      ':' + rel.label + ';\n';
-    }
-  }
-  return str;
-};
-
-// Convert messengers to string
-var _contactInstantMessengeToString = function(obj) {
-  if (obj.messengers.length === 0 || !obj.messengers[0] instanceof ContactInstantMessenger) {
-    return '';
-  }
-  var str = '';
-  for (var messenger in obj.messengers) {
-    if (messenger instanceof ContactInstantMessenger) {
-      str += 'X-MESSANGER;' + messenger.imAddress + ':' + messenger.type +
-      ':' + messenger.label + ';\n';
-    }
-  }
-  return str;
-};
-
-// Auxiliary function, allows to parse JSON to Contact
-var _JSONToContactType = function(type, obj) {
-  var contact = new type();
-
-  for (var prop in obj) {
-    if (contact.hasOwnProperty(prop)) {
-      if (contact[prop] instanceof Date && Type.isNumber(obj[prop])) {
-        contact[prop] = new Date(1000 * obj[prop]);
-      } else {
-        contact[prop] = obj[prop];
-      }
-    }
-  }
-
-  return contact;
-};
-
-// Converts the Contact item to a string format.
-Contact.prototype.convertToString = function(format) {
-  format = format || TypeEnum[0];
-
-  if (!Type.isString(format)) {
-    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR, 'Invalid format');
-  }
-
-  if (TypeEnum.indexOf(format) < 0) {
-    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR, 'Invalid format');
-  }
-
-  if (this.id === '') {
-    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR,
-      'Contact ID is empty.');
-  }
-
-  var str = 'BEGIN:VCARD\nVERSION:3.0\n';
-
-  // set contact name
-  str += 'N:' + this.name.lastName + ';' + this.name.firstName + ';' +
-  this.name.middleName + ';' + this.name.prefix + ';' + this.name.suffix + '\n';
-  str += 'FN' + this.name.displayName + '\n';
-
-  // set phonetic names
-  str += 'X-PHONETIC-FIRST-NAME' + this.name.phoneticFirstName + '\n' +
-  'X-PHONETIC-LAST-NAME' + this.name.phoneticLastName + '\n';
-
-  // set contact address
-  str += _contactAddressToString(this);
-
-  // set Birthday
-  if (this.birthday) {
-    str += 'BDAY:' + this.birthday.getYear() + '-' + this.birthday.getMonth() +
-    '-' + this.birthday.getDay() + '\n';
-  }
-
-  // set anniversary
-  str += _contactAnniversaryToString(this);
-
-  // set relationship
-  str += _contactRelationshipsToString(this);
-
-  // set emails
-  str += _contactEmailToString(this);
-
-  // set organization data
-  str += _contactOrganizationToString(this);
-
-  // set role
-  str += _contactRoleToString(this);
-
-  // set phone numbers
-  str += _contactPhoneNumbersToString(this);
-
-  // set user ID
-  str += 'UID:' + this.id + '\n';
-
-  // set isFavorite
-  str += 'X-IS-FAVORITE' + this.isFavorite + '\n';
-
-  // set URLs
-  str += _contactURLToString(this);
-
-  // set messengers
-  str += _contactInstantMessengeToString(this);
-
-  // set last revision
-  str += 'REV:' + this.lastUpdated.getYear() + '-' + this.lastUpdated.getMonth() +
-  '-' + this.lastUpdated.getDay() + 'T' + this.lastUpdated.getHours() + ':' +
-  this.lastUpdated.getMinutes() + ':' + this.lastUpdated.getSeconds() + 'Z\n';
-
-  str += 'END:VCARD\n';
-
-  return str;
-};
-
-// Creates a clone of the Contact object, detached from any address book
-Contact.prototype.clone = function() {
-  return new Contact(this);
-};
-
-// exports /////////////////////////////////////////////////////////////////
-tizen.Contact = Contact;
diff --git a/src/contact/js/tizen.contact.ContactDataStructures.js b/src/contact/js/tizen.contact.ContactDataStructures.js
deleted file mode 100644 (file)
index eab6256..0000000
+++ /dev/null
@@ -1,743 +0,0 @@
-// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// An enumerator that indicates the types for the relationships.
-var ContactRelationshipType = {
-  ASSISTANT: 'ASSISTANT',
-  BROTHER: 'BROTHER',
-  CHILD: 'CHILD',
-  DOMESTIC_PARTNER: 'DOMESTIC_PARTNER',
-  FATHER: 'FATHER',
-  FRIEND: 'FRIEND',
-  MANAGER: 'MANAGER',
-  MOTHER: 'MOTHER',
-  PARENT: 'PARENT',
-  PARTNER: 'PARTNER',
-  REFERRED_BY: 'REFERRED_BY',
-  RELATIVE: 'RELATIVE',
-  SISTER: 'SISTER',
-  SPOUSE: 'SPOUSE',
-  OTHER: 'OTHER',
-  CUSTOM: 'CUSTOM'
-};
-
-// An enumerator that indicates the types for instant messenger.
-var ContactInstantMessengerType = {
-  GOOGLE: 'GOOGLE',
-  WLM: 'WLM',
-  YAHOO: 'YAHOO',
-  FACEBOOK: 'FACEBOOK',
-  ICQ: 'ICQ',
-  AIM: 'AIM',
-  QQ: 'QQ',
-  JABBER: 'JABBER',
-  SKYPE: 'SKYPE',
-  IRC: 'IRC',
-  OTHER: 'OTHER',
-  CUSTOM: 'CUSTOM'
-};
-
-// class ContactRef ////////////////////////////////////////////////////////
-
-var ContactRef = function(data) {
-  AV.isConstructorCall(this, ContactRef);
-  var _contactId = '';
-  var _addressBookId = '';
-  Object.defineProperties(this, {
-    addressBookId: {
-      get: function() {
-        return _addressBookId;
-      },
-      set: function(v) {
-        _addressBookId = Converter.toString(v, false);
-      },
-      enumerable: true
-    },
-    contactId: {
-      get: function() {
-        return _contactId;
-      },
-      set: function(v) {
-        _contactId = Converter.toString(v, false);
-      },
-      enumerable: true
-    }
-  });
-
-  if (Type.isObject(data)) {
-    this.addressBookId = data.addressBookId;
-    this.contactId = data.contactId;
-  } else {
-    try {
-      var args = AV.validateArgs(arguments, [
-        {
-          name: 'addressBookId',
-          type: AV.Types.STRING,
-          optional: false,
-          nullable: false
-        },
-        {
-          name: 'contactId',
-          type: AV.Types.STRING,
-          optional: false,
-          nullable: false
-        }
-      ]);
-      _addressBookId = args.addressBookId;
-      _contactId = args.contactId;
-    } catch (x) {
-      // Constructors shouldn't throw
-    }
-  }
-};
-
-// class ContactGroup //////////////////////////////////////////////////
-
-var ContactGroup = function(name, ringtone, photo) {
-  AV.isConstructorCall(this, ContactGroup);
-
-  var _id = null;
-  var _address = null;
-  var _readOnly = false;
-  var _name = '';
-  var _ringtoneURI = null;
-  var _photoURI = null;
-
-  if (name && Type.isString(name)) {
-    _name = name.length ? name : '';
-  }
-
-  if (ringtone && Type.isString(ringtone)) {
-    _ringtoneURI = ringtone.length ? ringtone : null;
-  }
-
-  if (photo && Type.isString(photo)) {
-    _photoURI = photo.length ? photo : null;
-  }
-
-  Object.defineProperties(this, {
-    id: {
-      get: function() {
-        return _id;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          _id = Converter.toString(v, true);
-        }
-      },
-      enumerable: true
-    },
-    addressBookId: {
-      get: function() {
-        return _address;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          _address = Converter.toString(v, true);
-        }
-      },
-      enumerable: true
-    },
-    name: {
-      get: function() {
-        return _name;
-      },
-      set: function(v) {
-        _name = Converter.toString(v, false);
-      },
-      enumerable: true
-    },
-    ringtoneURI: {
-      get: function() {
-        return _ringtoneURI;
-      },
-      set: function(v) {
-        _ringtoneURI = Converter.toString(v, true);
-      },
-      enumerable: true
-    },
-    photoURI: {
-      get: function() {
-        return _photoURI;
-      },
-      set: function(v) {
-        _photoURI = Converter.toString(v, true);
-      },
-      enumerable: true
-    },
-    readOnly: {
-      get: function() {
-        return _readOnly;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          _readOnly = Converter.toBoolean(v, false);
-        }
-      },
-      enumerable: true
-    }
-  });
-
-  if (_editGuard.isEditEnabled()) {
-    var data = arguments[0];
-    if (Type.isObject(data)) {
-      for (var prop in data) {
-        if (this.hasOwnProperty(prop)) {
-          this[prop] = data[prop];
-        }
-      }
-    }
-  }
-};
-
-// class ContactEmailAddress ///////////////////////////////////////////
-
-var ContactEmailAddress = function(address, types, isDefault) {
-  AV.isConstructorCall(this, ContactEmailAddress);
-
-  var _email = '';
-  var _label = null;
-  var _isDefault = false;
-  var _types = ['WORK'];
-
-  if (Type.isString(address) && address.indexOf('@') > 0 &&
-      address.indexOf('@') !== (address.length - 1)) {
-    _email = address;
-  }
-
-  if (Type.isBoolean(isDefault)) {
-    _isDefault = isDefault;
-  }
-
-  if (Type.isArray(types)) {
-    _types = [];
-    for (var i = 0; i < types.length; ++i) {
-      if (Type.isString(types[i])) {
-        _types.push(types[i]);
-      }
-    }
-  } else if (Type.isString(types)) {
-    _types = [];
-    _types.push(types);
-  }
-
-  Object.defineProperties(this, {
-    email: {
-      get: function() {
-        return _email;
-      },
-      set: function(v) {
-        if (Type.isString(v) && v.indexOf('@') > 0 &&
-            v.indexOf('@') !== (v.length - 1)) {
-          _email = v;
-        }
-      },
-      enumerable: true
-    },
-    isDefault: {
-      get: function() {
-        return _isDefault;
-      },
-      set: function(v) {
-        _isDefault = Converter.toBoolean(v, false);
-      },
-      enumerable: true
-    },
-    types: {
-      get: function() {
-        return _types;
-      },
-      set: function(v) {
-        if (Type.isArray(v)) {
-          _types = [];
-          for (var i = 0; i < v.length; ++i) {
-            if (Type.isString(v[i])) {
-              _types.push(v[i]);
-            }
-          }
-        } else if (Type.isString(v)) {
-          _types = [];
-          _types.push(v);
-        }
-      },
-      enumerable: true
-    },
-    label: {
-      get: function() {
-        return _label;
-      },
-      set: function(v) {
-        _label = Converter.toString(v, true);
-      },
-      enumerable: true
-    }
-  });
-
-  if (_editGuard.isEditEnabled()) {
-    for (var prop in arguments[0]) {
-      if (this.hasOwnProperty(prop)) {
-        this[prop] = arguments[0][prop];
-      }
-    }
-  }
-};
-
-// class ContactPhoneNumber ////////////////////////////////////////////
-
-var ContactPhoneNumber = function(number, type, isDefault) {
-  AV.isConstructorCall(this, ContactPhoneNumber);
-
-  var _isDefault = false;
-  var _number = '';
-  var _types = ['VOICE'];
-
-  if (Type.isString(number)) {
-    _number = number;
-  }
-
-  if (Type.isArray(type)) {
-    _types = [];
-    for (var i = 0; i < type.length; ++i) {
-      _types.push(Converter.toString(type[i], false));
-    }
-  } else if (Type.isString(type)) {
-    _types = [];
-    _types.push(type, false);
-  }
-
-  if (Type.isBoolean(isDefault)) {
-    _isDefault = isDefault;
-  }
-
-  Object.defineProperties(this, {
-    number: {
-      get: function() {
-        return _number;
-      },
-      set: function(v) {
-        _number = Converter.toString(v, false);
-      },
-      enumerable: true
-    },
-    isDefault: {
-      get: function() {
-        return _isDefault;
-      },
-      set: function(v) {
-        _isDefault = Converter.toBoolean(v, false);
-      },
-      enumerable: true
-    },
-    types: {
-      get: function() {
-        return _types;
-      },
-      set: function(v) {
-        if (Type.isArray(v)) {
-          _types = [];
-          for (var i = 0; i < v.length; ++i) {
-            _types.push(Converter.toString(v[i], false));
-          }
-        } else if (Type.isString(v)) {
-          _types = [];
-          _types.push(v, false);
-        }
-      },
-      enumerable: true
-    },
-    label: {
-      value: null,
-      writable: true,
-      enumerable: true
-    }
-  });
-
-  if (_editGuard.isEditEnabled()) {
-    for (var prop in arguments[0]) {
-      if (this.hasOwnProperty(prop)) {
-        this[prop] = arguments[0][prop];
-      }
-    }
-  }
-};
-
-// class ContactAddress ////////////////////////////////////////////////
-
-var ContactAddress = function(data) {
-  AV.isConstructorCall(this, ContactAddress);
-
-  var _isDefault = false;
-  var _types = ['HOME'];
-
-  Object.defineProperties(this, {
-    country: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    region: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    city: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    streetAddress: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    additionalInformation: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    postalCode: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    isDefault: {
-      get: function() {
-        return _isDefault;
-      },
-      set: function(v) {
-        _isDefault = Converter.toBoolean(v, false);
-      },
-      enumerable: true
-    },
-    types: {
-      get: function() {
-        return _types;
-      },
-      set: function(v) {
-        if (Type.isString(v)) {
-          _types = [];
-          _types.push(v);
-        } else if (Type.isArray(v)) {
-          _types = [];
-          for (var i = 0; i < v.length; ++i) {
-            if (Type.isString(v[i])) {
-              _types.push(v[i]);
-            }
-          }
-        }
-      },
-      enumerable: true
-    },
-    label: {
-      value: null,
-      writable: true,
-      enumerable: true
-    }
-  });
-
-  if (Type.isObject(data)) {
-    for (var prop in data) {
-      if (this.hasOwnProperty(prop)) {
-        this[prop] = data[prop];
-      }
-    }
-  }
-};
-
-// class ContactAnniversary ////////////////////////////////////////////////
-
-var ContactAnniversary = function(anniversary_date, anniversary_label) {
-  AV.isConstructorCall(this, ContactAnniversary);
-
-  var _anniversary_date = new Date();
-  var _anniversary_label = null;
-
-  Object.defineProperties(this, {
-    date: {
-      get: function() {
-        return _anniversary_date;
-      },
-      set: function(v) {
-        _anniversary_date = v instanceof Date ? v : new Date();
-      },
-      enumerable: true
-    },
-    label: {
-      get: function() {
-        return _anniversary_label;
-      },
-      set: function(v) {
-        _anniversary_label = Converter.toString(v, true);
-      },
-      enumerable: true
-    }
-  });
-
-  if (_editGuard.isEditEnabled()) {
-    _anniversary_date = _fromJsonDate(arguments[0].date);
-    _anniversary_label = arguments[0].label;
-  } else {
-    if (Type.isDate(anniversary_date)) {
-      _anniversary_date = anniversary_date;
-    }
-    if (Type.isString(anniversary_label)) {
-      _anniversary_label = anniversary_label;
-    }
-  }
-};
-
-// class ContactWebSite ////////////////////////////////////////////////////
-
-var ContactWebSite = function(contact_url, contact_type) {
-  AV.isConstructorCall(this, ContactWebSite);
-
-  var _url = '';
-  var _type = 'HOMEPAGE';
-
-  if (Type.isString(contact_url)) {
-    _url = contact_url;
-  }
-  if (Type.isString(contact_type)) {
-    _type = contact_type;
-  }
-
-  Object.defineProperties(this, {
-    url: {
-      get: function() {
-        return _url;
-      },
-      set: function(v) {
-        _url = Converter.toString(v, false);
-      },
-      enumerable: true
-    },
-    type: {
-      get: function() {
-        return _type;
-      },
-      set: function(v) {
-        _type = Converter.toString(v, false);
-      },
-      enumerable: true
-    }
-  });
-};
-
-// class ContactOrganization ///////////////////////////////////////////////
-
-var ContactOrganization = function(data) {
-  AV.isConstructorCall(this, ContactOrganization);
-  Object.defineProperties(this, {
-    name: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    department: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    title: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    role: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    logoURI: {
-      value: null,
-      writable: true,
-      enumerable: true
-    }
-  });
-
-  if (Type.isObject(data)) {
-    for (var prop in data) {
-      if (this.hasOwnProperty(prop)) {
-        this[prop] = data[prop];
-      }
-    }
-  }
-};
-
-// class ContactName ///////////////////////////////////////////////////////
-
-var ContactName = function(data) {
-  AV.isConstructorCall(this, ContactName);
-
-  var _displayName = null;
-  var _nicknames = [];
-
-  Object.defineProperties(this, {
-    prefix: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    suffix: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    firstName: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    middleName: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    lastName: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    nicknames: {
-      get: function() {
-        return _nicknames;
-      },
-      set: function(nicknames) {
-        if (Type.isArray(nicknames)) {
-          _nicknames = nicknames;
-        }
-      },
-      enumerable: true
-    },
-    phoneticFirstName: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    phoneticMiddleName: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    phoneticLastName: {
-      value: null,
-      writable: true,
-      enumerable: true
-    },
-    displayName: {
-      get: function() {
-        return _displayName;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          _displayName = Converter.toString(v, true);
-        }
-      },
-      enumerable: true
-    }
-  });
-
-  if (Type.isObject(data)) {
-    for (var prop in data) {
-      if (this.hasOwnProperty(prop)) {
-        this[prop] = data[prop];
-      }
-    }
-  }
-};
-
-var ContactRelationship = function(relativeName, type) {
-  AV.isConstructorCall(this, ContactRelationship);
-
-  var _relativeName = Converter.toString(relativeName, false);
-  var _type = type ? Converter.toEnum(type, Object.keys(ContactRelationshipType), false)
-            : ContactRelationshipType.OTHER;
-  var _label = null;
-
-  Object.defineProperties(this, {
-    relativeName: {
-      get: function () {
-        return _relativeName;
-      },
-      set: function (v) {
-        _relativeName = Converter.toString(v, false);
-      },
-      enumerable: true
-    },
-    type: {
-      get: function () {
-        return _type;
-      },
-      set: function (v) {
-        _type = v ? Converter.toEnum(v, Object.keys(ContactRelationshipType), false)
-                  : _type;
-      },
-      enumerable: true
-    },
-    label: {
-      get: function () {
-        return _label;
-      },
-      set: function (v) {
-        _label = Converter.toString(v, true);
-      },
-      enumerable: true
-    }
-  });
-};
-
-var ContactInstantMessenger = function(imAddress, type) {
-  AV.isConstructorCall(this, ContactInstantMessenger);
-
-  var imAddress_ = '';
-  var type_ = 'OTHER';
-
-  Object.defineProperties(this, {
-    imAddress: {
-      get: function() {
-        return imAddress_;
-      },
-      set: function(v) {
-        if (Type.isNullOrUndefined(v)) {
-          return;
-        }
-        imAddress_ = Converter.toString(v, false);
-      },
-      enumerable: true
-    },
-    type: {
-      get: function() {
-        return type_;
-      },
-      set: function(v) {
-        if (Type.isNullOrUndefined(v)) {
-          return;
-        }
-        type_ = Converter.toEnum(v, Object.keys(ContactInstantMessengerType), false);
-      },
-      enumerable: true
-    },
-    label: {
-      value: null,
-      writable: true,
-      enumerable: true
-    }
-  });
-
-  this.imAddress = imAddress;
-  this.type = type;
-};
-
-// exports /////////////////////////////////////////////////////////////////
-tizen.ContactRef = ContactRef;
-tizen.ContactName = ContactName;
-tizen.ContactOrganization = ContactOrganization;
-tizen.ContactWebSite = ContactWebSite;
-tizen.ContactAnniversary = ContactAnniversary;
-tizen.ContactAddress = ContactAddress;
-tizen.ContactPhoneNumber = ContactPhoneNumber;
-tizen.ContactEmailAddress = ContactEmailAddress;
-tizen.ContactGroup = ContactGroup;
-tizen.ContactRelationship = ContactRelationship;
-tizen.ContactInstantMessenger = ContactInstantMessenger;
diff --git a/src/contact/js/tizen.contact.ContactManager.js b/src/contact/js/tizen.contact.ContactManager.js
deleted file mode 100644 (file)
index c27b512..0000000
+++ /dev/null
@@ -1,467 +0,0 @@
-// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-var _personListenerRegistered = false;
-var _personCallbackMap = {};
-var _personChangeListener = function(result) {
-  for (var key in _personCallbackMap) {
-    if (_personCallbackMap.hasOwnProperty(key)) {
-      if (result.added.length) {
-        native_.callIfPossible(_personCallbackMap[key].onpersonsadded,
-            _promote(result.added, Person));
-      }
-      if (result.updated.length) {
-        native_.callIfPossible(_personCallbackMap[key].onpersonsupdated,
-            _promote(result.updated, Person));
-      }
-      if (result.removed.length) {
-        native_.callIfPossible(_personCallbackMap[key].onpersonsremoved,
-            result.removed);
-      }
-    }
-  }
-};
-
-
-var ContactManager = function() {};
-
-// Gets the available address books
-ContactManager.prototype.getAddressBooks = function() {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'successCallback',
-      type: AV.Types.FUNCTION,
-      optional: false,
-      nullable: false
-    },
-    {
-      name: 'errorCallback',
-      type: AV.Types.FUNCTION,
-      optional: true,
-      nullable: true
-    }
-  ]);
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
-    } else {
-      var books = native_.getResultObject(result);
-      var tmp = [];
-
-      books.forEach(function(data) {
-        return _editGuard.run(function() {
-          var addressBook = new AddressBook(result.accountId, result.name);
-          addressBook.id = data.id;
-          addressBook.readOnly = result.readOnly;
-
-          tmp.push(addressBook);
-        });
-      });
-
-      native_.callIfPossible(args.successCallback, tmp);
-    }
-  };
-
-  native_.call('ContactManager_getAddressBooks', {}, callback);
-};
-
-// Gets the aggregation of all address books.
-ContactManager.prototype.getUnifiedAddressBook = function() {
-  // TODO check privileges
-  //var result = native_.callSync('CheckReadPrivileges', {});
-  //if (native_.isFailure(result)) {
-  //  throw new tizen.WebAPIException(WebAPIException.SECURITY_ERR,
-  //      'You do not have privileges for this operation');
-  //}
-
-  return _editGuard.run(function() {
-    var addressBook = new AddressBook(0, 'Unified address book');
-    addressBook.id = UNIFIED_ADDRESSBOOK_ID;
-    addressBook.readOnly = false;
-
-    return addressBook;
-  });
-};
-
-// Gets the default address book.
-ContactManager.prototype.getDefaultAddressBook = function() {
-  //privileges are checked in getAddressBook function
-  return this.getAddressBook(DEFAULT_ADDRESSBOOK_ID);
-};
-
-// Gets the address book with the specified identifier.
-ContactManager.prototype.getAddressBook = function() {
-  var args = AV.validateArgs(arguments, [{
-    name: 'addressBookId',
-    type: AV.Types.STRING,
-    optional: false,
-    nullable: false
-  }]);
-
-  if (String(Converter.toLong(args.addressBookId)) !== args.addressBookId) {
-    // TCT: ContactManager_getAddressBook_addressBookId_invalid
-    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
-  }
-
-  var result = native_.callSync('ContactManager_getAddressBook', {
-    addressBookId: args.addressBookId
-  });
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-
-  result = native_.getResultObject(result);
-
-  return _editGuard.run(function() {
-    var addressBook = new AddressBook(result.accountId, result.name);
-    addressBook.id = args.addressBookId;
-    addressBook.readOnly = result.readOnly;
-
-    return addressBook;
-  });
-};
-
-ContactManager.prototype.addAddressBook = function() {
-  var args = AV.validateArgs(arguments, [{
-    name: 'addressBook',
-    type: AV.Types.PLATFORM_OBJECT,
-    values: tizen.AddressBook,
-    optional: false,
-    nullable: false
-  }]);
-
-  var result = native_.callSync('ContactManager_addAddressBook', {
-    addressBook: args.addressBook
-  });
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-
-  var data = native_.getResultObject(result);
-  _editGuard.run(function() {
-    for (var prop in data) {
-      if (args.addressBook.hasOwnProperty(prop)) {
-        args.addressBook[prop] = data[prop];
-      }
-    }
-  });
-};
-
-ContactManager.prototype.removeAddressBook = function() {
-  // TCT: ContactManager_removeAddressBook_misarg
-  if (Type.isNullOrUndefined(arguments[0])) {
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
-  }
-
-  var args = AV.validateArgs(arguments, [{
-    name: 'addressBookId',
-    type: AV.Types.STRING,
-    optional: false,
-    nullable: false
-  }]);
-
-  if (args.addressBookId === UNIFIED_ADDRESSBOOK_ID) {
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
-        'Unified address book can not be deleted');
-  }
-
-  if (args.addressBookId === DEFAULT_ADDRESSBOOK_ID) {
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
-        'Default address book can not be deleted');
-  }
-
-  var result = native_.callSync('ContactManager_removeAddressBook', {
-    addressBookId: args.addressBookId
-  });
-
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-};
-
-// Gets the person with the specified identifier.
-ContactManager.prototype.get = function() {
-  // validation
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'personId',
-      type: AV.Types.STRING,
-      optional: false,
-      nullable: false
-    }
-  ]);
-
-  if (String(Converter.toLong(args.personId)) !== args.personId) {
-    // TCT: ContactManager_get_personId_invalid
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
-  }
-
-  var result = native_.callSync('ContactManager_get', {
-    personId: args.personId
-  });
-  _checkError(result);
-
-  return _editGuard.run(function() {
-    return new Person(native_.getResultObject(result));
-  });
-};
-
-// Updates a person in the address book synchronously.
-ContactManager.prototype.update = function() {
-  // validation
-  var args = AV.validateArgs(arguments, [{
-    name: 'person',
-    type: AV.Types.PLATFORM_OBJECT,
-    values: Person,
-    optional: false,
-    nullable: false
-  }]);
-  var result = native_.callSync('ContactManager_update', { person: args.person });
-  _checkError(result);
-
-  result = native_.getResultObject(result);
-  for (var prop in result) {
-    if (args.person.hasOwnProperty(prop)) {
-      args.person[prop] = result[prop];
-    }
-  }
-};
-
-// Updates several existing persons in the contact DB asynchronously.
-ContactManager.prototype.updateBatch = function() {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'persons',
-      type: AV.Types.ARRAY,
-      values: Person,
-      optional: false,
-      nullable: false
-    },
-    {
-      name: 'successCallback',
-      type: AV.Types.FUNCTION,
-      optional: true,
-      nullable: true
-    },
-    {
-      name: 'errorCallback',
-      type: AV.Types.FUNCTION,
-      optional: true,
-      nullable: true
-    }
-  ]);
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
-      return;
-    }
-
-    native_.callIfPossible(args.successCallback);
-  };
-
-  native_.call('ContactManager_updateBatch', {
-    addressBook: {},
-    batchArgs: _toJsonObject(args.persons)
-  }, callback);
-};
-
-// Removes a person from the contact DB synchronously.
-ContactManager.prototype.remove = function() {
-  // validation
-  var args = AV.validateArgs(arguments, [{
-    name: 'personId',
-    type: AV.Types.STRING,
-    optional: false,
-    nullable: false
-  }]);
-
-  if (String(Converter.toLong(args.personId)) !== args.personId) {
-    // TCT: ContactManager_remove_personId_invalid
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
-  }
-
-  var result = native_.callSync('ContactManager_remove', {personId: args.personId});
-  _checkError(result);
-};
-
-// Removes persons from contact DB asynchronously.
-ContactManager.prototype.removeBatch = function() {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'personIds',
-      type: AV.Types.ARRAY,
-      values: AV.Types.STRING,
-      optional: false,
-      nullable: false
-    },
-    {
-      name: 'successCallback',
-      type: AV.Types.FUNCTION,
-      optional: true,
-      nullable: true
-    },
-    {
-      name: 'errorCallback',
-      type: AV.Types.FUNCTION,
-      optional: true,
-      nullable: true
-    }
-  ]);
-
-  var callback = function(result) {
-    if (native_.isFailure(result)) {
-      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
-      return;
-    }
-
-    native_.callIfPossible(args.successCallback);
-  };
-
-  native_.call('ContactManager_removeBatch', {
-    addressBook: {},
-    batchArgs: _toJsonObject(args.personIds)
-  }, callback);
-};
-
-// Gets an array of all Person objects from the contact DB or the ones that match the
-// optionally supplied filter.
-ContactManager.prototype.find = function() {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'successCallback',
-      type: AV.Types.FUNCTION,
-      optional: false,
-      nullable: false
-    },
-    {
-      name: 'errorCallback',
-      type: AV.Types.FUNCTION,
-      optional: true,
-      nullable: true
-    },
-    {
-      name: 'filter',
-      type: AV.Types.PLATFORM_OBJECT,
-      values: [tizen.AttributeFilter,
-        tizen.AttributeRangeFilter,
-        tizen.CompositeFilter],
-      optional: true,
-      nullable: true
-    },
-    {
-      name: 'sortMode',
-      type: AV.Types.PLATFORM_OBJECT,
-      values: tizen.SortMode,
-      optional: true,
-      nullable: true
-    }
-  ]);
-
-  // TODO implement contact filtering/sorting.
-  var data = {
-    filter: C.repackFilter(args.filter),
-    sortMode: args.sortMode
-  };
-
-  var self = this;
-
-  var callback = function(result) {
-    if (native_.isSuccess(result)) {
-      var _result = native_.getResultObject(result);
-      var retval = [];
-      for (var i = 0; i < _result.length; ++i) {
-        retval.push(self.get(String(_result[i])));
-      }
-      //TODO: Move sorting to native code
-      retval = C.sort(retval, args.sortMode);
-      args.successCallback(retval);
-    } else {
-      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
-    }
-  };
-
-  native_.call('ContactManager_find', data, callback);
-};
-
-// Subscribes to receive notifications about persons' changes.
-ContactManager.prototype.addChangeListener = function() {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'successCallback',
-      type: AV.Types.LISTENER,
-      values: ['onpersonsadded', 'onpersonsupdated', 'onpersonsremoved'],
-      optional: false,
-      nullable: false
-    }
-  ]);
-
-  if (Type.isEmptyObject(_personCallbackMap)) {
-    var result = native_.callSync('ContactManager_startListening', {});
-
-    if (native_.isFailure(result)) {
-      throw native_.getErrorObject(result);
-    }
-  }
-
-  if (!_personListenerRegistered) {
-    native_.addListener('ContactPersonChangeListener', _personChangeListener);
-    _personListenerRegistered = true;
-  }
-
-  var currentWatchId = _getNextWatchId();
-
-  _personCallbackMap[currentWatchId] = args.successCallback;
-
-  return currentWatchId;
-};
-
-// Unsubscribes a persons' changes watch operation.
-ContactManager.prototype.removeChangeListener = function() {
-  var args = AV.validateArgs(arguments, [
-    {
-      name: 'watchId',
-      type: AV.Types.LONG,
-      optional: false,
-      nullable: false
-    }
-  ]);
-
-  // This makes UTC_contact_removeChangeListenerPerson_N_001 pass.
-  // watch id's start at 1
-  if (args.watchId === 0) {
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
-      'id is null or undefined');
-  }
-
-  if (args.watchId < 0) {
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR,
-        'Negative watch id');
-  }
-
-  if (!_personCallbackMap.hasOwnProperty(args.watchId)) {
-    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR,
-        'watch id not found');
-  }
-
-  delete _personCallbackMap[args.watchId];
-
-  if (Type.isEmptyObject(_personCallbackMap)) {
-    native_.removeListener('ContactPersonChangeListener', _personChangeListener);
-    _personListenerRegistered = false;
-
-    var result = native_.callSync('ContactManager_stopListening', {});
-
-    if (native_.isFailure(result)) {
-      throw native_.getErrorObject(result);
-    }
-  }
-};
-
-// exports /////////////////////////////////////////////////////////////////
-exports = new ContactManager();
diff --git a/src/contact/js/tizen.contact.Person.js b/src/contact/js/tizen.contact.Person.js
deleted file mode 100644 (file)
index d6c1ef5..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-var Person = function(data) {
-  AV.isConstructorCall(this, Person);
-
-  var _id = '';
-  var _displayName = '';
-  var _contactCount = 0;
-  var _hasPhoneNumber = false;
-  var _hasEmail = false;
-  var _isFavorite = false;
-  var _displayContactId = '';
-
-  if (data.hasOwnProperty('id') && Type.isString(data.id)) {
-    _id = data.id;
-  }
-  if (data.hasOwnProperty('displayName') && Type.isString(data.displayName)) {
-    _displayName = data.displayName;
-  }
-  if (data.hasOwnProperty('contactCount') && Type.isNumber(data.contactCount)) {
-    _contactCount = data.contactCount;
-  }
-  if (data.hasOwnProperty('hasPhoneNumber') && Type.isBoolean(data.hasPhoneNumber)) {
-    _hasPhoneNumber = data.hasPhoneNumber;
-  }
-  if (data.hasOwnProperty('hasEmail') && Type.isBoolean(data.hasEmail)) {
-    _hasEmail = data.hasEmail;
-  }
-  if (data.hasOwnProperty('displayContactId') && Type.isString(data.displayContactId)) {
-    _displayContactId = data.displayContactId;
-  }
-  if (data.hasOwnProperty('isFavorite') && Type.isBoolean(data.isFavorite)) {
-    _isFavorite = data.isFavorite;
-  }
-
-  Object.defineProperties(this, {
-    id: {
-      get: function() {
-        return _id;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          _id = Converter.toString(v, false);
-        }
-      },
-      enumerable: true
-    },
-    displayName: {
-      get: function() {
-        return _displayName;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          _displayName = Converter.toString(v, false);
-        }
-      },
-      enumerable: true
-    },
-    contactCount: {
-      get: function() {
-        return _contactCount;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          _contactCount = Converter.toLong(v, false);
-        }
-      },
-      enumerable: true
-    },
-    hasPhoneNumber: {
-      get: function() {
-        return _hasPhoneNumber;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          _hasPhoneNumber = Converter.toBoolean(v, false);
-        }
-      },
-      enumerable: true
-    },
-    hasEmail: {
-      get: function() {
-        return _hasEmail;
-      },
-      set: function(v) {
-        if (_editGuard.isEditEnabled()) {
-          _hasEmail = Converter.toBoolean(v, false);
-        }
-      },
-      enumerable: true
-    },
-
-    isFavorite: {
-      get: function() {
-        return _isFavorite;
-      },
-      set: function(v) {
-        _isFavorite = Converter.toBoolean(v, false);
-      },
-      enumerable: true
-    },
-    photoURI: {
-      value: data.hasOwnProperty('photoURI') ? data.photoURI : null,
-      writable: true,
-      enumerable: true
-    },
-    ringtoneURI: {
-      value: data.hasOwnProperty('ringtoneURI') ? data.ringtoneURI : null,
-      writable: true,
-      enumerable: true
-    },
-    displayContactId: {
-      get: function() {
-        return _displayContactId;
-      },
-      set: function(v) {
-        _displayContactId = Converter.toString(v, false);
-      },
-      enumerable: true
-    }
-  });
-};
-
-// Aggregates another person to this person.
-Person.prototype.link = function() {
-  var args = AV.validateArgs(arguments, [{
-    name: 'personId',
-    type: AV.Types.STRING,
-    optional: false,
-    nullable: false
-  }]);
-
-  if (String(Converter.toLong(args.personId)) !== args.personId) {
-    // TCT: Person_link_personId_invalid
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
-  }
-
-  var result = native_.callSync('Person_link', {
-    // TODO move to only sending the person id (in all functions)
-    person: this,
-    id: args.personId
-  });
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-  var _this = this;
-  _editGuard.run(function() {
-    _this.contactCount = _this.contactCount + 1;
-  });
-};
-
-// Separates a contact from this person.
-Person.prototype.unlink = function(contactId) {
-  var args = AV.validateArgs(arguments, [{
-    name: 'contactId',
-    type: AV.Types.STRING,
-    optional: false,
-    nullable: false
-  }]);
-
-  if (String(Converter.toLong(args.contactId)) !== args.contactId) {
-    // TCT: Person_unlink_contactId_invalid
-    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);
-  }
-
-  var result = native_.callSync('Person_unlink', {
-    // TODO move to only sending the person id (in all functions)
-    person: this,
-    id: args.contactId
-  });
-  if (native_.isFailure(result)) {
-    throw native_.getErrorObject(result);
-  }
-  var _this = this;
-  return _editGuard.run(function() {
-    _this.contactCount = _this.contactCount - 1;
-    return new Person(native_.getResultObject(result));
-  });
-};