2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <DatabaseManager.h>
20 #include "CustomManager.h"
21 #include "CustomProvider.h"
22 #include "CustomTypes.h"
26 static std::map<std::string, CustomProvider*> __customMap;
27 static DatabaseManager __dbManager;
29 static bool __isValidFact(std::string subject, Json& fact);
30 static bool __checkValueInt(Json& tmpl, std::string key, int value);
31 static bool __checkValueString(Json& tmpl, std::string key, std::string value);
33 CustomManager::CustomManager() :
34 BasicProvider(SUBJ_CUSTOM)
39 CustomManager::~CustomManager()
41 /* Custom provider instances will be deleted by Provider Handler */
45 bool CustomManager::isSupported()
50 bool CustomManager::unloadable()
55 int CustomManager::subscribe()
60 int CustomManager::unsubscribe()
65 int CustomManager::write(Json data, Json *requestResult)
69 data.get(NULL, CUSTOM_KEY_REQ, &req);
71 std::string packageId;
73 data.get(NULL, CUSTOM_KEY_PACKAGE_ID, &packageId);
74 data.get(NULL, CUSTOM_KEY_NAME, &name);
75 std::string subj = std::string(SUBJ_CUSTOM) + CUSTOM_SEPERATOR + packageId + CUSTOM_SEPERATOR + name;
77 if (req == CUSTOM_REQ_TYPE_ADD) {
79 data.get(NULL, CUSTOM_KEY_ATTRIBUTES, &tmpl);
81 error = __addCustomItem(subj, name, tmpl, packageId);
82 } else if (req == CUSTOM_REQ_TYPE_REMOVE) {
83 error = __removeCustomItem(subj);
84 if (error == ERR_NONE) {
85 requestResult->set(NULL, CUSTOM_KEY_SUBJECT, subj);
87 } else if (req == CUSTOM_REQ_TYPE_PUBLISH) {
89 data.get(NULL, CUSTOM_KEY_FACT, &fact);
91 error = __publishData(subj, fact);
97 ContextProvider* CustomManager::getProvider(const char* subject)
99 auto it = __customMap.find(subject);
100 IF_FAIL_RETURN_TAG(it != __customMap.end(), NULL, _E, "'%s' not found", subject);
102 CustomProvider* custom = static_cast<CustomProvider*>(it->second);
106 bool CustomManager::__initialize()
108 /* Create custom template table */
109 std::vector<Json> record;
110 bool ret = __dbManager.executeSync(CUSTOM_TEMPLATE_TABLE_SCHEMA, &record);
111 IF_FAIL_RETURN_TAG(ret, false, _E, "Create template table failed");
113 /* Register custom items */
114 std::string qSelect = "SELECT * FROM ContextTriggerCustomTemplate";
115 ret = __dbManager.executeSync(qSelect.c_str(), &record);
116 IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to query custom templates");
117 IF_FAIL_RETURN(record.size() > 0, true);
120 std::vector<Json>::iterator vedEnd = record.end();
121 for (auto vecPos = record.begin(); vecPos != vedEnd; ++vecPos) {
125 std::string attributes;
127 elem.get(NULL, CUSTOM_KEY_SUBJECT, &subject);
128 elem.get(NULL, CUSTOM_KEY_NAME, &name);
129 elem.get(NULL, CUSTOM_KEY_ATTRIBUTES, &attributes);
130 elem.get(NULL, CUSTOM_KEY_OWNER, &owner);
132 error = __addCustomItem(subject.c_str(), name, Json(attributes), owner, true);
133 if (error != ERR_NONE) {
134 _E("Failed to add custom item(%s): %#x", subject.c_str(), error);
141 int CustomManager::__addCustomItem(std::string subject, std::string name, Json tmpl, std::string owner, bool isInit)
143 std::map<std::string, CustomProvider*>::iterator it;
144 it = __customMap.find(subject);
146 if (it != __customMap.end()) {
147 if ((it->second)->getTemplate() != tmpl) { /* Same item name, different template */
148 return ERR_DATA_EXIST;
151 return ERR_NONE; /* Same item */
154 /* Create custom provider */
155 CustomProvider* custom = new(std::nothrow) CustomProvider(subject.c_str(), name, tmpl, owner);
156 IF_FAIL_RETURN_TAG(custom, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed");
157 __customMap[subject] = custom;
159 /* Register provider handler & template */
160 registerCustomProvider(subject.c_str(), OPS_SUBSCRIBE | OPS_READ, tmpl, NULL, owner.c_str());
162 /* Insert item to custom template db */
164 std::string q = "INSERT OR IGNORE INTO ContextTriggerCustomTemplate (subject, name, attributes, owner) VALUES ('"
165 + subject + "', '" + name + "', '" + tmpl.str() + "', '" + owner + "'); ";
166 std::vector<Json> record;
167 bool ret = __dbManager.executeSync(q.c_str(), &record);
168 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to query custom templates");
174 int CustomManager::__removeCustomItem(std::string subject)
176 std::map<std::string, CustomProvider*>::iterator it;
177 it = __customMap.find(subject);
178 IF_FAIL_RETURN_TAG(it != __customMap.end(), ERR_NOT_SUPPORTED, _E, "%s not supported", subject.c_str());
180 /* Unregister provider handler & template */
181 unregisterCustomProvider(subject.c_str());
182 __customMap.erase(it);
184 /* Delete item from custom template db */
185 std::string q = "DELETE FROM ContextTriggerCustomTemplate WHERE subject = '" + subject + "'";
186 std::vector<Json> record;
187 bool ret = __dbManager.executeSync(q.c_str(), &record);
188 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to query custom templates");
193 int CustomManager::__publishData(std::string subject, Json fact)
195 std::map<std::string, CustomProvider*>::iterator it;
196 it = __customMap.find(subject);
197 IF_FAIL_RETURN_TAG(it != __customMap.end(), ERR_NOT_SUPPORTED, _E, "%s not supported", subject.c_str());
199 bool ret = __isValidFact(subject, fact);
200 IF_FAIL_RETURN_TAG(ret, ERR_INVALID_DATA, _E, "Invalid fact(%s)", subject.c_str());
202 __customMap[subject]->handleUpdate(fact);
206 bool __isValidFact(std::string subject, Json& fact)
208 Json tmpl = __customMap[subject]->getTemplate();
209 IF_FAIL_RETURN_TAG(tmpl != EMPTY_JSON_OBJECT, false, _E, "Failed to get template");
212 std::list<std::string> keys;
215 for (std::list<std::string>::iterator it = keys.begin(); it != keys.end(); it++) {
216 std::string key = *it;
219 tmpl.get(key.c_str(), "type", &type);
220 if (type == "integer") {
222 ret = fact.get(NULL, key.c_str(), &val);
223 IF_FAIL_RETURN_TAG(ret, false, _E, "Custom fact: invalid data type");
225 ret = __checkValueInt(tmpl, key, val);
226 IF_FAIL_RETURN_TAG(ret, false, _E, "Custom fact: invalid value");
227 } else if (type == "string") {
229 ret = fact.get(NULL, key.c_str(), &val_str);
230 IF_FAIL_RETURN_TAG(ret, false, _E, "Custom fact: invalid data type");
232 ret = __checkValueString(tmpl, key, val_str);
233 IF_FAIL_RETURN_TAG(ret, false, _E, "Custom fact: invalid value");
235 _E("Custom fact: invalid data type");
243 bool __checkValueInt(Json& tmpl, std::string key, int value)
247 if (tmpl.get(key.c_str(), "min", &min)) {
248 IF_FAIL_RETURN(value >= min, false);
251 if (tmpl.get(key.c_str(), "max", &max)) {
252 IF_FAIL_RETURN(value <= max, false);
258 bool __checkValueString(Json& tmpl, std::string key, std::string value)
260 /* case1: any value is accepted */
261 if (tmpl.getSize(key.c_str(), "values") <= 0)
264 /* case2: check acceptable value */
265 std::string tmplValue;
266 for (int i = 0; tmpl.getAt(key.c_str(), "values", i, &tmplValue); i++) {
267 if (tmplValue == value)