DataSync tizen plugin implementation
authorTomasz Iwanek <t.iwanek@samsung.com>
Wed, 9 Jul 2014 09:45:07 +0000 (11:45 +0200)
committerTomasz Iwanek <t.iwanek@samsung.com>
Tue, 23 Sep 2014 14:13:00 +0000 (16:13 +0200)
SPEC=https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/datasync.html

BUG=XWALK-1061

----------------------------------------------------

Running TCT:
 - install rpms on device:
     - libwbxml2,
     - sync-agent,
     - oma-ds-agent (and start: systemctl start oma-ds-agent.service),
 - copy 'tct-datasync-tizen-tests.wgt' to device,
 - install and run application,

Current TCT datasync passrate: 63/63

--------------------------------------------------

22 files changed:
datasync/datasync.gyp [new file with mode: 0644]
datasync/datasync_api.js [new file with mode: 0644]
datasync/datasync_error.h [new file with mode: 0644]
datasync/datasync_extension.cc [new file with mode: 0644]
datasync/datasync_extension.h [new file with mode: 0644]
datasync/datasync_instance.cc [new file with mode: 0644]
datasync/datasync_instance.h [new file with mode: 0644]
datasync/datasync_log.h [new file with mode: 0644]
datasync/datasync_manager.cc [new file with mode: 0644]
datasync/datasync_manager.h [new file with mode: 0644]
datasync/datasync_scoped_exit.h [new file with mode: 0644]
datasync/datasync_serialization.h [new file with mode: 0644]
datasync/sync_info.cc [new file with mode: 0644]
datasync/sync_info.h [new file with mode: 0644]
datasync/sync_profile_info.cc [new file with mode: 0644]
datasync/sync_profile_info.h [new file with mode: 0644]
datasync/sync_service_info.cc [new file with mode: 0644]
datasync/sync_service_info.h [new file with mode: 0644]
datasync/sync_statistics.cc [new file with mode: 0644]
datasync/sync_statistics.h [new file with mode: 0644]
packaging/tizen-extensions-crosswalk.spec
tizen-wrt.gyp

