From cb73638e58ab69a39c73ae2798da7396d60ff2a7 Mon Sep 17 00:00:00 2001 From: Somin Kim Date: Thu, 21 Jan 2016 13:58:06 +0900 Subject: [PATCH] Added custom provider Change-Id: I4fee414b0d952b02e0256bf71f6e4a7c05593167 Signed-off-by: Somin Kim --- include/custom_context_provider.h | 33 +++++ src/CMakeLists.txt | 1 + src/custom/CMakeLists.txt | 25 ++++ src/custom/custom_base.cpp | 91 +++++++++++++ src/custom/custom_base.h | 55 ++++++++ src/custom/custom_context_provider.cpp | 180 +++++++++++++++++++++++++ 6 files changed, 385 insertions(+) create mode 100644 include/custom_context_provider.h create mode 100644 src/custom/CMakeLists.txt create mode 100644 src/custom/custom_base.cpp create mode 100644 src/custom/custom_base.h create mode 100644 src/custom/custom_context_provider.cpp diff --git a/include/custom_context_provider.h b/include/custom_context_provider.h new file mode 100644 index 0000000..584cf3b --- /dev/null +++ b/include/custom_context_provider.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_CUSTOM_CONTEXT_PROVIDER_H__ +#define __CONTEXT_CUSTOM_CONTEXT_PROVIDER_H__ + +namespace ctx { + bool init_custom_context_provider(); + + namespace custom_context_provider { + int add_item(std::string subject, std::string name, ctx::json tmpl, const char* owner); + int remove_item(std::string subject); + int publish_data(std::string subject, ctx::json fact); + + context_provider_iface* create(void* data); + void destroy(void* data); + } +} + +#endif //__CONTEXT_CUSTOM_CONTEXT_PROVIDER_H__ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ed81952..737a746 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,7 @@ ENDFUNCTION(add_provider) add_provider(device) add_provider(statistics) add_provider(place) +add_provider(custom) SEPARATE_ARGUMENTS(deps_list) LIST(REMOVE_DUPLICATES deps_list) diff --git a/src/custom/CMakeLists.txt b/src/custom/CMakeLists.txt new file mode 100644 index 0000000..881c3a4 --- /dev/null +++ b/src/custom/CMakeLists.txt @@ -0,0 +1,25 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(target "ctx-custom") + +# Common Profile +FILE(GLOB srcs ./*.cpp) + +MESSAGE("Custom Provider Sources: ${srcs}") + +# Build +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(custom_pkgs REQUIRED ${deps_common}) + +FOREACH(flag ${custom_pkgs_CFLAGS}) + SET(extra_cflags "${extra_cflags} ${flag}") +ENDFOREACH(flag) + +ADD_LIBRARY(${target} SHARED ${srcs}) +TARGET_LINK_LIBRARIES(${target} ${custom_pkgs_LDFLAGS}) +SET_TARGET_PROPERTIES(${target} PROPERTIES COMPILE_FLAGS ${extra_cflags}) +SET_TARGET_PROPERTIES(${target} PROPERTIES COMPILE_DEFINITIONS "LOG_TAG=\"CONTEXT-CUSTOM\"") +SET_TARGET_PROPERTIES(${target} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${target} PROPERTIES VERSION ${FULLVER}) + +# Install +INSTALL(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT RuntimeLibraries) diff --git a/src/custom/custom_base.cpp b/src/custom/custom_base.cpp new file mode 100644 index 0000000..59cbec9 --- /dev/null +++ b/src/custom/custom_base.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "custom_base.h" + +ctx::custom_base::custom_base(std::string subject, std::string name, ctx::json tmpl, std::string owner) : + _subject(subject), + _name(name), + _tmpl(tmpl), + _owner(owner) +{ +} + +ctx::custom_base::~custom_base() +{ +} + +bool ctx::custom_base::is_supported() +{ + return true; +} + +void ctx::custom_base::submit_trigger_item() +{ + context_manager::register_trigger_item(_subject.c_str(), OPS_SUBSCRIBE | OPS_READ, + _tmpl.str(), NULL, _owner.c_str()); +} + +void ctx::custom_base::unsubmit_trigger_item() +{ + context_manager::unregister_trigger_item(_subject.c_str()); +} + +int ctx::custom_base::subscribe(const char *subject, ctx::json option, ctx::json *request_result) +{ + return ERR_NONE; + +} + +int ctx::custom_base::unsubscribe(const char *subject, ctx::json option) +{ + return ERR_NONE; +} + +int ctx::custom_base::read(const char *subject, ctx::json option, ctx::json *request_result) +{ + ctx::json data = latest.str(); + ctx::context_manager::reply_to_read(_subject.c_str(), NULL, ERR_NONE, data); + return ERR_NONE; +} + +int ctx::custom_base::write(const char *subject, ctx::json data, ctx::json *request_result) +{ + return ERR_NONE; +} + +void ctx::custom_base::handle_update(ctx::json data) +{ + // Store latest state + latest = data.str(); + ctx::context_manager::publish(_subject.c_str(), NULL, ERR_NONE, data); +} + +const char* ctx::custom_base::get_subject() +{ + return _subject.c_str(); +} + +std::string ctx::custom_base::get_owner() +{ + return _owner; +} + +ctx::json ctx::custom_base::get_template() +{ + return _tmpl; +} diff --git a/src/custom/custom_base.h b/src/custom/custom_base.h new file mode 100644 index 0000000..e2e8bce --- /dev/null +++ b/src/custom/custom_base.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CUSTOM_BASE_H_ +#define _CUSTOM_BASE_H_ + +#include +#include +#include + +namespace ctx { + + class custom_base : public context_provider_iface { + public: + custom_base(std::string subject, std::string name, ctx::json tmpl, std::string owner); + ~custom_base(); + + int subscribe(const char *subject, ctx::json option, ctx::json *request_result); + int unsubscribe(const char *subject, ctx::json option); + int read(const char *subject, ctx::json option, ctx::json *request_result); + int write(const char *subject, ctx::json data, ctx::json *request_result); + + static bool is_supported(); + void submit_trigger_item(); + void unsubmit_trigger_item(); + + void handle_update(ctx::json data); + + const char* get_subject(); + std::string get_owner(); + ctx::json get_template(); + + private: + std::string _subject; + std::string _name; + ctx::json _tmpl; + std::string _owner; + ctx::json latest; + }; +} + +#endif // _CUSTOM_BASE_H_ diff --git a/src/custom/custom_context_provider.cpp b/src/custom/custom_context_provider.cpp new file mode 100644 index 0000000..923fa1a --- /dev/null +++ b/src/custom/custom_context_provider.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "custom_base.h" + +std::map custom_map; + +static bool is_valid_fact(std::string subject, ctx::json& fact); +static bool check_value_int(ctx::json& tmpl, std::string key, int value); +static bool check_value_string(ctx::json& tmpl, std::string key, std::string value); + +void register_provider(const char *subject, const char *privilege) +{ + ctx::context_provider_info provider_info(ctx::custom_context_provider::create, + ctx::custom_context_provider::destroy, + const_cast(subject), privilege); + ctx::context_manager::register_provider(subject, provider_info); + custom_map[subject]->submit_trigger_item(); +} + +void unregister_provider(const char* subject) +{ + custom_map[subject]->unsubmit_trigger_item(); + ctx::context_manager::unregister_provider(subject); +} + +EXTAPI ctx::context_provider_iface* ctx::custom_context_provider::create(void *data) +{ + // Already created in add_item() function. Return corresponding custom provider + return custom_map[static_cast(data)]; +} + +EXTAPI void ctx::custom_context_provider::destroy(void *data) +{ + std::map::iterator it = custom_map.find(static_cast(data)); + if (it != custom_map.end()) { + delete it->second; + custom_map.erase(it); + } +} + +EXTAPI bool ctx::init_custom_context_provider() +{ + return true; +} + +EXTAPI int ctx::custom_context_provider::add_item(std::string subject, std::string name, ctx::json tmpl, const char* owner) +{ + std::map::iterator it; + it = custom_map.find(subject); + + if (it != custom_map.end()) { + if ((it->second)->get_template() != tmpl) { // Same item name, but different template + return ERR_DATA_EXIST; + } + // Same item name with same template + return ERR_NONE; + } + + // Create custom base + ctx::custom_base* custom = new(std::nothrow) custom_base(subject, name, tmpl, owner); + IF_FAIL_RETURN_TAG(custom, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + custom_map[subject] = custom; + + register_provider(custom->get_subject(), NULL); + + return ERR_NONE; +} + +EXTAPI int ctx::custom_context_provider::remove_item(std::string subject) +{ + std::map::iterator it; + it = custom_map.find(subject); + IF_FAIL_RETURN_TAG(it != custom_map.end(), ERR_NOT_SUPPORTED, _E, "%s not supported", subject.c_str()); + + unregister_provider(subject.c_str()); + + return ERR_NONE; +} + +EXTAPI int ctx::custom_context_provider::publish_data(std::string subject, ctx::json fact) +{ + std::map::iterator it; + it = custom_map.find(subject); + IF_FAIL_RETURN_TAG(it != custom_map.end(), ERR_NOT_SUPPORTED, _E, "%s not supported", subject.c_str()); + + bool ret = is_valid_fact(subject, fact); + IF_FAIL_RETURN_TAG(ret, ERR_INVALID_DATA, _E, "Invalid fact(%s)", subject.c_str()); + + custom_map[subject]->handle_update(fact); + return ERR_NONE; +} + +bool is_valid_fact(std::string subject, ctx::json& fact) +{ + ctx::json tmpl = custom_map[subject]->get_template(); + IF_FAIL_RETURN_TAG(tmpl != EMPTY_JSON_OBJECT, false, _E, "Failed to get template"); + + bool ret; + std::list keys; + fact.get_keys(&keys); + + for (std::list::iterator it = keys.begin(); it != keys.end(); it++) { + std::string key = *it; + + std::string type; + tmpl.get(key.c_str(), "type", &type); + if (type == "integer") { + int val; + ret = fact.get(NULL, key.c_str(), &val); + IF_FAIL_RETURN_TAG(ret, false, _E, "Custom fact: invalid data type"); + + ret = check_value_int(tmpl, key, val); + IF_FAIL_RETURN_TAG(ret, false, _E, "Custom fact: invalid value"); + } else if (type == "string") { + std::string val_str; + ret = fact.get(NULL, key.c_str(), &val_str); + IF_FAIL_RETURN_TAG(ret, false, _E, "Custom fact: invalid data type"); + + ret = check_value_string(tmpl, key, val_str); + IF_FAIL_RETURN_TAG(ret, false, _E, "Custom fact: invalid value"); + } else { + _E("Custom fact: invalid data type"); + return false; + } + } + + return true; +} + +bool check_value_int(ctx::json& tmpl, std::string key, int value) +{ + int min, max; + + if (tmpl.get(key.c_str(), "min", &min)) { + IF_FAIL_RETURN(value >= min, false); + } + + if (tmpl.get(key.c_str(), "max", &max)) { + IF_FAIL_RETURN(value <= max, false); + } + + return true; +} + +bool check_value_string(ctx::json& tmpl, std::string key, std::string value) +{ + // case1: any value is accepted + if (tmpl.array_get_size(key.c_str(), "values") <= 0) + return true; + + // case2: check acceptable value + std::string t_val; + for (int i = 0; tmpl.get_array_elem(key.c_str(), "values", i, &t_val); i++) { + if (t_val == value) + return true; + } + + return false; +} + + -- 2.34.1