[iotcon] Resource.setRequestListener()/unsetRequestListener().
authorPawel Andruszkiewicz <p.andruszkie@samsung.com>
Mon, 8 Feb 2016 12:31:13 +0000 (13:31 +0100)
committerPawel Andruszkiewicz <p.andruszkie@samsung.com>
Wed, 10 Feb 2016 09:59:09 +0000 (18:59 +0900)
Change-Id: I216c8274221d5d089cfd19b30b9235f84f60c50c
Signed-off-by: Pawel Andruszkiewicz <p.andruszkie@samsung.com>
src/iotcon/iotcon_api.js
src/iotcon/iotcon_instance.cc
src/iotcon/iotcon_instance.h
src/iotcon/iotcon_server_manager.cc
src/iotcon/iotcon_server_manager.h
src/iotcon/iotcon_utils.cc
src/iotcon/iotcon_utils.h

index f3ab15f5f69f03fb3c8331b3a08114108d53131c..e6ab9047bb66760236aadc44487f05354c58f60b 100644 (file)
@@ -29,8 +29,11 @@ function createListener(name, c) {
   var jsListenerRegistered = false;
 
   function internalCallback(response) {
-    if (listeners[response.id]) {
-      listeners[response.id](callback(response));
+    if (native.isSuccess(response)) {
+      response = native.getResultObject(response);
+      if (listeners[response.id]) {
+        listeners[response.id](callback(response));
+      }
     }
   }
 
@@ -199,45 +202,6 @@ function PresenceResponse(data) {
   decorateWithData(data, this);
 }
 
-function Query(resourceTypes, resourceInterface, filters) {
-  validator.isConstructorCall(this, tizen.Query);
-
-  Object.defineProperties(this, {
-    resourceTypes: {
-      value: resourceTypes || null,
-      writable: true,
-      enumerable: true
-    },
-    resourceInterface: {
-      value: resourceInterface || null,
-      writable: true,
-      enumerable: true
-    },
-    filters: {
-      value: filters || null,
-      writable: true,
-      enumerable: true
-    }
-  });
-}
-
-function QueryFilter(key, value) {
-  validator.isConstructorCall(this, tizen.QueryFilter);
-
-  Object.defineProperties(this, {
-    key: {
-      value: key,
-      writable: true,
-      enumerable: true
-    },
-    value: {
-      value: value,
-      writable: true,
-      enumerable: true
-    }
-  });
-}
-
 function Representation(uriPath) {
   validator.isConstructorCall(this, tizen.Representation);
 
@@ -295,6 +259,18 @@ function Request(data) {
 
   delete data.id;
 
+  if (data.representation) {
+    data.representation = createRepresentation(data.representation);
+  }
+
+  if (data.options) {
+    var options = [];
+    for (var i = 0; i < data.options.length; ++i) {
+      options.push(new IotconOption(data.options[i].id, data.options[i].data));
+    }
+    data.options = options;
+  }
+
   decorateWithData(data, this);
 }
 
@@ -422,7 +398,9 @@ Resource.prototype.removeChildResource = function() {
   }
 };
 
-var resourceRequestListener = createListener('ResourceRequestListener');
+var resourceRequestListener = createListener('ResourceRequestListener', function(response) {
+  return new Request(response.data);
+});
 
 Resource.prototype.setRequestListener = function() {
   var args = validator.validateMethod(arguments, [{
@@ -434,7 +412,7 @@ Resource.prototype.setRequestListener = function() {
   callArgs.id = this[kIdKey];
 
   var listener = function(result) {
-    native.callIfPossible(args.successCallback, native.getResultObject(result));
+    args.successCallback(result);
   };
 
   var result = native.callSync('IotconResource_setRequestListener', callArgs);
@@ -450,7 +428,7 @@ Resource.prototype.unsetRequestListener = function() {
   var callArgs = {};
   callArgs.id = this[kIdKey];
 
-  var result = native.callSync('IotconRemoteResource_unsetRequestListener', callArgs);
+  var result = native.callSync('IotconResource_unsetRequestListener', callArgs);
 
   if (native.isFailure(result)) {
     throw native.getErrorObject(result);
@@ -565,8 +543,7 @@ function RemoteResource(data) {
 RemoteResource.prototype.methodGet = function() {
   var args = validator.validateMethod(arguments, [{
     name: 'query',
-    type: types.PLATFORM_OBJECT,
-    values: Query
+    type: types.DICTIONARY
   }, {
     name: 'responseCallback',
     type: types.FUNCTION
@@ -604,8 +581,7 @@ RemoteResource.prototype.methodPut = function() {
     values: Representation
   }, {
     name: 'query',
-    type: types.PLATFORM_OBJECT,
-    values: Query
+    type: types.DICTIONARY
   }, {
     name: 'responseCallback',
     type: types.FUNCTION
@@ -644,8 +620,7 @@ RemoteResource.prototype.methodPost = function() {
     values: Representation
   }, {
     name: 'query',
-    type: types.PLATFORM_OBJECT,
-    values: Query
+    type: types.DICTIONARY
   }, {
     name: 'responseCallback',
     type: types.FUNCTION
@@ -712,8 +687,7 @@ var stateChangeListener = createListener('RemoteResourceStateChangeListener');
 RemoteResource.prototype.setStateChangeListener = function() {
   var args = validator.validateMethod(arguments, [{
     name: 'query',
-    type: types.PLATFORM_OBJECT,
-    values: Query
+    type: types.DICTIONARY
   }, {
     name: 'observePolicy',
     type: types.ENUM,
@@ -1117,8 +1091,6 @@ Iotcon.prototype.setTimeout = function() {
 
 // Exports
 tizen.IotconOption = IotconOption;
-tizen.Query = Query;
-tizen.QueryFilter = QueryFilter;
 tizen.Representation = Representation;
 tizen.Response = Response;
 tizen.State = State;
index e32b858b8c8cd5cf41c45865ffedb49eff0b7a3d..9d390392641cf4ee1fa46ec19e37f9e8b22ca78a 100644 (file)
@@ -33,7 +33,7 @@ namespace {
   }
 
 long long GetId(const picojson::object& args) {
-  return static_cast<long long>(args.find(kResourceId)->second.get<double>());
+  return static_cast<long long>(args.find(kId)->second.get<double>());
 }
 
 const picojson::value& GetArg(const picojson::object& args, const std::string& name) {
@@ -47,6 +47,8 @@ const picojson::value& GetArg(const picojson::object& args, const std::string& n
   }
 }
 
+const common::ListenerToken kResourceRequestListenerToken{"ResourceRequestListener"};
+
 }  // namespace
 
 IotconInstance::IotconInstance() : manager_(this) {
@@ -60,7 +62,7 @@ IotconInstance::IotconInstance() : manager_(this) {
 
   REGISTER_SYNC("IotconResource_getObserverIds", ResourceGetObserverIds);
   REGISTER_SYNC("IotconResource_setRequestListener", ResourceSetRequestListener);
-  REGISTER_SYNC("IotconRemoteResource_unsetRequestListener", RemoteResourceUnsetRequestListener);
+  REGISTER_SYNC("IotconResource_unsetRequestListener", ResourceUnsetRequestListener);
   REGISTER_SYNC("IotconResponse_send", ResponseSend);
   REGISTER_SYNC("IotconRemoteResource_getCachedRepresentation", RemoteResourceGetCachedRepresentation);
   REGISTER_SYNC("IotconRemoteResource_setStateChangeListener", RemoteResourceSetStateChangeListener);
@@ -176,12 +178,47 @@ common::TizenResult IotconInstance::ResourceRemoveChildResource(const picojson::
 
 common::TizenResult IotconInstance::ResourceSetRequestListener(const picojson::object& args) {
   ScopeLogger();
-  return common::UnknownError("Not implemented");
+
+  CHECK_EXIST(args, kId);
+
+  ResourceInfoPtr resource;
+  long long id = GetId(args);
+  auto result = manager_.GetResourceById(id, &resource);
+
+  if (!result) {
+    return result;
+  }
+
+  if (!resource->request_listener) {
+    resource->request_listener = [this, id](const common::TizenResult&, const picojson::value& v) {
+      picojson::value response{picojson::object{}};
+      auto& obj = response.get<picojson::object>();
+
+      obj.insert(std::make_pair(kId, picojson::value{static_cast<double>(id)}));
+      obj.insert(std::make_pair("data", v));
+
+      Post(kResourceRequestListenerToken, common::TizenSuccess{response});
+    };
+  }
+
+  return common::TizenSuccess();
 }
 
-common::TizenResult IotconInstance::RemoteResourceUnsetRequestListener(const picojson::object& args) {
+common::TizenResult IotconInstance::ResourceUnsetRequestListener(const picojson::object& args) {
   ScopeLogger();
-  return common::UnknownError("Not implemented");
+
+  CHECK_EXIST(args, kId);
+
+  ResourceInfoPtr resource;
+  auto result = manager_.GetResourceById(GetId(args), &resource);
+
+  if (!result) {
+    return result;
+  }
+
+  resource->request_listener = nullptr;
+
+  return common::TizenSuccess();
 }
 
 common::TizenResult IotconInstance::ResponseSend(const picojson::object& args) {
@@ -330,7 +367,7 @@ common::TizenResult IotconInstance::ServerCreateResource(const picojson::object&
 common::TizenResult IotconInstance::ServerRemoveResource(const picojson::object& args) {
   ScopeLogger();
 
-  CHECK_EXIST(args, kResourceId);
+  CHECK_EXIST(args, kId);
 
   return manager_.DestroyResource(GetId(args));
 }
index 1d0b646fd08de953b025d53d33286919d3d669cf..556d0c98aa18e881c4cf3cc302366a64972d24cc 100644 (file)
@@ -43,7 +43,7 @@ class IotconInstance : public common::TizenInstance {
   common::TizenResult ResourceRemoveChildResource(const picojson::object& args,
                                                   const common::AsyncToken& token);
   common::TizenResult ResourceSetRequestListener(const picojson::object& args);
-  common::TizenResult RemoteResourceUnsetRequestListener(const picojson::object& args);
+  common::TizenResult ResourceUnsetRequestListener(const picojson::object& args);
   common::TizenResult ResponseSend(const picojson::object& args);
   common::TizenResult RemoteResourceGetCachedRepresentation(const picojson::object& args);
   common::TizenResult RemoteResourceMethodGet(const picojson::object& args,
index 56a917b5a9ffb5b2327e4fa5e1b49cfc5d9a4946..18523498720ef08e13e6811dbb61238bc53b9713 100644 (file)
@@ -26,9 +26,17 @@ namespace iotcon {
 using common::TizenResult;
 using common::TizenSuccess;
 
+namespace {
+
+long long GetNextId() {
+  static long long id = 0;
+  return ++id;
+}
+
+}  // namespace
+
 IotconServerManager::IotconServerManager(IotconInstance* instance)
-      : instance_(instance),
-        global_id_(0) {
+      : instance_(instance) {
   ScopeLogger();
 }
 
@@ -59,7 +67,7 @@ TizenResult IotconServerManager::RestoreHandles() {
 
     int ret = iotcon_resource_create(uri_path, res_types, ifaces, properties,
                                      RequestHandler, // request_callback
-                                     nullptr, // user_data
+                                     this, // user_data
                                      &(resource->handle));
     if (IOTCON_ERROR_NONE != ret || nullptr == resource->handle) {
       LogAndReturnTizenError(IotconUtils::ConvertIotconError(ret),
@@ -82,7 +90,78 @@ TizenResult IotconServerManager::RestoreHandles() {
 void IotconServerManager::RequestHandler(iotcon_resource_h resource,
                                          iotcon_request_h request, void *user_data) {
   ScopeLogger();
-  // TODO probably should be handled somehow later
+
+  auto that = static_cast<IotconServerManager*>(user_data);
+  ResourceInfoPtr r;
+  auto result = that->GetResourceByHandle(resource, &r);
+
+  if (!result) {
+    LoggerE("Resource is not handled by the manager!");
+    return;
+  }
+
+  // handle observer changes
+  iotcon_observe_type_e type = IOTCON_OBSERVE_NO_TYPE;
+  result = IotconUtils::ConvertIotconError(iotcon_request_get_observe_type(request, &type));
+
+  if (!result) {
+    LoggerE("iotcon_request_get_observe_type() failed");
+    return;
+  }
+
+  int observer_id = -1;
+  result = IotconUtils::ConvertIotconError(iotcon_request_get_observe_id(request, &observer_id));
+
+  if (!result) {
+    LoggerE("iotcon_request_get_observe_id() failed");
+    return;
+  }
+
+  switch (type) {
+    case IOTCON_OBSERVE_NO_TYPE:
+      LoggerD("observer did not change");
+      break;
+
+    case IOTCON_OBSERVE_REGISTER:
+      LoggerD("Observer has been registered: %d", observer_id);
+      r->observers.insert(observer_id);
+      break;
+
+    case IOTCON_OBSERVE_DEREGISTER:
+      LoggerD("Observer has been deregistered: %d", observer_id);
+      r->observers.erase(observer_id);
+      break;
+  }
+
+  if (r->request_listener) {
+    // convert request to JSON
+    picojson::value value{picojson::object{}};
+    auto& obj = value.get<picojson::object>();
+
+    result = IotconUtils::RequestToJson(request, &obj);
+
+    if (!result) {
+      LoggerE("RequestToJson() failed");
+      return;
+    }
+
+    // create response
+    iotcon_response_h response = nullptr;
+    result = IotconUtils::ConvertIotconError(iotcon_response_create(request, &response));
+
+    if (!result) {
+      LoggerE("iotcon_response_create() failed");
+      return;
+    }
+
+    // store data
+    long long id = GetNextId();
+    obj.insert(std::make_pair(kId, picojson::value{static_cast<double>(id)}));
+    r->unhandled_responses.insert(std::make_pair(id, response));
+
+    // call listener
+    r->request_listener(TizenSuccess(), value);
+  }
 }
 
 TizenResult IotconServerManager::CreateResource(const std::string& uri_path,
@@ -111,7 +190,7 @@ TizenResult IotconServerManager::CreateResource(const std::string& uri_path,
                                interfaces,
                                properties,
                                RequestHandler, // request_callback
-                               nullptr, // user_data
+                               this, // user_data
                                &(res_pointer->handle));
   if (IOTCON_ERROR_NONE != ret || nullptr == res_pointer->handle) {
     LogAndReturnTizenError(IotconUtils::ConvertIotconError(ret),
@@ -120,7 +199,7 @@ TizenResult IotconServerManager::CreateResource(const std::string& uri_path,
   }
 
   // storing ResourceInfo into map
-  res_pointer->id = ++global_id_;
+  res_pointer->id = GetNextId();
   resource_map_.insert(std::make_pair(res_pointer->id, res_pointer));
   return TizenSuccess();
 }
@@ -150,5 +229,23 @@ common::TizenResult IotconServerManager::DestroyResource(long long id) {
   }
 }
 
+common::TizenResult IotconServerManager::GetResourceByHandle(
+    iotcon_resource_h resource, ResourceInfoPtr* res_pointer) const {
+  ScopeLogger();
+
+  auto it = std::find_if(resource_map_.begin(), resource_map_.end(), [resource](const ResourceInfoMap::value_type& p) -> bool {
+    return p.second->handle == resource;
+  });
+
+  if (it == resource_map_.end()) {
+    return LogAndCreateTizenError(NotFoundError, "Resource with specified handle does not exist");
+  }
+
+  LoggerE("Resource found");
+  *res_pointer = it->second;
+
+  return TizenSuccess();
+}
+
 }  // namespace iotcon
 }  // namespace extension
index 1fd3865a01f6b27f8abaeda76e53c124db8f4a56..4c8bf8afbdcae5ccbb9052b5491e229e6367468b 100644 (file)
@@ -47,10 +47,12 @@ class IotconServerManager {
   common::TizenResult GetResourceById(long long id, ResourceInfoPtr* res_pointer) const;
   common::TizenResult DestroyResource(long long id);
  private:
+  common::TizenResult GetResourceByHandle(iotcon_resource_h resource, ResourceInfoPtr* res_pointer) const;
+
   IotconInstance* instance_;
   ResourceInfoMap resource_map_;
-  long long global_id_;
 };
+
 } // namespace iotcon
 } // namespace extension
 
index a6560c32a1148621e52c6880d7ee4d5a5b5476b1..bc5276cf28bdf56e6e80aa5f309c3954aa976781 100644 (file)
 #include "common/logger.h"
 #include "common/platform_exception.h"
 #include "common/scope_exit.h"
+#include "common/tools.h"
 
 #include "iotcon/iotcon_server_manager.h"
 
 namespace extension {
 namespace iotcon {
 
+namespace {
+
+#define IOTCON_CONNECTIVITY_TYPE_E \
+  X(IOTCON_CONNECTIVITY_IPV4, "IPV4") \
+  X(IOTCON_CONNECTIVITY_IPV6, "IPV6") \
+  X(IOTCON_CONNECTIVITY_BT_EDR, "BT_EDR") \
+  X(IOTCON_CONNECTIVITY_BT_LE, "BT_LE") \
+  X(IOTCON_CONNECTIVITY_ALL, "ALL") \
+  XD(IOTCON_CONNECTIVITY_ALL, "unknown")
+
+#define IOTCON_REQUEST_TYPE_E \
+  X(IOTCON_REQUEST_UNKNOWN, "unknown") \
+  X(IOTCON_REQUEST_GET, "GET") \
+  X(IOTCON_REQUEST_PUT, "PUT") \
+  X(IOTCON_REQUEST_POST, "POST") \
+  X(IOTCON_REQUEST_DELETE, "DELETE") \
+  XD(IOTCON_REQUEST_UNKNOWN, "unknown")
+
+#define IOTCON_OBSERVE_TYPE_E \
+  X(IOTCON_OBSERVE_NO_TYPE, "NO_TYPE") \
+  X(IOTCON_OBSERVE_REGISTER, "REGISTER") \
+  X(IOTCON_OBSERVE_DEREGISTER, "DEREGISTER") \
+  XD(IOTCON_OBSERVE_NO_TYPE, "unknown")
+
+#define IOTCON_INTERFACE_E \
+  X(IOTCON_INTERFACE_NONE, "NONE") \
+  X(IOTCON_INTERFACE_DEFAULT, "DEFAULT") \
+  X(IOTCON_INTERFACE_LINK, "LINK") \
+  X(IOTCON_INTERFACE_BATCH, "BATCH") \
+  X(IOTCON_INTERFACE_GROUP, "GROUP") \
+  X(IOTCON_INTERFACE_READONLY, "READONLY") \
+  XD(IOTCON_INTERFACE_NONE, "unknown")
+
+}  // namespace
+
 const std::string kIsDiscoverable = "isDiscoverable";
 const std::string kIsObservable = "isObservable";
 const std::string kIsActive = "isActive";
@@ -37,32 +73,30 @@ const std::string kResourceTypes = "resourceTypes";
 const std::string kResourceInterfaces = "resourceInterfaces";
 const std::string kResourceChildren = "resources";
 const std::string kUriPath = "uriPath";
-const std::string kResourceId = "id";
+const std::string kStates = "states";
+const std::string kId = "id";
 
-const std::string kInterfaceDefault = "DEFAULT";
-const std::string kInterfaceLink = "LINK";
-const std::string kInterfaceBatch = "BATCH";
-const std::string kInterfaceGroup = "GROUP";
+const std::string kHostAddress = "hostAddress";
+const std::string kConnectivityType = "connectivityType";
+const std::string kRepresentation = "representation";
+const std::string kRepresentations = "representations";
+const std::string kRequestType = "type";
+const std::string kOptions = "options";
+const std::string kQuery = "query";
+const std::string kObserverId = "observerId";
+const std::string kObserveType = "observeType";
 
-using common::TizenResult;
-using common::TizenSuccess;
+const std::string kOptionsId = "id";
+const std::string kOptionsData = "data";
 
-TizenResult IotconUtils::StringToInterface(const std::string& interface, iotcon_interface_e* res) {
-  ScopeLogger();
+const std::string kResourceType = "resourceType";
+const std::string kResourceInterface = "resourceInterface";
+const std::string kFilter = "filter";
 
-  if (kInterfaceDefault == interface) {
-    *res = IOTCON_INTERFACE_DEFAULT;
-  } else if (kInterfaceLink == interface) {
-    *res = IOTCON_INTERFACE_LINK;
-  } else if (kInterfaceBatch == interface) {
-    *res = IOTCON_INTERFACE_BATCH;
-  } else if (kInterfaceGroup == interface) {
-    *res = IOTCON_INTERFACE_GROUP;
-  } else {
-    return LogAndCreateTizenError(InvalidValuesError, "Not supported interface name");
-  }
-  return TizenSuccess();
-}
+const std::string kHexPrefix = "0x";
+
+using common::TizenResult;
+using common::TizenSuccess;
 
 TizenResult IotconUtils::ArrayToInterfaces(const picojson::array& interfaces, int* res) {
   ScopeLogger();
@@ -73,11 +107,7 @@ TizenResult IotconUtils::ArrayToInterfaces(const picojson::array& interfaces, in
     if (!iter->is<std::string>()) {
       return LogAndCreateTizenError(InvalidValuesError, "Array holds incorrect interface names");
     } else {
-      iotcon_interface_e interface = IOTCON_INTERFACE_NONE;
-      auto ret = StringToInterface(iter->get<std::string>(), &interface);
-      if (!ret) {
-        return ret;
-      }
+      iotcon_interface_e interface = ToInterface(iter->get<std::string>());
       result_value |= interface;
     }
   }
@@ -90,16 +120,19 @@ picojson::array IotconUtils::InterfacesToArray(int interfaces) {
 
   picojson::array res;
   if (interfaces & IOTCON_INTERFACE_DEFAULT) {
-    res.push_back(picojson::value(kInterfaceDefault));
+    res.push_back(picojson::value(FromInterface(IOTCON_INTERFACE_DEFAULT)));
   }
   if (interfaces & IOTCON_INTERFACE_LINK) {
-    res.push_back(picojson::value(kInterfaceLink));
+    res.push_back(picojson::value(FromInterface(IOTCON_INTERFACE_LINK)));
   }
   if (interfaces & IOTCON_INTERFACE_BATCH) {
-    res.push_back(picojson::value(kInterfaceBatch));
+    res.push_back(picojson::value(FromInterface(IOTCON_INTERFACE_BATCH)));
   }
   if (interfaces & IOTCON_INTERFACE_GROUP) {
-    res.push_back(picojson::value(kInterfaceGroup));
+    res.push_back(picojson::value(FromInterface(IOTCON_INTERFACE_GROUP)));
+  }
+  if (interfaces & IOTCON_INTERFACE_READONLY) {
+    res.push_back(picojson::value(FromInterface(IOTCON_INTERFACE_READONLY)));
   }
   return res;
 }
@@ -183,7 +216,7 @@ TizenResult IotconUtils::ResourceToJson(ResourceInfoPtr pointer,
   if (!ret){
     return ret;
   }
-  res->insert(std::make_pair(kResourceId, picojson::value(static_cast<double>(pointer->id))));
+  res->insert(std::make_pair(kId, picojson::value(static_cast<double>(pointer->id))));
   res->insert(std::make_pair(kUriPath, picojson::value(uri_path)));
 
   picojson::array types;
@@ -231,6 +264,515 @@ TizenResult IotconUtils::ResourceToJson(ResourceInfoPtr pointer,
   return TizenSuccess();
 }
 
+common::TizenResult IotconUtils::RequestToJson(iotcon_request_h request,
+                                               picojson::object* out) {
+  ScopeLogger();
+
+  {
+    // hostAddress
+    char* host_address = nullptr;
+    auto result = ConvertIotconError(iotcon_request_get_host_address(request, &host_address));
+    if (!result || !host_address) {
+      LogAndReturnTizenError(result, ("iotcon_request_get_host_address() failed"));
+    }
+    out->insert(std::make_pair(kHostAddress, picojson::value{host_address}));
+  }
+
+  {
+    // connectivityType
+    iotcon_connectivity_type_e connectivity_type = IOTCON_CONNECTIVITY_ALL;
+    auto result = ConvertIotconError(iotcon_request_get_connectivity_type(request, &connectivity_type));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_request_get_connectivity_type() failed"));
+    }
+    out->insert(std::make_pair(kConnectivityType, picojson::value{FromConnectivityType(connectivity_type)}));
+  }
+
+  {
+    // representation
+    iotcon_representation_h representation = nullptr;
+    auto result = ConvertIotconError(iotcon_request_get_representation(request, &representation));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_request_get_representation() failed"));
+    }
+    picojson::value v{picojson::object{}};
+    result = RepresentationToJson(representation, &v.get<picojson::object>());
+    if (!result) {
+      LogAndReturnTizenError(result, ("RepresentationToJson() failed"));
+    }
+    out->insert(std::make_pair(kRepresentation, v));
+  }
+
+  {
+    // requestType
+    iotcon_request_type_e request_type = IOTCON_REQUEST_UNKNOWN;
+    auto result = ConvertIotconError(iotcon_request_get_request_type(request, &request_type));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_request_get_request_type() failed"));
+    }
+    out->insert(std::make_pair(kRequestType, picojson::value{FromRequestType(request_type)}));
+  }
+
+  {
+    // options
+    iotcon_options_h options = nullptr;
+    auto result = ConvertIotconError(iotcon_request_get_options(request, &options));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_request_get_options() failed"));
+    }
+    picojson::value v{picojson::array{}};
+    result = OptionsToJson(options, &v.get<picojson::array>());
+    if (!result) {
+      LogAndReturnTizenError(result, ("OptionsToJson() failed"));
+    }
+    out->insert(std::make_pair(kOptions, v));
+  }
+
+  {
+    // query
+    iotcon_query_h query = nullptr;
+    auto result = ConvertIotconError(iotcon_request_get_query(request, &query));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_request_get_query() failed"));
+    }
+    picojson::value v{picojson::object{}};
+    result = QueryToJson(query, &v.get<picojson::object>());
+    if (!result) {
+      LogAndReturnTizenError(result, ("QueryToJson() failed"));
+    }
+    out->insert(std::make_pair(kQuery, v));
+  }
+
+  {
+    // observerId
+    int observer_id = -1;
+    auto result = ConvertIotconError(iotcon_request_get_observe_id(request, &observer_id));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_request_get_observe_id() failed"));
+    }
+    out->insert(std::make_pair(kObserverId, picojson::value{static_cast<double>(observer_id)}));
+  }
+
+  {
+    // observeType
+    iotcon_observe_type_e observe_type = IOTCON_OBSERVE_NO_TYPE;
+    auto result = ConvertIotconError(iotcon_request_get_observe_type(request, &observe_type));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_request_get_observe_type() failed"));
+    }
+    out->insert(std::make_pair(kRequestType, picojson::value{FromObserveType(observe_type)}));
+  }
+
+  return TizenSuccess();
+}
+
+common::TizenResult IotconUtils::RepresentationToJson(iotcon_representation_h representation,
+                                                      picojson::object* out) {
+  ScopeLogger();
+
+  {
+    // hostAddress
+    char* uri_path = nullptr;
+    auto result = ConvertIotconError(iotcon_representation_get_uri_path(representation, &uri_path));
+    if (!result || !uri_path) {
+      LogAndReturnTizenError(result, ("iotcon_representation_get_uri_path() failed"));
+    }
+    out->insert(std::make_pair(kUriPath, picojson::value{uri_path}));
+  }
+
+  {
+    // resourceTypes
+    iotcon_resource_types_h resource_types = nullptr;
+    auto result = ConvertIotconError(iotcon_representation_get_resource_types(representation, &resource_types));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_representation_get_resource_types() failed"));
+    }
+    picojson::value v{picojson::array{}};
+    iotcon_resource_types_foreach(resource_types, ResourceTypeIterator, &v.get<picojson::array>());
+    out->insert(std::make_pair(kResourceTypes, v));
+  }
+
+  {
+    // resourceInterfaces
+    int interfaces = 0;
+    auto result = ConvertIotconError(iotcon_representation_get_resource_interfaces(representation, &interfaces));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_representation_get_resource_interfaces() failed"));
+    }
+    out->insert(std::make_pair(kResourceInterfaces, picojson::value{InterfacesToArray(interfaces)}));
+  }
+
+  {
+    // states
+    iotcon_state_h state = nullptr;
+    auto result = ConvertIotconError(iotcon_representation_get_state(representation, &state));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_representation_get_state() failed"));
+    }
+    picojson::value v{picojson::object{}};
+    result = StateToJson(state, &v.get<picojson::object>());
+    if (!result) {
+      LogAndReturnTizenError(result, ("StateToJson() failed"));
+    }
+    out->insert(std::make_pair(kStates, v));
+  }
+
+  {
+    // representations
+    picojson::value v{picojson::array{}};
+    auto result = ConvertIotconError(iotcon_representation_foreach_children(representation, [](iotcon_representation_h child, void* user_data) -> bool {
+      auto arr = static_cast<picojson::array*>(user_data);
+      arr->push_back(picojson::value{picojson::object{}});
+      auto result = RepresentationToJson(child, &arr->back().get<picojson::object>());
+      if (!result) {
+        LoggerE("Failed to convert child representation");
+      }
+      // always continue with iteration
+      return true;
+    }, &v.get<picojson::array>()));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_representation_foreach_children() failed"));
+    }
+    out->insert(std::make_pair(kRepresentations, v));
+  }
+
+  return TizenSuccess();
+}
+
+common::TizenResult IotconUtils::StateToJson(iotcon_state_h state,
+                                             picojson::object* out) {
+  ScopeLogger();
+
+  auto result = ConvertIotconError(iotcon_state_foreach(state, [](iotcon_state_h state, const char* key, void* user_data) -> bool {
+    iotcon_type_e type = IOTCON_TYPE_NONE;
+    auto result = ConvertIotconError(iotcon_state_get_type(state, key, &type));
+
+    if (result) {
+      auto out = static_cast<picojson::object*>(user_data);
+
+      switch (type) {
+        case IOTCON_TYPE_NONE:
+          LoggerE("Key %s has type NONE", key);
+          break;
+
+        case IOTCON_TYPE_INT:
+          {
+            int value = 0;
+            result = ConvertIotconError(iotcon_state_get_int(state, key, &value));
+            if (result) {
+              out->insert(std::make_pair(key, picojson::value{static_cast<double>(value)}));
+            } else {
+              LoggerE("iotcon_state_get_int() failed");
+            }
+          }
+          break;
+
+        case IOTCON_TYPE_BOOL:
+          {
+            bool value = false;
+            result = ConvertIotconError(iotcon_state_get_bool(state, key, &value));
+            if (result) {
+              out->insert(std::make_pair(key, picojson::value{value}));
+            } else {
+              LoggerE("iotcon_state_get_bool() failed");
+            }
+          }
+          break;
+
+        case IOTCON_TYPE_DOUBLE:
+          {
+            double value = 0.0;
+            result = ConvertIotconError(iotcon_state_get_double(state, key, &value));
+            if (result) {
+              out->insert(std::make_pair(key, picojson::value{value}));
+            } else {
+              LoggerE("iotcon_state_get_double() failed");
+            }
+          }
+          break;
+
+        case IOTCON_TYPE_STR:
+          {
+            char* value = nullptr;
+            result = ConvertIotconError(iotcon_state_get_str(state, key, &value));
+            if (result && value) {
+              out->insert(std::make_pair(key, picojson::value{value}));
+            } else {
+              LoggerE("iotcon_state_get_str() failed");
+            }
+          }
+          break;
+
+        case IOTCON_TYPE_BYTE_STR:
+          {
+            unsigned char* value = nullptr;
+            int length = 0;
+            result = ConvertIotconError(iotcon_state_get_byte_str(state, key, &value, &length));
+
+            if (result && length) {
+              std::unique_ptr<char[]> data{new char[2 * length]};
+              common::tools::BinToHex(value, length, data.get(), 2 * length);
+              out->insert(std::make_pair(key, picojson::value{kHexPrefix + data.get()}));
+            } else {
+              LoggerE("iotcon_state_get_byte_str() failed");
+            }
+          }
+          break;
+
+        case IOTCON_TYPE_NULL:
+          out->insert(std::make_pair(key, picojson::value{}));
+          break;
+
+        case IOTCON_TYPE_LIST:
+          {
+            iotcon_list_h list = nullptr;
+            result = ConvertIotconError(iotcon_state_get_list(state, key, &list));
+            if (result) {
+              picojson::value value{picojson::array{}};
+
+              result = StateListToJson(list, &value.get<picojson::array>());
+              if (result) {
+                out->insert(std::make_pair(key, picojson::value{value}));
+              } else {
+                LoggerE("StateListToJson() failed");
+              }
+            } else {
+              LoggerE("iotcon_state_get_list() failed");
+            }
+          }
+          break;
+
+        case IOTCON_TYPE_STATE:
+          {
+            iotcon_state_h child = nullptr;
+            result = ConvertIotconError(iotcon_state_get_state(state, key, &child));
+            if (result) {
+              picojson::value value{picojson::object{}};
+
+              result = StateToJson(child, &value.get<picojson::object>());
+              if (result) {
+                out->insert(std::make_pair(key, picojson::value{value}));
+              } else {
+                LoggerE("StateToJson() failed");
+              }
+            } else {
+              LoggerE("iotcon_state_get_state() failed");
+            }
+          }
+          break;
+      }
+    } else {
+      LoggerE("iotcon_state_get_type() failed");
+    }
+
+    // always continue with iteration
+    return true;
+  }, out));
+
+  if (!result) {
+    LogAndReturnTizenError(result, ("iotcon_state_foreach() failed"));
+  }
+
+  return TizenSuccess();
+}
+
+common::TizenResult IotconUtils::StateListToJson(iotcon_list_h list,
+                                                 picojson::array* out) {
+  ScopeLogger();
+
+  iotcon_type_e type = IOTCON_TYPE_NONE;
+  auto result = ConvertIotconError(iotcon_list_get_type(list, &type));
+
+  if (!result) {
+    LogAndReturnTizenError(result, ("iotcon_list_get_type() failed"));
+  }
+
+  switch (type) {
+    case IOTCON_TYPE_NONE:
+      LoggerE("List has type NONE");
+      break;
+
+    case IOTCON_TYPE_INT:
+      result = ConvertIotconError(iotcon_list_foreach_int(list, [](int, int value, void* user_data) -> bool {
+        auto out = static_cast<picojson::array*>(user_data);
+        out->push_back(picojson::value{static_cast<double>(value)});
+        // always continue with iteration
+        return true;
+      }, out));
+      if (!result) {
+        LogAndReturnTizenError(result, ("iotcon_list_foreach_int() failed"));
+      }
+      break;
+
+    case IOTCON_TYPE_BOOL:
+      result = ConvertIotconError(iotcon_list_foreach_bool(list, [](int, bool value, void* user_data) -> bool {
+        auto out = static_cast<picojson::array*>(user_data);
+        out->push_back(picojson::value{value});
+        // always continue with iteration
+        return true;
+      }, out));
+      if (!result) {
+        LogAndReturnTizenError(result, ("iotcon_list_foreach_bool() failed"));
+      }
+      break;
+
+    case IOTCON_TYPE_DOUBLE:
+      result = ConvertIotconError(iotcon_list_foreach_double(list, [](int, double value, void* user_data) -> bool {
+        auto out = static_cast<picojson::array*>(user_data);
+        out->push_back(picojson::value{value});
+        // always continue with iteration
+        return true;
+      }, out));
+      if (!result) {
+        LogAndReturnTizenError(result, ("iotcon_list_foreach_double() failed"));
+      }
+      break;
+
+    case IOTCON_TYPE_STR:
+      result = ConvertIotconError(iotcon_list_foreach_str(list, [](int, const char* value, void* user_data) -> bool {
+        if (value) {
+          auto out = static_cast<picojson::array*>(user_data);
+          out->push_back(picojson::value{value});
+        }
+        // always continue with iteration
+        return true;
+      }, out));
+      if (!result) {
+        LogAndReturnTizenError(result, ("iotcon_list_foreach_str() failed"));
+      }
+      break;
+
+    case IOTCON_TYPE_BYTE_STR:
+      result = ConvertIotconError(iotcon_list_foreach_byte_str(list, [](int, const unsigned char* value, int length, void* user_data) -> bool {
+        if (length) {
+          std::unique_ptr<char[]> data{new char[2 * length]};
+          common::tools::BinToHex(value, length, data.get(), 2 * length);
+
+          auto out = static_cast<picojson::array*>(user_data);
+          out->push_back(picojson::value{kHexPrefix + data.get()});
+        }
+        // always continue with iteration
+        return true;
+      }, out));
+      if (!result) {
+        LogAndReturnTizenError(result, ("iotcon_list_foreach_str() failed"));
+      }
+      break;
+
+    case IOTCON_TYPE_NULL:
+      LoggerE("List has type NULL");
+      break;
+
+    case IOTCON_TYPE_LIST:
+      result = ConvertIotconError(iotcon_list_foreach_list(list, [](int, iotcon_list_h list, void* user_data) -> bool {
+        picojson::value value{picojson::array{}};
+        auto result = StateListToJson(list, &value.get<picojson::array>());
+        if (result) {
+          auto out = static_cast<picojson::array*>(user_data);
+          out->push_back(picojson::value{value});
+        } else {
+          LoggerE("StateListToJson() failed");
+        }
+        // always continue with iteration
+        return true;
+      }, out));
+      if (!result) {
+        LogAndReturnTizenError(result, ("iotcon_list_foreach_list() failed"));
+      }
+      break;
+
+    case IOTCON_TYPE_STATE:
+      result = ConvertIotconError(iotcon_list_foreach_state(list, [](int, iotcon_state_h state, void* user_data) -> bool {
+        picojson::value value{picojson::object{}};
+        auto result = StateToJson(state, &value.get<picojson::object>());
+        if (result) {
+          auto out = static_cast<picojson::array*>(user_data);
+          out->push_back(picojson::value{value});
+        } else {
+          LoggerE("StateToJson() failed");
+        }
+        // always continue with iteration
+        return true;
+      }, out));
+      if (!result) {
+        LogAndReturnTizenError(result, ("iotcon_list_foreach_state() failed"));
+      }
+      break;
+  }
+
+  return TizenSuccess();
+}
+
+common::TizenResult IotconUtils::OptionsToJson(iotcon_options_h  options,
+                                               picojson::array* out) {
+  ScopeLogger();
+
+  auto result = ConvertIotconError(iotcon_options_foreach(options, [](unsigned short id, const char *data, void* user_data) -> bool {
+    if (data) {
+      picojson::value v{picojson::object{}};
+      auto& obj = v.get<picojson::object>();
+
+      obj.insert(std::make_pair(kOptionsId, picojson::value{static_cast<double>(id)}));
+      obj.insert(std::make_pair(kOptionsData, picojson::value{data}));
+
+      auto out = static_cast<picojson::array*>(user_data);
+      out->push_back(v);
+    }
+    // always continue with iteration
+    return true;
+  }, out));
+
+  if (!result) {
+    LogAndReturnTizenError(result, ("iotcon_options_foreach() failed"));
+  }
+
+  return TizenSuccess();
+}
+
+common::TizenResult IotconUtils::QueryToJson(iotcon_query_h query,
+                                             picojson::object* out) {
+  ScopeLogger();
+
+  {
+    // resourceType
+    char* resource_type = nullptr;
+    auto result = ConvertIotconError(iotcon_query_get_resource_type(query, &resource_type));
+    if (!result || !resource_type) {
+      LogAndReturnTizenError(result, ("iotcon_query_get_resource_type() failed"));
+    }
+    out->insert(std::make_pair(kResourceType, picojson::value{resource_type}));
+  }
+
+  {
+    // resourceInterface
+    iotcon_interface_e interface = IOTCON_INTERFACE_NONE;
+    auto result = ConvertIotconError(iotcon_query_get_interface(query, &interface));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_query_get_interface() failed"));
+    }
+    out->insert(std::make_pair(kResourceInterface, picojson::value{FromInterface(interface)}));
+  }
+
+  {
+    // filter
+    picojson::value v{picojson::object{}};
+    auto result = ConvertIotconError(iotcon_query_foreach(query, [](const char* key, const char* value, void* user_data) -> bool {
+      if (key && value) {
+        auto obj = static_cast<picojson::object*>(user_data);
+        obj->insert(std::make_pair(key, picojson::value{value}));
+      }
+      // always continue with iteration
+      return true;
+    }, &v.get<picojson::object>()));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_query_foreach() failed"));
+    }
+    out->insert(std::make_pair(kFilter, v));
+  }
+
+  return TizenSuccess();
+}
+
 common::TizenResult IotconUtils::ConvertIotconError(int error) {
   switch (error) {
     case IOTCON_ERROR_NONE:
@@ -270,5 +812,60 @@ common::TizenResult IotconUtils::ConvertIotconError(int error) {
   }
 }
 
+#define X(v, s) case v: return s;
+#define XD(v, s) \
+  default: \
+    LoggerE("Unknown value: %d, returning default: %s", e, s); \
+    return s;
+
+std::string IotconUtils::FromConnectivityType(iotcon_connectivity_type_e e) {
+  ScopeLogger();
+
+  switch (e) {
+    IOTCON_CONNECTIVITY_TYPE_E
+  }
+}
+
+std::string IotconUtils::FromRequestType(iotcon_request_type_e e) {
+  ScopeLogger();
+
+  switch (e) {
+    IOTCON_REQUEST_TYPE_E
+  }
+}
+
+std::string IotconUtils::FromObserveType(iotcon_observe_type_e e) {
+  ScopeLogger();
+
+  switch (e) {
+    IOTCON_OBSERVE_TYPE_E
+  }
+}
+
+std::string IotconUtils::FromInterface(iotcon_interface_e e) {
+  ScopeLogger();
+
+  switch (e) {
+    IOTCON_INTERFACE_E
+  }
+}
+
+#undef X
+#undef XD
+
+#define X(v, s) if (e == s) return v;
+#define XD(v, s) \
+  LoggerE("Unknown value: %s, returning default: %d", e.c_str(), v); \
+  return v;
+
+iotcon_interface_e IotconUtils::ToInterface(const std::string& e) {
+  ScopeLogger();
+
+  IOTCON_INTERFACE_E
+}
+
+#undef X
+#undef XD
+
 } // namespace iotcon
 } // namespace extension
index 4c1cac068b043e0964ba027b27a3be9c01de0eff..6861103751aafddbdc2bab7ac912e627f22000a7 100644 (file)
 #ifndef WEBAPI_PLUGINS_IOTCON_IOTCON_UTILS_H__
 #define WEBAPI_PLUGINS_IOTCON_IOTCON_UTILS_H__
 
-#include <string>
-#include <memory>
-#include <vector>
 #include <map>
+#include <memory>
+#include <set>
 #include <stdlib.h>
+#include <string>
+#include <unordered_map>
+#include <vector>
 
 #include <iotcon.h>
 
+#include "common/tizen_instance.h"
 #include "common/tizen_result.h"
 
 namespace extension {
@@ -40,16 +43,23 @@ extern const std::string kResourceTypes;
 extern const std::string kResourceInterfaces;
 extern const std::string kResourceChildren;
 extern const std::string kUriPath;
-extern const std::string kResourceId;
+extern const std::string kStates;
+extern const std::string kId;
 
 struct ResourceInfo {
   long long id;
   std::vector<long long> children_ids;
   iotcon_resource_h handle;
+  std::set<int> observers;
+  common::PostCallback request_listener;
+  std::unordered_map<long long, iotcon_response_h> unhandled_responses;
   ResourceInfo() :
     id(0), handle(nullptr) {}
   ~ResourceInfo() {
-    iotcon_resource_destroy (handle);
+    iotcon_resource_destroy(handle);
+    for (auto& it : unhandled_responses) {
+      iotcon_response_destroy(it.second);
+    }
   }
 };
 
@@ -60,7 +70,6 @@ class IotconServerManager;
 
 class IotconUtils {
  public:
-  static common::TizenResult StringToInterface(const std::string& interface, iotcon_interface_e* res);
   static common::TizenResult ArrayToInterfaces(const picojson::array& interfaces, int* res);
   static picojson::array InterfacesToArray(int interfaces);
   static common::TizenResult ArrayToTypes(const picojson::array& types, iotcon_resource_types_h* res);
@@ -73,7 +82,26 @@ class IotconUtils {
                                             const IotconServerManager& manager,
                                             picojson::object* res);
 
+  static common::TizenResult RequestToJson(iotcon_request_h request,
+                                           picojson::object* out);
+  static common::TizenResult RepresentationToJson(iotcon_representation_h representation,
+                                                  picojson::object* out);
+  static common::TizenResult StateToJson(iotcon_state_h state,
+                                         picojson::object* out);
+  static common::TizenResult StateListToJson(iotcon_list_h list,
+                                             picojson::array* out);
+  static common::TizenResult OptionsToJson(iotcon_options_h  options,
+                                           picojson::array* out);
+  static common::TizenResult QueryToJson(iotcon_query_h query,
+                                         picojson::object* out);
+
   static common::TizenResult ConvertIotconError(int error);
+  static std::string FromConnectivityType(iotcon_connectivity_type_e e);
+  static std::string FromRequestType(iotcon_request_type_e e);
+  static std::string FromObserveType(iotcon_observe_type_e e);
+  static std::string FromInterface(iotcon_interface_e e);
+
+  static iotcon_interface_e ToInterface(const std::string& e);
 };
 
 } // namespace iotcon