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);
32 static bool __checkValueEnum(Json& tmpl, std::string key, std::string value);
34 CustomManager::CustomManager() :
35 BasicProvider(SUBJ_CUSTOM)
40 CustomManager::~CustomManager()
42 /* Custom provider instances will be deleted by Provider Handler */
46 bool CustomManager::isSupported()
51 bool CustomManager::unloadable()
56 int CustomManager::subscribe()
61 int CustomManager::unsubscribe()
66 int CustomManager::write(Json data, Json *requestResult)
70 data.get(NULL, CUSTOM_KEY_REQ, &req);
72 std::string packageId;
74 data.get(NULL, KEY_CLIENT_PKG_ID, &packageId);
75 data.get(NULL, CUSTOM_KEY_NAME, &name);
76 std::string subj = std::string(SUBJ_CUSTOM) + CUSTOM_SEPERATOR + packageId + CUSTOM_SEPERATOR + name;
78 if (req == CUSTOM_REQ_TYPE_ADD) {
80 data.get(NULL, CUSTOM_KEY_ATTRIBUTES, &tmpl);
82 error = __addCustomItem(subj, name, tmpl, packageId);
83 } else if (req == CUSTOM_REQ_TYPE_REMOVE) {
84 error = __removeCustomItem(subj);
85 if (error == ERR_NONE) {
86 requestResult->set(NULL, CUSTOM_KEY_SUBJECT, subj);
88 } else if (req == CUSTOM_REQ_TYPE_PUBLISH) {
90 data.get(NULL, CUSTOM_KEY_FACT, &fact);
92 error = __publishData(subj, fact);
98 ContextProvider* CustomManager::getProvider(const char* subject)
100 auto it = __customMap.find(subject);
101 IF_FAIL_RETURN_TAG(it != __customMap.end(), NULL, _E, "'%s' not found", subject);
103 CustomProvider* custom = static_cast<CustomProvider*>(it->second);
107 bool CustomManager::__initialize()
109 /* Create custom template table */
110 std::vector<Json> record;
111 bool ret = __dbManager.executeSync(CUSTOM_TEMPLATE_TABLE_SCHEMA, &record);
112 IF_FAIL_RETURN_TAG(ret, false, _E, "Create template table failed");
114 /* Register custom items */
115 std::string qSelect = "SELECT * FROM ContextTriggerCustomTemplate";
116 ret = __dbManager.executeSync(qSelect.c_str(), &record);
117 IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to query custom templates");
118 IF_FAIL_RETURN(record.size() > 0, true);
121 std::vector<Json>::iterator vedEnd = record.end();
122 for (auto vecPos = record.begin(); vecPos != vedEnd; ++vecPos) {
126 std::string attributes;
128 elem.get(NULL, CUSTOM_KEY_SUBJECT, &subject);
129 elem.get(NULL, CUSTOM_KEY_NAME, &name);
130 elem.get(NULL, CUSTOM_KEY_ATTRIBUTES, &attributes);
131 elem.get(NULL, CUSTOM_KEY_OWNER, &owner);
133 error = __addCustomItem(subject.c_str(), name, Json(attributes), owner, true);
134 if (error != ERR_NONE) {
135 _E("Failed to add custom item(%s): %#x", subject.c_str(), error);
142 int CustomManager::__addCustomItem(std::string subject, std::string name, Json tmpl, std::string owner, bool isInit)
144 std::map<std::string, CustomProvider*>::iterator it;
145 it = __customMap.find(subject);
147 if (it != __customMap.end()) {
148 if ((it->second)->getTemplate() != tmpl) { /* Same item name, different template */
149 return ERR_DATA_EXIST;
152 return ERR_NONE; /* Same item */
155 /* Create custom provider */
156 CustomProvider* custom = new(std::nothrow) CustomProvider(subject.c_str(), name, tmpl, owner);
157 IF_FAIL_RETURN_TAG(custom, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed");
158 __customMap[subject] = custom;
160 /* Register provider handler & template */
161 registerCustomProvider(subject.c_str(), OPS_SUBSCRIBE | OPS_READ, tmpl, NULL, owner.c_str());
163 /* Insert item to custom template db */
165 std::string q = "INSERT OR IGNORE INTO ContextTriggerCustomTemplate (subject, name, attributes, owner) VALUES ('"
166 + subject + "', '" + name + "', '" + tmpl.str() + "', '" + owner + "'); ";
167 std::vector<Json> record;
168 bool ret = __dbManager.executeSync(q.c_str(), &record);
169 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to query custom templates");
175 int CustomManager::__removeCustomItem(std::string subject)
177 std::map<std::string, CustomProvider*>::iterator it;
178 it = __customMap.find(subject);
179 IF_FAIL_RETURN_TAG(it != __customMap.end(), ERR_NOT_SUPPORTED, _E, "%s not supported", subject.c_str());
181 /* Unregister provider handler & template */
182 unregisterCustomProvider(subject.c_str());
183 __customMap.erase(it);
185 /* Delete item from custom template db */
186 std::string q = "DELETE FROM ContextTriggerCustomTemplate WHERE subject = '" + subject + "'";
187 std::vector<Json> record;
188 bool ret = __dbManager.executeSync(q.c_str(), &record);
189 IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to query custom templates");
194 int CustomManager::__publishData(std::string subject, Json fact)
196 std::map<std::string, CustomProvider*>::iterator it;
197 it = __customMap.find(subject);
198 IF_FAIL_RETURN_TAG(it != __customMap.end(), ERR_NOT_SUPPORTED, _E, "%s not supported", subject.c_str());
200 bool ret = __isValidFact(subject, fact);
201 IF_FAIL_RETURN_TAG(ret, ERR_INVALID_DATA, _E, "Invalid fact(%s)", subject.c_str());
203 __customMap[subject]->handleUpdate(fact);
207 bool __isValidFact(std::string subject, Json& fact)
209 Json tmpl = __customMap[subject]->getTemplate();
210 IF_FAIL_RETURN_TAG(tmpl != EMPTY_JSON_OBJECT, false, _E, "Failed to get template");
213 std::list<std::string> keys;
216 for (std::list<std::string>::iterator it = keys.begin(); it != keys.end(); it++) {
217 std::string key = *it;
220 ret = tmpl.get(key.c_str(), "type", &type);
222 int size = tmpl.getSize(key.c_str(), "enum");
223 IF_FAIL_RETURN_TAG(size >= 0, false, _E, "Invalid template");
227 if (type == "integer") {
229 ret = fact.get(NULL, key.c_str(), &val);
230 IF_FAIL_RETURN_TAG(ret, false, _E, "Custom fact: invalid data type");
232 ret = __checkValueInt(tmpl, key, val);
233 IF_FAIL_RETURN_TAG(ret, false, _E, "Custom fact: invalid value");
234 } else if (type == "string") {
236 ret = fact.get(NULL, key.c_str(), &val_str);
237 IF_FAIL_RETURN_TAG(ret, false, _E, "Custom fact: invalid data type");
239 ret = __checkValueString(tmpl, key, val_str);
240 IF_FAIL_RETURN_TAG(ret, false, _E, "Custom fact: invalid value");
241 } else if (type == "enum") {
243 ret = fact.get(NULL, key.c_str(), &val_str);
244 IF_FAIL_RETURN_TAG(ret, false, _E, "Custom fact: invalid data type");
246 ret = __checkValueEnum(tmpl, key, val_str);
247 IF_FAIL_RETURN_TAG(ret, false, _E, "Custom fact: invalid value");
249 _E("Custom fact: invalid data type");
257 bool __checkValueInt(Json& tmpl, std::string key, int value)
261 if (tmpl.get(key.c_str(), "minimum", &min)) {
262 IF_FAIL_RETURN(value >= min, false);
265 if (tmpl.get(key.c_str(), "maximum", &max)) {
266 IF_FAIL_RETURN(value <= max, false);
272 bool __checkValueString(Json& tmpl, std::string key, std::string value)
274 /* any value is accepted */
278 bool __checkValueEnum(Json& tmpl, std::string key, std::string value)
280 /* check acceptable value */
281 std::string tmplValue;
282 for (int i = 0; tmpl.getAt(key.c_str(), "enum", i, &tmplValue); i++) {
283 if (tmplValue == value)