diff --git a/datasync/datasync.gyp b/datasync/datasync.gyp
new file mode 100644 (file)
index 0000000..92c1187
--- /dev/null
@@ -0,0 +1,43 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_datasync',
+      'type': 'loadable_module',
+      'variables': {
+        'packages': [
+          'sync-agent',
+        ],
+      },
+      'dependencies': [
+        '../tizen/tizen.gyp:tizen',
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'sources': [
+        'datasync_api.js',
+        'datasync_error.h',
+        'datasync_extension.cc',
+        'datasync_extension.h',
+        'datasync_instance.cc',
+        'datasync_instance.h',
+        'datasync_log.h',
+        'datasync_manager.cc',
+        'datasync_manager.h',
+        'datasync_scoped_exit.h',
+        'datasync_serialization.h',
+        'sync_info.cc',
+        'sync_info.h',
+        'sync_profile_info.cc',
+        'sync_profile_info.h',
+        'sync_service_info.cc',
+        'sync_service_info.h',
+        'sync_statistics.cc',
+        'sync_statistics.h',
+      ],
+    },
+  ],
+}
diff --git a/datasync/datasync_api.js b/datasync/datasync_api.js
new file mode 100644 (file)
index 0000000..d2e8cb3
--- /dev/null
@@ -0,0 +1,576 @@
+// Copyright (c) 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.
+
+// those variables are not exported anyway so no closure
+var callbackId = 0;
+var callbacks = {};
+var hideProtectedProporties = true;
+
+// for the time of serialization 'write-only' and 'read-only' properties
+// should be able to run with correct value
+function executeUnrestricted(func) {
+  try {
+    hideProtectedProporties = false;
+    func();
+  } finally {
+    hideProtectedProporties = true;
+  }
+}
+
+function nextCallbackId() {
+  return callbackId++;
+}
+
+extension.setMessageListener(function(msg) {
+  var m = JSON.parse(msg);
+
+  if (typeof callbacks[m['callback_key']] !== 'object') {
+    return;
+  }
+
+  var callback = callbacks[m['callback_key']];
+  var answer = m['answer'];
+  var callbackName = m['callback_name'];
+
+  if (typeof answer['profileId'] !== 'string') {
+    return;
+  }
+  var profileId = answer['profileId'];
+
+  if (callbackName === 'onprogress') {
+    if (SyncServiceType.indexOf(answer['serviceType']) === -1 ||
+        typeof answer['isFromServer'] !== 'boolean' ||
+        typeof answer['totalPerService'] !== 'number' ||
+        typeof answer['syncedPerService'] !== 'number') {
+      return;
+    }
+
+    var serviceType = answer['serviceType'];
+    var isFromServer = answer['isFromServer'];
+    var totalPerService = answer['totalPerService'];
+    var syncedPerService = answer['syncedPerService'];
+
+    callback['onprogress'](profileId, serviceType,
+        isFromServer, totalPerService, syncedPerService);
+  } else if (callbackName === 'oncompleted') {
+    // callback will not be needed anymore
+    delete callbacks[m['callback_key']];
+
+    callback['oncompleted'](profileId);
+  } else if (callbackName === 'onstopped') {
+    // callback will not be needed anymore
+    delete callbacks[m['callback_key']];
+
+    callback['onstopped'](profileId);
+  } else if (callbackName === 'onfailed') {
+    // callback will not be needed anymore
+    delete callbacks[m['callback_key']];
+
+    if (typeof answer['error'] !== 'object' ||
+        typeof answer['error']['code'] !== 'number' ||
+        typeof answer['error']['name'] !== 'string' ||
+        typeof answer['error']['message'] !== 'string') {
+      return;
+    }
+    var code = answer['error']['code'];
+    var name = answer['error']['name'];
+    var message = answer['error']['message'];
+
+    var error = new tizen.WebAPIError(code, name, message);
+    callback['onfailed'](profileId, error);
+  }
+});
+
+function sendSyncMessage(msg) {
+  var data = null;
+  executeUnrestricted(function() {
+    data = JSON.stringify(msg);
+  });
+
+  var result = JSON.parse(extension.internal.sendSyncMessage(data));
+
+  if (typeof result !== 'object') {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_UNKNOWN_ERR);
+  }
+
+  if (result['exception'] !== undefined) {
+    if (typeof result['exception'] !== 'object' ||
+        typeof result['exception']['code'] !== 'number' ||
+        typeof result['exception']['name'] !== 'string' ||
+        typeof result['exception']['message'] !== 'string') {
+      throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_UNKNOWN_ERR);
+    }
+
+    var code = result['exception']['code'];
+    var name = result['exception']['name'];
+    var message = result['exception']['message'];
+
+    throw new tizen.WebAPIException(code, name, message);
+  } else if (result['answer'] !== undefined) {
+    return result['answer'];
+  } else {
+    return; //undefined
+  }
+}
+
+function postSyncMessageWithCallback(msg, callback) {
+  if (callback) {
+    var id = nextCallbackId();
+    msg['callback_key'] = id;
+    callbacks[id] = callback;
+  }
+  return sendSyncMessage(msg);
+}
+
+function defineReadWriteProperty(object, key, value) {
+  Object.defineProperty(object, key, {
+    enumerable: true,
+    writable: true,
+    value: value
+  });
+}
+
+function defineReadWriteNonNullProperty(object, key, value) {
+  var hvalue = value;
+  Object.defineProperty(object, key, {
+    enumerable: true,
+    set: function(val) {
+      if (val !== null && val !== undefined) {
+        hvalue = val;
+      }
+    },
+    get: function() {
+      return hvalue;
+    }
+  });
+}
+
+function defineReadWriteWithAcceptListProperty(object, key, value, acceptList, doThrow) {
+  var hvalue = value;
+  Object.defineProperty(object, key, {
+    enumerable: true,
+    set: function(val) {
+      if (acceptList.indexOf(val) !== -1) {
+        hvalue = val;
+      } else {
+        if (doThrow) {
+          throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+        }
+      }
+    },
+    get: function() {
+      return hvalue;
+    }
+  });
+}
+
+function defineReadOnlyProperty(object, key, value) {
+  var hvalue = value;
+  Object.defineProperty(object, key, {
+    enumerable: true,
+    set: function(val) {
+      if (!hideProtectedProporties) {
+        hvalue = val;
+      }
+    },
+    get: function() {
+      return hvalue;
+    }
+  });
+}
+
+function defineWriteOnlyProperty(object, key, value, accessedValue) {
+  var hvalue = value;
+  Object.defineProperty(object, key, {
+    enumerable: true,
+    set: function(val) {
+      hvalue = val;
+    },
+    get: function() {
+      if (hideProtectedProporties) {
+        return accessedValue;
+      } else {
+        return hvalue;
+      }
+    }
+  });
+}
+
+// enums
+var SyncModes = ['MANUAL', 'PERIODIC', 'PUSH'];
+var SyncType = ['TWO_WAY', 'SLOW', 'ONE_WAY_FROM_CLIENT', 'REFRESH_FROM_CLIENT',
+                'ONE_WAY_FROM_SERVER', 'REFRESH_FROM_SERVER'];
+var SyncInterval = ['5_MINUTES', '15_MINUTES', '1_HOUR', '4_HOURS',
+                    '12_HOURS', '1_DAY', '1_WEEK', '1_MONTH'];
+var SyncServiceType = ['CONTACT', 'EVENT'];
+var SyncStatus = ['SUCCESS', 'FAIL', 'STOP', 'NONE'];
+
+// SyncInfo interface
+tizen.SyncInfo = function(url, id, password, mode, typeorinterval) {
+  if (!(this instanceof tizen.SyncInfo)) {
+    throw new TypeError;
+  }
+
+  if (typeof url !== 'string' ||
+      typeof id !== 'string' ||
+      typeof password !== 'string' ||
+      typeof mode !== 'string' ||
+      SyncModes.indexOf(mode) === -1) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+  }
+
+  defineReadWriteNonNullProperty(this, 'url', url);
+  defineWriteOnlyProperty(this, 'id', id, null);
+  defineWriteOnlyProperty(this, 'password', password, null);
+  defineReadWriteWithAcceptListProperty(this, 'mode', mode, SyncModes, false);
+
+  if (mode === 'MANUAL' && SyncType.indexOf(typeorinterval) !== -1) {
+    defineReadWriteWithAcceptListProperty(
+        this, 'type', typeorinterval, SyncType.concat([null]), false
+    );
+    defineReadWriteWithAcceptListProperty(
+        this, 'interval', null, SyncInterval.concat([null]), false
+    );
+  } else if (mode === 'PERIODIC' && SyncInterval.indexOf(typeorinterval) !== -1) {
+    defineReadWriteWithAcceptListProperty(
+        this, 'type', null, SyncType.concat([null]), false
+    );
+    defineReadWriteWithAcceptListProperty(
+        this, 'interval', typeorinterval, SyncInterval.concat([null]), false
+    );
+  } else {
+    defineReadWriteWithAcceptListProperty(
+        this, 'type', null, SyncType.concat([null]), true
+    );
+    defineReadWriteWithAcceptListProperty(
+        this, 'interval', null, SyncInterval.concat([null]), false
+    );
+  }
+};
+
+// SyncServiceInfo interface
+tizen.SyncServiceInfo = function(enable, serviceType, serverDatabaseUri, id, password) {
+  if (!(this instanceof tizen.SyncServiceInfo)) {
+    throw new TypeError;
+  }
+
+  if (typeof enable !== 'boolean') {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+  }
+  if (SyncServiceType.indexOf(serviceType) === -1) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+  }
+  if (typeof serverDatabaseUri !== 'string') {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+  }
+
+  defineReadWriteNonNullProperty(this, 'enable', enable);
+  defineReadWriteWithAcceptListProperty(this, 'serviceType', serviceType, SyncServiceType, false);
+  defineReadWriteNonNullProperty(this, 'serverDatabaseUri', serverDatabaseUri);
+
+  if (id !== undefined) {
+    if (typeof id !== 'string') {
+      throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+    } else {
+      defineWriteOnlyProperty(this, 'id', id, null);
+    }
+  } else {
+    defineWriteOnlyProperty(this, 'id', null, null);
+  }
+
+  if (password !== undefined) {
+    if (typeof password !== 'string') {
+      throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+    } else {
+      defineWriteOnlyProperty(this, 'password', password, null);
+    }
+  } else {
+    defineWriteOnlyProperty(this, 'password', null, null);
+  }
+};
+
+// SyncProfileInfo interface
+tizen.SyncProfileInfo = function(profileName, syncInfo, serviceInfo) {
+  if (!(this instanceof tizen.SyncProfileInfo)) {
+    throw new TypeError;
+  }
+
+  if (typeof profileName !== 'string') {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+  }
+  if (!(syncInfo instanceof tizen.SyncInfo)) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+  }
+
+  defineReadOnlyProperty(this, 'profileId', null);
+  defineReadWriteNonNullProperty(this, 'profileName', profileName);
+  defineReadWriteNonNullProperty(this, 'syncInfo', syncInfo);
+
+  if (serviceInfo !== undefined) {
+    if (serviceInfo instanceof Array) {
+      for (var i = 0; i < serviceInfo.length; i++) {
+        if (!(serviceInfo[i] instanceof tizen.SyncServiceInfo)) {
+          throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+        }
+      }
+      defineReadWriteProperty(this, 'serviceInfo', serviceInfo);
+    } else if (serviceInfo === null) {
+      defineReadWriteProperty(this, 'serviceInfo', null);
+    } else {
+      throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+    }
+  } else {
+    defineReadWriteProperty(this, 'serviceInfo', null);
+  }
+};
+
+// SyncStatistics interface.
+function SyncStatistics(json) {
+  for (var field in json) {
+    var val = json[field];
+    if (val !== undefined) {
+      if (field === 'lastSyncTime') {
+        val = new Date(val * 1000);
+      }
+    }
+    defineReadOnlyProperty(this, field, val);
+  }
+}
+
+function validateCallbacks(callbacks) {
+  var callbackNames = ['onprogress', 'oncompleted', 'onstopped', 'onfailed'];
+
+  for (var i = 0; i < callbackNames.length; i++) {
+    if (typeof callbacks[callbackNames[i]] !== 'function') {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+function convertToSyncStatistics(data) {
+  if (!(data instanceof Array)) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_UNKNOWN_ERR);
+  }
+  var result = [];
+  for (var i = 0; i < data.length; i++) {
+    result.push(new SyncStatistics(data[i]));
+  }
+  return result;
+}
+
+function convertToProfileInfo(data) {
+  if (typeof data !== 'object') {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_UNKNOWN_ERR);
+  }
+
+  var profileId = data['profileId'];
+  var profileName = data['profileName'];
+  var syncInfo = data['syncInfo'];
+  var serviceInfo = data['serviceInfo'];
+
+  if (typeof profileId !== 'string') {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_UNKNOWN_ERR);
+  }
+  if (typeof profileName !== 'string') {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_UNKNOWN_ERR);
+  }
+  if (syncInfo === undefined) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_UNKNOWN_ERR);
+  }
+
+  var serviceInfoList = [];
+  if (serviceInfo instanceof Array) {
+    for (var i = 0; i < serviceInfo.length; i++) {
+      serviceInfoList.push(convertToServiceInfo(serviceInfo[i]));
+    }
+  } else if (serviceInfo === null) {
+    serviceInfoList = null;
+  } else {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_UNKNOWN_ERR);
+  }
+
+  var profile = new tizen.SyncProfileInfo(profileName,
+      convertToSyncInfo(syncInfo), serviceInfoList);
+
+  executeUnrestricted(function() {
+    profile.profileId = profileId;
+  });
+
+  return profile;
+}
+
+function convertToSyncInfo(data) {
+  try {
+    var mode = data['mode'];
+    var type = data['type'];
+    var interval = data['interval'];
+
+    var typeorinterval = null;
+    if (mode === 'MANUAL') {
+      typeorinterval = type;
+    } else if (mode === 'PERIODIC') {
+      typeorinterval = interval;
+    }
+
+    return new tizen.SyncInfo(data['url'], data['id'], data['password'],
+        mode, typeorinterval);
+  } catch (e) {
+    if (e instanceof tizen.WebAPIException) {
+      throw tizen.WebAPIException(tizen.WebAPIException.TYPE_UNKNOWN_ERR);
+    } else {
+      throw e;
+    }
+  }
+}
+
+function convertToServiceInfo(data) {
+  try {
+    return new tizen.SyncServiceInfo(data['enable'], data['serviceType'],
+        data['serverDatabaseUri'], data['id'], data['password']);
+  } catch (e) {
+    if (e instanceof tizen.WebAPIException) {
+      throw tizen.WebAPIException(tizen.WebAPIException.TYPE_UNKNOWN_ERR);
+    } else {
+      throw e;
+    }
+  }
+}
+
+// DataSynchronizationManager interface
+function DataSynchronizationManager() {
+  if (!(this instanceof DataSynchronizationManager)) {
+    throw new TypeError;
+  }
+}
+
+DataSynchronizationManager.prototype.add = function(profile) {
+  if (!(profile instanceof tizen.SyncProfileInfo)) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+  }
+  var msg = {
+    cmd: 'add',
+    arg: profile
+  };
+
+  var id = sendSyncMessage(msg);
+  executeUnrestricted(function() {
+    profile.profileId = id;
+  });
+};
+
+DataSynchronizationManager.prototype.update = function(profile) {
+  if (!(profile instanceof tizen.SyncProfileInfo)) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+  }
+  var msg = {
+    cmd: 'update',
+    arg: profile
+  };
+  return sendSyncMessage(msg);
+};
+
+DataSynchronizationManager.prototype.remove = function(profileId) {
+  if (typeof profileId !== 'string') {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+  }
+  var msg = {
+    cmd: 'remove',
+    arg: profileId
+  };
+  return sendSyncMessage(msg);
+};
+
+DataSynchronizationManager.prototype.getMaxProfilesNum = function() {
+  var msg = {
+    cmd: 'getMaxProfilesNum'
+  };
+  return sendSyncMessage(msg);
+};
+
+DataSynchronizationManager.prototype.getProfilesNum = function() {
+  var msg = {
+    cmd: 'getProfilesNum'
+  };
+  return sendSyncMessage(msg);
+};
+
+DataSynchronizationManager.prototype.get = function(profileId) {
+  if (typeof profileId !== 'string') {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+  }
+  var msg = {
+    cmd: 'get',
+    arg: profileId
+  };
+
+  return convertToProfileInfo(sendSyncMessage(msg));
+};
+
+DataSynchronizationManager.prototype.getAll = function() {
+  var msg = {
+    cmd: 'getAll'
+  };
+
+  var result = sendSyncMessage(msg);
+  if (!(result instanceof Array)) {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_UNKNOWN_ERR);
+  }
+  var final = [];
+  for (var i = 0; i < result.length; i++) {
+    final.push(convertToProfileInfo(result[i]));
+  }
+  return final;
+};
+
+DataSynchronizationManager.prototype.startSync = function(profileId, progressCallback) {
+  if (typeof profileId !== 'string') {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+  }
+  if (arguments.length > 1) {
+    // Array is an object, should not accept Array
+    if (progressCallback instanceof Array) {
+      throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+    }
+    if (typeof progressCallback !== 'object') {
+      throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+    }
+    if (!validateCallbacks(progressCallback)) {
+      throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+    }
+  }
+
+  var msg = {
+    cmd: 'startSync',
+    arg: profileId
+  };
+
+  return postSyncMessageWithCallback(msg, progressCallback);
+};
+
+DataSynchronizationManager.prototype.stopSync = function(profileId) {
+  if (typeof profileId !== 'string') {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+  }
+  var msg = {
+    cmd: 'stopSync',
+    arg: profileId
+  };
+  return sendSyncMessage(msg);
+};
+
+DataSynchronizationManager.prototype.getLastSyncStatistics = function(profileId) {
+  if (typeof profileId !== 'string') {
+    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+  }
+  var msg = {
+    cmd: 'getLastSyncStatistics',
+    arg: profileId
+  };
+  var result = sendSyncMessage(msg);
+  return convertToSyncStatistics(result);
+};
+
+exports = new DataSynchronizationManager();
diff --git a/datasync/datasync_error.h b/datasync/datasync_error.h
new file mode 100644 (file)
index 0000000..b22b617
--- /dev/null
@@ -0,0 +1,123 @@
+// Copyright (c) 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.
+
+#ifndef DATASYNC_DATASYNC_ERROR_H_
+#define DATASYNC_DATASYNC_ERROR_H_
+
+#include <cassert>
+#include <functional>
+#include <string>
+
+namespace datasync {
+
+class Error {
+ public:
+  Error() { }
+  Error(const std::string& name, const std::string& message)
+      : name_(name),
+        message_(message) {}
+  const std::string& message() const { return message_; }
+  const std::string& name() const { return name_; }
+
+ private:
+  std::string name_;
+  std::string message_;
+};
+
+/**
+ * Abstraction for returning result or error from function as one piece
+ *
+ * This type allows you to pass two callback to this object which will
+ * be called respectively on Success or Failure.
+ *
+ * Code example:
+ *
+ * ResultOrError<std::string> func(bool ok) {
+ *   return ok ? "string" : Error("string", "string");
+ * }
+ *
+ * func(x).Success([]() {
+ *   // success of calculations...
+ * }).Failure([]() {
+ *   // failure of calculations...
+ * });
+ *
+ */
+template<class Result> class ResultOrError {
+ public:
+  typedef std::function<void(Result)> SuccessFunction;
+  typedef std::function<void(const Error&)> HandlerFunction;
+
+  ResultOrError(const Error& ex)  // NOLINT
+      : error_(ex),
+        is_error_(true) {
+  }
+
+  ResultOrError(Result r)  // NOLINT
+      : result_(r),
+        is_error_(false) {
+  }
+
+  const ResultOrError& Failure(const HandlerFunction& f) const {
+    if (is_error()) {
+      f(error_);
+    }
+    return *this;
+  }
+
+  const ResultOrError& Success(const SuccessFunction& f) const {
+    if (!is_error()) {
+      f(result_);
+    }
+    return *this;
+  }
+
+ private:
+  bool is_error() const {
+    return is_error_;
+  }
+
+  Error error_;
+  Result result_;
+  bool is_error_;
+};
+
+template<> class ResultOrError<void> {
+ public:
+  typedef std::function<void()> SuccessFunction;
+  typedef std::function<void(const Error&)> HandlerFunction;
+
+  ResultOrError<void>(const Error& ex)
+      : error_(ex),
+        is_error_(true) {
+  }
+
+  ResultOrError<void>() : is_error_(false) { }
+
+  const ResultOrError<void>& Failure(const HandlerFunction& f) const {
+    if (is_error()) {
+      f(error_);
+    }
+    return *this;
+  }
+
+  const ResultOrError& Success(const SuccessFunction& f) const {
+    if (!is_error()) {
+      f();
+    }
+    return *this;
+  }
+
+ private:
+  bool is_error() const {
+    return is_error_;
+  }
+
+  Error error_;
+  bool is_error_;
+};
+
+}  // namespace datasync
+
+#endif  // DATASYNC_DATASYNC_ERROR_H_
diff --git a/datasync/datasync_extension.cc b/datasync/datasync_extension.cc
new file mode 100644 (file)
index 0000000..bff3e7e
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright (c) 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.
+
+#include "datasync/datasync_extension.h"
+#include "datasync/datasync_instance.h"
+
+// This will be generated from datasync_api.js.
+extern const char kSource_datasync_api[];
+
+namespace datasync {
+
+DatasyncExtension::DatasyncExtension() {
+  SetExtensionName("tizen.datasync");
+  SetJavaScriptAPI(kSource_datasync_api);
+
+  const char* entry_points[] = {
+      "tizen.SyncInfo", "tizen.SyncProfileInfo", "tizen.SyncServiceInfo", NULL};
+  SetExtraJSEntryPoints(entry_points);
+}
+
+DatasyncExtension::~DatasyncExtension() {}
+
+common::Instance* DatasyncExtension::CreateInstance() {
+  return new DatasyncInstance;
+}
+
+}  // namespace datasync
+
+// entry point
+common::Extension* CreateExtension() {
+  return new datasync::DatasyncExtension;
+}
diff --git a/datasync/datasync_extension.h b/datasync/datasync_extension.h
new file mode 100644 (file)
index 0000000..b539c77
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright (c) 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.
+
+#ifndef DATASYNC_DATASYNC_EXTENSION_H_
+#define DATASYNC_DATASYNC_EXTENSION_H_
+
+#include "common/extension.h"
+
+namespace datasync {
+
+class DatasyncExtension : public common::Extension {
+ public:
+  DatasyncExtension();
+  virtual ~DatasyncExtension();
+
+ private:
+  // common::Extension implementation.
+  virtual common::Instance* CreateInstance();
+};
+
+}  // namespace datasync
+
+#endif  // DATASYNC_DATASYNC_EXTENSION_H_
diff --git a/datasync/datasync_instance.cc b/datasync/datasync_instance.cc
new file mode 100644 (file)
index 0000000..3652a73
--- /dev/null
@@ -0,0 +1,312 @@
+// Copyright (c) 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.
+
+#include "datasync/datasync_instance.h"
+
+#include "datasync/datasync_log.h"
+#include "datasync/datasync_serialization.h"
+
+#include "tizen/tizen.h"
+
+namespace datasync {
+
+DatasyncInstance::DatasyncInstance()
+    : manager_(new DataSyncManager(*this)) {
+}
+
+DatasyncInstance::~DatasyncInstance() {}
+
+void DatasyncInstance::HandleMessage(const char* msg) {
+  // this is stub, no async messages
+  LogError("No handling of async message: " << msg);
+}
+
+void DatasyncInstance::HandleSyncMessage(const char* msg) {
+  LogDebug("HandleSyncMessage: " << msg);
+  picojson::value v;
+  std::string err;
+
+  picojson::parse(v, msg, msg + strlen(msg), &err);
+  if (!err.empty()) {
+    LogError("Ignoring message");
+    return;
+  }
+
+  int callback_id = -1;
+  std::string cmd = v.get("cmd").to_str();
+  picojson::value arg = v.get("arg");
+
+  LogDebug("cmd:" << cmd << " arg: " << arg.to_str());
+
+  if (v.contains("callback_key")) {
+    callback_id = static_cast<int>(v.get("callback_key").get<double>());
+  }
+
+  if (cmd == "getMaxProfilesNum") {
+    HandleGetMaxProfilesNum(arg);
+  } else if (cmd == "getProfilesNum") {
+    HandleGetProfilesNum(arg);
+  } else if (cmd == "get") {
+    HandleGet(arg);
+  } else if (cmd == "getAll") {
+    HandleGetAll(arg);
+  } else if (cmd == "getLastSyncStatistics") {
+    HandleGetLastSyncStatistics(arg);
+  } else if (cmd == "add") {
+    HandleAdd(arg);
+  } else if (cmd == "update") {
+    HandleUpdate(arg);
+  } else if (cmd == "remove") {
+    HandleRemove(arg);
+  } else if (cmd == "startSync") {
+    HandleStartSync(arg, callback_id);
+  } else if (cmd == "stopSync") {
+    HandleStopSync(arg);
+  } else {
+    LogError("Unknown command");
+  }
+}
+
+void DatasyncInstance::ReplySyncAnswer(const picojson::value& value) {
+  picojson::object answer;
+  answer["answer"] = value;
+
+  LogDebug("ReplySyncAnswer: " << picojson::value(answer).serialize().c_str());
+
+  SendSyncReply(picojson::value(answer).serialize().c_str());
+}
+
+void DatasyncInstance::ReplySyncUndefinedAnswer() {
+  picojson::object answer;
+  std::string message = picojson::value(answer).serialize();
+  LogDebug("ReplySyncUndefinedAnswer: " << message.c_str());
+
+  SendSyncReply(message.c_str());
+}
+
+void DatasyncInstance::ReplySyncException(unsigned code,
+    const std::string& name,
+    const std::string& message) {
+  picojson::object exception;
+  picojson::object error;
+  error["code"] = picojson::value(static_cast<double>(code));
+  error["name"] = picojson::value(name);
+  error["message"] = picojson::value(message);
+  exception["exception"] = picojson::value(error);
+
+  std::string ret = picojson::value(exception).serialize();
+  LogDebug("ReplySyncException: " << ret.c_str());
+
+  SendSyncReply(ret.c_str());
+}
+
+void DatasyncInstance::MakeExceptionAndReply(const Error& e) {
+  ReplySyncException(WebApiAPIErrors::UNKNOWN_ERR, e.name(), e.message());
+}
+
+void DatasyncInstance::ReplyAsyncAnswer(int key, const std::string& name,
+    const picojson::value& ret) {
+  picojson::object toSend;
+  toSend["callback_key"] = picojson::value(static_cast<double>(key));
+  toSend["callback_name"] = picojson::value(name);
+  toSend["answer"] = ret;
+
+  LogDebug("ReplyAsync: " << picojson::value(toSend).serialize().c_str());
+
+  PostMessage(picojson::value(toSend).serialize().c_str());
+}
+
+void DatasyncInstance::ReplyAsyncOnCompleted(int key,
+    const std::string& profile_id) {
+  picojson::object ret;
+  ret["profileId"] = picojson::value(profile_id);
+  ReplyAsyncAnswer(key, "oncompleted", picojson::value(ret));
+}
+
+void DatasyncInstance::ReplyAsyncOnStopped(int key,
+    const std::string& profile_id) {
+  picojson::object ret;
+  ret["profileId"] = picojson::value(profile_id);
+  ReplyAsyncAnswer(key, "onstopped", picojson::value(ret));
+}
+
+void DatasyncInstance::ReplyAsyncOnFailed(int key,
+    const std::string& profile_id,
+    int error_code,
+    const std::string& name,
+    const std::string& message) {
+  picojson::object ret;
+  picojson::object error;
+
+  error["code"] = picojson::value(static_cast<double>(error_code));
+  error["name"] = picojson::value(name);
+  error["message"] = picojson::value(message);
+
+  ret["error"] = picojson::value(error);
+  ret["profileId"] = picojson::value(profile_id);
+
+  ReplyAsyncAnswer(key, "onfailed", picojson::value(ret));
+}
+
+void DatasyncInstance::ReplyAsyncOnProgress(int key,
+    const std::string& profile_id,
+    bool is_from_server,
+    int synced_per_db,
+    int total_per_db,
+    SyncServiceInfo::SyncServiceType type) {
+  picojson::object ret;
+  ret["profileId"] = picojson::value(profile_id);
+
+  ret["isFromServer"] = picojson::value(is_from_server);
+  ret["syncedPerService"] = picojson::value(static_cast<double>(synced_per_db));
+  ret["totalPerService"] = picojson::value(static_cast<double>(total_per_db));
+
+  ret["serviceType"] =
+      picojson::value(SyncServiceInfo::SyncServiceTypeToString(type));
+
+  ReplyAsyncAnswer(key, "onprogress", picojson::value(ret));
+}
+
+void DatasyncInstance::HandleGetMaxProfilesNum(const picojson::value&) {
+  manager_->GetMaxProfilesNum().Success([this](unsigned max){
+    ReplySyncAnswer(serialization::ToJson(max));
+  });
+}
+
+void DatasyncInstance::HandleGetProfilesNum(const picojson::value&) {
+  manager_->GetProfilesNum().Success([this](unsigned num) {
+    ReplySyncAnswer(serialization::ToJson(num));
+  }).Failure([this](const Error& e) {
+    MakeExceptionAndReply(e);
+  });
+}
+
+void DatasyncInstance::HandleGet(const picojson::value& arg) {
+  std::unique_ptr<std::string> profile_id =
+      serialization::FromJson<std::string>(arg);
+  if (profile_id) {
+    manager_->Get(*profile_id).Success([this](SyncProfileInfoPtr profileInfo) {
+      ReplySyncAnswer(serialization::ToJson(*profileInfo));
+    }).Failure([this](const Error& e) {
+      MakeExceptionAndReply(e);
+    });
+  } else {
+    ReplySyncException(WebApiAPIErrors::UNKNOWN_ERR, "PlatformException",
+                       "Error during SyncProfile Construction");
+  }
+}
+
+void DatasyncInstance::HandleGetAll(const picojson::value&) {
+  manager_->GetAll().Success([this](SyncProfileInfoListPtr profileInfoList) {
+    picojson::array array;
+
+    for (const auto& element : *profileInfoList) {
+      array.push_back(serialization::ToJson(*element));
+    }
+
+    ReplySyncAnswer(serialization::ToJson(array));
+  }).Failure([this](const Error& e) {
+    MakeExceptionAndReply(e);
+  });
+}
+
+void DatasyncInstance::HandleGetLastSyncStatistics(const picojson::value& arg) {
+  std::unique_ptr<std::string> profile_id =
+      serialization::FromJson<std::string>(arg);
+  if (profile_id) {
+    manager_->GetLastSyncStatistics(*profile_id)
+        .Success([this](SyncStatisticsListPtr statisticsList) {
+      picojson::array array;
+
+      for (const auto& element : *statisticsList) {
+        array.push_back(serialization::ToJson(*element));
+      }
+
+      ReplySyncAnswer(serialization::ToJson(array));
+    }).Failure([this](const Error& e) {
+      MakeExceptionAndReply(e);
+    });
+  } else {
+    ReplySyncException(WebApiAPIErrors::UNKNOWN_ERR, "PlatformException",
+                       "Error during object construction");
+  }
+}
+
+void DatasyncInstance::HandleAdd(const picojson::value& arg) {
+  std::unique_ptr<SyncProfileInfo> profile =
+      serialization::FromJson<SyncProfileInfo>(arg);
+  if (profile) {
+    manager_->Add(*profile).Success([this](std::string id) {
+      ReplySyncAnswer(serialization::ToJson(id));
+    }).Failure([this](const Error& e) {
+      MakeExceptionAndReply(e);
+    });
+  } else {
+    ReplySyncException(WebApiAPIErrors::UNKNOWN_ERR, "PlatformException",
+                       "Error during object construction");
+  }
+}
+
+void DatasyncInstance::HandleUpdate(const picojson::value& arg) {
+  std::unique_ptr<SyncProfileInfo> profile =
+      serialization::FromJson<SyncProfileInfo>(arg);
+  if (profile) {
+    manager_->Update(*profile).Success([this]() {
+      ReplySyncUndefinedAnswer();
+    }).Failure([this](const Error& e) {
+      MakeExceptionAndReply(e);
+    });
+  } else {
+    ReplySyncException(WebApiAPIErrors::UNKNOWN_ERR, "PlatformException",
+                       "Error during object construction");
+  }
+}
+
+void DatasyncInstance::HandleRemove(const picojson::value& arg) {
+  std::unique_ptr<std::string> profile_id =
+      serialization::FromJson<std::string>(arg);
+  if (profile_id) {
+    manager_->Remove(*profile_id).Success([this]() {
+      ReplySyncUndefinedAnswer();
+    }).Failure([this](const Error& e) {
+      MakeExceptionAndReply(e);
+    });
+  } else {
+    ReplySyncException(WebApiAPIErrors::UNKNOWN_ERR, "PlatformException",
+                       "Error during object construction");
+  }
+}
+
+void DatasyncInstance::HandleStartSync(
+    const picojson::value& arg, int callback_id) {
+  std::unique_ptr<std::string> profile_id =
+      serialization::FromJson<std::string>(arg);
+  if (profile_id) {
+    manager_->StartSync(*profile_id, callback_id).Success([this]() {
+      ReplySyncUndefinedAnswer();
+    }).Failure([this](const Error& e) {
+      MakeExceptionAndReply(e);
+    });
+  } else {
+    ReplySyncException(WebApiAPIErrors::UNKNOWN_ERR, "PlatformException",
+                       "Error during object construction");
+  }
+}
+
+void DatasyncInstance::HandleStopSync(const picojson::value& arg) {
+  std::unique_ptr<std::string> profile_id =
+      serialization::FromJson<std::string>(arg);
+  if (profile_id) {
+    manager_->StopSync(*profile_id).Success([this]() {
+      ReplySyncUndefinedAnswer();
+    }).Failure([this](const Error& e) {
+      MakeExceptionAndReply(e);
+    });
+  } else {
+    ReplySyncException(WebApiAPIErrors::UNKNOWN_ERR, "PlatformException",
+                       "Error during object construction");
+  }
+}
+
+}  // namespace datasync
diff --git a/datasync/datasync_instance.h b/datasync/datasync_instance.h
new file mode 100644 (file)
index 0000000..762fbec
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (c) 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.
+
+#ifndef DATASYNC_DATASYNC_INSTANCE_H_
+#define DATASYNC_DATASYNC_INSTANCE_H_
+
+#include <memory>
+#include <string>
+
+#include "common/extension.h"
+#include "common/picojson.h"
+
+#include "datasync/datasync_manager.h"
+
+namespace datasync {
+
+class DatasyncInstance : public common::Instance {
+ public:
+  DatasyncInstance();
+  virtual ~DatasyncInstance();
+
+  void ReplyAsyncOnCompleted(int key, const std::string& profile_id);
+  void ReplyAsyncOnStopped(int key, const std::string& profile_id);
+  void ReplyAsyncOnFailed(int key,
+      const std::string& profile_id,
+      int error_code,
+      const std::string& name,
+      const std::string& message);
+  void ReplyAsyncOnProgress(int key,
+      const std::string& profile_id,
+      bool is_from_server,
+      int synced_per_db,
+      int total_per_db,
+      SyncServiceInfo::SyncServiceType type);
+
+ private:
+  void HandleMessage(const char* msg);
+  void HandleSyncMessage(const char* msg);
+
+  void ReplySyncAnswer(const picojson::value& value);
+  void ReplySyncUndefinedAnswer();
+  void ReplySyncException(unsigned code, const std::string& name,
+      const std::string& message);
+  void MakeExceptionAndReply(const Error& e);
+
+  void ReplyAsyncAnswer(int key, const std::string& name,
+      const picojson::value& returnValue);
+
+  // Synchronous message handlers
+
+  // with result
+  void HandleGetMaxProfilesNum(const picojson::value& arg);
+  void HandleGetProfilesNum(const picojson::value& arg);
+  void HandleGet(const picojson::value& arg);
+  void HandleGetAll(const picojson::value& arg);
+  void HandleGetLastSyncStatistics(const picojson::value& arg);
+
+  // undefined result
+  void HandleAdd(const picojson::value& arg);
+  void HandleUpdate(const picojson::value& arg);
+  void HandleRemove(const picojson::value& arg);
+  void HandleStartSync(const picojson::value& arg, int callback_id);
+  void HandleStopSync(const picojson::value& arg);
+
+  std::unique_ptr<DataSyncManager> manager_;
+};
+
+}  // namespace datasync
+
+#endif  // DATASYNC_DATASYNC_INSTANCE_H_
diff --git a/datasync/datasync_log.h b/datasync/datasync_log.h
new file mode 100644 (file)
index 0000000..24dee81
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (c) 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.
+
+#ifndef DATASYNC_DATASYNC_LOG_H_
+#define DATASYNC_DATASYNC_LOG_H_
+
+#include <iostream>
+
+// TODO(t.iwanek): this header is to be removed
+// when some common logging mechanism will be introduced
+
+#define LogInfo(MESSAGE) \
+  { std::cerr << MESSAGE << std::endl; }
+#define LogDebug(MESSAGE) \
+  { std::cerr << MESSAGE << std::endl; }
+#define LogWarning(MESSAGE) \
+  { std::cerr << MESSAGE << std::endl; }
+#define LogError(MESSAGE) \
+  { std::cerr << MESSAGE << std::endl; }
+
+#endif  // DATASYNC_DATASYNC_LOG_H_
diff --git a/datasync/datasync_manager.cc b/datasync/datasync_manager.cc
new file mode 100644 (file)
index 0000000..e8b4b0d
--- /dev/null
@@ -0,0 +1,1094 @@
+// Copyright (c) 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.
+
+#include "datasync/datasync_manager.h"
+
+#include "datasync/datasync_instance.h"
+#include "datasync/datasync_log.h"
+#include "datasync/datasync_scoped_exit.h"
+#include "datasync/sync_info.h"
+#include "datasync/sync_service_info.h"
+#include "datasync/sync_profile_info.h"
+
+#include "tizen/tizen.h"
+
+namespace {
+
+const int MAX_PROFILES_NUM = 5;
+
+sync_agent_ds_sync_mode_e ConvertToPlatformSyncMode(
+    datasync::SyncInfo::SyncMode sync_mode) {
+  switch (sync_mode) {
+    case datasync::SyncInfo::MANUAL_MODE: {
+      return SYNC_AGENT_SYNC_MODE_MANUAL;
+    }
+    case datasync::SyncInfo::PERIODIC_MODE: {
+      return SYNC_AGENT_SYNC_MODE_PERIODIC;
+    }
+    case datasync::SyncInfo::PUSH_MODE: {
+      return SYNC_AGENT_SYNC_MODE_PUSH;
+    }
+    default: {
+      LogWarning("Error while converting a sync mode.");
+      return SYNC_AGENT_SYNC_MODE_MANUAL;
+    }
+  }
+}
+
+datasync::SyncInfo::SyncMode ConvertToSyncMode(
+    sync_agent_ds_sync_mode_e sync_mode) {
+  switch (sync_mode) {
+    case SYNC_AGENT_SYNC_MODE_MANUAL: {
+      return datasync::SyncInfo::MANUAL_MODE;
+    }
+    case SYNC_AGENT_SYNC_MODE_PERIODIC: {
+      return datasync::SyncInfo::PERIODIC_MODE;
+    }
+    case SYNC_AGENT_SYNC_MODE_PUSH: {
+      return datasync::SyncInfo::PUSH_MODE;
+    }
+    default: {
+      LogWarning("Error while converting a sync mode.");
+      return datasync::SyncInfo::UNDEFINED_MODE;
+    }
+  }
+}
+
+sync_agent_ds_sync_type_e ConvertToPlatformSyncType(
+    datasync::SyncInfo::SyncType syncType) {
+  switch (syncType) {
+    case datasync::SyncInfo::TWO_WAY_TYPE: {
+      return SYNC_AGENT_SYNC_TYPE_UPDATE_BOTH;
+    }
+    case datasync::SyncInfo::SLOW_TYPE: {
+      return SYNC_AGENT_SYNC_TYPE_FULL_SYNC;
+    }
+    case datasync::SyncInfo::ONE_WAY_FROM_CLIENT_TYPE: {
+      return SYNC_AGENT_SYNC_TYPE_UPDATE_TO_SERVER;
+    }
+    case datasync::SyncInfo::REFRESH_FROM_CLIENT_TYPE: {
+      return SYNC_AGENT_SYNC_TYPE_REFRESH_FROM_PHONE;
+    }
+    case datasync::SyncInfo::ONE_WAY_FROM_SERVER_TYPE: {
+      return SYNC_AGENT_SYNC_TYPE_UPDATE_TO_PHONE;
+    }
+    case datasync::SyncInfo::REFRESH_FROM_SERVER_TYPE: {
+      return SYNC_AGENT_SYNC_TYPE_REFRESH_FROM_SERVER;
+    }
+    default: {
+      LogWarning("Error while converting a sync type.");
+      return SYNC_AGENT_SYNC_TYPE_UPDATE_BOTH;
+    }
+  }
+}
+
+sync_agent_ds_src_uri_e ConvertToPlatformSourceUri(
+    datasync::SyncServiceInfo::SyncServiceType serviceType) {
+  switch (serviceType) {
+    case datasync::SyncServiceInfo::CONTACT_SERVICE_TYPE: {
+      return SYNC_AGENT_SRC_URI_CONTACT;
+    }
+    case datasync::SyncServiceInfo::EVENT_SERVICE_TYPE: {
+      return SYNC_AGENT_SRC_URI_CALENDAR;
+    }
+    default: {
+      LogWarning("Error while converting a sync service.");
+      return SYNC_AGENT_SRC_URI_CONTACT;
+    }
+  }
+}
+
+datasync::SyncStatistics::SyncStatus ConvertToSyncStatus(char* status) {
+  if (0 == strncmp(status, "success", 7)) {
+    return datasync::SyncStatistics::SUCCESS_STATUS;
+  } else if (0 == strncmp(status, "stop", 4)) {
+    return datasync::SyncStatistics::STOP_STATUS;
+  } else if (0 == strncmp(status, "fail", 4)) {
+    return datasync::SyncStatistics::FAIL_STATUS;
+  } else if (0 == strncmp(status, "No", 2)) {
+    return datasync::SyncStatistics::NONE_STATUS;
+  } else {
+    LogWarning("Error while converting a sync status.");
+  }
+
+  return datasync::SyncStatistics::NONE_STATUS;
+}
+
+datasync::SyncInfo::SyncType ConvertToSyncType(
+    sync_agent_ds_sync_type_e sync_type) {
+  switch (sync_type) {
+    case SYNC_AGENT_SYNC_TYPE_UPDATE_BOTH: {
+      return datasync::SyncInfo::TWO_WAY_TYPE;
+    }
+    case SYNC_AGENT_SYNC_TYPE_FULL_SYNC: {
+      return datasync::SyncInfo::SLOW_TYPE;
+    }
+    case SYNC_AGENT_SYNC_TYPE_UPDATE_TO_SERVER: {
+      return datasync::SyncInfo::ONE_WAY_FROM_CLIENT_TYPE;
+    }
+    case SYNC_AGENT_SYNC_TYPE_REFRESH_FROM_PHONE: {
+      return datasync::SyncInfo::REFRESH_FROM_CLIENT_TYPE;
+    }
+    case  SYNC_AGENT_SYNC_TYPE_UPDATE_TO_PHONE: {
+      return datasync::SyncInfo::ONE_WAY_FROM_SERVER_TYPE;
+    }
+    case SYNC_AGENT_SYNC_TYPE_REFRESH_FROM_SERVER: {
+      return datasync::SyncInfo::REFRESH_FROM_SERVER_TYPE;
+    }
+    default: {
+      LogWarning("Error while converting a sync type.");
+      return datasync::SyncInfo::UNDEFINED_TYPE;
+    }
+  }
+}
+
+sync_agent_ds_sync_interval_e ConvertToPlatformSyncInterval(
+    datasync::SyncInfo::SyncInterval sync_interval) {
+  switch (sync_interval) {
+    case datasync::SyncInfo::INTERVAL_5_MINUTES: {
+      return SYNC_AGENT_SYNC_INTERVAL_5_MINUTES;
+    }
+    case datasync::SyncInfo::INTERVAL_15_MINUTES: {
+      return SYNC_AGENT_SYNC_INTERVAL_15_MINUTES;
+    }
+    case datasync::SyncInfo::INTERVAL_1_HOUR: {
+      return SYNC_AGENT_SYNC_INTERVAL_1_HOUR;
+    }
+    case datasync::SyncInfo::INTERVAL_4_HOURS: {
+      return SYNC_AGENT_SYNC_INTERVAL_4_HOURS;
+    }
+    case datasync::SyncInfo::INTERVAL_12_HOURS: {
+      return SYNC_AGENT_SYNC_INTERVAL_12_HOURS;
+    }
+    case datasync::SyncInfo::INTERVAL_1_DAY: {
+      return SYNC_AGENT_SYNC_INTERVAL_1_DAY;
+    }
+    case datasync::SyncInfo::INTERVAL_1_WEEK: {
+      return SYNC_AGENT_SYNC_INTERVAL_1_WEEK;
+    }
+    case datasync::SyncInfo::INTERVAL_1_MONTH: {
+      return SYNC_AGENT_SYNC_INTERVAL_1_MONTH;
+    }
+    case datasync::SyncInfo::INTERVAL_UNDEFINED: {
+      return SYNC_AGENT_SYNC_INTERVAL_NONE;
+    }
+    default: {
+      LogWarning("Error while converting a JS sync interval.");
+      return SYNC_AGENT_SYNC_INTERVAL_1_WEEK;
+    }
+  }
+}
+
+datasync::SyncInfo::SyncInterval ConvertToSyncInterval(
+    sync_agent_ds_sync_interval_e sync_interval) {
+  switch (sync_interval) {
+    case SYNC_AGENT_SYNC_INTERVAL_5_MINUTES: {
+      return datasync::SyncInfo::INTERVAL_5_MINUTES;
+    }
+    case SYNC_AGENT_SYNC_INTERVAL_15_MINUTES: {
+      return datasync::SyncInfo::INTERVAL_15_MINUTES;
+    }
+    case SYNC_AGENT_SYNC_INTERVAL_1_HOUR: {
+      return datasync::SyncInfo::INTERVAL_1_HOUR;
+    }
+    case SYNC_AGENT_SYNC_INTERVAL_4_HOURS: {
+      return datasync::SyncInfo::INTERVAL_4_HOURS;
+    }
+    case SYNC_AGENT_SYNC_INTERVAL_12_HOURS: {
+      return datasync::SyncInfo::INTERVAL_12_HOURS;
+    }
+    case SYNC_AGENT_SYNC_INTERVAL_1_DAY: {
+      return datasync::SyncInfo::INTERVAL_1_DAY;
+    }
+    case SYNC_AGENT_SYNC_INTERVAL_1_WEEK: {
+      return datasync::SyncInfo::INTERVAL_1_WEEK;
+    }
+    case SYNC_AGENT_SYNC_INTERVAL_1_MONTH: {
+      return datasync::SyncInfo::INTERVAL_1_MONTH;
+    }
+    case SYNC_AGENT_SYNC_INTERVAL_NONE: {
+      return datasync::SyncInfo::INTERVAL_UNDEFINED;
+    }
+    default: {
+      LogWarning("Error while converting a platform sync interval.");
+      return datasync::SyncInfo::INTERVAL_UNDEFINED;
+    }
+  }
+}
+
+sync_agent_ds_service_type_e ConvertToPlatformSyncServiceType(
+    datasync::SyncServiceInfo::SyncServiceType service_type) {
+  switch (service_type) {
+    case datasync::SyncServiceInfo::CONTACT_SERVICE_TYPE: {
+      return SYNC_AGENT_CONTACT;
+    }
+    case datasync::SyncServiceInfo::EVENT_SERVICE_TYPE: {
+      return SYNC_AGENT_CALENDAR;
+    }
+    default: {
+      LogWarning("Error while converting a sync service type.");
+      return SYNC_AGENT_CONTACT;
+    }
+  }
+}
+
+datasync::SyncServiceInfo::SyncServiceType ConvertToSyncServiceType(
+    sync_agent_ds_service_type_e service_type) {
+  switch (service_type) {
+    case SYNC_AGENT_CONTACT: {
+      return datasync::SyncServiceInfo::CONTACT_SERVICE_TYPE;
+    }
+    case SYNC_AGENT_CALENDAR: {
+      return datasync::SyncServiceInfo::EVENT_SERVICE_TYPE;
+    }
+    default: {
+      LogWarning("Error while converting a sync service type.");
+      return datasync::SyncServiceInfo::UNDEFINED_SERVICE_TYPE;
+    }
+  }
+}
+
+}  // namespace
+
+namespace datasync {
+
+bool DataSyncManager::sync_agent_initialized_ = false;
+
+DataSyncManager::DataSyncManager(DatasyncInstance& parent)
+    : instance_(parent) {
+  // initialize sync agent once per process
+  if (sync_agent_initialized_) {
+    return;
+  }
+
+  LogInfo("Initialize the datasync manager");
+  sync_agent_ds_error_e ds_err = sync_agent_ds_init();
+  if (SYNC_AGENT_DS_SUCCESS != ds_err) {
+    LogError("Failed to init oma ds.");
+  } else {
+    sync_agent_initialized_ = true;
+  }
+}
+
+DataSyncManager::~DataSyncManager() {
+// TODO(t.iwanek): sync-agent crashes internally..
+// sync-agent should fix it's deinitialization
+}
+
+ResultOrError<std::string> DataSyncManager::Add(SyncProfileInfo& profile_info) {
+  ds_profile_h profile_h = nullptr;
+  char* profile_name = nullptr;
+
+  // Check if the quota is full first.
+  GList* profile_list = nullptr;
+  GList* iter = nullptr;
+
+  ScopedExit exit([&profile_name, &profile_h](){
+    if (profile_name) {
+      free(profile_name);
+    }
+
+    if (profile_h) {
+      sync_agent_ds_free_profile_info(profile_h);
+    }
+  });
+
+  sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+  ret = sync_agent_ds_get_all_profile(&profile_list);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while getting all profiles");
+  }
+
+  int num_profiles = g_list_length(profile_list);
+  for (iter = profile_list; iter != nullptr; iter = g_list_next(iter)) {
+    sync_agent_ds_free_profile_info((ds_profile_h)iter->data);
+  }
+  if (profile_list) {
+    g_list_free(profile_list);
+  }
+  LogDebug("numProfiles: " << num_profiles);
+  if (MAX_PROFILES_NUM == num_profiles) {
+    return Error("OutOfRangeException",
+        "There are already maximum number of profiles!");
+  }
+
+  ret = sync_agent_ds_create_profile_info(&profile_h);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while creating a profile");
+  }
+
+  ret = sync_agent_ds_set_profile_name(
+      profile_h, const_cast<char*>(profile_info.profile_name().c_str()));
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while settting a profile name");
+  }
+
+  ret = sync_agent_ds_set_server_info(
+      profile_h, const_cast<char*>(profile_info.sync_info()->url().c_str()),
+      const_cast<char*>(profile_info.sync_info()->id().c_str()),
+      const_cast<char*>(profile_info.sync_info()->password().c_str()));
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while settting a server info");
+  }
+
+  sync_agent_ds_sync_mode_e sync_mode =
+      ConvertToPlatformSyncMode(profile_info.sync_info()->sync_mode());
+  sync_agent_ds_sync_type_e sync_type =
+      ConvertToPlatformSyncType(profile_info.sync_info()->sync_type());
+  sync_agent_ds_sync_interval_e sync_interval =
+      ConvertToPlatformSyncInterval(profile_info.sync_info()->sync_interval());
+  LogDebug("syncMode: " << sync_mode << ", syncType: " << sync_type
+                        << ", syncInterval: " << sync_interval);
+
+  ret = sync_agent_ds_set_sync_info(profile_h, sync_mode, sync_type,
+                                    sync_interval);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while settting a sync info");
+  }
+
+  // Set the sync categories.
+  SyncServiceInfoListPtr categories = profile_info.service_info();
+  for (unsigned int i = 0; categories->size() < i; ++i) {
+    sync_agent_ds_service_type_e service_type =
+        ConvertToPlatformSyncServiceType(
+            categories->at(i)->sync_service_type());
+    std::string tgt_uri = categories->at(i)->server_database_uri();
+    sync_agent_ds_src_uri_e src_uri =
+        ConvertToPlatformSourceUri(categories->at(i)->sync_service_type());
+    std::string id = categories->at(i)->id();
+    std::string password = categories->at(i)->password();
+    bool enable = categories->at(i)->enable();
+
+    LogInfo("serviceType: " << service_type << ", tgtURI: " << tgt_uri
+                            << ", enable: " << enable << " for index: " << i);
+
+    ret = sync_agent_ds_set_sync_service_info(
+        profile_h, service_type, enable, src_uri,
+        const_cast<char*>(tgt_uri.c_str()),
+        0 == id.size() ? nullptr : const_cast<char*>(id.c_str()),
+        0 == password.size() ? nullptr : const_cast<char*>(password.c_str()));
+    if (SYNC_AGENT_DS_SUCCESS != ret) {
+      return Error("Exception",
+          "Platform error while settting a sync service info");
+    }
+  }
+
+  int profile_id;
+  ret = sync_agent_ds_add_profile(profile_h, &profile_id);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while adding a profile");
+  }
+
+  LogDebug("profileId from platform: " << profile_id);
+
+  ret = sync_agent_ds_get_profile_name(profile_h, &profile_name);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while getting a profile name");
+  }
+
+  LogDebug("profileName: " << profile_name << ", profileId: " << profile_id);
+
+  profile_info.set_profile_id(std::to_string(profile_id));
+
+  return profile_info.profile_id();
+}
+
+ResultOrError<void> DataSyncManager::Update(SyncProfileInfo& profile_info) {
+  ds_profile_h profile_h = nullptr;
+
+  ScopedExit exit([&profile_h]() {
+    if (profile_h) {
+      sync_agent_ds_free_profile_info(profile_h);
+    }
+  });
+
+  sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+  int profile_id = std::stoi(profile_info.profile_id());
+  LogDebug("profileId: " << profile_id);
+
+  ret = sync_agent_ds_get_profile(profile_id, &profile_h);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("NotFoundException",
+        "Platform error while getting a profile");
+  }
+
+  ret = sync_agent_ds_set_profile_name(
+      profile_h, const_cast<char*>(profile_info.profile_name().c_str()));
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while settting a profile name");
+  }
+
+  ret = sync_agent_ds_set_server_info(
+      profile_h, const_cast<char*>(profile_info.sync_info()->url().c_str()),
+      const_cast<char*>(profile_info.sync_info()->id().c_str()),
+      const_cast<char*>(profile_info.sync_info()->password().c_str()));
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while settting a server info");
+  }
+
+  sync_agent_ds_sync_mode_e sync_mode =
+      ConvertToPlatformSyncMode(profile_info.sync_info()->sync_mode());
+  sync_agent_ds_sync_type_e sync_type =
+      ConvertToPlatformSyncType(profile_info.sync_info()->sync_type());
+  sync_agent_ds_sync_interval_e sync_interval =
+      ConvertToPlatformSyncInterval(profile_info.sync_info()->sync_interval());
+  LogDebug("syncMode: " << sync_mode << ", syncType: " << sync_type
+                        << ", syncInterval: " << sync_interval);
+
+  ret = sync_agent_ds_set_sync_info(profile_h, sync_mode, sync_type,
+                                    sync_interval);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while settting a sync info");
+  }
+
+  // Set the sync categories.
+  SyncServiceInfoListPtr categories = profile_info.service_info();
+  for (unsigned int i = 0; categories->size() < i; ++i) {
+    sync_agent_ds_service_type_e service_type =
+        ConvertToPlatformSyncServiceType(
+            categories->at(i)->sync_service_type());
+    std::string tgt_uri = categories->at(i)->server_database_uri();
+    sync_agent_ds_src_uri_e src_uri =
+        ConvertToPlatformSourceUri(categories->at(i)->sync_service_type());
+    std::string id = categories->at(i)->id();
+    std::string password = categories->at(i)->password();
+    bool enable = categories->at(i)->enable();
+
+    LogDebug("serviceType: " << service_type << ", tgtURI: " << tgt_uri
+                             << " for index: " << i);
+
+    ret = sync_agent_ds_set_sync_service_info(
+        profile_h, service_type, enable, src_uri,
+        const_cast<char*>(tgt_uri.c_str()),
+        0 == id.size() ? nullptr : const_cast<char*>(id.c_str()),
+        0 == password.size() ? nullptr : const_cast<char*>(password.c_str()));
+    if (SYNC_AGENT_DS_SUCCESS != ret) {
+      return Error("Exception",
+          "Platform error while settting a sync service info");
+    }
+  }
+
+  ret = sync_agent_ds_update_profile(profile_h);
+  if (SYNC_AGENT_DS_SUCCESS != ret && SYNC_AGENT_DS_SYNCHRONISING != ret) {
+    return Error("Exception",
+        "Platform error while updating a profile");
+  }
+  return {};
+}
+
+ResultOrError<void> DataSyncManager::Remove(const std::string& id) {
+  ds_profile_h profile_h = nullptr;
+
+  ScopedExit exit([&profile_h]() {
+    if (profile_h) {
+      sync_agent_ds_free_profile_info(profile_h);
+    }
+  });
+
+  sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+  int profile_id = std::stoi(id);
+  LogDebug("profileId: " << profile_id);
+
+  ret = sync_agent_ds_get_profile(profile_id, &profile_h);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while getting a profile");
+  }
+
+  ret = sync_agent_ds_delete_profile(profile_h);
+  if (SYNC_AGENT_DS_SUCCESS != ret && SYNC_AGENT_DS_SYNCHRONISING != ret) {
+    return Error("Exception",
+        "Platform error while deleting a profile");
+  }
+
+  return {};
+}
+
+ResultOrError<unsigned> DataSyncManager::GetMaxProfilesNum() const {
+  return MAX_PROFILES_NUM;
+}
+
+ResultOrError<unsigned> DataSyncManager::GetProfilesNum() const {
+  GList* profile_list = nullptr;
+  GList* iter = nullptr;
+
+  sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+  ret = sync_agent_ds_get_all_profile(&profile_list);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while getting all profiles");
+  }
+
+  int num_profiles = 0;
+  for (iter = profile_list; iter != nullptr; iter = g_list_next(iter)) {
+    sync_agent_ds_free_profile_info((ds_profile_h)iter->data);
+    num_profiles++;
+    LogDebug("Free sync_agent_ds_profile_info for index: " << num_profiles);
+  }
+
+  LogDebug("numProfiles: " << num_profiles);
+
+  return num_profiles;
+}
+
+ResultOrError<SyncProfileInfoPtr> DataSyncManager::Get(
+    const std::string& profile_id) const {
+  ds_profile_h profile_h = nullptr;
+  GList* category_list = nullptr;
+
+  ScopedExit exit([&category_list, &profile_h]() {
+    if (category_list) {
+      g_list_free(category_list);
+    }
+
+    if (profile_h) {
+      sync_agent_ds_free_profile_info(profile_h);
+    }
+  });
+
+  SyncProfileInfoPtr profile(new SyncProfileInfo());
+
+  sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+  int profile_id_str = std::stoi(profile_id);
+  LogDebug("profileId: " << profile_id_str);
+
+  ret = sync_agent_ds_get_profile(profile_id_str, &profile_h);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("NotFoundException",
+        "Platform error while getting a profile");
+  }
+
+  profile->set_profile_id(profile_id);
+
+  char* profile_name = nullptr;
+  ret = sync_agent_ds_get_profile_name(profile_h, &profile_name);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while gettting a profile name");
+  }
+  profile->set_profile_name(profile_name);
+
+  sync_agent_ds_server_info server_info = {nullptr};
+  ret = sync_agent_ds_get_server_info(profile_h, &server_info);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while gettting a server info");
+  }
+  profile->sync_info()->set_url(server_info.addr);
+  profile->sync_info()->set_id(server_info.id);
+  profile->sync_info()->set_password(server_info.password);
+
+  sync_agent_ds_sync_info sync_info;
+  ret = sync_agent_ds_get_sync_info(profile_h, &sync_info);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while gettting a sync info");
+  }
+  profile->sync_info()->set_sync_mode(ConvertToSyncMode(sync_info.sync_mode));
+  profile->sync_info()->set_sync_type(ConvertToSyncType(sync_info.sync_type));
+  profile->sync_info()->set_sync_interval(
+      ConvertToSyncInterval(sync_info.interval));
+
+  LogDebug("Sync mode: " << sync_info.sync_mode
+                         << ", type: " << sync_info.sync_type
+                         << ", interval: " << sync_info.interval);
+
+  sync_agent_ds_service_info* category_info = nullptr;
+  ret = sync_agent_ds_get_sync_service_info(profile_h, &category_list);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while gettting sync categories");
+  }
+  int category_count = g_list_length(category_list);
+  LogDebug("category_count: " << category_count);
+  while (category_count--) {
+    category_info = static_cast<sync_agent_ds_service_info*>(
+        g_list_nth_data(category_list, category_count));
+    if (SYNC_AGENT_CALENDAR < category_info->service_type) {
+      LogDebug("Skip unsupported sync service type: "
+               << category_info->service_type);
+      continue;
+    }
+
+    SyncServiceInfoPtr service_info(new SyncServiceInfo());
+    service_info->set_enable(category_info->enabled);
+    if (category_info->id) {
+      service_info->set_id(category_info->id);
+    }
+    if (category_info->password) {
+      service_info->set_password(category_info->password);
+    }
+    service_info->set_sync_service_type(
+        ConvertToSyncServiceType(category_info->service_type));
+    if (category_info->tgt_uri) {
+      service_info->set_server_database_uri(category_info->tgt_uri);
+    }
+
+    LogDebug("Service type: " << service_info->sync_service_type());
+    profile->service_info()->push_back(service_info);
+  }
+
+  return profile;
+}
+
+ResultOrError<SyncProfileInfoListPtr> DataSyncManager::GetAll() const {
+  GList* profile_list = nullptr;
+  GList* iter = nullptr;
+
+  ds_profile_h profile_h = nullptr;
+
+  ScopedExit exit([&profile_list, &profile_h, &iter]() {
+    LogDebug("Free profiles list.");
+    for (iter = profile_list; iter != nullptr; iter = g_list_next(iter)) {
+      sync_agent_ds_free_profile_info((ds_profile_h)iter->data);
+    }
+
+    if (profile_list) {
+      g_list_free(profile_list);
+    }
+  });
+
+  SyncProfileInfoListPtr profiles = std::make_shared<SyncProfileInfoList>();
+
+  sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+  ret = sync_agent_ds_get_all_profile(&profile_list);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while getting all profiles");
+  }
+
+  int profile_id;
+  LogDebug("Number of profiles: " << g_list_length(profile_list));
+  for (iter = profile_list; iter != nullptr; iter = g_list_next(iter)) {
+    profile_h = (ds_profile_h)iter->data;
+    SyncProfileInfoPtr profile(new SyncProfileInfo());
+
+    ret = sync_agent_ds_get_profile_id(profile_h, &profile_id);
+    if (SYNC_AGENT_DS_SUCCESS != ret) {
+      return Error("Exception",
+          "Platform error while gettting a profile id");
+    }
+
+    profile->set_profile_id(std::to_string(profile_id));
+
+    LogDebug("Processing a profile with id: " << profile->profile_id());
+
+    char* profile_name = nullptr;
+    ret = sync_agent_ds_get_profile_name(profile_h, &profile_name);
+    if (SYNC_AGENT_DS_SUCCESS != ret) {
+      return Error("Exception",
+          "Platform error while gettting a profile name");
+    }
+    profile->set_profile_name(profile_name);
+
+    sync_agent_ds_server_info server_info = {nullptr};
+    ret = sync_agent_ds_get_server_info(profile_h, &server_info);
+    if (SYNC_AGENT_DS_SUCCESS != ret) {
+      return Error("Exception",
+          "Platform error while gettting a server info");
+    }
+    profile->sync_info()->set_url(server_info.addr);
+    profile->sync_info()->set_id(server_info.id);
+    profile->sync_info()->set_password(server_info.password);
+
+    sync_agent_ds_sync_info sync_info;
+    ret = sync_agent_ds_get_sync_info(profile_h, &sync_info);
+    if (SYNC_AGENT_DS_SUCCESS != ret) {
+      return Error("Exception",
+          "Platform error while gettting a sync info");
+    }
+    profile->sync_info()->set_sync_mode(
+        ConvertToSyncMode(sync_info.sync_mode));
+    profile->sync_info()->set_sync_type(
+        ConvertToSyncType(sync_info.sync_type));
+    profile->sync_info()->set_sync_interval(
+        ConvertToSyncInterval(sync_info.interval));
+
+    LogDebug("Sync mode: " << sync_info.sync_mode
+                           << ", type: " << sync_info.sync_type
+                           << ", interval: " << sync_info.interval);
+
+    GList* category_list = nullptr;
+    sync_agent_ds_service_info* category_info = nullptr;
+    ret = sync_agent_ds_get_sync_service_info(profile_h, &category_list);
+    if (SYNC_AGENT_DS_SUCCESS != ret) {
+      return Error(
+          "Exception",
+          "Platform error while gettting sync categories");
+    }
+    int category_count = g_list_length(category_list);
+    LogDebug("category_count: " << category_count);
+    while (category_count--) {
+      category_info = static_cast<sync_agent_ds_service_info*>(
+          g_list_nth_data(category_list, category_count));
+      if (SYNC_AGENT_CALENDAR < category_info->service_type) {
+        LogDebug("Skip unsupported sync service type: "
+            << category_info->service_type);
+        continue;
+      }
+
+      SyncServiceInfoPtr service_info(new SyncServiceInfo());
+      service_info->set_enable(category_info->enabled);
+      if (category_info->id) {
+        service_info->set_id(category_info->id);
+      }
+      if (category_info->password) {
+        service_info->set_password(category_info->password);
+      }
+      service_info->set_sync_service_type(
+          ConvertToSyncServiceType(category_info->service_type));
+      if (category_info->tgt_uri) {
+        service_info->set_server_database_uri(category_info->tgt_uri);
+      }
+
+      LogDebug("Service type: " << service_info->sync_service_type());
+      profile->service_info()->push_back(service_info);
+    }
+    if (category_list) {
+      g_list_free(category_list);
+    }
+
+    LogDebug("Adding a profile to the list.");
+    profiles->push_back(profile);
+  }
+
+  return profiles;
+}
+
+ResultOrError<void> DataSyncManager::StartSync(
+    const std::string& profile_id_str, int callback_id) {
+  ds_profile_h profile_h = nullptr;
+
+  ScopedExit exit([&profile_h]() {
+    if (profile_h) {
+      sync_agent_ds_free_profile_info(profile_h);
+    }
+  });
+
+  sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+  sync_agent_event_error_e err = SYNC_AGENT_EVENT_FAIL;
+
+  int profile_id = std::stoi(profile_id_str);
+  LogDebug("profileId: " << profile_id);
+
+  ret = sync_agent_ds_get_profile(profile_id, &profile_h);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while getting a profile");
+  }
+
+  err = sync_agent_set_noti_callback(
+      1, [](sync_agent_event_data_s* d, void* ud) {
+           return static_cast<DataSyncManager*>(ud)->StateChangedCallback(d);
+         },
+      static_cast<void*>(this));
+  if (SYNC_AGENT_EVENT_SUCCESS != err) {
+    return Error("Exception",
+        "Platform error while setting state changed cb");
+  }
+
+  err = sync_agent_set_noti_callback(
+      2, [](sync_agent_event_data_s* d, void* ud) {
+           return static_cast<DataSyncManager*>(ud)->ProgressCallback(d);
+         },
+      static_cast<void*>(this));
+  if (SYNC_AGENT_EVENT_SUCCESS != err) {
+    return Error("Exception",
+        "Platform error while setting progress cb");
+  }
+
+  ret = sync_agent_ds_start_sync(profile_h);
+  if (SYNC_AGENT_DS_SUCCESS != ret && SYNC_AGENT_DS_SYNCHRONISING != ret) {
+    return Error("Exception",
+        "Platform error while starting a profile");
+  }
+
+  if (callback_id >= 0) {
+    callbacks_.insert({profile_id, callback_id});
+  }
+
+  return {};
+}
+
+ResultOrError<void> DataSyncManager::StopSync(
+    const std::string& profile_id_str) {
+  ds_profile_h profile_h = nullptr;
+
+  ScopedExit exit([&profile_h]() {
+    if (profile_h) {
+      sync_agent_ds_free_profile_info(profile_h);
+    }
+  });
+
+  sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+  int profile_id = std::stoi(profile_id_str.c_str());
+  LogDebug("profileId: " << profile_id);
+
+  ret = sync_agent_ds_get_profile(profile_id, &profile_h);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while getting a profile");
+  }
+
+  ret = sync_agent_ds_stop_sync(profile_h);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+        "Platform error while stopping a profile");
+  }
+
+  return {};
+}
+
+ResultOrError<SyncStatisticsListPtr> DataSyncManager::GetLastSyncStatistics(
+    const std::string& profile_str_id) const {
+  ds_profile_h profile_h = nullptr;
+  GList* statistics_list = nullptr;
+
+  ScopedExit exit([&statistics_list, &profile_h]() {
+    if (statistics_list) {
+      g_list_free(statistics_list);
+    }
+
+    if (profile_h) {
+      sync_agent_ds_free_profile_info(profile_h);
+    }
+  });
+
+  SyncStatisticsListPtr statistics_list_ptr(new SyncStatisticsList());
+
+  sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+  int profile_id = std::stoi(profile_str_id);
+  LogDebug("profileId: " << profile_id);
+  ret = sync_agent_ds_get_profile(profile_id, &profile_h);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("NotFoundException",
+                            "Platform error while getting a profile");
+  }
+
+  ret = sync_agent_ds_get_sync_statistics(profile_h, &statistics_list);
+  if (SYNC_AGENT_DS_SUCCESS != ret) {
+    return Error("Exception",
+                            "Platform error while gettting sync statistics");
+  }
+
+  int statistics_count = g_list_length(statistics_list);
+  LogDebug("statistics_count: " << statistics_count);
+  sync_agent_ds_statistics_info* statistics = nullptr;
+  for (int i = 0; i < statistics_count; i++) {
+    statistics = static_cast<sync_agent_ds_statistics_info*>(
+        g_list_nth_data(statistics_list, i));
+
+    SyncStatisticsPtr statistics_ptr(new SyncStatistics());
+
+    if (0 == i) {
+      LogDebug("Statistics for contact.");
+      statistics_ptr->set_service_type(
+          ConvertToSyncServiceType(SYNC_AGENT_CONTACT));
+    } else if (1 == i) {
+      LogDebug("Statistics for event.");
+      statistics_ptr->set_service_type(
+          ConvertToSyncServiceType(SYNC_AGENT_CALENDAR));
+    } else {
+      LogWarning("Unsupported category for statistics: " << i);
+      continue;
+    }
+
+    LogDebug("dbsynced: " << statistics->dbsynced);
+    if (statistics->dbsynced) {
+      statistics_ptr->set_sync_status(
+          ConvertToSyncStatus(statistics->dbsynced));
+      statistics_ptr->set_client_to_server_total(
+          statistics->client2server_total);
+      statistics_ptr->set_client_to_server_added(
+          statistics->client2server_nrofadd);
+      statistics_ptr->set_client_to_server_updated(
+          statistics->client2server_nrofreplace);
+      statistics_ptr->set_client_to_server_removed(
+          statistics->client2server_nrofdelete);
+      statistics_ptr->set_server_to_client_total(
+          statistics->server2client_total);
+      statistics_ptr->set_server_to_client_added(
+          statistics->server2client_nrofadd);
+      statistics_ptr->set_server_to_client_updated(
+          statistics->server2client_nrofreplace);
+      statistics_ptr->set_server_to_client_removed(
+          statistics->server2client_nrofdelete);
+
+      statistics_ptr->set_last_sync_time(
+          static_cast<unsigned>(statistics->last_session_time));
+    }
+
+    LogDebug(
+        "ClientToServerTotal: " << statistics_ptr->client_to_server_total()
+                                << ", ServerToClientTotal: "
+                                << statistics_ptr->server_to_client_total());
+
+    statistics_list_ptr->push_back(statistics_ptr);
+  }
+
+  return statistics_list_ptr;
+}
+
+int DataSyncManager::StateChangedCallback(sync_agent_event_data_s* request) {
+  LogDebug("DataSync session state changed.");
+
+  char* profile_dir_name = nullptr;
+  int sync_type = 0;
+  char* progress = nullptr;
+  char* error = nullptr;
+
+  LogDebug("Get state info.");
+  sync_agent_get_event_data_param(request, &profile_dir_name);
+  sync_agent_get_event_data_param(request, &sync_type);
+  sync_agent_get_event_data_param(request, &progress);
+  sync_agent_get_event_data_param(request, &error);
+
+  LogInfo("profileDirName: " << profile_dir_name
+                             << ", sync_type: " << sync_type
+                             << ", progress: " << progress
+                             << ", error: " << error);
+
+  if (profile_dir_name) {
+    std::string profileDirNameStr(profile_dir_name);
+
+    // truncate the rest
+    profileDirNameStr.resize(4);
+    int profileId = std::stoi(profileDirNameStr);
+
+    auto it = callbacks_.find(profileId);
+    if (it != callbacks_.end()) {
+      int callback_id = it->second;
+      callbacks_.erase(it);
+
+      if (nullptr == progress) {
+        LogWarning("nullptr status.");
+        instance_.ReplyAsyncOnFailed(callback_id, profileDirNameStr,
+                                     UNKNOWN_ERR, "Exception",
+                                     "nullptr status");
+      } else if (0 == strncmp(progress, "DONE", 4)) {
+        instance_.ReplyAsyncOnCompleted(callback_id, profileDirNameStr);
+      } else if (0 == strncmp(progress, "CANCEL", 6)) {
+        instance_.ReplyAsyncOnStopped(callback_id, profileDirNameStr);
+      } else if (0 == strncmp(progress, "ERROR", 5)) {
+        instance_.ReplyAsyncOnFailed(callback_id, profileDirNameStr,
+                                     UNKNOWN_ERR, "Exception",
+                                     "Datasync failed");
+      } else {
+        LogInfo("Undefined status");
+        instance_.ReplyAsyncOnFailed(callback_id, profileDirNameStr,
+                                     UNKNOWN_ERR, "Exception",
+                                     "Undefined status");
+      }
+    }
+  }
+
+  g_free(profile_dir_name);
+  g_free(progress);
+  g_free(error);
+
+  if (request->size != nullptr) {
+    g_free(request->size);
+  }
+  g_free(request);
+
+  return 0;
+}
+
+int DataSyncManager::ProgressCallback(sync_agent_event_data_s* request) {
+  LogDebug("DataSync progress called.");
+
+  char* profile_dir_name = nullptr;
+  int sync_type = 0;
+  int uri;
+  char* progress_status = nullptr;
+  char* operation_type = nullptr;
+
+  int is_from_server, total_per_operation, synced_per_operation, total_per_db,
+      synced_per_db;
+
+  LogDebug("Get progress info.");
+  sync_agent_get_event_data_param(request, &profile_dir_name);
+  sync_agent_get_event_data_param(request, &sync_type);
+  sync_agent_get_event_data_param(request, &uri);
+  sync_agent_get_event_data_param(request, &progress_status);
+  sync_agent_get_event_data_param(request, &operation_type);
+
+  LogInfo("profileDirName: " << profile_dir_name << ", syncType: " << sync_type
+                             << ", uri: " << uri
+                             << ", progressStatus: " << progress_status
+                             << ", operationType " << operation_type);
+
+  sync_agent_get_event_data_param(request, &is_from_server);
+  sync_agent_get_event_data_param(request, &total_per_operation);
+  sync_agent_get_event_data_param(request, &synced_per_operation);
+  sync_agent_get_event_data_param(request, &total_per_db);
+  sync_agent_get_event_data_param(request, &synced_per_db);
+
+  LogInfo("isFromServer: " << is_from_server
+                           << ", totalPerOperation: " << total_per_operation
+                           << ", syncedPerOperation: " << synced_per_operation
+                           << ", totalPerDb: " << total_per_db
+                           << ", syncedPerDb " << synced_per_db);
+
+  if (profile_dir_name) {
+    std::string profile_dir_name_str(profile_dir_name);
+    profile_dir_name_str.resize(4);
+    int profile_id = std::stoi(profile_dir_name_str);
+
+    auto it = callbacks_.find(profile_id);
+    if (it != callbacks_.end()) {
+      int callback_id = it->second;
+
+      if (SYNC_AGENT_SRC_URI_CONTACT == uri) {
+        instance_.ReplyAsyncOnProgress(callback_id, profile_dir_name_str,
+                                       is_from_server, synced_per_db,
+                                       total_per_db,
+                                       SyncServiceInfo::CONTACT_SERVICE_TYPE);
+      } else if (SYNC_AGENT_SRC_URI_CALENDAR == uri) {
+        instance_.ReplyAsyncOnProgress(callback_id, profile_dir_name_str,
+                                       is_from_server, synced_per_db,
+                                       total_per_db,
+                                       SyncServiceInfo::EVENT_SERVICE_TYPE);
+      } else {
+        LogWarning("Wrong service type");
+        instance_.ReplyAsyncOnFailed(callback_id, profile_dir_name_str,
+                                     UNKNOWN_ERR, "Exception",
+                                     "Wrong service type");
+      }
+    }
+  }
+
+  g_free(profile_dir_name);
+  g_free(progress_status);
+  g_free(operation_type);
+
+  if (request != nullptr) {
+    if (request->size != nullptr) {
+      g_free(request->size);
+    }
+    g_free(request);
+  }
+
+  return 0;
+}
+
+}  // namespace datasync
diff --git a/datasync/datasync_manager.h b/datasync/datasync_manager.h
new file mode 100644 (file)
index 0000000..b025e0f
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright (c) 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.
+
+#ifndef DATASYNC_DATASYNC_MANAGER_H_
+#define DATASYNC_DATASYNC_MANAGER_H_
+
+#include <sync_agent.h>
+
+#include <map>
+#include <string>
+
+#include "common/utils.h"
+#include "datasync/datasync_error.h"
+#include "datasync/sync_profile_info.h"
+#include "datasync/sync_statistics.h"
+
+namespace datasync {
+
+class DatasyncInstance;
+
+class DataSyncManager {
+ public:
+  typedef std::map<int, int> ProfileIdToCallbackIdMap;
+
+  explicit DataSyncManager(DatasyncInstance& parent);
+  ~DataSyncManager();
+
+  ResultOrError<std::string> Add(SyncProfileInfo& profile_info);
+  ResultOrError<void> Update(SyncProfileInfo& profile_info);
+  ResultOrError<void> Remove(const std::string& id);
+
+  ResultOrError<unsigned> GetMaxProfilesNum() const;
+  ResultOrError<unsigned> GetProfilesNum() const;
+
+  ResultOrError<SyncProfileInfoPtr> Get(
+      const std::string& profile_id) const;
+  ResultOrError<SyncProfileInfoListPtr> GetAll() const;
+  ResultOrError<SyncStatisticsListPtr> GetLastSyncStatistics(
+      const std::string& profile_str_id) const;
+
+  ResultOrError<void> StartSync(
+      const std::string& profile_id_str, int callback_id);
+  ResultOrError<void> StopSync(const std::string& profile_id_str);
+
+ private:
+  int StateChangedCallback(sync_agent_event_data_s* request);
+  int ProgressCallback(sync_agent_event_data_s* request);
+
+  DatasyncInstance& instance_;
+  ProfileIdToCallbackIdMap callbacks_;
+
+  static bool sync_agent_initialized_;
+
+  DISALLOW_COPY_AND_ASSIGN(DataSyncManager);
+};
+
+}  // namespace datasync
+
+#endif  // DATASYNC_DATASYNC_MANAGER_H_
diff --git a/datasync/datasync_scoped_exit.h b/datasync/datasync_scoped_exit.h
new file mode 100644 (file)
index 0000000..48f9b8c
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (c) 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.
+
+#ifndef DATASYNC_DATASYNC_SCOPED_EXIT_H_
+#define DATASYNC_DATASYNC_SCOPED_EXIT_H_
+
+#include <functional>
+
+namespace datasync {
+
+class ScopedExit {
+ public:
+  explicit ScopedExit(std::function<void()> func) : func_(func) { }
+  ~ScopedExit() { func_(); }
+ private:
+  std::function<void()> func_;
+};
+
+}  // namespace datasync
+
+#endif  // DATASYNC_DATASYNC_SCOPED_EXIT_H_
diff --git a/datasync/datasync_serialization.h b/datasync/datasync_serialization.h
new file mode 100644 (file)
index 0000000..04fd336
--- /dev/null
@@ -0,0 +1,478 @@
+// Copyright (c) 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.
+
+#ifndef DATASYNC_DATASYNC_SERIALIZATION_H_
+#define DATASYNC_DATASYNC_SERIALIZATION_H_
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include "common/picojson.h"
+
+#include "datasync/sync_info.h"
+#include "datasync/sync_profile_info.h"
+#include "datasync/sync_service_info.h"
+#include "datasync/sync_statistics.h"
+
+namespace datasync {
+namespace serialization {
+namespace detail {
+
+enum class ConvResult {
+  SUCCESS,
+  MISSING,
+  ERROR
+};
+
+// picojson does not accepts int in value construction
+template <class Type>
+struct ConvertToPicojsonType {
+  typedef Type AccessType;
+  typedef Type ConstructType;
+};
+
+template <>
+struct ConvertToPicojsonType<unsigned> {
+  typedef int AccessType;
+  typedef double ConstructType;
+};
+
+template <>
+struct ConvertToPicojsonType<int> {
+  typedef int AccessType;
+  typedef double ConstructType;
+};
+
+/**
+ * Gets member 'field' field for given 'obj' object.
+ *
+ * Template parameter T of type of field to be extracted.
+ */
+template <class T>
+ConvResult GetMember(const picojson::object& obj, const char* field, T* out) {
+  const auto& it = obj.find(field);
+  if (it != obj.end()) {
+    if (it->second.is<typename ConvertToPicojsonType<T>::AccessType>()) {
+      *out = it->second.get<typename ConvertToPicojsonType<T>::AccessType>();
+      return ConvResult::SUCCESS;
+    } else {
+      return ConvResult::ERROR;
+    }
+  } else {
+    return ConvResult::MISSING;
+  }
+}
+
+/**
+ * Gets member 'field' field for given 'obj' object and converts value to
+ * expected type T using adapter functor.
+ *
+ * Template parameter T states for type of target type of extracted field
+ * Template parameter A states for type of type of extracted field received
+ * from picojson.
+ * Template parameter Adapter states for functor type converting A to T type
+ */
+template <class T, class A, class Adapter>
+ConvResult GetMember(const picojson::object& obj, const char* field,
+    const Adapter& adapter, T* out) {
+  const auto& it = obj.find(field);
+  if (it != obj.end()) {
+    const auto& fld = it->second;
+    if (fld.is<typename ConvertToPicojsonType<A>::AccessType>()) {
+      *out = adapter(fld.get<typename ConvertToPicojsonType<A>::AccessType>());
+      return ConvResult::SUCCESS;
+    } else {
+      return ConvResult::ERROR;
+    }
+  } else {
+    return ConvResult::MISSING;
+  }
+}
+
+}  // namespace detail
+
+template <class T>
+struct SerializationDefinition {
+  static picojson::value ToJson(const T& type) {
+    return picojson::value(
+        static_cast<typename detail::ConvertToPicojsonType<T>::ConstructType>(
+            type));
+  }
+
+  static std::unique_ptr<T> FromJson(const picojson::value& value) {
+    if (value.is<typename detail::ConvertToPicojsonType<T>::AccessType>()) {
+      return std::unique_ptr<T>(new T(
+          value.get<typename detail::ConvertToPicojsonType<T>::AccessType>()));
+    } else {
+      return nullptr;
+    }
+  }
+};
+
+template <>
+struct SerializationDefinition<SyncStatistics> {
+  static picojson::value ToJson(const SyncStatistics& type) {
+    picojson::object obj;
+    obj["syncStatus"] = picojson::value(
+        SyncStatistics::SyncStatusToString(type.sync_status()));
+    obj["serviceType"] = picojson::value(
+        SyncServiceInfo::SyncServiceTypeToString(type.service_type()));
+    obj["lastSyncTime"] =
+        picojson::value(static_cast<double>(type.last_sync_time()));
+
+    obj["serverToClientTotal"] =
+        picojson::value(static_cast<double>(type.server_to_client_total()));
+    obj["serverToClientAdded"] =
+        picojson::value(static_cast<double>(type.server_to_client_added()));
+    obj["serverToClientUpdated"] =
+        picojson::value(static_cast<double>(type.server_to_client_updated()));
+    obj["serverToClientRemoved"] =
+        picojson::value(static_cast<double>(type.server_to_client_removed()));
+
+    obj["clientToServerTotal"] =
+        picojson::value(static_cast<double>(type.client_to_server_total()));
+    obj["clientToServerAdded"] =
+        picojson::value(static_cast<double>(type.client_to_server_added()));
+    obj["clientToServerUpdated"] =
+        picojson::value(static_cast<double>(type.client_to_server_updated()));
+    obj["clientToServerRemoved"] =
+        picojson::value(static_cast<double>(type.client_to_server_removed()));
+
+    return picojson::value(obj);
+  }
+
+  static std::unique_ptr<SyncStatistics> FromJson(
+      const picojson::value& value) {
+    std::unique_ptr<SyncStatistics> result;
+
+    if (!value.is<picojson::object>()) {
+      return nullptr;
+    }
+    const picojson::object& obj = value.get<picojson::object>();
+
+    SyncStatistics::SyncStatus sync_status;
+    if (detail::GetMember<SyncStatistics::SyncStatus, std::string>(
+        obj, "syncStatus",
+        std::bind(SyncStatistics::ConvertToSyncStatus, std::placeholders::_1),
+        &sync_status)
+        != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    SyncServiceInfo::SyncServiceType sync_service_type;
+    if (detail::GetMember<SyncServiceInfo::SyncServiceType, std::string>(
+        obj, "syncServiceType",
+        std::bind(SyncServiceInfo::ConvertToSyncServiceType,
+            std::placeholders::_1),
+        &sync_service_type) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    unsigned last_sync_time;
+    if (detail::GetMember(obj, "lastSyncTime",
+        &last_sync_time) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    unsigned server_to_client_total;
+    if (detail::GetMember(obj, "serverToClientTotal",
+        &server_to_client_total) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    unsigned server_to_client_added;
+    if (detail::GetMember(obj, "serverToClientAdded",
+        &server_to_client_added) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    unsigned server_to_client_updated;
+    if (detail::GetMember(obj, "serverToClientUpdated",
+        &server_to_client_updated) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    unsigned server_to_client_removed;
+    if (detail::GetMember(obj, "serverToClientRemoved",
+        &server_to_client_removed) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    unsigned client_to_server_total;
+    if (detail::GetMember(obj, "clientToServerTotal",
+        &client_to_server_total) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    unsigned client_to_server_added;
+    if (detail::GetMember(obj, "clientToServerAdded",
+        &client_to_server_added) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    unsigned client_to_server_updated;
+    if (detail::GetMember(obj, "clientToServerUpdated",
+        &client_to_server_updated) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    unsigned client_to_server_removed;
+    if (detail::GetMember(obj, "clientToServerRemoved",
+        &client_to_server_removed) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    result.reset(new SyncStatistics(
+        sync_status, sync_service_type, last_sync_time,
+        server_to_client_total, server_to_client_added,
+        server_to_client_updated, server_to_client_removed,
+        client_to_server_total, client_to_server_added,
+        client_to_server_updated, client_to_server_removed));
+
+    return result;
+  }
+};
+
+template <>
+struct SerializationDefinition<SyncServiceInfo> {
+  static picojson::value ToJson(const SyncServiceInfo& type) {
+    picojson::object obj;
+    obj["enable"] = picojson::value(type.enable());
+    obj["serviceType"] = picojson::value(
+        SyncServiceInfo::SyncServiceTypeToString(type.sync_service_type()));
+    obj["serverDatabaseUri"] = picojson::value(type.server_database_uri());
+
+    std::string id = type.id();
+    if (!id.empty()) {
+      obj["id"] = picojson::value(id);
+    }
+
+    std::string password = type.password();
+    if (!password.empty()) {
+      obj["password"] = picojson::value(password);
+    }
+
+    return picojson::value(obj);
+  }
+
+  static std::unique_ptr<SyncServiceInfo> FromJson(
+      const picojson::value& value) {
+    if (!value.is<picojson::object>()) {
+      return nullptr;
+    }
+    const picojson::object& obj = value.get<picojson::object>();
+
+    bool enable;
+    if (detail::GetMember(obj, "enable",
+        &enable) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    SyncServiceInfo::SyncServiceType serviceType;
+    if (detail::GetMember<SyncServiceInfo::SyncServiceType, std::string>(
+        obj, "serviceType",
+        std::bind(&SyncServiceInfo::ConvertToSyncServiceType,
+            std::placeholders::_1),
+        &serviceType) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    std::string serverDatabaseUri;
+    if (detail::GetMember(obj, "serverDatabaseUri",
+        &serverDatabaseUri) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    std::string id;
+    std::string password;
+    detail::GetMember(obj, "id", &id);
+    detail::GetMember(obj, "password", &password);
+
+    std::unique_ptr<SyncServiceInfo> result(
+        new SyncServiceInfo(enable,
+                            serviceType,
+                            serverDatabaseUri,
+                            id,
+                            password));
+    return result;
+  }
+};
+
+template <>
+struct SerializationDefinition<SyncInfo> {
+  static picojson::value ToJson(const SyncInfo& type) {
+    picojson::object obj;
+    obj["url"] = picojson::value(type.url());
+    obj["id"] = picojson::value(type.id());
+    obj["password"] = picojson::value(type.password());
+
+    SyncInfo::SyncMode mode = type.sync_mode();
+
+    obj["mode"] = picojson::value(SyncInfo::SyncModeToString(mode));
+
+    if (mode == SyncInfo::MANUAL_MODE) {
+      obj["type"] =
+          picojson::value(SyncInfo::SyncTypeToString(type.sync_type()));
+    } else if (mode == SyncInfo::PERIODIC_MODE) {
+      obj["interval"] = picojson::value(
+          SyncInfo::SyncIntervalToString(type.sync_interval()));
+    }
+
+    return picojson::value(obj);
+  }
+
+  static std::unique_ptr<SyncInfo> FromJson(const picojson::value& value) {
+    if (!value.is<picojson::object>()) {
+      return nullptr;
+    }
+    const picojson::object& obj = value.get<picojson::object>();
+
+    std::string url;
+    if (detail::GetMember(obj, "url",
+        &url) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    std::string id;
+    if (detail::GetMember(obj, "id",
+        &id) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    std::string password;
+    if (detail::GetMember(obj, "password",
+        &password) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    SyncInfo::SyncMode mode;
+    if (detail::GetMember<SyncInfo::SyncMode, std::string>(
+        obj, "mode",
+        std::bind(SyncInfo::ConvertToSyncMode, std::placeholders::_1),
+        &mode) != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    std::unique_ptr<SyncInfo> result;
+    if (mode == SyncInfo::MANUAL_MODE) {
+      SyncInfo::SyncType type;
+      detail::ConvResult res =
+          detail::GetMember<SyncInfo::SyncType, std::string>(
+            obj, "type",
+            std::bind(SyncInfo::ConvertToSyncType, std::placeholders::_1),
+            &type);
+
+      if (res == detail::ConvResult::ERROR) {
+        return nullptr;
+      } else if (res == detail::ConvResult::SUCCESS) {
+        result.reset(new SyncInfo(url, id, password, mode, type,
+                                  SyncInfo::INTERVAL_UNDEFINED));
+      } else {
+        result.reset(new SyncInfo(url, id, password, mode,
+                                  SyncInfo::UNDEFINED_TYPE,
+                                  SyncInfo::INTERVAL_UNDEFINED));
+      }
+    } else if (mode == SyncInfo::PERIODIC_MODE) {
+      SyncInfo::SyncInterval interval;
+      detail::ConvResult res =
+          detail::GetMember<SyncInfo::SyncInterval, std::string>(
+              obj, "interval",
+              std::bind(SyncInfo::ConvertToSyncInterval,
+                  std::placeholders::_1),
+              &interval);
+
+      if (res == detail::ConvResult::ERROR) {
+        return nullptr;
+      } else if (res == detail::ConvResult::SUCCESS) {
+        result.reset(new SyncInfo(url, id, password, mode,
+                                  SyncInfo::UNDEFINED_TYPE, interval));
+      } else {
+        result.reset(new SyncInfo(url, id, password, mode,
+                                  SyncInfo::UNDEFINED_TYPE,
+                                  SyncInfo::INTERVAL_UNDEFINED));
+      }
+    } else {
+      result.reset(new SyncInfo(url, id, password, mode,
+                                SyncInfo::UNDEFINED_TYPE,
+                                SyncInfo::INTERVAL_UNDEFINED));
+    }
+
+    return result;
+  }
+};
+
+template <>
+struct SerializationDefinition<SyncProfileInfo> {
+  static picojson::value ToJson(const SyncProfileInfo& type) {
+    picojson::object obj;
+    obj["profileId"] = picojson::value(type.profile_id());
+    obj["profileName"] = picojson::value(type.profile_name());
+    obj["syncInfo"] =
+        SerializationDefinition<SyncInfo>::ToJson(*type.sync_info());
+
+    picojson::array array;
+    for (const auto& element : *type.service_info()) {
+      array.push_back(
+          SerializationDefinition<SyncServiceInfo>::ToJson(*element));
+    }
+
+    if (array.empty()) {
+      obj["serviceInfo"] = picojson::value();
+    } else {
+      obj["serviceInfo"] = picojson::value(array);
+    }
+
+    return picojson::value(obj);
+  }
+
+  static std::unique_ptr<SyncProfileInfo> FromJson(
+      const picojson::value& value) {
+    std::unique_ptr<SyncProfileInfo> result;
+
+    if (!value.is<picojson::object>()) {
+      return nullptr;
+    }
+    const picojson::object& obj = value.get<picojson::object>();
+
+    std::string profileName;
+    if (detail::GetMember(obj, "profileName", &profileName)
+        != detail::ConvResult::SUCCESS)
+      return nullptr;
+
+    auto syncInfoIt = obj.find("syncInfo");
+    if (syncInfoIt == obj.end()) {
+      return nullptr;
+    }
+    std::unique_ptr<SyncInfo> syncInfo =
+        SerializationDefinition<SyncInfo>::FromJson(syncInfoIt->second);
+    if (!syncInfo) {
+      return nullptr;
+    }
+
+    SyncServiceInfoListPtr serviceList =
+        std::make_shared<SyncServiceInfoList>();
+
+    auto serviceInfoIt = obj.find("serviceInfo");
+    if (serviceInfoIt == obj.end()) {
+      return nullptr;
+    }
+    if (serviceInfoIt->second.is<picojson::array>()) {
+      const picojson::array& array =
+          serviceInfoIt->second.get<picojson::array>();
+      for (const auto& element : array) {
+        serviceList->push_back(SyncServiceInfoPtr(
+            SerializationDefinition<SyncServiceInfo>::FromJson(element)
+            .release()));
+      }
+    } else if (!serviceInfoIt->second.is<picojson::null>()) {
+      return nullptr;
+    }
+
+    std::string profileId;
+    detail::GetMember(obj, "profileId", &profileId);
+
+    result.reset(new SyncProfileInfo(profileId, profileName,
+                                     SyncInfoPtr(syncInfo.release()),
+                                     serviceList));
+    return result;
+  }
+};
+
+template <class T>
+picojson::value ToJson(const T& type) {
+  return SerializationDefinition<T>::ToJson(type);
+}
+
+template <class T>
+std::unique_ptr<T> FromJson(const picojson::value& value) {
+  return SerializationDefinition<T>::FromJson(value);
+}
+
+}  // namespace serialization
+}  // namespace datasync
+
+#endif  // DATASYNC_DATASYNC_SERIALIZATION_H_
diff --git a/datasync/sync_info.cc b/datasync/sync_info.cc
new file mode 100644 (file)
index 0000000..f1591cc
--- /dev/null
@@ -0,0 +1,169 @@
+// Copyright (c) 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.
+
+#include "datasync/sync_info.h"
+
+namespace datasync {
+
+std::string SyncInfo::SyncModeToString(SyncMode mode) {
+  switch (mode) {
+    case MANUAL_MODE:
+      return "MANUAL";
+    case PERIODIC_MODE:
+      return "PERIODIC";
+    case PUSH_MODE:
+      return "PUSH";
+    default:
+      return "";
+  }
+}
+
+std::string SyncInfo::SyncTypeToString(SyncType type) {
+  switch (type) {
+    case TWO_WAY_TYPE:
+      return "TWO_WAY";
+    case SLOW_TYPE:
+      return "SLOW";
+    case ONE_WAY_FROM_CLIENT_TYPE:
+      return "ONE_WAY_FROM_CLIENT";
+    case REFRESH_FROM_CLIENT_TYPE:
+      return "REFRESH_FROM_CLIENT";
+    case ONE_WAY_FROM_SERVER_TYPE:
+      return "ONE_WAY_FROM_SERVER";
+    case REFRESH_FROM_SERVER_TYPE:
+      return "REFRESH_FROM_SERVER";
+    default:
+      return "";
+  }
+}
+
+std::string SyncInfo::SyncIntervalToString(SyncInterval interval) {
+  switch (interval) {
+    case INTERVAL_5_MINUTES:
+      return "5_MINUTES";
+    case INTERVAL_15_MINUTES:
+      return "15_MINUTES";
+    case INTERVAL_1_HOUR:
+      return "1_HOUR";
+    case INTERVAL_4_HOURS:
+      return "4_HOURS";
+    case INTERVAL_12_HOURS:
+      return "12_HOURS";
+    case INTERVAL_1_DAY:
+      return "1_DAY";
+    case INTERVAL_1_WEEK:
+      return "1_WEEK";
+    case INTERVAL_1_MONTH:
+      return "1_MONTH";
+    default:
+      return "";
+  }
+}
+
+SyncInfo::SyncMode SyncInfo::ConvertToSyncMode(const std::string& str) {
+  if (str == "MANUAL") {
+    return MANUAL_MODE;
+  } else if (str == "PERIODIC") {
+    return PERIODIC_MODE;
+  } else if (str == "PUSH") {
+    return PUSH_MODE;
+  } else {
+    return UNDEFINED_MODE;
+  }
+}
+
+SyncInfo::SyncType SyncInfo::ConvertToSyncType(const std::string& str) {
+  if (str == "TWO_WAY") {
+    return TWO_WAY_TYPE;
+  } else if (str == "SLOW") {
+    return SLOW_TYPE;
+  } else if (str == "ONE_WAY_FROM_CLIENT") {
+    return ONE_WAY_FROM_CLIENT_TYPE;
+  } else if (str == "REFRESH_FROM_CLIENT") {
+    return REFRESH_FROM_CLIENT_TYPE;
+  } else if (str == "ONE_WAY_FROM_SERVER") {
+    return ONE_WAY_FROM_SERVER_TYPE;
+  } else if (str == "REFRESH_FROM_SERVER") {
+    return REFRESH_FROM_SERVER_TYPE;
+  } else {
+    return UNDEFINED_TYPE;
+  }
+}
+
+SyncInfo::SyncInterval SyncInfo::ConvertToSyncInterval(const std::string& str) {
+  if (str == "5_MINUTES") {
+    return INTERVAL_5_MINUTES;
+  } else if (str == "15_MINUTES") {
+    return INTERVAL_15_MINUTES;
+  } else if (str == "1_HOUR") {
+    return INTERVAL_1_HOUR;
+  } else if (str == "4_HOURS") {
+    return INTERVAL_4_HOURS;
+  } else if (str == "12_HOURS") {
+    return INTERVAL_12_HOURS;
+  } else if (str == "1_DAY") {
+    return INTERVAL_1_DAY;
+  } else if (str == "1_WEEK") {
+    return INTERVAL_1_WEEK;
+  } else if (str == "1_MONTH") {
+    return INTERVAL_1_MONTH;
+  } else {
+    return INTERVAL_UNDEFINED;
+  }
+}
+
+SyncInfo::SyncInfo()
+    : sync_mode_(UNDEFINED_MODE),
+      sync_type_(UNDEFINED_TYPE),
+      sync_interval_(INTERVAL_UNDEFINED) {
+}
+
+SyncInfo::SyncInfo(std::string url, std::string id, std::string password,
+    SyncMode sync_mode, SyncType sync_type,
+    SyncInterval sync_interval)
+    : url_(url),
+      id_(id),
+      password_(password),
+      sync_mode_(sync_mode),
+      sync_type_(sync_type),
+      sync_interval_(sync_interval) {
+}
+
+SyncInfo::~SyncInfo() {}
+
+std::string SyncInfo::url() const { return url_; }
+
+void SyncInfo::set_url(const std::string& url) { url_ = url; }
+
+std::string SyncInfo::id() const { return id_; }
+
+void SyncInfo::set_id(const std::string& id) { id_ = id; }
+
+std::string SyncInfo::password() const { return password_; }
+
+void SyncInfo::set_password(const std::string& password) {
+  password_ = password;
+}
+
+SyncInfo::SyncMode SyncInfo::sync_mode() const { return sync_mode_; }
+
+void SyncInfo::set_sync_mode(SyncInfo::SyncMode syncMode) {
+  sync_mode_ = syncMode;
+}
+
+SyncInfo::SyncType SyncInfo::sync_type() const { return sync_type_; }
+
+void SyncInfo::set_sync_type(SyncInfo::SyncType syncType) {
+  sync_type_ = syncType;
+}
+
+SyncInfo::SyncInterval SyncInfo::sync_interval() const {
+  return sync_interval_;
+}
+
+void SyncInfo::set_sync_interval(SyncInfo::SyncInterval syncInterval) {
+  sync_interval_ = syncInterval;
+}
+
+}  // namespace datasync
diff --git a/datasync/sync_info.h b/datasync/sync_info.h
new file mode 100644 (file)
index 0000000..eb84c3d
--- /dev/null
@@ -0,0 +1,91 @@
+// Copyright (c) 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.
+
+#ifndef DATASYNC_SYNC_INFO_H_
+#define DATASYNC_SYNC_INFO_H_
+
+#include <memory>
+#include <string>
+
+namespace datasync {
+
+/**
+ * Representation of SyncInfo JS type
+ */
+class SyncInfo {
+ public:
+  typedef enum {
+    MANUAL_MODE,
+    PERIODIC_MODE,
+    PUSH_MODE,
+    UNDEFINED_MODE
+  } SyncMode;
+
+  typedef enum {
+    TWO_WAY_TYPE,
+    SLOW_TYPE,
+    ONE_WAY_FROM_CLIENT_TYPE,
+    REFRESH_FROM_CLIENT_TYPE,
+    ONE_WAY_FROM_SERVER_TYPE,
+    REFRESH_FROM_SERVER_TYPE,
+    UNDEFINED_TYPE
+  } SyncType;
+
+  typedef enum {
+    INTERVAL_5_MINUTES,
+    INTERVAL_15_MINUTES,
+    INTERVAL_1_HOUR,
+    INTERVAL_4_HOURS,
+    INTERVAL_12_HOURS,
+    INTERVAL_1_DAY,
+    INTERVAL_1_WEEK,
+    INTERVAL_1_MONTH,
+    INTERVAL_UNDEFINED
+  } SyncInterval;
+
+  static std::string SyncModeToString(SyncMode mode);
+  static std::string SyncTypeToString(SyncType type);
+  static std::string SyncIntervalToString(SyncInterval interval);
+
+  static SyncMode ConvertToSyncMode(const std::string& str);
+  static SyncType ConvertToSyncType(const std::string& str);
+  static SyncInterval ConvertToSyncInterval(const std::string& str);
+
+  SyncInfo();
+  SyncInfo(std::string url, std::string id, std::string password,
+           SyncMode sync_mode, SyncType sync_type, SyncInterval sync_interval);
+  virtual ~SyncInfo();
+
+  std::string url() const;
+  void set_url(const std::string& value);
+
+  std::string id() const;
+  void set_id(const std::string& value);
+
+  std::string password() const;
+  void set_password(const std::string& value);
+
+  SyncMode sync_mode() const;
+  void set_sync_mode(SyncMode value);
+
+  SyncType sync_type() const;
+  void set_sync_type(SyncType value);
+
+  SyncInterval sync_interval() const;
+  void set_sync_interval(SyncInterval value);
+
+ protected:
+  std::string url_;
+  std::string id_;
+  std::string password_;
+  SyncMode sync_mode_;
+  SyncType sync_type_;
+  SyncInterval sync_interval_;
+};
+
+typedef std::shared_ptr<SyncInfo> SyncInfoPtr;
+
+}  // namespace datasync
+
+#endif  // DATASYNC_SYNC_INFO_H_
diff --git a/datasync/sync_profile_info.cc b/datasync/sync_profile_info.cc
new file mode 100644 (file)
index 0000000..30bd779
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (c) 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.
+
+#include "datasync/sync_profile_info.h"
+
+namespace datasync {
+
+SyncProfileInfo::SyncProfileInfo()
+    : sync_info_(new SyncInfo()),
+      service_info_(new SyncServiceInfoList()) {
+}
+
+SyncProfileInfo::SyncProfileInfo(const std::string& profileId,
+    const std::string& profile_name,
+    SyncInfoPtr sync_info,
+    SyncServiceInfoListPtr service_info)
+    : profile_id_(profileId),
+      profile_name_(profile_name),
+      sync_info_(sync_info),
+      service_info_(service_info) {
+}
+
+std::string SyncProfileInfo::profile_id() const { return profile_id_; }
+
+void SyncProfileInfo::set_profile_id(const std::string &profileId) {
+  profile_id_ = profileId;
+}
+
+std::string SyncProfileInfo::profile_name() const { return profile_name_; }
+
+void SyncProfileInfo::set_profile_name(const std::string &profileName) {
+  profile_name_ = profileName;
+}
+
+SyncInfoPtr SyncProfileInfo::sync_info() const { return sync_info_; }
+
+void SyncProfileInfo::set_sync_info(SyncInfoPtr syncInfo) {
+  sync_info_ = syncInfo;
+}
+
+SyncServiceInfoListPtr SyncProfileInfo::service_info() const {
+  return service_info_;
+}
+
+void SyncProfileInfo::set_service_info(SyncServiceInfoListPtr serviceInfo) {
+  service_info_ = serviceInfo;
+}
+
+}  // namespace datasync
diff --git a/datasync/sync_profile_info.h b/datasync/sync_profile_info.h
new file mode 100644 (file)
index 0000000..6daba34
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (c) 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.
+
+#ifndef DATASYNC_SYNC_PROFILE_INFO_H_
+#define DATASYNC_SYNC_PROFILE_INFO_H_
+
+#include <string>
+#include <vector>
+
+#include "datasync/sync_info.h"
+#include "datasync/sync_service_info.h"
+
+namespace datasync {
+
+/**
+ * Representation of SyncProfileInfo JS type
+ */
+class SyncProfileInfo {
+ public:
+  SyncProfileInfo();
+  SyncProfileInfo(const std::string& profileId, const std::string& profile_name,
+                  SyncInfoPtr sync_info, SyncServiceInfoListPtr service_info);
+
+  std::string profile_id() const;
+  void set_profile_id(const std::string &value);
+
+  std::string profile_name() const;
+  void set_profile_name(const std::string &value);
+
+  SyncInfoPtr sync_info() const;
+  void set_sync_info(SyncInfoPtr value);
+
+  SyncServiceInfoListPtr service_info() const;
+  void set_service_info(SyncServiceInfoListPtr value);
+
+ protected:
+  std::string profile_id_;
+  std::string profile_name_;
+  SyncInfoPtr sync_info_;
+  SyncServiceInfoListPtr service_info_;
+};
+
+typedef std::shared_ptr<SyncProfileInfo> SyncProfileInfoPtr;
+typedef std::vector<SyncProfileInfoPtr> SyncProfileInfoList;
+typedef std::shared_ptr<SyncProfileInfoList> SyncProfileInfoListPtr;
+
+}  // namespace datasync
+
+#endif  // DATASYNC_SYNC_PROFILE_INFO_H_
diff --git a/datasync/sync_service_info.cc b/datasync/sync_service_info.cc
new file mode 100644 (file)
index 0000000..8be9743
--- /dev/null
@@ -0,0 +1,79 @@
+// Copyright (c) 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.
+
+#include "datasync/sync_service_info.h"
+
+namespace datasync {
+
+SyncServiceInfo::SyncServiceType SyncServiceInfo::ConvertToSyncServiceType(
+    const std::string &type) {
+  if (type == "CONTACT") {
+    return CONTACT_SERVICE_TYPE;
+  } else if (type == "EVENT") {
+    return EVENT_SERVICE_TYPE;
+  } else {
+    return INVALID;
+  }
+}
+
+std::string SyncServiceInfo::SyncServiceTypeToString(SyncServiceType type) {
+  switch (type) {
+    case CONTACT_SERVICE_TYPE:
+      return "CONTACT";
+    case EVENT_SERVICE_TYPE:
+      return "EVENT";
+    default:
+      return "";
+  }
+}
+
+SyncServiceInfo::SyncServiceInfo()
+    : enable_(true),
+      sync_service_type_(UNDEFINED_SERVICE_TYPE) {
+}
+
+SyncServiceInfo::SyncServiceInfo(bool enable,
+    SyncServiceType sync_service_type,
+    std::string server_database_uri,
+    std::string id,
+    std::string password)
+    : enable_(enable),
+      sync_service_type_(sync_service_type),
+      server_database_uri_(server_database_uri),
+      id_(id),
+      password_(password) {
+}
+
+bool SyncServiceInfo::enable() const { return enable_; }
+
+void SyncServiceInfo::set_enable(bool enable) { enable_ = enable; }
+
+SyncServiceInfo::SyncServiceType SyncServiceInfo::sync_service_type() const {
+  return sync_service_type_;
+}
+
+void SyncServiceInfo::set_sync_service_type(
+    SyncServiceInfo::SyncServiceType syncServiceType) {
+  sync_service_type_ = syncServiceType;
+}
+
+std::string SyncServiceInfo::server_database_uri() const {
+  return server_database_uri_;
+}
+
+void SyncServiceInfo::set_server_database_uri(const std::string &uri) {
+  server_database_uri_ = uri;
+}
+
+std::string SyncServiceInfo::id() const { return id_; }
+
+void SyncServiceInfo::set_id(const std::string &id) { id_ = id; }
+
+std::string SyncServiceInfo::password() const { return password_; }
+
+void SyncServiceInfo::set_password(const std::string &password) {
+  password_ = password;
+}
+
+}  // namespace datasync
diff --git a/datasync/sync_service_info.h b/datasync/sync_service_info.h
new file mode 100644 (file)
index 0000000..ca98875
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright (c) 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.
+
+#ifndef DATASYNC_SYNC_SERVICE_INFO_H_
+#define DATASYNC_SYNC_SERVICE_INFO_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace datasync {
+
+/**
+ * Representation of SyncServiceInfo JS type
+ */
+class SyncServiceInfo {
+ public:
+  typedef enum {
+    CONTACT_SERVICE_TYPE,
+    EVENT_SERVICE_TYPE,
+    UNDEFINED_SERVICE_TYPE,
+    INVALID
+  } SyncServiceType;
+
+  static SyncServiceType ConvertToSyncServiceType(const std::string &type);
+  static std::string SyncServiceTypeToString(SyncServiceType type);
+
+  SyncServiceInfo();
+  SyncServiceInfo(bool enable, SyncServiceType sync_service_type,
+                  std::string server_database_uri, std::string id,
+                  std::string password);
+
+  bool enable() const;
+  void set_enable(bool value);
+
+  SyncServiceType sync_service_type() const;
+  void set_sync_service_type(SyncServiceType value);
+
+  std::string server_database_uri() const;
+  void set_server_database_uri(const std::string &value);
+
+  std::string id() const;
+  void set_id(const std::string &value);
+
+  std::string password() const;
+  void set_password(const std::string &value);
+
+ protected:
+  bool enable_;
+  SyncServiceType sync_service_type_;
+  std::string server_database_uri_;
+  std::string id_;
+  std::string password_;
+};
+
+typedef std::shared_ptr<SyncServiceInfo> SyncServiceInfoPtr;
+typedef std::vector<SyncServiceInfoPtr> SyncServiceInfoList;
+typedef std::shared_ptr<SyncServiceInfoList> SyncServiceInfoListPtr;
+
+}  // namespace datasync
+
+#endif  // DATASYNC_SYNC_SERVICE_INFO_H_
diff --git a/datasync/sync_statistics.cc b/datasync/sync_statistics.cc
new file mode 100644 (file)
index 0000000..fffbdef
--- /dev/null
@@ -0,0 +1,166 @@
+// Copyright (c) 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.
+
+#include "datasync/sync_statistics.h"
+
+namespace {
+
+const int kUndefinedTime = -1;
+
+}
+
+namespace datasync {
+
+SyncStatistics::SyncStatus SyncStatistics::ConvertToSyncStatus(
+    const std::string& status) {
+  if (status == "SUCCESS") {
+    return SUCCESS_STATUS;
+  } else if (status == "FAIL") {
+    return FAIL_STATUS;
+  } else if (status == "STOP") {
+    return STOP_STATUS;
+  } else if (status == "NONE") {
+    return NONE_STATUS;
+  } else {
+    return INVALID;
+  }
+}
+
+std::string SyncStatistics::SyncStatusToString(SyncStatus status) {
+  switch (status) {
+    case SUCCESS_STATUS:
+      return "SUCCESS";
+    case FAIL_STATUS:
+      return "FAIL";
+    case STOP_STATUS:
+      return "STOP";
+    case NONE_STATUS:
+      return "NONE";
+    default:
+      return "";
+  }
+}
+
+SyncStatistics::SyncStatistics()
+    : sync_status_(NONE_STATUS),
+      service_type_(SyncServiceInfo::UNDEFINED_SERVICE_TYPE),
+      last_sync_time_(kUndefinedTime),
+      server_to_client_total_(0),
+      server_to_client_added_(0),
+      server_to_client_updated_(0),
+      server_to_client_removed_(0),
+      client_to_server_total_(0),
+      client_to_server_added_(0),
+      client_to_server_updated_(0),
+      client_to_server_removed_(0) {
+}
+
+SyncStatistics::SyncStatistics(
+    SyncStatus sync_status, SyncServiceInfo::SyncServiceType service_type,
+    unsigned last_sync_time, unsigned server_to_client_total,
+    unsigned server_to_client_added, unsigned server_to_client_updated,
+    unsigned server_to_client_removed, unsigned client_to_server_total,
+    unsigned client_to_server_added, unsigned client_to_server_updated,
+    unsigned client_to_server_removed)
+    : sync_status_(sync_status),
+      service_type_(service_type),
+      last_sync_time_(last_sync_time),
+      server_to_client_total_(server_to_client_total),
+      server_to_client_added_(server_to_client_added),
+      server_to_client_updated_(server_to_client_updated),
+      server_to_client_removed_(server_to_client_removed),
+      client_to_server_total_(client_to_server_total),
+      client_to_server_added_(client_to_server_added),
+      client_to_server_updated_(client_to_server_updated),
+      client_to_server_removed_(client_to_server_removed) {
+}
+
+SyncStatistics::SyncStatus SyncStatistics::sync_status() const {
+  return sync_status_;
+}
+
+void SyncStatistics::set_sync_status(SyncStatistics::SyncStatus sync_status) {
+  sync_status_ = sync_status;
+}
+
+SyncServiceInfo::SyncServiceType SyncStatistics::service_type() const {
+  return service_type_;
+}
+
+void SyncStatistics::set_service_type(
+    SyncServiceInfo::SyncServiceType service_type) {
+  service_type_ = service_type;
+}
+
+unsigned SyncStatistics::last_sync_time() const { return last_sync_time_; }
+
+void SyncStatistics::set_last_sync_time(unsigned value) {
+  last_sync_time_ = value;
+}
+
+unsigned SyncStatistics::server_to_client_total() const {
+  return server_to_client_total_;
+}
+
+void SyncStatistics::set_server_to_client_total(unsigned value) {
+  server_to_client_total_ = value;
+}
+
+unsigned SyncStatistics::server_to_client_added() const {
+  return server_to_client_added_;
+}
+
+void SyncStatistics::set_server_to_client_added(unsigned value) {
+  server_to_client_added_ = value;
+}
+
+unsigned SyncStatistics::server_to_client_updated() const {
+  return server_to_client_updated_;
+}
+
+void SyncStatistics::set_server_to_client_updated(unsigned value) {
+  server_to_client_updated_ = value;
+}
+
+unsigned SyncStatistics::server_to_client_removed() const {
+  return server_to_client_removed_;
+}
+
+void SyncStatistics::set_server_to_client_removed(unsigned value) {
+  server_to_client_removed_ = value;
+}
+
+unsigned SyncStatistics::client_to_server_total() const {
+  return client_to_server_total_;
+}
+
+void SyncStatistics::set_client_to_server_total(unsigned value) {
+  client_to_server_total_ = value;
+}
+
+unsigned SyncStatistics::client_to_server_added() const {
+  return client_to_server_added_;
+}
+
+void SyncStatistics::set_client_to_server_added(unsigned value) {
+  client_to_server_added_ = value;
+}
+
+unsigned SyncStatistics::client_to_server_updated() const {
+  return client_to_server_updated_;
+}
+
+void SyncStatistics::set_client_to_server_updated(unsigned value) {
+  client_to_server_updated_ = value;
+}
+
+unsigned SyncStatistics::client_to_server_removed() const {
+  return client_to_server_removed_;
+}
+
+void SyncStatistics::set_client_to_server_removed(unsigned value) {
+  client_to_server_removed_ = value;
+}
+
+}  // namespace datasync
diff --git a/datasync/sync_statistics.h b/datasync/sync_statistics.h
new file mode 100644 (file)
index 0000000..f4b966e
--- /dev/null
@@ -0,0 +1,97 @@
+// Copyright (c) 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.
+
+#ifndef DATASYNC_SYNC_STATISTICS_H_
+#define DATASYNC_SYNC_STATISTICS_H_
+
+#include <string>
+#include <vector>
+
+#include "datasync/sync_service_info.h"
+
+namespace datasync {
+
+/**
+ *Representation of SyncStatistics JS type
+ */
+class SyncStatistics {
+ public:
+  typedef enum {
+    SUCCESS_STATUS,
+    FAIL_STATUS,
+    STOP_STATUS,
+    NONE_STATUS,
+    INVALID
+  } SyncStatus;
+
+  static SyncStatus ConvertToSyncStatus(const std::string& status);
+  static std::string SyncStatusToString(SyncStatus status);
+
+  SyncStatistics();
+  SyncStatistics(SyncStatus sync_status,
+       SyncServiceInfo::SyncServiceType service_type,
+       unsigned last_sync_time,
+       unsigned server_to_client_total,
+       unsigned server_to_client_added,
+       unsigned server_to_client_updated,
+       unsigned server_to_client_removed,
+       unsigned client_to_server_total,
+       unsigned client_to_server_added,
+       unsigned client_to_server_updated,
+       unsigned client_to_server_removed);
+
+  SyncStatus sync_status() const;
+  void set_sync_status(SyncStatus sync_status);
+
+  SyncServiceInfo::SyncServiceType service_type() const;
+  void set_service_type(SyncServiceInfo::SyncServiceType service_type);
+
+  unsigned last_sync_time() const;
+  void set_last_sync_time(unsigned value);
+
+  unsigned server_to_client_total() const;
+  void set_server_to_client_total(unsigned value);
+
+  unsigned server_to_client_added() const;
+  void set_server_to_client_added(unsigned value);
+
+  unsigned server_to_client_updated() const;
+  void set_server_to_client_updated(unsigned value);
+
+  unsigned server_to_client_removed() const;
+  void set_server_to_client_removed(unsigned value);
+
+  unsigned client_to_server_total() const;
+  void set_client_to_server_total(unsigned value);
+
+  unsigned client_to_server_added() const;
+  void set_client_to_server_added(unsigned value);
+
+  unsigned client_to_server_updated() const;
+  void set_client_to_server_updated(unsigned value);
+
+  unsigned client_to_server_removed() const;
+  void set_client_to_server_removed(unsigned value);
+
+ private:
+  SyncStatus sync_status_;
+  SyncServiceInfo::SyncServiceType service_type_;
+  unsigned last_sync_time_;
+  unsigned server_to_client_total_;
+  unsigned server_to_client_added_;
+  unsigned server_to_client_updated_;
+  unsigned server_to_client_removed_;
+  unsigned client_to_server_total_;
+  unsigned client_to_server_added_;
+  unsigned client_to_server_updated_;
+  unsigned client_to_server_removed_;
+};
+
+typedef std::shared_ptr<SyncStatistics> SyncStatisticsPtr;
+typedef std::vector<SyncStatisticsPtr> SyncStatisticsList;
+typedef std::shared_ptr<SyncStatisticsList> SyncStatisticsListPtr;
+
+}  // namespace datasync
+
+#endif  // DATASYNC_SYNC_STATISTICS_H_
index 429cd04..3fc7e29 100644 (file)
@@ -64,6 +64,7 @@ BuildRequires: pkgconfig(pkgmgr)
 BuildRequires: pkgconfig(pkgmgr-info)
 BuildRequires: pkgconfig(pmapi)
 BuildRequires: pkgconfig(tapi)
+BuildRequires: pkgconfig(sync-agent)
 BuildRequires: pkgconfig(vconf)
 %if %{with wayland}
 BuildRequires: pkgconfig(wayland-client)
index 87bdc1a..e32b197 100644 (file)
@@ -30,6 +30,7 @@
             'application/application.gyp:*',
             'bookmark/bookmark.gyp:*',
             'content/content.gyp:*',
+            'datasync/datasync.gyp:*',
             'download/download.gyp:*',
             'filesystem/filesystem.gyp:*',
             'messageport/messageport.gyp:*',