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);
+ }
}
};
const std::string kObserverIds = "observerIds";
const std::string kQos = "qos";
+const std::string kChildId = "childId";
} // namespace
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);
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);
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<long long>(GetArg(args, kChildId).get<double>());
+ 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<long long>(GetArg(args, kChildId).get<double>());
+ 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) {
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);
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){
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();
}
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;
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(
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<picojson::object>()));
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<picojson::object>()));
- 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();
extern const std::string kHostAddress;
extern const std::string kConnectivityType;
+class ResourceInfo;
+typedef std::shared_ptr<ResourceInfo> ResourceInfoPtr;
+typedef std::map<long long, ResourceInfoPtr> ResourceInfoMap;
+
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;
+ std::set<ResourceInfoPtr> children;
+ std::set<ResourceInfoPtr> parents;
+
ResourceInfo() :
id(0), handle(nullptr) {}
~ResourceInfo() {
}
};
-typedef std::shared_ptr<ResourceInfo> ResourceInfoPtr;
-typedef std::map<long long, ResourceInfoPtr> ResourceInfoMap;
-
class IotconUtils {
public:
static common::TizenResult ArrayToInterfaces(const picojson::array& interfaces, int* res);