2 * Copyright (c) 2017 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.
18 #include <context_trigger.h>
19 #include "CustomTemplate.h"
21 #define CT_KEY_MIN "minimum"
22 #define CT_KEY_MAX "maximum"
23 #define CT_KEY_TYPE "type"
24 #define CT_TYPE_INTEGER "integer"
25 #define CT_TYPE_STRING "string"
26 #define CT_TYPE_ENUM "enum"
27 #define CT_TYPE_DOUBLE "double"
29 static std::list<CustomTemplate> __instances;
31 CustomTemplate::CustomTemplate(const std::string& name, const Json::Value& templateJson) :
33 __templateJson(templateJson)
37 const std::string& CustomTemplate::getName() const
42 int CustomTemplate::match(const std::string& fact)
44 // true if the given fact is valid w.r.t. the template
48 // Error: Invalid Json
49 if (!reader.parse(fact, factJson)) {
50 _E("Fact: invalid json");
51 return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER;
54 // Error: Invalid fact
55 IF_FAIL_RETURN_TAG(isValidFact(__templateJson, factJson), CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "Invalid fact");
57 return CONTEXT_TRIGGER_ERROR_NONE;
60 bool CustomTemplate::isValidFact(const Json::Value& tmplJson, const Json::Value& factJson)
62 Json::Value::Members keys = factJson.getMemberNames();
65 for (auto& key : keys) {
67 if (tmplJson[key].isMember(CT_TYPE_ENUM)) {
68 dataType = CT_TYPE_ENUM;
69 } else if (tmplJson[key].isMember(CT_KEY_TYPE)) {
70 dataType = tmplJson[key][CT_KEY_TYPE].asString();
73 if (dataType == CT_TYPE_INTEGER) {
74 IF_FAIL_RETURN_TAG(factJson[key].isInt(), false, _E, "Custom fact: Invalid data type");
76 int val = factJson[key].asInt();
77 if (tmplJson[key].isMember(CT_KEY_MIN)) {
78 IF_FAIL_RETURN_TAG(val >= tmplJson[key][CT_KEY_MIN].asInt(), false, _E, "Custom fact: Invalid value");
80 if (tmplJson[key].isMember(CT_KEY_MAX)) {
81 IF_FAIL_RETURN_TAG(val <= tmplJson[key][CT_KEY_MAX].asInt(), false, _E, "Custom fact: Invalid value");
83 } else if (dataType == CT_TYPE_STRING) {
84 IF_FAIL_RETURN_TAG(factJson[key].isString(), false, _E, "Custom fact: Invalid data type");
85 } else if (dataType == CT_TYPE_ENUM) {
86 IF_FAIL_RETURN_TAG(factJson[key].isString(), false, _E, "Custom fact: Invalid data type");
88 std::string val = factJson[key].asString();
91 Json::Value::Members tmplValues;
92 for (auto& tmplValue : tmplValues) {
97 IF_FAIL_RETURN_TAG(found, false, _E, "Custom fact: Invalid value");
99 _E("Custom fact: Invalid data type");
106 bool CustomTemplate::isValidTemplate(const Json::Value& tmplJson)
108 bool success = false;
109 Json::Value::Members keys = tmplJson.getMemberNames();
111 std::string dataType;
112 for (auto& key : keys) {
114 if (tmplJson[key].isMember(CT_TYPE_ENUM)) {
115 success = tmplJson[key][CT_TYPE_ENUM].isArray();
116 IF_FAIL_RETURN_TAG(success, false, _E, "Invalid template");
117 dataType = CT_TYPE_ENUM;
118 } else if (tmplJson[key].isMember(CT_KEY_TYPE)) {
119 dataType = tmplJson[key][CT_KEY_TYPE].asString();
120 IF_FAIL_RETURN_TAG(dataType == CT_TYPE_INTEGER || dataType == CT_TYPE_STRING,
121 false, _E, "Invalid template");
124 if (dataType == CT_TYPE_INTEGER) {
125 success = checkTemplateInt(tmplJson[key]);
126 IF_FAIL_RETURN(success, false);
127 } else if (dataType == CT_TYPE_STRING) {
128 success = checkTemplateString(tmplJson[key]);
129 IF_FAIL_RETURN(success, false);
130 } else if (dataType == CT_TYPE_ENUM) {
131 success = checkTemplateEnum(tmplJson[key]);
132 IF_FAIL_RETURN(success, false);
139 bool CustomTemplate::checkTemplateInt(const Json::Value& elem)
146 Json::Value::Members elemKeys = elem.getMemberNames();
148 for (auto& elemKey : elemKeys) {
149 if (elemKey == CT_KEY_MIN) {
151 minVal = elem[elemKey].asInt();
152 } else if (elemKey == CT_KEY_MAX) {
154 maxVal = elem[elemKey].asInt();
156 IF_FAIL_RETURN_TAG(elemKey == CT_KEY_TYPE, false, _E, "invalid key");
161 IF_FAIL_RETURN_TAG(minVal <= maxVal, false, _E, "Invalid min, max value");
167 bool CustomTemplate::checkTemplateString(const Json::Value& elem)
169 Json::Value::Members elemKeys = elem.getMemberNames();
171 for (auto& elemKey : elemKeys) {
172 IF_FAIL_RETURN_TAG(elemKey == CT_KEY_TYPE, false, _E, "invalid key");
178 bool CustomTemplate::checkTemplateEnum(const Json::Value& elem)
180 Json::Value::Members elemKeys = elem.getMemberNames();
182 for (auto& elemKey : elemKeys) {
183 if (elemKey == CT_TYPE_ENUM) {
184 IF_FAIL_RETURN_TAG(!elem[CT_TYPE_ENUM].empty(), false, _E, "Invalid enum");
186 for (unsigned int i = 0; i < elem[CT_TYPE_ENUM].size(); i++) {
187 IF_FAIL_RETURN_TAG(elem[CT_TYPE_ENUM][i].isString(), false, _E, "Enum value sholud be string");
190 IF_FAIL_RETURN_TAG(elemKey == CT_KEY_TYPE, false, _E, "invalid key");
197 int CustomTemplate::add(const std::string& name, const std::string& attrTmpl)
199 static std::regex nameRegex(R"~(^[\w-\._\/]+$)~", std::regex::optimize);
200 IF_FAIL_RETURN_TAG(std::regex_match(name, nameRegex), CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Invalid name");
203 Json::Value tmplJson;
205 // Error: Invalid Json
206 if (!reader.parse(attrTmpl, tmplJson)) {
207 _E("Template: invalid json");
208 return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER;
211 // Error: already exist
212 CustomTemplate* tmpl = get(name);
214 if (tmplJson == tmpl->__templateJson) {
215 return CONTEXT_TRIGGER_ERROR_NONE;
217 _E("Template already exists");
218 return CONTEXT_TRIGGER_ERROR_DATA_EXIST;
222 // Error: Invalid template
223 IF_FAIL_RETURN_TAG(isValidTemplate(tmplJson), CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "Invalid template");
225 __instances.emplace_back(name, tmplJson);
227 return CONTEXT_TRIGGER_ERROR_NONE;
230 void CustomTemplate::remove(const std::string& name)
232 __instances.remove_if(
233 [&name](const CustomTemplate& tmpl)->bool {
234 return tmpl.getName() == name;
238 CustomTemplate* CustomTemplate::get(const std::string& name)
240 for (auto& tmpl : __instances) {
241 if (tmpl.getName() == name)