From: Pawel Andruszkiewicz
Date: Thu, 11 Feb 2016 07:48:07 +0000 (+0100)
Subject: [iotcon] Implementation of Response.send().
X-Git-Tag: submit/tizen/20160222.104327^2~14
X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=02fd865a58307ce45b20b474e2f0e1dd1dcbf228;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git
[iotcon] Implementation of Response.send().
Change-Id: Idced64c3cf411aaf2c217b3ddd9c2c34a194cb5b
Signed-off-by: Pawel Andruszkiewicz
---
diff --git a/src/iotcon/iotcon_api.js b/src/iotcon/iotcon_api.js
index cee73089..288447b9 100644
--- a/src/iotcon/iotcon_api.js
+++ b/src/iotcon/iotcon_api.js
@@ -496,11 +496,18 @@ function Response(request) {
}
Response.prototype.send = function() {
+ var args = validator.validateMethod(arguments, [{
+ name: 'iface',
+ type: types.ENUM,
+ values: T.getValues(ResourceInterface)
+ }]);
+
var callArgs = {};
callArgs.id = this.request[kIdKey];
callArgs.result = this.result;
callArgs.representation = this.representation;
callArgs.options = this.options;
+ callArgs.iface = args.iface;
var result = native.callSync('IotconResponse_send', callArgs);
diff --git a/src/iotcon/iotcon_instance.cc b/src/iotcon/iotcon_instance.cc
index ae913dff..3f024f64 100644
--- a/src/iotcon/iotcon_instance.cc
+++ b/src/iotcon/iotcon_instance.cc
@@ -65,6 +65,7 @@ const std::string kQos = "qos";
const std::string kChildId = "childId";
const std::string kType = "type";
const std::string kInterface = "iface";
+const std::string kResult = "result";
const std::string kTimeout = "timeout";
} // namespace
@@ -422,7 +423,79 @@ common::TizenResult IotconInstance::ResourceUnsetRequestListener(const picojson:
common::TizenResult IotconInstance::ResponseSend(const picojson::object& args) {
ScopeLogger();
- return common::UnknownError("Not implemented");
+
+ CHECK_EXIST(args, kId);
+ CHECK_EXIST(args, kResult);
+ CHECK_EXIST(args, kRepresentation);
+ CHECK_EXIST(args, kOptions);
+ CHECK_EXIST(args, kInterface);
+
+ ResponsePtr response = nullptr;
+ auto result = IotconServerManager::GetInstance().GetResponseById(GetId(args), &response);
+ if (!result) {
+ LogAndReturnTizenError(result, ("GetResponseById() failed"));
+ }
+
+ {
+ const auto& js_response_result = GetArg(args, kResult);
+ if (!js_response_result.is()) {
+ return LogAndCreateTizenError(TypeMismatchError, "ResponseResult should be a string");
+ }
+ iotcon_response_result_e response_result = IotconUtils::ToResponseResult(js_response_result.get());
+
+ result = IotconUtils::ConvertIotconError(iotcon_response_set_result(response.get(), response_result));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_response_set_result() failed"));
+ }
+ }
+
+ {
+ const auto& js_representation = GetArg(args, kRepresentation);
+ if (!js_representation.is()) {
+ return LogAndCreateTizenError(TypeMismatchError, "Representation should be an object");
+ }
+ iotcon_representation_h representation = nullptr;
+ result = IotconUtils::RepresentationFromJson(js_representation.get(), &representation);
+ if (!result) {
+ LogAndReturnTizenError(result, ("RepresentationFromJson() failed"));
+ }
+ SCOPE_EXIT {
+ iotcon_representation_destroy(representation);
+ };
+
+ result = IotconUtils::ConvertIotconError(iotcon_response_set_representation(response.get(), IotconUtils::ToInterface(GetArg(args, kInterface).get()), representation));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_response_set_representation() failed"));
+ }
+ }
+
+ {
+ const auto& js_options = GetArg(args, kOptions);
+
+ if (js_options.is()) {
+ iotcon_options_h options = nullptr;
+
+ result = IotconUtils::OptionsFromJson(js_options.get(), &options);
+ if (!result) {
+ LogAndReturnTizenError(result, ("OptionsFromJson() failed"));
+ }
+ SCOPE_EXIT {
+ iotcon_options_destroy(options);
+ };
+
+ result = IotconUtils::ConvertIotconError(iotcon_response_set_options(response.get(), options));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_response_set_options() failed"));
+ }
+ }
+ }
+
+ result = IotconUtils::ConvertIotconError(iotcon_response_send(response.get()));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_response_send() failed"));
+ }
+
+ return common::TizenSuccess();
}
common::TizenResult IotconInstance::RemoteResourceGetCachedRepresentation(const picojson::object& args) {
diff --git a/src/iotcon/iotcon_server_manager.cc b/src/iotcon/iotcon_server_manager.cc
index 9a1144eb..079e7832 100644
--- a/src/iotcon/iotcon_server_manager.cc
+++ b/src/iotcon/iotcon_server_manager.cc
@@ -161,7 +161,7 @@ void IotconServerManager::RequestHandler(iotcon_resource_h resource,
// store data
long long id = GetNextId();
obj.insert(std::make_pair(kId, picojson::value{static_cast(id)}));
- r->unhandled_responses.insert(std::make_pair(id, response));
+ r->pending_responses.insert(std::make_pair(id, ResponsePtr{response, &iotcon_response_destroy}));
// call listener
r->request_listener(TizenSuccess(), value);
@@ -264,5 +264,19 @@ common::TizenResult IotconServerManager::GetResourceByHandle(
return TizenSuccess();
}
+common::TizenResult IotconServerManager::GetResponseById(long long id, ResponsePtr* out) const {
+ ScopeLogger();
+
+ for (const auto& resource : resource_map_) {
+ const auto& it = resource.second->pending_responses.find(id);
+ if (resource.second->pending_responses.end() != it) {
+ *out = it->second;
+ return TizenSuccess();
+ }
+ }
+
+ return LogAndCreateTizenError(NotFoundError, "Response with specified ID does not exist");
+}
+
} // namespace iotcon
} // namespace extension
diff --git a/src/iotcon/iotcon_server_manager.h b/src/iotcon/iotcon_server_manager.h
index b15e362f..3f9d8ef8 100644
--- a/src/iotcon/iotcon_server_manager.h
+++ b/src/iotcon/iotcon_server_manager.h
@@ -44,6 +44,7 @@ class IotconServerManager {
common::TizenResult GetResourceById(long long id, ResourceInfoPtr* res_pointer) const;
common::TizenResult DestroyResource(long long id);
common::TizenResult GetResourceByHandle(iotcon_resource_h resource, ResourceInfoPtr* res_pointer) const;
+ common::TizenResult GetResponseById(long long id, ResponsePtr* out) const;
private:
IotconServerManager() = default;
diff --git a/src/iotcon/iotcon_utils.cc b/src/iotcon/iotcon_utils.cc
index 88c8a711..6f2a99f9 100644
--- a/src/iotcon/iotcon_utils.cc
+++ b/src/iotcon/iotcon_utils.cc
@@ -76,6 +76,15 @@ namespace {
X(IOTCON_PRESENCE_RESOURCE_UPDATED, "UPDATED") \
XD(IOTCON_PRESENCE_RESOURCE_DESTROYED, "DESTROYED")
+#define IOTCON_RESPONSE_RESULT_E \
+ X(IOTCON_RESPONSE_OK, "SUCCESS") \
+ X(IOTCON_RESPONSE_ERROR, "ERROR") \
+ X(IOTCON_RESPONSE_RESOURCE_CREATED, "RESOURCE_CREATED") \
+ X(IOTCON_RESPONSE_RESOURCE_DELETED, "RESOURCE_DELETED") \
+ X(IOTCON_RESPONSE_SLOW, "SLOW") \
+ X(IOTCON_RESPONSE_FORBIDDEN, "FORBIDDEN") \
+ XD(IOTCON_RESPONSE_ERROR, "unknown")
+
} // namespace
const std::string kIsDiscoverable = "isDiscoverable";
@@ -1338,6 +1347,155 @@ common::TizenResult IotconUtils::ExtractFromPresenceEvent(const PresenceEventPtr
return TizenSuccess();
}
+common::TizenResult IotconUtils::OptionsFromJson(const picojson::array& o,
+ iotcon_options_h* out) {
+ ScopeLogger();
+
+ iotcon_options_h options = nullptr;
+
+ auto result = ConvertIotconError(iotcon_options_create(&options));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_options_create() failed"));
+ }
+
+ std::unique_ptr::type, void(*)(iotcon_options_h)> ptr{options, &iotcon_options_destroy};
+
+ // we ignore values with incorrect types
+ // TODO: should we convert them in JS?
+ for (const auto& option : o) {
+ if (option.is()) {
+ const auto& js_id = option.get(kOptionsId);
+ const auto& js_data = option.get(kOptionsData);
+
+ if (js_id.is() && js_data.is()) {
+ result = ConvertIotconError(iotcon_options_add(options, js_id.get(), js_data.get().c_str()));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_options_add() failed"));
+ }
+ }
+ }
+ }
+
+ *out = ptr.release();
+ return TizenSuccess();
+}
+
+common::TizenResult IotconUtils::RepresentationFromJson(const picojson::object& r,
+ iotcon_representation_h* out) {
+ ScopeLogger();
+
+ iotcon_representation_h representation = nullptr;
+
+ auto result = ConvertIotconError(iotcon_representation_create(&representation));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_representation_create() failed"));
+ }
+
+ std::unique_ptr::type, void(*)(iotcon_representation_h)> ptr{representation, &iotcon_representation_destroy};
+
+ {
+ const auto& uri_path = r.find(kUriPath);
+ if (r.end() != uri_path && uri_path->second.is()) {
+ result = ConvertIotconError(iotcon_representation_set_uri_path(representation, uri_path->second.get().c_str()));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_representation_set_uri_path() failed"));
+ }
+ } else {
+ return LogAndCreateTizenError(TypeMismatchError, "Representation object needs to have an uriPath attribute which is a string.");
+ }
+ }
+
+ {
+ const auto& resource_types = r.find(kResourceTypes);
+ if (r.end() != resource_types && resource_types->second.is()) {
+ iotcon_resource_types_h types = nullptr;
+
+ result = ArrayToTypes(resource_types->second.get(), &types);
+ if (!result) {
+ LogAndReturnTizenError(result, ("ArrayToTypes() failed"));
+ }
+ SCOPE_EXIT {
+ iotcon_resource_types_destroy(types);
+ };
+
+ result = ConvertIotconError(iotcon_representation_set_resource_types(representation, types));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_representation_set_resource_types() failed"));
+ }
+ } else {
+ return LogAndCreateTizenError(TypeMismatchError, "Representation object needs to have a resourceTypes attribute which is an array.");
+ }
+ }
+
+ {
+ const auto& resource_interfaces = r.find(kResourceInterfaces);
+ if (r.end() != resource_interfaces && resource_interfaces->second.is()) {
+ int interfaces = IOTCON_INTERFACE_NONE;
+
+ result = ArrayToInterfaces(resource_interfaces->second.get(), &interfaces);
+ if (!result) {
+ LogAndReturnTizenError(result, ("ArrayToInterfaces() failed"));
+ }
+
+ result = ConvertIotconError(iotcon_representation_set_resource_interfaces(representation, interfaces));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_representation_set_resource_interfaces() failed"));
+ }
+ } else {
+ return LogAndCreateTizenError(TypeMismatchError, "Representation object needs to have a resourceInterfaces attribute which is an array.");
+ }
+ }
+
+ {
+ const auto& states = r.find(kStates);
+ if (r.end() != states && states->second.is()) {
+ iotcon_state_h s = nullptr;
+
+ result = StateFromJson(states->second.get(), &s);
+ if (!result) {
+ LogAndReturnTizenError(result, ("StateFromJson() failed"));
+ }
+ SCOPE_EXIT {
+ iotcon_state_destroy(s);
+ };
+
+ result = ConvertIotconError(iotcon_representation_set_state(representation, s));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_representation_set_state() failed"));
+ }
+ }
+ }
+
+ {
+ const auto& representations = r.find(kRepresentations);
+ if (r.end() != representations && representations->second.is()) {
+ for (const auto& js_child : representations->second.get()) {
+ if (js_child.is()) {
+ iotcon_representation_h child = nullptr;
+
+ result = RepresentationFromJson(js_child.get(), &child);
+ if (!result) {
+ LogAndReturnTizenError(result, ("RepresentationFromJson() failed"));
+ }
+ SCOPE_EXIT {
+ iotcon_representation_destroy(child);
+ };
+
+ result = ConvertIotconError(iotcon_representation_add_child(representation, child));
+ if (!result) {
+ LogAndReturnTizenError(result, ("iotcon_representation_add_child() failed"));
+ }
+ } else {
+ return LogAndCreateTizenError(TypeMismatchError, "The Representation.representations attribute needs to be an array of Representation objects.");
+ }
+ }
+ }
+ }
+
+ *out = ptr.release();
+ return TizenSuccess();
+}
+
common::TizenResult IotconUtils::PlatformInfoGetProperty(iotcon_platform_info_h platform,
iotcon_platform_info_e property_e,
const std::string& name,
@@ -1641,6 +1799,10 @@ iotcon_connectivity_type_e IotconUtils::ToConnectivityType(const std::string& e)
IOTCON_CONNECTIVITY_TYPE_E
}
+iotcon_response_result_e IotconUtils::ToResponseResult(const std::string& e) {
+ IOTCON_RESPONSE_RESULT_E
+}
+
#undef X
#undef XD
diff --git a/src/iotcon/iotcon_utils.h b/src/iotcon/iotcon_utils.h
index b8fb9345..e171dcfe 100644
--- a/src/iotcon/iotcon_utils.h
+++ b/src/iotcon/iotcon_utils.h
@@ -50,6 +50,8 @@ extern const std::string kDeviceId;
extern const std::string kHostAddress;
extern const std::string kConnectivityType;
extern const std::string kResourceType;
+extern const std::string kRepresentation;
+extern const std::string kOptions;
class ResourceInfo;
class PresenceEvent;
@@ -59,12 +61,14 @@ typedef std::map ResourceInfoMap;
typedef std::shared_ptr PresenceEventPtr;
typedef std::map PresenceMap;
+using ResponsePtr = std::shared_ptr::type>;
+
struct ResourceInfo {
long long id;
iotcon_resource_h handle;
std::set observers;
common::PostCallback request_listener;
- std::unordered_map unhandled_responses;
+ std::unordered_map pending_responses;
std::set children;
std::set parents;
@@ -72,9 +76,6 @@ struct ResourceInfo {
id(0), handle(nullptr) {}
~ResourceInfo() {
iotcon_resource_destroy(handle);
- for (auto& it : unhandled_responses) {
- iotcon_response_destroy(it.second);
- }
}
};
@@ -161,6 +162,10 @@ class IotconUtils {
iotcon_state_h* out);
static common::TizenResult StateListFromJson(const picojson::array& list,
iotcon_list_h* out);
+ static common::TizenResult OptionsFromJson(const picojson::array& options,
+ iotcon_options_h* out);
+ static common::TizenResult RepresentationFromJson(const picojson::object& representation,
+ iotcon_representation_h* out);
static common::TizenResult ConvertIotconError(int error);
static std::string FromConnectivityType(iotcon_connectivity_type_e e);
@@ -173,6 +178,7 @@ class IotconUtils {
static iotcon_interface_e ToInterface(const std::string& e);
static iotcon_connectivity_type_e ToConnectivityType(const std::string& e);
static iotcon_qos_e ToQos(const std::string& e);
+ static iotcon_response_result_e ToResponseResult(const std::string& e);
};
} // namespace iotcon