Re-establish custom provider 22/73722/6
authorSomin Kim <somin926.kim@samsung.com>
Thu, 9 Jun 2016 08:45:14 +0000 (17:45 +0900)
committerMu-Woong Lee <muwoong.lee@samsung.com>
Fri, 17 Jun 2016 10:28:10 +0000 (03:28 -0700)
Change-Id: I58f9f6e99f1d4b881cbcda57bfb80ced85a1147b
Signed-off-by: Somin Kim <somin926.kim@samsung.com>
14 files changed:
include/ProviderList.h
include/ProviderTypes.h
packaging/context-provider.spec
src/CMakeLists.txt
src/custom/CMakeLists.txt
src/custom/CreateProvider.cpp [new file with mode: 0644]
src/custom/CustomBase.cpp [deleted file]
src/custom/CustomBase.h [deleted file]
src/custom/CustomContextProvider.cpp [deleted file]
src/custom/CustomManager.cpp [new file with mode: 0644]
src/custom/CustomManager.h [new file with mode: 0644]
src/custom/CustomProvider.cpp [new file with mode: 0644]
src/custom/CustomProvider.h [new file with mode: 0644]
src/custom/CustomTypes.h [new file with mode: 0644]

index 11e54f35e7e10d67cb834a2af9476272074e3529..f1dbe3bec6351b9ed077386f60b4783ae602dc88 100644 (file)
@@ -32,7 +32,7 @@ const struct {
        {SUBJ_APP_STATS,                "app-stats"},
        {SUBJ_STATE_CALL,               "call"},
        {SUBJ_STATE_CONTACTS,   "contacts"},
-       // {SUBJ_CUSTOM, ""},
+       {SUBJ_CUSTOM,                   "custom"},
        {SUBJ_STATE_EMAIL,              "email"},
        {SUBJ_PLACE_GEOFENCE,   "geofence"},
        {SUBJ_STATE_HEADPHONE,  "headphone"},
@@ -93,6 +93,12 @@ const struct {
                "}",
                NULL
        },
+       {
+               SUBJ_CUSTOM,
+               OPS_SUBSCRIBE,
+               "{}",
+               NULL
+       },
        {
                SUBJ_STATE_EMAIL,
                OPS_SUBSCRIBE,
index 323f505d4e7b7356f1d35b200ebf51a6725af02d..ed815e39648541ae94a3f6866d4abe255619e836 100644 (file)
@@ -89,6 +89,8 @@
 #define SUBJ_PLACE_GEOFENCE            "place/geofence"
 #define SUBJ_PLACE_DETECTION   PLACE_DETECTION_SUBJECT
 
+#define SUBJ_CUSTOM                            "custom"
+
 /* Data & Option Keys */
 #define KEY_QUERY_RESULT       "QueryResult"
 #define KEY_RESULT_SIZE                "ResultSize"
index 97fb3bec849aa2dfacebd8f058b510dc436c858b..4af42f5b7c819d3f1a1f5f3e4b49f0062a1ef1bf 100644 (file)
@@ -1,6 +1,6 @@
 Name:       context-provider
 Summary:    Context Provider
-Version:    0.9.0
+Version:    0.9.1
 Release:    1
 Group:      Service/Context
 License:    Apache-2.0
index 89bbb8303f4869ff152e045a205e4a4d0cdbd202..967c384956cf068011f932773963194b46db48e3 100644 (file)
@@ -6,7 +6,7 @@ SET(DEPS
 ADD_SUBDIRECTORY(shared)
 ADD_SUBDIRECTORY(activity)
 ADD_SUBDIRECTORY(app-stats)
-#ADD_SUBDIRECTORY(custom)
+ADD_SUBDIRECTORY(custom)
 ADD_SUBDIRECTORY(headphone)
 ADD_SUBDIRECTORY(system)
 ADD_SUBDIRECTORY(time)
index 4623e2b522e3a520ad7722d9db4197c05421fcf6..412769031866537cf0e3267c576218e96a4ffc36 100644 (file)
@@ -1,5 +1,19 @@
-CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-# prvd_cdef, prvd_deps, and prvd_srcs need to be set properly
+SET(target "${target_prefix}-custom")
 
-# Common Profile
-FILE(GLOB prvd_srcs ./*.cpp)
+#SET(DEPS ${DEPS}
+#)
+
+FILE(GLOB SRCS *.cpp)
+#FILE(GLOB SRCS CreateProvider.cpp CustomManager.cpp CustomProvider.cpp)
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(PKG_CUSTOM REQUIRED ${DEPS})
+
+FOREACH(flag ${PKG_CUSTOM_CFLAGS})
+       SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+ADD_LIBRARY(${target} SHARED ${SRCS})
+TARGET_LINK_LIBRARIES(${target} ${PKG_CUSTOM_LDFLAGS} ${target_shared})
+
+INSTALL(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR}/${target_dir})
diff --git a/src/custom/CreateProvider.cpp b/src/custom/CreateProvider.cpp
new file mode 100644 (file)
index 0000000..3a57524
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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 <CreateProvider.h>
+#include "CustomManager.h"
+
+using namespace ctx;
+
+extern "C" SO_EXPORT ContextProvider* CreateProvider(const char *subject)
+{
+       static CustomManager *__customMgr = NULL;
+
+       if (!__customMgr) {
+               __customMgr = new(std::nothrow) CustomManager;
+               IF_FAIL_RETURN_TAG(__customMgr, NULL, _E, "Memory allocation failed");
+       }
+
+       /* Request from client */
+       if (STR_EQ(SUBJ_CUSTOM, subject)) {
+               return __customMgr;
+       }
+
+       /* Request for each custom provider */
+       return __customMgr->getProvider(subject);
+}
diff --git a/src/custom/CustomBase.cpp b/src/custom/CustomBase.cpp
deleted file mode 100644 (file)
index 529835b..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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 <ContextManager.h>
-#include "CustomBase.h"
-
-ctx::CustomBase::CustomBase(std::string subject, std::string name, ctx::Json tmpl, std::string owner) :
-       __subject(subject),
-       __name(name),
-       __tmpl(tmpl),
-       __owner(owner)
-{
-}
-
-ctx::CustomBase::~CustomBase()
-{
-}
-
-bool ctx::CustomBase::isSupported()
-{
-       return true;
-}
-
-void ctx::CustomBase::submitTriggerItem()
-{
-       context_manager::registerTriggerItem(__subject.c_str(), OPS_SUBSCRIBE | OPS_READ,
-                       __tmpl.str(), NULL, __owner.c_str());
-}
-
-void ctx::CustomBase::unsubmitTriggerItem()
-{
-       context_manager::unregisterTriggerItem(__subject.c_str());
-}
-
-int ctx::CustomBase::subscribe(const char *subject, ctx::Json option, ctx::Json *requestResult)
-{
-       return ERR_NONE;
-
-}
-
-int ctx::CustomBase::unsubscribe(const char *subject, ctx::Json option)
-{
-       return ERR_NONE;
-}
-
-int ctx::CustomBase::read(const char *subject, ctx::Json option, ctx::Json *requestResult)
-{
-       ctx::Json data = __latest.str();
-       ctx::context_manager::replyToRead(__subject.c_str(), NULL, ERR_NONE, data);
-       return ERR_NONE;
-}
-
-int ctx::CustomBase::write(const char *subject, ctx::Json data, ctx::Json *requestResult)
-{
-       return ERR_NONE;
-}
-
-void ctx::CustomBase::handleUpdate(ctx::Json data)
-{
-       // Store latest state
-       __latest = data.str();
-       ctx::context_manager::publish(__subject.c_str(), NULL, ERR_NONE, data);
-}
-
-const char* ctx::CustomBase::getSubject()
-{
-       return __subject.c_str();
-}
-
-std::string ctx::CustomBase::getOwner()
-{
-       return __owner;
-}
-
-ctx::Json ctx::CustomBase::getTemplate()
-{
-       return __tmpl;
-}
diff --git a/src/custom/CustomBase.h b/src/custom/CustomBase.h
deleted file mode 100644 (file)
index 13c9d99..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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_BASE_H_
-#define _CONTEXT_CUSTOM_BASE_H_
-
-#include <Json.h>
-#include <ContextProvider.h>
-#include <Types.h>
-
-namespace ctx {
-
-       class CustomBase : public ContextProvider {
-       public:
-               CustomBase(std::string subject, std::string name, ctx::Json tmpl, std::string owner);
-               ~CustomBase();
-
-               int subscribe(const char *subject, ctx::Json option, ctx::Json *requestResult);
-               int unsubscribe(const char *subject, ctx::Json option);
-               int read(const char *subject, ctx::Json option, ctx::Json *requestResult);
-               int write(const char *subject, ctx::Json data, ctx::Json *requestResult);
-
-               static bool isSupported();
-               void submitTriggerItem();
-               void unsubmitTriggerItem();
-
-               void handleUpdate(ctx::Json data);
-
-               const char* getSubject();
-               std::string getOwner();
-               ctx::Json getTemplate();
-
-       private:
-               std::string __subject;
-               std::string __name;
-               ctx::Json __tmpl;
-               std::string __owner;
-               ctx::Json __latest;
-       };
-}
-
-#endif /* End of _CONTEXT_CUSTOM_BASE_H_ */
diff --git a/src/custom/CustomContextProvider.cpp b/src/custom/CustomContextProvider.cpp
deleted file mode 100644 (file)
index bcfb7bc..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * 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 <map>
-#include <vector>
-#include <Types.h>
-#include <ContextManager.h>
-#include <ContextProvider.h>
-#include <DatabaseManager.h>
-#include <CustomContextProvider.h>
-#include "CustomBase.h"
-
-static std::map<std::string, ctx::CustomBase*> __customMap;
-static ctx::DatabaseManager __dbManager;
-
-static bool __isValidFact(std::string subject, ctx::Json& fact);
-static bool __checkValueInt(ctx::Json& tmpl, std::string key, int value);
-static bool __checkValueString(ctx::Json& tmpl, std::string key, std::string value);
-
-void registerProvider(const char *subject, const char *privilege)
-{
-       ctx::ContextProviderInfo providerInfo(ctx::custom_context_provider::create,
-                                                                                       ctx::custom_context_provider::destroy,
-                                                                                       const_cast<char*>(subject), privilege);
-       ctx::context_manager::registerProvider(subject, providerInfo);
-       __customMap[subject]->submitTriggerItem();
-}
-
-void unregisterProvider(const char* subject)
-{
-       __customMap[subject]->unsubmitTriggerItem();
-       ctx::context_manager::unregisterProvider(subject);
-}
-
-SO_EXPORT ctx::ContextProvider* ctx::custom_context_provider::create(void *data)
-{
-       // Already created in addItem() function. Return corresponding custom provider
-       return __customMap[static_cast<const char*>(data)];
-}
-
-SO_EXPORT void ctx::custom_context_provider::destroy(void *data)
-{
-       std::map<std::string, ctx::CustomBase*>::iterator it = __customMap.find(static_cast<char*>(data));
-       if (it != __customMap.end()) {
-               delete it->second;
-               __customMap.erase(it);
-       }
-}
-
-SO_EXPORT bool ctx::initCustomContextProvider()
-{
-       // Create custom template db
-       std::string q = std::string("CREATE TABLE IF NOT EXISTS context_trigger_custom_template ")
-                       + "(subject TEXT DEFAULT '' NOT NULL PRIMARY KEY, name TEXT DEFAULT '' NOT NULL, operation INTEGER DEFAULT 3 NOT NULL, "
-                       + "attributes TEXT DEFAULT '' NOT NULL, owner TEXT DEFAULT '' NOT NULL)";
-
-       std::vector<Json> record;
-       bool ret = __dbManager.executeSync(q.c_str(), &record);
-       IF_FAIL_RETURN_TAG(ret, false, _E, "Create template table failed");
-
-       // Register custom items
-       std::string qSelect = "SELECT * FROM context_trigger_custom_template";
-       ret = __dbManager.executeSync(qSelect.c_str(), &record);
-       IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to query custom templates");
-       IF_FAIL_RETURN(record.size() > 0, true);
-
-       int error;
-       std::vector<Json>::iterator vedEnd = record.end();
-       for (auto vecPos = record.begin(); vecPos != vedEnd; ++vecPos) {
-               ctx::Json elem = *vecPos;
-               std::string subject;
-               std::string name;
-               std::string attributes;
-               std::string owner;
-               elem.get(NULL, "subject", &subject);
-               elem.get(NULL, "name", &name);
-               elem.get(NULL, "attributes", &attributes);
-               elem.get(NULL, "owner", &owner);
-
-               error = ctx::custom_context_provider::addItem(subject, name, ctx::Json(attributes), owner.c_str(), true);
-               if (error != ERR_NONE) {
-                       _E("Failed to add custom item(%s): %#x", subject.c_str(), error);
-               }
-       }
-
-       return true;
-}
-
-SO_EXPORT int ctx::custom_context_provider::addItem(std::string subject, std::string name, ctx::Json tmpl, const char* owner, bool isInit)
-{
-       std::map<std::string, ctx::CustomBase*>::iterator it;
-       it = __customMap.find(subject);
-
-       if (it != __customMap.end()) {
-               if ((it->second)->getTemplate() != tmpl) {      // Same item name, but different template
-                       return ERR_DATA_EXIST;
-               }
-               // Same item name with same template
-               return ERR_NONE;
-       }
-
-       // Create custom base
-       ctx::CustomBase* custom = new(std::nothrow) CustomBase(subject, name, tmpl, owner);
-       IF_FAIL_RETURN_TAG(custom, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed");
-       __customMap[subject] = custom;
-
-       registerProvider(custom->getSubject(), NULL);
-
-       // Add item to custom template db
-       if (!isInit) {
-               std::string q = "INSERT OR IGNORE INTO context_trigger_custom_template (subject, name, attributes, owner) VALUES ('"
-                               + subject + "', '" + name +  "', '" + tmpl.str() + "', '" + owner + "'); ";
-               std::vector<Json> record;
-               bool ret = __dbManager.executeSync(q.c_str(), &record);
-               IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to query custom templates");
-       }
-
-       return ERR_NONE;
-}
-
-SO_EXPORT int ctx::custom_context_provider::removeItem(std::string subject)
-{
-       std::map<std::string, ctx::CustomBase*>::iterator it;
-       it = __customMap.find(subject);
-       IF_FAIL_RETURN_TAG(it != __customMap.end(), ERR_NOT_SUPPORTED, _E, "%s not supported", subject.c_str());
-
-       unregisterProvider(subject.c_str());
-
-       // Remove item from custom template db
-       std::string q = "DELETE FROM context_trigger_custom_template WHERE subject = '" + subject + "'";
-       std::vector<Json> record;
-       bool ret = __dbManager.executeSync(q.c_str(), &record);
-       IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to query custom templates");
-
-       return ERR_NONE;
-}
-
-SO_EXPORT int ctx::custom_context_provider::publishData(std::string subject, ctx::Json fact)
-{
-       std::map<std::string, ctx::CustomBase*>::iterator it;
-       it = __customMap.find(subject);
-       IF_FAIL_RETURN_TAG(it != __customMap.end(), ERR_NOT_SUPPORTED, _E, "%s not supported", subject.c_str());
-
-       bool ret = __isValidFact(subject, fact);
-       IF_FAIL_RETURN_TAG(ret, ERR_INVALID_DATA, _E, "Invalid fact(%s)", subject.c_str());
-
-       __customMap[subject]->handleUpdate(fact);
-       return ERR_NONE;
-}
-
-bool __isValidFact(std::string subject, ctx::Json& fact)
-{
-       ctx::Json tmpl = __customMap[subject]->getTemplate();
-       IF_FAIL_RETURN_TAG(tmpl != EMPTY_JSON_OBJECT, false, _E, "Failed to get template");
-
-       bool ret;
-       std::list<std::string> keys;
-       fact.getKeys(&keys);
-
-       for (std::list<std::string>::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 = __checkValueInt(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 = __checkValueString(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 __checkValueInt(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 __checkValueString(ctx::Json& tmpl, std::string key, std::string value)
-{
-       // case1: any value is accepted
-       if (tmpl.getSize(key.c_str(), "values") <= 0)
-               return true;
-
-       // case2: check acceptable value
-       std::string tmplValue;
-       for (int i = 0; tmpl.getAt(key.c_str(), "values", i, &tmplValue); i++) {
-               if (tmplValue == value)
-                       return true;
-       }
-
-       return false;
-}
-
-
diff --git a/src/custom/CustomManager.cpp b/src/custom/CustomManager.cpp
new file mode 100644 (file)
index 0000000..8c01a4b
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * 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 <map>
+#include <Util.h>
+#include <DatabaseManager.h>
+#include "CustomManager.h"
+#include "CustomProvider.h"
+#include "CustomTypes.h"
+
+using namespace ctx;
+
+static std::map<std::string, CustomProvider*> __customMap;
+static DatabaseManager __dbManager;
+
+static bool __isValidFact(std::string subject, Json& fact);
+static bool __checkValueInt(Json& tmpl, std::string key, int value);
+static bool __checkValueString(Json& tmpl, std::string key, std::string value);
+
+CustomManager::CustomManager() :
+       BasicProvider(SUBJ_CUSTOM)
+{
+       __initialize();
+}
+
+CustomManager::~CustomManager()
+{
+       /* Custom provider instances will be deleted by Provider Handler */
+       __customMap.clear();
+}
+
+bool CustomManager::isSupported()
+{
+       return true;
+}
+
+bool CustomManager::unloadable()
+{
+       return false;
+}
+
+int CustomManager::subscribe()
+{
+       return ERR_NONE;
+}
+
+int CustomManager::unsubscribe()
+{
+       return ERR_NONE;
+}
+
+int CustomManager::write(Json data, Json *requestResult)
+{
+       int error = ERR_NONE;
+       std::string req;
+       data.get(NULL, CUSTOM_KEY_REQ, &req);
+
+       std::string packageId;
+       std::string name;
+       data.get(NULL, CUSTOM_KEY_PACKAGE_ID, &packageId);
+       data.get(NULL, CUSTOM_KEY_NAME, &name);
+       std::string subj = std::string(SUBJ_CUSTOM) + CUSTOM_SEPERATOR + packageId + CUSTOM_SEPERATOR + name;
+
+       if (req == CUSTOM_REQ_TYPE_ADD) {
+               Json tmpl;
+               data.get(NULL, CUSTOM_KEY_ATTRIBUTES, &tmpl);
+
+               error = __addCustomItem(subj, name, tmpl, packageId);
+       } else if (req == CUSTOM_REQ_TYPE_REMOVE) {
+               error = __removeCustomItem(subj);
+               if (error == ERR_NONE) {
+                       requestResult->set(NULL, CUSTOM_KEY_SUBJECT, subj);
+               }
+       } else if (req == CUSTOM_REQ_TYPE_PUBLISH) {
+               Json fact;
+               data.get(NULL, CUSTOM_KEY_FACT, &fact);
+
+               error = __publishData(subj, fact);
+       }
+
+       return error;
+}
+
+ContextProvider* CustomManager::getProvider(const char* subject)
+{
+       auto it = __customMap.find(subject);
+       IF_FAIL_RETURN_TAG(it != __customMap.end(), NULL, _E, "'%s' not found", subject);
+
+       CustomProvider* custom = static_cast<CustomProvider*>(it->second);
+       return custom;
+}
+
+bool CustomManager::__initialize()
+{
+       /* Create custom template table */
+       std::vector<Json> record;
+       bool ret = __dbManager.executeSync(CUSTOM_TEMPLATE_TABLE_SCHEMA, &record);
+       IF_FAIL_RETURN_TAG(ret, false, _E, "Create template table failed");
+
+       /* Register custom items */
+       std::string qSelect = "SELECT * FROM context_trigger_custom_template";
+       ret = __dbManager.executeSync(qSelect.c_str(), &record);
+       IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to query custom templates");
+       IF_FAIL_RETURN(record.size() > 0, true);
+
+       int error;
+       std::vector<Json>::iterator vedEnd = record.end();
+       for (auto vecPos = record.begin(); vecPos != vedEnd; ++vecPos) {
+               Json elem = *vecPos;
+               std::string subject;
+               std::string name;
+               std::string attributes;
+               std::string owner;
+               elem.get(NULL, CUSTOM_KEY_SUBJECT, &subject);
+               elem.get(NULL, CUSTOM_KEY_NAME, &name);
+               elem.get(NULL, CUSTOM_KEY_ATTRIBUTES, &attributes);
+               elem.get(NULL, CUSTOM_KEY_OWNER, &owner);
+
+               error = __addCustomItem(subject.c_str(), name, Json(attributes), owner, true);
+               if (error != ERR_NONE) {
+                       _E("Failed to add custom item(%s): %#x", subject.c_str(), error);
+               }
+       }
+
+       return true;
+}
+
+int CustomManager::__addCustomItem(std::string subject, std::string name, Json tmpl, std::string owner, bool isInit)
+{
+       std::map<std::string, CustomProvider*>::iterator it;
+       it = __customMap.find(subject);
+
+       if (it != __customMap.end()) {
+               if ((it->second)->getTemplate() != tmpl) {      /* Same item name, different template */
+                       return ERR_DATA_EXIST;
+               }
+
+               return ERR_NONE;        /* Same item */
+       }
+
+       /* Create custom provider */
+       CustomProvider* custom = new(std::nothrow) CustomProvider(subject.c_str(), name, tmpl, owner);
+       IF_FAIL_RETURN_TAG(custom, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed");
+       __customMap[subject] = custom;
+
+       /* Register provider handler & template */
+       registerCustomProvider(subject.c_str(), OPS_SUBSCRIBE | OPS_READ, tmpl, NULL, owner.c_str());
+
+       /* Insert item to custom template db */
+       if (!isInit) {
+               std::string q = "INSERT OR IGNORE INTO context_trigger_custom_template (subject, name, attributes, owner) VALUES ('"
+                               + subject + "', '" + name +  "', '" + tmpl.str() + "', '" + owner + "'); ";
+               std::vector<Json> record;
+               bool ret = __dbManager.executeSync(q.c_str(), &record);
+               IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to query custom templates");
+       }
+
+       return ERR_NONE;
+}
+
+int CustomManager::__removeCustomItem(std::string subject)
+{
+       std::map<std::string, CustomProvider*>::iterator it;
+       it = __customMap.find(subject);
+       IF_FAIL_RETURN_TAG(it != __customMap.end(), ERR_NOT_SUPPORTED, _E, "%s not supported", subject.c_str());
+
+       /* Unregister provider handler & template */
+       unregisterCustomProvider(subject.c_str());
+       __customMap.erase(it);
+
+       /* Delete item from custom template db */
+       std::string q = "DELETE FROM context_trigger_custom_template WHERE subject = '" + subject + "'";
+       std::vector<Json> record;
+       bool ret = __dbManager.executeSync(q.c_str(), &record);
+       IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to query custom templates");
+
+       return ERR_NONE;
+}
+
+int CustomManager::__publishData(std::string subject, Json fact)
+{
+       std::map<std::string, CustomProvider*>::iterator it;
+       it = __customMap.find(subject);
+       IF_FAIL_RETURN_TAG(it != __customMap.end(), ERR_NOT_SUPPORTED, _E, "%s not supported", subject.c_str());
+
+       bool ret = __isValidFact(subject, fact);
+       IF_FAIL_RETURN_TAG(ret, ERR_INVALID_DATA, _E, "Invalid fact(%s)", subject.c_str());
+
+       __customMap[subject]->handleUpdate(fact);
+       return ERR_NONE;
+}
+
+bool __isValidFact(std::string subject, Json& fact)
+{
+       Json tmpl = __customMap[subject]->getTemplate();
+       IF_FAIL_RETURN_TAG(tmpl != EMPTY_JSON_OBJECT, false, _E, "Failed to get template");
+
+       bool ret;
+       std::list<std::string> keys;
+       fact.getKeys(&keys);
+
+       for (std::list<std::string>::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 = __checkValueInt(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 = __checkValueString(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 __checkValueInt(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 __checkValueString(Json& tmpl, std::string key, std::string value)
+{
+       /* case1: any value is accepted */
+       if (tmpl.getSize(key.c_str(), "values") <= 0)
+               return true;
+
+       /* case2: check acceptable value */
+       std::string tmplValue;
+       for (int i = 0; tmpl.getAt(key.c_str(), "values", i, &tmplValue); i++) {
+               if (tmplValue == value)
+                       return true;
+       }
+
+       return false;
+}
diff --git a/src/custom/CustomManager.h b/src/custom/CustomManager.h
new file mode 100644 (file)
index 0000000..8561cce
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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_MANAGER_H_
+#define _CONTEXT_CUSTOM_MANAGER_H_
+
+#include <CustomRegister.h>
+#include <BasicProvider.h>
+#include <ProviderTypes.h>
+
+namespace ctx {
+
+       class CustomManager : public BasicProvider, CustomRegister {
+       public:
+               CustomManager();
+               ~CustomManager();
+
+               int subscribe();
+               int unsubscribe();
+               int write(Json data, Json *requestResult);
+
+               bool isSupported();
+
+               bool unloadable();
+
+               ContextProvider* getProvider(const char* subject);
+
+       private:
+               bool __initialize();
+               int __addCustomItem(std::string subject, std::string name, ctx::Json tmpl, std::string owner, bool isInit = false);
+               int __removeCustomItem(std::string subject);
+               int __publishData(std::string, ctx::Json fact);
+       };
+}
+
+#endif /* End of _CONTEXT_CUSTOM_MANAGER_H_ */
diff --git a/src/custom/CustomProvider.cpp b/src/custom/CustomProvider.cpp
new file mode 100644 (file)
index 0000000..53f23c6
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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 "CustomProvider.h"
+
+using namespace ctx;
+
+CustomProvider::CustomProvider(const char* subject, std::string name, Json tmpl, std::string owner) :
+       BasicProvider(subject),
+       __name(name),
+       __tmpl(tmpl),
+       __owner(owner)
+{
+}
+
+CustomProvider::~CustomProvider()
+{
+}
+
+bool CustomProvider::isSupported()
+{
+       return true;
+}
+
+bool CustomProvider::unloadable()
+{
+       return false;
+}
+
+int CustomProvider::subscribe()
+{
+       return ERR_NONE;
+
+}
+
+int CustomProvider::unsubscribe()
+{
+       return ERR_NONE;
+}
+
+int CustomProvider::read()
+{
+       Json data = __latest.str();
+
+       replyToRead(NULL, ERR_NONE, data);
+       return ERR_NONE;
+}
+
+void CustomProvider::handleUpdate(Json data)
+{
+       /* Store latest state for read request */
+       __latest = data.str();
+
+       publish(NULL, ERR_NONE, data);
+}
+
+std::string CustomProvider::getOwner()
+{
+       return __owner;
+}
+
+Json CustomProvider::getTemplate()
+{
+       return __tmpl;
+}
diff --git a/src/custom/CustomProvider.h b/src/custom/CustomProvider.h
new file mode 100644 (file)
index 0000000..3def760
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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_PROVIDER_H_
+#define _CONTEXT_CUSTOM_PROVIDER_H_
+
+#include <ProviderTypes.h>
+#include <BasicProvider.h>
+
+namespace ctx {
+
+       class CustomProvider : public BasicProvider {
+       public:
+               CustomProvider(const char* subject, std::string name, ctx::Json tmpl, std::string owner);
+               ~CustomProvider();
+
+               int subscribe();
+               int unsubscribe();
+               int read();
+
+               bool isSupported();
+
+               bool unloadable();
+
+               void handleUpdate(ctx::Json data);
+
+               std::string getOwner();
+               ctx::Json getTemplate();
+
+       private:
+               std::string __name;
+               ctx::Json __tmpl;
+               std::string __owner;
+               ctx::Json __latest;
+       };
+}
+
+#endif /* End of _CONTEXT_CUSTOM_PROVIDER_H_ */
diff --git a/src/custom/CustomTypes.h b/src/custom/CustomTypes.h
new file mode 100644 (file)
index 0000000..797be6c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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_TYPES_H_
+#define _CONTEXT_CUSTOM_TYPES_H_
+
+#include <ProviderTypes.h>
+
+#define CUSTOM_KEY_REQ                         "req"
+#define CUSTOM_KEY_PACKAGE_ID          "packageId"
+#define CUSTOM_KEY_NAME                                "name"
+#define CUSTOM_KEY_ATTRIBUTES          "attributes"
+#define CUSTOM_KEY_FACT                                "fact"
+#define CUSTOM_KEY_SUBJECT                     "subject"
+#define CUSTOM_KEY_OWNER                       "owner"
+
+#define CUSTOM_REQ_TYPE_ADD                    "add"
+#define CUSTOM_REQ_TYPE_REMOVE         "remove"
+#define CUSTOM_REQ_TYPE_PUBLISH                "publish"
+
+#define CUSTOM_SEPERATOR                       "/"
+
+#define MEDIA_TABLE_NAME       "Log_MediaPlayback"
+
+#define CUSTOM_TEMPLATE_TABLE_SCHEMA \
+       "CREATE TABLE IF NOT EXISTS context_trigger_custom_template " \
+       "(subject TEXT DEFAULT '' NOT NULL PRIMARY KEY, name TEXT DEFAULT '' NOT NULL," \
+       " operation INTEGER DEFAULT 3 NOT NULL, attributes TEXT DEFAULT '' NOT NULL, " \
+       " owner TEXT DEFAULT '' NOT NULL)"
+
+
+#endif /* End of _CONTEXT_CUSTOM_TYPES_H_ */