From 841e0abe41d699b0a4aa4376fac8e63ed70c271c Mon Sep 17 00:00:00 2001
From: Pawel Andruszkiewicz
Date: Wed, 10 Feb 2016 10:59:19 +0100
Subject: [PATCH] [iotcon] Implementation of
Resource.addChildResource()/removeChildResource().
Change-Id: I94f127970b3ea39da131e7f893c02da2e3c2cdbd
Signed-off-by: Pawel Andruszkiewicz
---
src/iotcon/iotcon_api.js | 31 +++++++------
src/iotcon/iotcon_instance.cc | 67 +++++++++++++++++++++++++----
src/iotcon/iotcon_instance.h | 6 +--
src/iotcon/iotcon_server_manager.cc | 45 +++++++++++++------
src/iotcon/iotcon_utils.cc | 21 +++------
src/iotcon/iotcon_utils.h | 11 +++--
6 files changed, 125 insertions(+), 56 deletions(-)
diff --git a/src/iotcon/iotcon_api.js b/src/iotcon/iotcon_api.js
index 98e7ffc2..5a8a331a 100644
--- a/src/iotcon/iotcon_api.js
+++ b/src/iotcon/iotcon_api.js
@@ -381,40 +381,47 @@ Resource.prototype.addResourceInterfaces = function() {
Resource.prototype.addChildResource = function() {
var args = validator.validateMethod(arguments, [{
name: 'resource',
- type: types_.PLATFORM_OBJECT,
- values: Resource,
- optional: false,
- nullable: false
+ type: types.PLATFORM_OBJECT,
+ values: Resource
}]);
var callArgs = {};
callArgs.id = this[kIdKey];
- callArgs.resource = args.resource;
+ callArgs.childId = args.resource[kIdKey];
- var result = native.call('IotconResource_addChildResource', callArgs);
+ var result = native.callSync('IotconResource_addChildResource', callArgs);
if (native.isFailure(result)) {
throw native.getErrorObject(result);
+ } else {
+ var children = this.resources;
+ children.push(args.resource);
+ updateWithInternalData({ resources: children }, this);
}
};
Resource.prototype.removeChildResource = function() {
var args = validator.validateMethod(arguments, [{
name: 'resource',
- type: types_.PLATFORM_OBJECT,
- values: Resource,
- optional: false,
- nullable: false
+ type: types.PLATFORM_OBJECT,
+ values: Resource
}]);
var callArgs = {};
callArgs.id = this[kIdKey];
- callArgs.resource = args.resource;
+ callArgs.childId = args.resource[kIdKey];
- var result = native.call('IotconResource_removeChildResource', callArgs);
+ var result = native.callSync('IotconResource_removeChildResource', callArgs);
if (native.isFailure(result)) {
throw native.getErrorObject(result);
+ } else {
+ var children = this.resources;
+ var position = children.indexOf(args.resource);
+ if (-1 !== position) {
+ children.splice(position, 1);
+ updateWithInternalData({ resources: children }, this);
+ }
}
};
diff --git a/src/iotcon/iotcon_instance.cc b/src/iotcon/iotcon_instance.cc
index 73243eab..092ae134 100644
--- a/src/iotcon/iotcon_instance.cc
+++ b/src/iotcon/iotcon_instance.cc
@@ -58,6 +58,7 @@ const common::ListenerToken kResourceRequestListenerToken{"ResourceRequestListen
const std::string kObserverIds = "observerIds";
const std::string kQos = "qos";
+const std::string kChildId = "childId";
} // namespace
@@ -72,6 +73,8 @@ IotconInstance::IotconInstance() {
REGISTER_SYNC("IotconResource_getObserverIds", ResourceGetObserverIds);
REGISTER_SYNC("IotconResource_notify", ResourceNotify);
+ REGISTER_SYNC("IotconResource_addChildResource", ResourceAddChildResource);
+ REGISTER_SYNC("IotconResource_removeChildResource", ResourceRemoveChildResource);
REGISTER_SYNC("IotconResource_setRequestListener", ResourceSetRequestListener);
REGISTER_SYNC("IotconResource_unsetRequestListener", ResourceUnsetRequestListener);
REGISTER_SYNC("IotconResponse_send", ResponseSend);
@@ -96,8 +99,6 @@ IotconInstance::IotconInstance() {
REGISTER_ASYNC("IotconResource_addResourceTypes", ResourceAddResourceTypes);
REGISTER_ASYNC("IotconResource_addResourceInterfaces", ResourceAddResourceInterfaces);
- REGISTER_ASYNC("IotconResource_addChildResource", ResourceAddChildResource);
- REGISTER_ASYNC("IotconResource_removeChildResource", ResourceRemoveChildResource);
REGISTER_ASYNC("IotconRemoteResource_methodGet", RemoteResourceMethodGet);
REGISTER_ASYNC("IotconRemoteResource_methodPut", RemoteResourceMethodPut);
REGISTER_ASYNC("IotconRemoteResource_methodPost", RemoteResourceMethodPost);
@@ -246,16 +247,66 @@ common::TizenResult IotconInstance::ResourceAddResourceInterfaces(const picojson
return common::UnknownError("Not implemented");
}
-common::TizenResult IotconInstance::ResourceAddChildResource(const picojson::object& args,
- const common::AsyncToken& token) {
+common::TizenResult IotconInstance::ResourceAddChildResource(const picojson::object& args) {
ScopeLogger();
- return common::UnknownError("Not implemented");
+
+ CHECK_EXIST(args, kId);
+ CHECK_EXIST(args, kChildId);
+
+ ResourceInfoPtr parent;
+ auto result = IotconServerManager::GetInstance().GetResourceById(GetId(args), &parent);
+ if (!result) {
+ LogAndReturnTizenError(result, ("GetResourceById() parent failed"));
+ }
+
+ long long child_id = static_cast(GetArg(args, kChildId).get());
+ ResourceInfoPtr child;
+
+ result = IotconServerManager::GetInstance().GetResourceById(child_id, &child);
+ if (!result) {
+ LogAndReturnTizenError(result, ("GetResourceById() failed"));
+ }
+
+ result = IotconUtils::ConvertIotconError(iotcon_resource_bind_child_resource(parent->handle, child->handle));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_resource_bind_child_resource() failed"));
+ }
+
+ parent->children.insert(child);
+ child->parents.insert(parent);
+
+ return common::TizenSuccess();
}
-common::TizenResult IotconInstance::ResourceRemoveChildResource(const picojson::object& args,
- const common::AsyncToken& token) {
+common::TizenResult IotconInstance::ResourceRemoveChildResource(const picojson::object& args) {
ScopeLogger();
- return common::UnknownError("Not implemented");
+
+ CHECK_EXIST(args, kId);
+ CHECK_EXIST(args, kChildId);
+
+ ResourceInfoPtr parent;
+ auto result = IotconServerManager::GetInstance().GetResourceById(GetId(args), &parent);
+ if (!result) {
+ LogAndReturnTizenError(result, ("GetResourceById() parent failed"));
+ }
+
+ long long child_id = static_cast(GetArg(args, kChildId).get());
+ ResourceInfoPtr child;
+
+ result = IotconServerManager::GetInstance().GetResourceById(child_id, &child);
+ if (!result) {
+ LogAndReturnTizenError(result, ("GetResourceById() failed"));
+ }
+
+ result = IotconUtils::ConvertIotconError(iotcon_resource_unbind_child_resource(parent->handle, child->handle));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_resource_unbind_child_resource() failed"));
+ }
+
+ parent->children.erase(child);
+ child->parents.erase(parent);
+
+ return common::TizenSuccess();
}
common::TizenResult IotconInstance::ResourceSetRequestListener(const picojson::object& args) {
diff --git a/src/iotcon/iotcon_instance.h b/src/iotcon/iotcon_instance.h
index 57b9c194..960ba497 100644
--- a/src/iotcon/iotcon_instance.h
+++ b/src/iotcon/iotcon_instance.h
@@ -37,10 +37,8 @@ class IotconInstance : public common::TizenInstance {
const common::AsyncToken& token);
common::TizenResult ResourceAddResourceInterfaces(const picojson::object& args,
const common::AsyncToken& token);
- common::TizenResult ResourceAddChildResource(const picojson::object& args,
- const common::AsyncToken& token);
- common::TizenResult ResourceRemoveChildResource(const picojson::object& args,
- const common::AsyncToken& token);
+ common::TizenResult ResourceAddChildResource(const picojson::object& args);
+ common::TizenResult ResourceRemoveChildResource(const picojson::object& args);
common::TizenResult ResourceSetRequestListener(const picojson::object& args);
common::TizenResult ResourceUnsetRequestListener(const picojson::object& args);
common::TizenResult ResponseSend(const picojson::object& args);
diff --git a/src/iotcon/iotcon_server_manager.cc b/src/iotcon/iotcon_server_manager.cc
index 19ae602c..9a1144eb 100644
--- a/src/iotcon/iotcon_server_manager.cc
+++ b/src/iotcon/iotcon_server_manager.cc
@@ -43,14 +43,15 @@ IotconServerManager& IotconServerManager::GetInstance() {
TizenResult IotconServerManager::RestoreHandles() {
ScopeLogger();
- for (auto it = resource_map_.begin(); it != resource_map_.end(); ++it) {
- LoggerD ("Restoring handle for resource with id: %lld", it->first);
- ResourceInfoPtr resource = it->second;
+ for (const auto& it : resource_map_) {
+ LoggerD("Restoring handle for resource with id: %lld", it.first);
+ ResourceInfoPtr resource = it.second;
char* uri_path = nullptr;
iotcon_resource_types_h res_types = nullptr;
int ifaces = 0;
int properties = 0;
+
auto res = IotconUtils::ExtractFromResource(resource, &uri_path,
&res_types, &ifaces, &properties);
if (!res){
@@ -76,9 +77,16 @@ TizenResult IotconServerManager::RestoreHandles() {
iotcon_resource_destroy(old_handle);
}
}
- // TODO
- // bind children (consider if it is necessary?
- // Maybe holding children in resource_map is enough)
+
+ // rebind children
+ for (const auto& it : resource_map_) {
+ for (const auto& child : it.second->children) {
+ auto result = IotconUtils::ConvertIotconError(iotcon_resource_bind_child_resource(it.second->handle, child->handle));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_resource_bind_child_resource() failed"));
+ }
+ }
+ }
return TizenSuccess();
}
@@ -206,8 +214,7 @@ TizenResult IotconServerManager::GetResourceById(long long id,
auto it = resource_map_.find(id);
if (it == resource_map_.end()) {
- LoggerE("Not found such resource");
- return LogAndCreateTizenError(NotFoundError, "Not found such resource");
+ return LogAndCreateTizenError(NotFoundError, "Resource with specified ID does not exist");
}
LoggerE("Resource found");
*res_pointer = it->second;
@@ -218,11 +225,25 @@ TizenResult IotconServerManager::GetResourceById(long long id,
common::TizenResult IotconServerManager::DestroyResource(long long id) {
ScopeLogger();
- if (resource_map_.erase(id)) {
- return TizenSuccess();
- } else {
- return LogAndCreateTizenError(NotFoundError, "Resource with specified ID does not exist");
+ ResourceInfoPtr resource;
+ auto result = GetResourceById(id, &resource);
+ if (!result) {
+ LogAndReturnTizenError(result, ("GetResourceById() failed"));
}
+
+ // do not allow to destroy a resource which has a parent resource
+ if (resource->parents.size() > 0) {
+ return LogAndCreateTizenError(InvalidStateError, "Cannot destroy child resource, remove it from parent first");
+ }
+
+ // notify children they've lost a parent :(
+ for (const auto& child : resource->children) {
+ child->parents.erase(resource);
+ }
+
+ resource_map_.erase(id);
+
+ return TizenSuccess();
}
common::TizenResult IotconServerManager::GetResourceByHandle(
diff --git a/src/iotcon/iotcon_utils.cc b/src/iotcon/iotcon_utils.cc
index b91060e5..7b19dc89 100644
--- a/src/iotcon/iotcon_utils.cc
+++ b/src/iotcon/iotcon_utils.cc
@@ -260,26 +260,15 @@ TizenResult IotconUtils::ResourceToJson(ResourceInfoPtr pointer,
res->insert(std::make_pair(kIsExplicitDiscoverable, picojson::value(value)));
picojson::array children;
- for (auto iter = pointer->children_ids.begin(); iter != pointer->children_ids.end(); ++iter) {
- if (pointer->id == (*iter)) {
- // prevent infinite recurrence
- continue;
- }
- ResourceInfoPtr resource;
- ret = IotconServerManager::GetInstance().GetResourceById((*iter), &resource);
+ for (const auto& child_resource : pointer->children) {
+ picojson::value child = picojson::value(picojson::object());
+ ret = IotconUtils::ResourceToJson(child_resource, &(child.get()));
if (ret.IsSuccess()) {
- LoggerD("Found children RESOURCE\nid: %lld\nhandle: %p", resource->id, resource->handle);
-
- picojson::value child = picojson::value(picojson::object());
- ret = IotconUtils::ResourceToJson(resource, &(child.get()));
- if (ret.IsSuccess()) {
- children.push_back(child);
- }
- } else {
- LoggerD("Not found such resource");
+ children.push_back(child);
}
}
res->insert(std::make_pair(kResourceChildren, picojson::value(children)));
+
// observerIds would be done on demand from JS
return TizenSuccess();
diff --git a/src/iotcon/iotcon_utils.h b/src/iotcon/iotcon_utils.h
index efe13f23..bfcfd747 100644
--- a/src/iotcon/iotcon_utils.h
+++ b/src/iotcon/iotcon_utils.h
@@ -48,13 +48,19 @@ extern const std::string kId;
extern const std::string kHostAddress;
extern const std::string kConnectivityType;
+class ResourceInfo;
+typedef std::shared_ptr ResourceInfoPtr;
+typedef std::map ResourceInfoMap;
+
struct ResourceInfo {
long long id;
- std::vector children_ids;
iotcon_resource_h handle;
std::set observers;
common::PostCallback request_listener;
std::unordered_map unhandled_responses;
+ std::set children;
+ std::set parents;
+
ResourceInfo() :
id(0), handle(nullptr) {}
~ResourceInfo() {
@@ -65,9 +71,6 @@ struct ResourceInfo {
}
};
-typedef std::shared_ptr ResourceInfoPtr;
-typedef std::map ResourceInfoMap;
-
class IotconUtils {
public:
static common::TizenResult ArrayToInterfaces(const picojson::array& interfaces, int* res);
--
2.34.1