From: Mu-Woong Lee Date: Mon, 10 Jul 2017 02:04:42 +0000 (+0900) Subject: Cleanup the build scripts and reorganize the source directories X-Git-Tag: submit/tizen/20170802.043634~8 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F14%2F137814%2F3;p=platform%2Fcore%2Fapi%2Fcontext.git Cleanup the build scripts and reorganize the source directories Change-Id: I9121a3405d1497541afb929ff67e9c3185cfeb0c Signed-off-by: Mu-Woong Lee --- diff --git a/AUTHORS b/AUTHORS index 59ec358..15d0a89 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,2 @@ -Mu-Woong Lee Somin Kim +Mu-Woong Lee diff --git a/CMakeLists.txt b/CMakeLists.txt index 430be88..0a8d060 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,13 +5,15 @@ INCLUDE(GNUInstallDirs) # Targets SET(target ${PROJECT_NAME}) +# Dependencies +SET(DEPS "gio-2.0 jsoncpp bundle pkgmgr-info capi-base-common capi-appfw-app-control") +SET(DEPS "${DEPS} context-app-history-client context-job-scheduler-client") +SET(DEPS "${DEPS} context-common-legacy") + # Source Lists FILE(GLOB_RECURSE SRCS src/*.cpp) MESSAGE("Sources: ${SRCS}") -# Dependencies -SET(DEPS "gio-2.0 jsoncpp context-common-legacy aul bundle capi-appfw-app-control pkgmgr-info context-app-history-client") - # Common Options INCLUDE(FindPkgConfig) INCLUDE_DIRECTORIES( @@ -40,9 +42,9 @@ SET_TARGET_PROPERTIES(${target} PROPERTIES VERSION ${FULLVER}) # Installing INSTALL(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR}) INSTALL( - DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/context-service - FILES_MATCHING - PATTERN "*.h" + DIRECTORY ${CMAKE_SOURCE_DIR}/include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/context-service + FILES_MATCHING PATTERN "*.h" ) SET(VERSION ${FULLVER}) diff --git a/packaging/capi-context.spec b/packaging/capi-context.spec index 6eecaf9..c1c4712 100644 --- a/packaging/capi-context.spec +++ b/packaging/capi-context.spec @@ -1,19 +1,23 @@ Name: capi-context Summary: Tizen Context Framework Native API -Version: 1.0.2 +Version: 1.0.3 Release: 1 -Group: Service/Context +Group: Service Framework/Context License: Apache-2.0 Source0: %{name}-%{version}.tar.gz BuildRequires: cmake BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(jsoncpp) -BuildRequires: pkgconfig(aul) +#BuildRequires: pkgconfig(aul) BuildRequires: pkgconfig(bundle) -BuildRequires: pkgconfig(capi-appfw-app-control) BuildRequires: pkgconfig(pkgmgr-info) +BuildRequires: pkgconfig(capi-base-common) +BuildRequires: pkgconfig(capi-appfw-app-control) BuildRequires: pkgconfig(context-app-history-client) +BuildRequires: pkgconfig(context-job-scheduler-client) + +# Legacy support BuildRequires: pkgconfig(context-common-legacy) Requires: context-agent @@ -29,8 +33,8 @@ Tizen Context Framework Native API %build MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` -export CXXFLAGS+=" -Wextra -Wcast-align -Wshadow -Wwrite-strings -Wswitch-default -Wno-unused-parameter" -export CXXFLAGS+=" -Wno-empty-body -fomit-frame-pointer -fno-optimize-sibling-calls" +export CXXFLAGS+=" -Wall -Wextra -Wcast-align -Wshadow -Wwrite-strings -Wswitch-default -Wno-unused-parameter" +export CXXFLAGS+=" -Wformat=2 -Wno-empty-body -fomit-frame-pointer -fno-optimize-sibling-calls" export CXXFLAGS+=" -fno-strict-aliasing -fno-unroll-loops -fsigned-char -fstrict-overflow" export CXXFLAGS+=" -Wnon-virtual-dtor -std=c++0x" @@ -70,7 +74,7 @@ Tizen Context Framework Native API (Development) %package test Summary: Tizen Context Framework Testsuite -Group: Service/Context +Group: Service Framework/Context %description test Tizen Context Framework Testsuite diff --git a/src/ComparisonConverter.cpp b/src/ComparisonConverter.cpp deleted file mode 100644 index 3d73626..0000000 --- a/src/ComparisonConverter.cpp +++ /dev/null @@ -1,154 +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 -#include -#include -#include -#include "ComparisonConverter.h" - -using namespace ctx; - -ComparisonConverter::ComparisonConverter(const char* type, CtxJson1& info) : - __completed(false), - __size(0), - __logicalOp(TRIG_RULE_LOGICAL_DISJUNCTION), - __type(type), - __info(info.str()), - __result(EMPTY_JSON_OBJECT) -{ - __info.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &__key); - __info.get(NULL, OLD_TRIG_RULE_KEY_OPERATOR, &__logicalOp); - __size = __info.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR); -} - -int ComparisonConverter::getResult(CtxJson1* result) -{ - if (__result == EMPTY_JSON_OBJECT) - return ERR_INVALID_RULE; - - *result = __result.str(); - - return ERR_NONE; -} - -void ComparisonConverter::__convertComparison() -{ - IF_FAIL_VOID(!__convertEmptyComparison()); - IF_FAIL_VOID(!__convertSingleComparison()); - IF_FAIL_VOID(!__convertMultipleComparison()); - - _E("Failed to convert comparison as new format"); -} - -bool ComparisonConverter::__convertEmptyComparison() -{ - IF_FAIL_RETURN(__size == 0, false); - - CtxJson1 temp = EMPTY_JSON_OBJECT; - __result.set(NULL, __key.c_str(), temp); - - return true; -} - -bool ComparisonConverter::__convertSingleComparison() -{ - IF_FAIL_RETURN(__size == 1, false); - - std::string op; - __info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, 0, &op); - - __setConvertedOperator(op); - __setComparisonValue(); - - return true; -} - -bool ComparisonConverter::__convertMultipleComparison() -{ - IF_FAIL_RETURN(__size > 1, false); - - if (__checkOneOf()) { - return true; - } else if (__checkNoneOf()) { - return true; - } else if (__checkEtc()) { - return true; - } - - return false; -} - -bool ComparisonConverter::__checkOneOf() -{ - // Or of {==, ...} - IF_FAIL_RETURN(__logicalOp == TRIG_RULE_LOGICAL_DISJUNCTION, false); - IF_FAIL_RETURN(__size == __getOperatorCount(TRIG_RULE_OP_EQUAL_TO), false); - - __setConvertedOperator(TRIG_RULE_OP_ONE_OF); - __setComparisonValueArray(); - - return true; -} - -bool ComparisonConverter::__checkNoneOf() -{ - // And of {!=, ...} - IF_FAIL_RETURN(__logicalOp == TRIG_RULE_LOGICAL_CONJUNCTION, false); - IF_FAIL_RETURN(__size == __getOperatorCount(TRIG_RULE_OP_NOT_EQUAL_TO), false); - - __setConvertedOperator(TRIG_RULE_OP_NONE_OF); - __setComparisonValueArray(); - - return true; -} - -bool ComparisonConverter::__checkEtc() -{ - return false; -} - -void ComparisonConverter::__setConvertedOperator(std::string op) -{ - __result.set(__key.c_str(), TRIG_RULE_KEY_OPERATOR, op); -} - -void ComparisonConverter::__setComparisonValue() -{ - std::string valStr; - int val; - - if (__info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, 0, &valStr)) { - __result.set(__key.c_str(), TRIG_RULE_KEY_VALUE, valStr); - } else if (__info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, 0, &val)) { - __result.set(__key.c_str(), TRIG_RULE_KEY_VALUE, val); - } -} - -void ComparisonConverter::__setComparisonValueArray() -{ - std::string valStr; - int val; - // TODO sort - for (int i = 0; i < __size; i++) { - if (__info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, i, &valStr)) { - __result.append(__key.c_str(), TRIG_RULE_KEY_VALUE, valStr); - } else if (__info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, i, &val)) { - __result.append(__key.c_str(), TRIG_RULE_KEY_VALUE, val); - } - } -} - diff --git a/src/ComparisonConverter.h b/src/ComparisonConverter.h deleted file mode 100644 index 9cde85c..0000000 --- a/src/ComparisonConverter.h +++ /dev/null @@ -1,58 +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_COMPARISON_CONVERTER_H_ -#define _CONTEXT_COMPARISON_CONVERTER_H_ - -#include -#include "TriggerOldRuleTypes.h" - -namespace ctx { - - class ComparisonConverter { - public: - virtual ~ComparisonConverter() {}; - - int getResult(CtxJson1* result); - - protected: - bool __completed; - int __size; - std::string __logicalOp; - std::string __type; - CtxJson1 __info; - CtxJson1 __result; - std::string __key; - - ComparisonConverter(const char* type, CtxJson1& info); - void __convertComparison(); - virtual int __getOperatorCount(std::string op) = 0; - virtual bool __checkEtc(); - void __setConvertedOperator(std::string op); - - private: - bool __convertEmptyComparison(); - bool __convertSingleComparison(); - bool __convertMultipleComparison(); - bool __checkOneOf(); - bool __checkNoneOf(); - void __setComparisonValue(); - void __setComparisonValueArray(); - }; - -} /* namespace ctx */ - -#endif /* _CONTEXT_COMPARISON_CONVERTER_H_ */ diff --git a/src/IntComparisonConverter.cpp b/src/IntComparisonConverter.cpp deleted file mode 100644 index 9f1a4e5..0000000 --- a/src/IntComparisonConverter.cpp +++ /dev/null @@ -1,130 +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 -#include -#include -#include -#include -#include -#include "IntComparisonConverter.h" - -using namespace ctx; - -IntComparisonConverter::IntComparisonConverter(CtxJson1 info) : - ComparisonConverter(TRIG_TMPL_TYPE_INTEGER, info) -{ - if (__size >= 2) { - for (int i = 0; i < __size; i++) { - int val; - std::string op; - __info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, i, &val); - __info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, i, &op); - - __insertComparisonInfo(op, val); - } - __sort(); - } - - __convertComparison(); -} - -void IntComparisonConverter::__insertComparisonInfo(std::string op, int val) -{ - IntComparisonMap::iterator it = __map.find(op); - if (it == __map.end()) { - IntList list; - list.push_back(val); - __map[op] = list; - } else { - it->second.push_back(val); - } -} - -void IntComparisonConverter::__sort() -{ - for (IntComparisonMap::iterator it = __map.begin(); it != __map.end(); it++) { - it->second.sort(); - } -} - -int IntComparisonConverter::__getOperatorCount(std::string op) -{ - return __map[op].size(); -} - -int IntComparisonConverter::__getMaxValue(std::string op) -{ - return __map[op].back(); -} - -int IntComparisonConverter::__getMinValue(std::string op) -{ - return __map[op].front(); -} - -bool IntComparisonConverter::__checkEtc() -{ - // Simple version in, notIn - IF_FAIL_RETURN(!__checkIn(), true); - IF_FAIL_RETURN(!__checkNotIn(), true); - - return false; -} - - -bool IntComparisonConverter::__checkIn() -{ - // And of { >= min, <= max } - IF_FAIL_RETURN(__logicalOp == TRIG_RULE_LOGICAL_CONJUNCTION, false); - IF_FAIL_RETURN(__size == 2, false); - IF_FAIL_RETURN(__getOperatorCount(TRIG_RULE_OP_GREATER_THAN_OR_EQUAL_TO) == 1 - && __getOperatorCount(TRIG_RULE_OP_LESS_THAN_OR_EQUAL_TO) == 1, false); - - int maxOfGE = __getMaxValue(TRIG_RULE_OP_GREATER_THAN_OR_EQUAL_TO); - int minOfLE = __getMinValue(TRIG_RULE_OP_LESS_THAN_OR_EQUAL_TO); - IF_FAIL_RETURN(maxOfGE <= minOfLE, false); - - __setConvertedOperator(TRIG_RULE_OP_IN); - __setComparisonValue(maxOfGE, minOfLE); - - return true; -} - -bool IntComparisonConverter::__checkNotIn() -{ - // Or of { < min, > max } - IF_FAIL_RETURN(__logicalOp == TRIG_RULE_LOGICAL_DISJUNCTION, false); - IF_FAIL_RETURN(__size == 2, false); - IF_FAIL_RETURN(__getOperatorCount(TRIG_RULE_OP_GREATER_THAN) == 1 - && __getOperatorCount(TRIG_RULE_OP_LESS_THAN) == 1, false); - - int maxOfL = __getMaxValue(TRIG_RULE_OP_LESS_THAN); - int minOfG = __getMinValue(TRIG_RULE_OP_GREATER_THAN); - IF_FAIL_RETURN(maxOfL <= minOfG, false); - - __setConvertedOperator(TRIG_RULE_OP_NOT_IN); - __setComparisonValue(maxOfL, minOfG); - - return true; -} - -void IntComparisonConverter::__setComparisonValue(int val1, int val2) -{ - __result.append(__key.c_str(), TRIG_RULE_KEY_VALUE, val1); - __result.append(__key.c_str(), TRIG_RULE_KEY_VALUE, val2); -} - diff --git a/src/IntComparisonConverter.h b/src/IntComparisonConverter.h deleted file mode 100644 index f18cd2b..0000000 --- a/src/IntComparisonConverter.h +++ /dev/null @@ -1,52 +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_INT_COMPARISON_CONVERTER_H_ -#define _CONTEXT_INT_COMPARISON_CONVERTER_H_ - -#include -#include -#include "ComparisonConverter.h" - -namespace ctx { - - class IntComparisonConverter : public ComparisonConverter { - typedef std::list IntList; // Integer value list - typedef std::map IntComparisonMap; // { operator, IntList } - - public: - IntComparisonConverter(CtxJson1 info); - ~IntComparisonConverter() {}; - - private: - IntComparisonMap __map; - - void __insertComparisonInfo(std::string op, int val); - void __sort(); - int __getMaxValue(std::string op); - int __getMinValue(std::string op); - - bool __checkIn(); - bool __checkNotIn(); - void __setComparisonValue(int val1, int val2); - /* From CompariconConverter */ - int __getOperatorCount(std::string op); - bool __checkEtc(); - }; - -} /* namespace ctx */ - -#endif /* _CONTEXT_INT_COMPARISON_CONVERTER_H_ */ diff --git a/src/StringComparisonConverter.cpp b/src/StringComparisonConverter.cpp deleted file mode 100644 index f4c1757..0000000 --- a/src/StringComparisonConverter.cpp +++ /dev/null @@ -1,45 +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 -#include -#include -#include -#include "StringComparisonConverter.h" - -using namespace ctx; - -StringComparisonConverter::StringComparisonConverter(CtxJson1 info) : - ComparisonConverter(TRIG_TMPL_TYPE_STRING, info) -{ - if (__size >= 2) { - for (int i = 0; i < __size; i++) { - std::string op; - __info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, i, &op); - - __map[op]++; - } - } - - __convertComparison(); -} - - -int StringComparisonConverter::__getOperatorCount(std::string op) -{ - return __map[op]; -} - diff --git a/src/StringComparisonConverter.h b/src/StringComparisonConverter.h deleted file mode 100644 index 69fb110..0000000 --- a/src/StringComparisonConverter.h +++ /dev/null @@ -1,42 +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_STRING_COMPARISON_CONVERTER_H_ -#define _CONTEXT_STRING_COMPARISON_CONVERTER_H_ - -#include -#include -#include "ComparisonConverter.h" - -namespace ctx { - - class StringComparisonConverter : public ComparisonConverter { - typedef std::map StringComparisonMap; - - public: - StringComparisonConverter(CtxJson1 info); - ~StringComparisonConverter() {}; - - private: - StringComparisonMap __map; - - /* From CompariconConverter */ - int __getOperatorCount(std::string op); - }; - -} /* namespace ctx */ - -#endif /* _CONTEXT_STRING_COMPARISON_CONVERTER_H_ */ diff --git a/src/TriggerOldRuleTypes.h b/src/TriggerOldRuleTypes.h deleted file mode 100644 index fe85d67..0000000 --- a/src/TriggerOldRuleTypes.h +++ /dev/null @@ -1,36 +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_TRIGGER_OLD_RULE_TYPES_H_ -#define _CONTEXT_TRIGGER_OLD_RULE_TYPES_H_ - -/* Old Rule Keys */ -#define OLD_TRIG_RULE_KEY_EVENT "EVENT" -#define OLD_TRIG_RULE_KEY_EVENT_ITEM "ITEM_NAME" -#define OLD_TRIG_RULE_KEY_EVENT_OPERATOR "ITEM_OPERATOR" -#define OLD_TRIG_RULE_KEY_EVENT_OPTION "OPTION" -#define OLD_TRIG_RULE_KEY_OPERATOR "OPERATOR" -#define OLD_TRIG_RULE_KEY_CONDITION "CONDITION" -#define OLD_TRIG_RULE_KEY_CONDITION_ITEM "ITEM_NAME" -#define OLD_TRIG_RULE_KEY_CONDITION_OPERATOR "ITEM_OPERATOR" -#define OLD_TRIG_RULE_KEY_CONDITION_OPTION "OPTION" -#define OLD_TRIG_RULE_KEY_DATA_ARR "DATA_ARR" -#define OLD_TRIG_RULE_KEY_DATA_KEY "DATA_KEY" -#define OLD_TRIG_RULE_KEY_DATA_KEY_OPERATOR "DATA_KEY_OPERATOR" -#define OLD_TRIG_RULE_KEY_DATA_VALUE_ARR "DATA_VALUE_ARR" -#define OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR "DATA_VALUE_OPER_ARR" - -#endif /* _CONTEXT_TRIGGER_OLD_RULE_TYPES_H_ */ diff --git a/src/context_history.cpp b/src/context_history.cpp deleted file mode 100644 index 3770d2f..0000000 --- a/src/context_history.cpp +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Copyright (c) 2015 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 -#include -#include - -#define HISTORY_DEPRECATED_DATA "DEPRECATION WARNING: This history data type is deprecated and will be removed from next release" -#define HISTORY_DEPRECATED_FILTER "DEPRECATION WARNING: This history filter is deprecated and will be removed from next release" -#define TYPE_NUMERIC 0 -#define TYPE_STRING 1 -#define FILTER_KEY_LIMIT 10 - -#define ASSERT_ALLOC(X) IF_FAIL_RETURN_TAG(X, E_NO_MEM, _E, "Memory allocation failed") -#define ASSERT_NOT_NULL(X) IF_FAIL_RETURN_TAG(X, E_PARAM, _E, "Parameter null") - -// handles -typedef struct _context_history_handle_s { - /* At this point, this handle has no purpose. - But, it will be used to support other functionalities later, - e.g., async read or session management. */ - int tmp; -} _cx_history_handle; - -typedef struct _context_history_filter_handle_s { - Json::Value jfilter; -} _cx_history_filter_handle; - -typedef struct _context_history_list_handle_s { - ctx_history_cursor_h cursor; - - _context_history_list_handle_s() { - cursor = NULL; - } -} _cx_history_list_handle; - -typedef struct _context_history_record_handle_s { - std::vector keys; - std::shared_ptr tuple; -} _cx_history_record_handle; - -static std::string convert_filter_to_string(context_history_filter_e filter_type); -static std::string convert_data_to_string(context_history_data_e data_type); -static bool check_record_key_data_type(int type, std::string key); -static bool check_filter_data_int(context_history_filter_e filter_type, int val); -static bool check_filter_data_string(context_history_filter_e filter_type, const char* val); -static bool check_invalid_filter(context_history_data_e data_type, context_history_filter_h filter); -static int __getIndexOf(context_history_record_h record, const std::string& key); -static bool history_is_deprecated(context_history_data_e data_type); -static bool history_filter_is_deprecated(context_history_filter_e filter_type); - -// life-cycle -EXPORT_API int context_history_create(context_history_h* handle) -{ - ASSERT_NOT_NULL(handle); - - *handle = new(std::nothrow) _cx_history_handle(); - ASSERT_ALLOC(*handle); - - return CONTEXT_HISTORY_ERROR_NONE; -} - -EXPORT_API int context_history_destroy(context_history_h handle) -{ - ASSERT_NOT_NULL(handle); - delete handle; - return CONTEXT_HISTORY_ERROR_NONE; -} - -// Read filter manipulation -EXPORT_API int context_history_filter_create(context_history_filter_h* filter) -{ - ASSERT_NOT_NULL(filter); - - *filter = new(std::nothrow) _cx_history_filter_handle(); - ASSERT_ALLOC(*filter); - - return CONTEXT_HISTORY_ERROR_NONE; -} - -EXPORT_API int context_history_filter_destroy(context_history_filter_h filter) -{ - ASSERT_NOT_NULL(filter); - delete filter; - - return CONTEXT_HISTORY_ERROR_NONE; -} - -EXPORT_API int context_history_filter_set_int(context_history_filter_h filter, context_history_filter_e filter_type, int val) -{ - ASSERT_NOT_NULL(filter); - - if (history_filter_is_deprecated(filter_type)) { - _W(HISTORY_DEPRECATED_FILTER); - } - - std::string filter_str = convert_filter_to_string(filter_type); - if (filter_str.empty()) { - return CONTEXT_HISTORY_ERROR_INVALID_PARAMETER; - } - - // Check filter and its data type - IF_FAIL_RETURN_TAG(check_filter_data_int(filter_type, val), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Filter type mismatched"); - - filter->jfilter[filter_str] = val; - - return CONTEXT_HISTORY_ERROR_NONE; -} - -EXPORT_API int context_history_filter_set_string(context_history_filter_h filter, context_history_filter_e filter_type, const char* val) -{ - ASSERT_NOT_NULL(filter); - ASSERT_NOT_NULL(val); - - _W("DEPRECATION WARNING: context_history_filter_set_string() is deprecated and will be removed from next release."); - if (history_filter_is_deprecated(filter_type)) { - _W(HISTORY_DEPRECATED_FILTER); - } - - std::string filter_str = convert_filter_to_string(filter_type); - if (filter_str.empty()) { - return CONTEXT_HISTORY_ERROR_INVALID_PARAMETER; - } - - // Check filter and its data type - IF_FAIL_RETURN_TAG(check_filter_data_string(filter_type, val), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Filter type mismatched"); - - filter->jfilter[filter_str] = val; - - return CONTEXT_HISTORY_ERROR_NONE; -} - -EXPORT_API int context_history_is_supported(context_history_data_e data_type, bool* supported) -{ - ASSERT_NOT_NULL(supported); - - if (history_is_deprecated(data_type)) { - _W(HISTORY_DEPRECATED_DATA); - } - - std::string data_type_str = convert_data_to_string(data_type); - if (data_type_str.empty()) { - return CONTEXT_HISTORY_ERROR_INVALID_PARAMETER; - } - - return ctx_history_is_supported(data_type_str.c_str(), supported); -} - -EXPORT_API int context_history_get_list(context_history_h handle, context_history_data_e data_type, context_history_filter_h filter, context_history_list_h* list) -{ - ASSERT_NOT_NULL(handle); - ASSERT_NOT_NULL(list); - *list = NULL; - - if (history_is_deprecated(data_type)) { - _W(HISTORY_DEPRECATED_DATA); - } - /*TODO: Boundary check for filter values has to be done*/ - - std::string data_type_str = convert_data_to_string(data_type); - if (data_type_str.empty()) { - return CONTEXT_HISTORY_ERROR_INVALID_PARAMETER; - } - - // Check data type & filter - if (filter) - IF_FAIL_RETURN_TAG(check_invalid_filter(data_type, filter), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Invalid filter key"); - - *list = new(std::nothrow) _cx_history_list_handle(); - ASSERT_ALLOC(*list); - - std::string filterStr; - if (filter) { - Json::FastWriter fw; - fw.omitEndingLineFeed(); - filterStr = fw.write(filter->jfilter); - } - - int err = _ctx_history_query(data_type_str.c_str(), filterStr.c_str(), &((*list)->cursor)); - IF_FAIL_RETURN_TAG(err == E_NONE, err, _E, "Query failed"); - - return CONTEXT_HISTORY_ERROR_NONE; -} - -// Data object manipulation -EXPORT_API int context_history_list_get_count(context_history_list_h list, int* count) -{ - ASSERT_NOT_NULL(list && count); - - unsigned int value; - - int err = ctx_history_cursor_get_count(list->cursor, &value); - IF_FAIL_RETURN_TAG(err == E_NONE, err, _E, "Get count failed"); - - *count = value; - return E_NONE; -} - -EXPORT_API int context_history_list_get_current(context_history_list_h list, context_history_record_h* record) -{ - ASSERT_NOT_NULL(list); - ASSERT_NOT_NULL(record); - *record = NULL; - - unsigned int position = 0; - int err = ctx_history_cursor_get_position(list->cursor, &position); - IF_FAIL_RETURN_TAG(err == E_NONE, err, _E, "Get position failed"); - - *record = new(std::nothrow) _cx_history_record_handle(); - ASSERT_ALLOC(*record); - - (*record)->keys = list->cursor->keys; - (*record)->tuple = list->cursor->tuples[position]; - - return CONTEXT_HISTORY_ERROR_NONE; -} - -EXPORT_API int context_history_list_move_first(context_history_list_h list) -{ - ASSERT_NOT_NULL(list); - return ctx_history_cursor_first(list->cursor); -} - -EXPORT_API int context_history_list_move_next(context_history_list_h list) -{ - ASSERT_NOT_NULL(list); - return ctx_history_cursor_next(list->cursor); -} - -EXPORT_API int context_history_list_destroy(context_history_list_h list) -{ - ASSERT_NOT_NULL(list); - ctx_history_cursor_destroy(list->cursor); - delete list; - - return CONTEXT_HISTORY_ERROR_NONE; -} - -EXPORT_API int context_history_record_get_int(context_history_record_h record, const char* key, int* val) -{ - ASSERT_NOT_NULL(record && val && key); - - // Check key and data type - IF_FAIL_RETURN_TAG(check_record_key_data_type(TYPE_NUMERIC, key), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Data type mismatched"); - - int index = __getIndexOf(record, key); - IF_FAIL_RETURN_TAG(index >= 0, CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Invalid record key"); - - int64_t value; - IF_FAIL_RETURN_TAG(record->tuple->getAt(index, &value), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Invalid data"); - - *val = value; - - return CONTEXT_HISTORY_ERROR_NONE; -} - -EXPORT_API int context_history_record_get_double(context_history_record_h record, const char* key, double* val) -{ - ASSERT_NOT_NULL(record && val && key); - - // Check key and data type - IF_FAIL_RETURN_TAG(check_record_key_data_type(TYPE_NUMERIC, key), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Data type mismatched"); - - int index = __getIndexOf(record, key); - IF_FAIL_RETURN_TAG(index >= 0, CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Invalid record key"); - - IF_FAIL_RETURN_TAG(record->tuple->getAt(index, val), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Invalid data"); - - return CONTEXT_HISTORY_ERROR_NONE; -} - -EXPORT_API int context_history_record_get_string(context_history_record_h record, const char* key, char** val) -{ - ASSERT_NOT_NULL(record && val && key); - - // Check key and data type - IF_FAIL_RETURN_TAG(check_record_key_data_type(TYPE_STRING, key), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Data type mismatched"); - - int index = __getIndexOf(record, key); - IF_FAIL_RETURN_TAG(index >= 0, CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Invalid record key"); - - std::string str; - IF_FAIL_RETURN_TAG(record->tuple->getAt(index, &str), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Invalid data"); - - *val = g_strdup(str.c_str()); - ASSERT_ALLOC(*val); - - return CONTEXT_HISTORY_ERROR_NONE; -} - -EXPORT_API int context_history_record_destroy(context_history_record_h record) -{ - ASSERT_NOT_NULL(record); - delete record; - - return CONTEXT_HISTORY_ERROR_NONE; -} - -std::string convert_filter_to_string(context_history_filter_e filter_type) -{ - std::string str; - switch (filter_type) { - case CONTEXT_HISTORY_FILTER_TIME_SPAN: - str = KEY_TIME_SPAN; - break; - case CONTEXT_HISTORY_FILTER_RESULT_SIZE: - str = KEY_RESULT_SIZE; - break; - case CONTEXT_HISTORY_FILTER_APP_ID: - str = KEY_APP_ID; - break; - case CONTEXT_HISTORY_FILTER_DAY_OF_WEEK: - str = KEY_DAY_OF_WEEK; - break; - case CONTEXT_HISTORY_FILTER_START_TIME: - str = KEY_START_TIME; - break; - case CONTEXT_HISTORY_FILTER_END_TIME: - str = KEY_END_TIME; - break; - case CONTEXT_HISTORY_FILTER_WIFI_BSSID: - str = KEY_BSSID; - break; - case CONTEXT_HISTORY_FILTER_AUDIO_JACK: - str = KEY_AUDIO_JACK; - break; - case CONTEXT_HISTORY_FILTER_COMMUNICATION_TYPE: - str = KEY_COMMUNICATION_TYPE; - break; - default: - break; - } - return str; -} - -std::string convert_data_to_string(context_history_data_e data_type) -{ - std::string str; - switch (data_type) { - case CONTEXT_HISTORY_RECENTLY_USED_APP: - str = SUBJ_APP_RECENTLY_USED; - break; - case CONTEXT_HISTORY_FREQUENTLY_USED_APP: - str = SUBJ_APP_FREQUENTLY_USED; - break; - case CONTEXT_HISTORY_RARELY_USED_APP: - str = SUBJ_APP_RARELY_USED; - break; - case CONTEXT_HISTORY_PEAK_TIME_FOR_APP: - str = SUBJ_APP_PEAK_TIME; - break; - case CONTEXT_HISTORY_PEAK_TIME_FOR_MUSIC: - str = SUBJ_MUSIC_PEAK_TIME; - break; - case CONTEXT_HISTORY_PEAK_TIME_FOR_VIDEO: - str = SUBJ_VIDEO_PEAK_TIME; - break; - case CONTEXT_HISTORY_COMMON_SETTING_FOR_APP: - str = SUBJ_APP_COMMON_SETTING; - break; - case CONTEXT_HISTORY_COMMON_SETTING_FOR_MUSIC: - str = SUBJ_MUSIC_COMMON_SETTING; - break; - case CONTEXT_HISTORY_COMMON_SETTING_FOR_VIDEO: - str = SUBJ_VIDEO_COMMON_SETTING; - break; - case CONTEXT_HISTORY_FREQUENTLY_COMMUNICATED_ADDRESS: - str = SUBJ_SOCIAL_FREQ_ADDRESS; - break; - case CONTEXT_HISTORY_BATTERY_USAGE: - str = SUBJ_BATTERY_USAGE; - break; - case CONTEXT_HISTORY_RECENT_BATTERY_USAGE: - str = SUBJ_BATTERY_RECENT_USAGE; - break; - default: - break; - } - return str; -} - -bool check_record_key_data_type(int type, std::string key) -{ - if ((key.compare(CONTEXT_HISTORY_APP_ID) == 0) || - key.compare(CONTEXT_HISTORY_ADDRESS) == 0) { - return (type == TYPE_STRING); - } - - if ((key.compare(CONTEXT_HISTORY_TOTAL_COUNT) == 0) || - key.compare(CONTEXT_HISTORY_TOTAL_AMOUNT) == 0 || - key.compare(CONTEXT_HISTORY_TOTAL_DURATION) == 0 || - key.compare(CONTEXT_HISTORY_LAST_TIME) == 0 || - key.compare(CONTEXT_HISTORY_HOUR_OF_DAY) == 0 || - key.compare(CONTEXT_HISTORY_AUDIO_JACK) == 0 || - key.compare(CONTEXT_HISTORY_SYSTEM_VOLUME) == 0 || - key.compare(CONTEXT_HISTORY_MEDIA_VOLUME) == 0 || - key.compare(KEY_USED_TIME) == 0) { // Internal use for RecentBatteryUsage - return (type == TYPE_NUMERIC); - } - - return false; -} - -bool check_filter_data_int(context_history_filter_e filter_type, int val) -{ - switch (filter_type) { - case CONTEXT_HISTORY_FILTER_TIME_SPAN: - case CONTEXT_HISTORY_FILTER_RESULT_SIZE: - case CONTEXT_HISTORY_FILTER_START_TIME: - case CONTEXT_HISTORY_FILTER_END_TIME: - if (val > 0) - return true; - break; - case CONTEXT_HISTORY_FILTER_DAY_OF_WEEK: - if (val == CONTEXT_HISTORY_FILTER_DAY_OF_WEEK_WEEKDAYS || - val == CONTEXT_HISTORY_FILTER_DAY_OF_WEEK_WEEKENDS || - val == CONTEXT_HISTORY_FILTER_DAY_OF_WEEK_ALL) - return true; - break; - case CONTEXT_HISTORY_FILTER_AUDIO_JACK: - if (val == CONTEXT_HISTORY_FILTER_AUDIO_JACK_NOT_CONNECTED || - val == CONTEXT_HISTORY_FILTER_AUDIO_JACK_CONNECTED) - return true; - break; - case CONTEXT_HISTORY_FILTER_COMMUNICATION_TYPE: - if (val == CONTEXT_HISTORY_FILTER_COMMUNICATION_TYPE_CALL || - val == CONTEXT_HISTORY_FILTER_COMMUNICATION_TYPE_MESSAGE || - val == CONTEXT_HISTORY_FILTER_COMMUNICATION_TYPE_ALL) - return true; - break; - default: - return false; - } - return false; -} - -bool check_filter_data_string(context_history_filter_e filter_type, const char* val) -{ - IF_FAIL_RETURN(val, false); - - switch (filter_type) { - case CONTEXT_HISTORY_FILTER_APP_ID: - case CONTEXT_HISTORY_FILTER_WIFI_BSSID: - return (g_strstr_len(val, -1, ";") == NULL); - - default: - return false; - } -} - -bool check_invalid_filter(context_history_data_e data_type, context_history_filter_h filter) -{ - /* This should be aligned with context_history_filter_e */ - static const char *filter_key[FILTER_KEY_LIMIT] = { - NULL, - KEY_TIME_SPAN, - KEY_RESULT_SIZE, - KEY_APP_ID, - KEY_DAY_OF_WEEK, - KEY_START_TIME, - KEY_END_TIME, - KEY_BSSID, - KEY_AUDIO_JACK, - KEY_COMMUNICATION_TYPE, - }; - - bool allowed[FILTER_KEY_LIMIT] = {false}; - - allowed[CONTEXT_HISTORY_FILTER_TIME_SPAN] = true; - allowed[CONTEXT_HISTORY_FILTER_START_TIME] = true; - allowed[CONTEXT_HISTORY_FILTER_END_TIME] = true; - allowed[CONTEXT_HISTORY_FILTER_RESULT_SIZE] = true; - - switch (data_type) { - case CONTEXT_HISTORY_RECENTLY_USED_APP: - case CONTEXT_HISTORY_FREQUENTLY_USED_APP: - allowed[CONTEXT_HISTORY_FILTER_WIFI_BSSID] = true; - allowed[CONTEXT_HISTORY_FILTER_AUDIO_JACK] = true; - break; - - case CONTEXT_HISTORY_RARELY_USED_APP: - break; - - case CONTEXT_HISTORY_PEAK_TIME_FOR_APP: - allowed[CONTEXT_HISTORY_FILTER_APP_ID] = true; - allowed[CONTEXT_HISTORY_FILTER_DAY_OF_WEEK] = true; - break; - - case CONTEXT_HISTORY_PEAK_TIME_FOR_MUSIC: - case CONTEXT_HISTORY_PEAK_TIME_FOR_VIDEO: - allowed[CONTEXT_HISTORY_FILTER_DAY_OF_WEEK] = true; - break; - - case CONTEXT_HISTORY_COMMON_SETTING_FOR_APP: - allowed[CONTEXT_HISTORY_FILTER_RESULT_SIZE] = false; - allowed[CONTEXT_HISTORY_FILTER_APP_ID] = true; - break; - - case CONTEXT_HISTORY_COMMON_SETTING_FOR_MUSIC: - case CONTEXT_HISTORY_COMMON_SETTING_FOR_VIDEO: - allowed[CONTEXT_HISTORY_FILTER_RESULT_SIZE] = false; - break; - - case CONTEXT_HISTORY_FREQUENTLY_COMMUNICATED_ADDRESS: - allowed[CONTEXT_HISTORY_FILTER_COMMUNICATION_TYPE] = true; - break; - - case CONTEXT_HISTORY_BATTERY_USAGE: - break; - - case CONTEXT_HISTORY_RECENT_BATTERY_USAGE: - allowed[CONTEXT_HISTORY_FILTER_TIME_SPAN] = false; - allowed[CONTEXT_HISTORY_FILTER_START_TIME] = false; - allowed[CONTEXT_HISTORY_FILTER_END_TIME] = false; - break; - - default: - return false; - } - - bool found = true; - std::vector keys = filter->jfilter.getMemberNames(); - - for (auto& key : keys) { - found = false; - for (int i = 1; i < FILTER_KEY_LIMIT; ++i) { - if (allowed[i] && key == filter_key[i]) { - found = true; - break; - } - } - if (found == true) - continue; - - return false; - } - - return true; -} - -int __getIndexOf(context_history_record_h record, const std::string& key) -{ - unsigned int i = 0; - - for (i = 0; i < record->keys.size(); ++i) { - if (record->keys[i] == key) { - return i; - } - } - return -1; -} - -bool history_is_deprecated(context_history_data_e data_type) -{ - bool ret = false; - switch (data_type) { - case CONTEXT_HISTORY_RARELY_USED_APP: - case CONTEXT_HISTORY_PEAK_TIME_FOR_APP: - case CONTEXT_HISTORY_PEAK_TIME_FOR_MUSIC: - case CONTEXT_HISTORY_PEAK_TIME_FOR_VIDEO: - case CONTEXT_HISTORY_COMMON_SETTING_FOR_APP: - case CONTEXT_HISTORY_COMMON_SETTING_FOR_MUSIC: - case CONTEXT_HISTORY_COMMON_SETTING_FOR_VIDEO: - case CONTEXT_HISTORY_FREQUENTLY_COMMUNICATED_ADDRESS: - ret = true; - break; - default: - break; - } - return ret; -} - -bool history_filter_is_deprecated(context_history_filter_e filter_type) -{ - bool ret = false; - switch (filter_type) { - case CONTEXT_HISTORY_FILTER_APP_ID: - case CONTEXT_HISTORY_FILTER_DAY_OF_WEEK: - case CONTEXT_HISTORY_FILTER_WIFI_BSSID: - case CONTEXT_HISTORY_FILTER_COMMUNICATION_TYPE: - ret = true; - break; - default: - break; - } - return ret; -} diff --git a/src/context_trigger.cpp b/src/context_trigger.cpp deleted file mode 100644 index 941cc02..0000000 --- a/src/context_trigger.cpp +++ /dev/null @@ -1,1204 +0,0 @@ -/* - * Copyright (c) 2015 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include "TriggerOldRuleTypes.h" -#include "rule_validator.h" -#include "rule_util.h" - -#define TRIGGER_DEPRECATED_FUNCTION_MSG "DEPRECATION WARNING: %s is deprecated and will be removed from next release." -#define TRIGGER_DEPRECATED_EVENT_MSG "DEPRECATION WARNING: This event is deprecated and will be removed from next release." -#define TRIGGER_DEPRECATED_CONDITION_MSG "DEPRECATION WARNING: This condition is deprecated and will be removed from next release." - -//#define DOUBLE_PRECISION 2 -#define TYPE_EVENT 1 -#define TYPE_CONDITION 2 -#define TYPE_OPTION TRIG_TMPL_KEY_OPTION -#define TYPE_ATTRIBUTE TRIG_TMPL_KEY_ATTRIBUTE -#define OLD_INITIAL_ENTRY "{ \"" OLD_TRIG_RULE_KEY_DATA_ARR "\" : [ ] }" -#define INITIAL_REF "{ \"" TRIG_TMPL_KEY_OPTION "\" : [ ], \"" TRIG_TMPL_KEY_ATTRIBUTE "\" : [ ] }" -#define INITIAL_RULE \ -"{ \"" TRIG_RULE_KEY_DESCRIPTION "\" : \"\", \"" TRIG_RULE_KEY_EVENT "\" : { }, \"" TRIG_RULE_KEY_CONDITION "\" : [ ], \"" \ -TRIG_RULE_KEY_ACTION "\" : { }, \"" _TRIG_RULE_KEY_EXTRA "\": { } }" -#define INITIAL_ENTRY "{ \"" TRIG_RULE_KEY_OPTION "\": { }, \"" TRIG_RULE_KEY_COMPARISON "\" : { } }" - -static ctx::DBusClient __dbusClient; - -static int context_trigger_rule_event_create_internal(const char* event_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom = false); -static int context_trigger_rule_condition_create_internal(const char* condition_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom = false); -static std::string convert_event_to_string(context_trigger_event_e item); -static std::string convert_condition_to_string(context_trigger_condition_e item); -static std::string convert_logical_type_to_string(context_trigger_logical_type_e logical_type); -static std::string get_custom_item_subject(const char* provider, const char* item); -static bool event_is_deprecated(context_trigger_event_e item); -static bool condition_is_deprecated(context_trigger_condition_e item); - -//static std::string int_to_string(int value); -//static std::string double_to_string(int value); - -typedef struct _context_trigger_rule_s { - ctx::CtxJson1 jold_rule; - ctx::CtxJson1 jrule; // description, event{}, condition[], action{}, _extra{} - ctx::CtxJson1 jref; - - _context_trigger_rule_s() { - jold_rule = EMPTY_JSON_OBJECT; - jrule = INITIAL_RULE; - jref = INITIAL_REF; - } -} _context_trigger_rule_h; - -typedef struct _context_trigger_rule_entry_s { - int type; - ctx::CtxJson1 jentry; - ctx::CtxJson1 jref; - - _context_trigger_rule_entry_s(int t): type(t) { - jentry = OLD_INITIAL_ENTRY; - - if (t == TYPE_CONDITION) { - jref = INITIAL_REF; - } - } -} _context_trigger_rule_entry_h; - -// Add a rule -SO_EXPORT int context_trigger_add_rule(context_trigger_rule_h rule, int* rule_id) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(rule && rule_id); - - // Err: No event - if (!ctx::rule_util::isEventSet(rule->jrule)) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - - // Err: No action - if (!ctx::rule_util::isActionSet(rule->jrule)) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - - // If condition size isn't greater than 1, update logical operator as default - if ((rule->jrule).getSize(NULL, TRIG_RULE_KEY_CONDITION) <= 1) { - (rule->jrule).set(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_RULE_LOGICAL_OP, TRIG_RULE_LOGICAL_CONJUNCTION); - } - - ctx::CtxJson1 jrule_id; - int error = __dbusClient.write(SUBJ_TRIGGER_ADD, rule->jrule, &jrule_id); - - if (error == ERR_NONE) { - jrule_id.get(NULL, TRIG_KEY_RULE_ID, rule_id); - } - - return error; -} - -// Remove a rule -SO_EXPORT int context_trigger_remove_rule(int rule_id) -{ - _D("BEGIN"); - if (rule_id <= 0) - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - - ctx::CtxJson1 jrule_id; - jrule_id.set(NULL, TRIG_KEY_RULE_ID, rule_id); - int error = __dbusClient.write(SUBJ_TRIGGER_REMOVE, jrule_id, NULL); - - if (error == ERR_ALREADY_STARTED) { // Rule is still enabled. - return CONTEXT_TRIGGER_ERROR_RULE_ENABLED; - } else if (error == ERR_NO_DATA) { - return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; - } - - return error; -} - -// Enable a rule -SO_EXPORT int context_trigger_enable_rule(int rule_id) -{ - _D("BEGIN"); - if (rule_id <= 0) - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - - ctx::CtxJson1 jrule_id; - jrule_id.set(NULL, TRIG_KEY_RULE_ID, rule_id); - - int req_id; // Useless in context_trigger - int error = __dbusClient.subscribe(SUBJ_TRIGGER_ENABLE, jrule_id, &req_id, NULL); - - if (error == ERR_NO_DATA) { - return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; - } - - return error; -} - -// Disable a rule -SO_EXPORT int context_trigger_disable_rule(int rule_id) -{ - _D("BEGIN"); - if (rule_id <= 0) - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - - ctx::CtxJson1 jrule_id; - jrule_id.set(NULL, TRIG_KEY_RULE_ID, rule_id); - int error = __dbusClient.write(SUBJ_TRIGGER_DISABLE, jrule_id, NULL); - - if (error == ERR_NO_DATA) { - return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; - } - - return error; -} - -SO_EXPORT int context_trigger_get_own_rule_ids(int** enabled_rule_ids, int* enabled_rule_count, int** disabled_rule_ids, int* disabled_rule_count) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(enabled_rule_ids && enabled_rule_count && disabled_rule_ids && disabled_rule_count); - - int req_id; - ctx::CtxJson1 data_read; - int error = __dbusClient.readSync(SUBJ_TRIGGER_GET_RULE_IDS, NULL, &req_id, &data_read); - - if (error != ERR_NONE) { - return error; - } - - // Enabled rules - int* e_arr = NULL; - *enabled_rule_count = data_read.getSize(NULL, TRIG_KEY_ENABLED_IDS); - - if (*enabled_rule_count > 0) { - e_arr = static_cast(g_malloc((*enabled_rule_count) * sizeof(int))); - IF_FAIL_RETURN_TAG(e_arr, CONTEXT_TRIGGER_ERROR_OUT_OF_MEMORY, _E, "Memory allocation failed"); - - int id; - for (int i = 0; data_read.getAt(NULL, TRIG_KEY_ENABLED_IDS, i, &id); i++) { - *(e_arr + i) = id; - } - } - *enabled_rule_ids = e_arr; - - // Disabled rules - int* d_arr = NULL; - *disabled_rule_count = data_read.getSize(NULL, TRIG_KEY_DISABLED_IDS); - - if (*disabled_rule_count > 0) { - d_arr = static_cast(g_malloc((*disabled_rule_count) * sizeof(int))); - IF_FAIL_RETURN_TAG(d_arr, CONTEXT_TRIGGER_ERROR_OUT_OF_MEMORY, _E, "Memory allocation failed"); - - int id; - for (int i = 0; data_read.getAt(NULL, TRIG_KEY_DISABLED_IDS, i, &id); i++) { - *(d_arr + i) = id; - } - } - *disabled_rule_ids = d_arr; - - return error; -} - - -SO_EXPORT int context_trigger_get_rule_by_id(int rule_id, context_trigger_rule_h* rule) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(rule); - if (rule_id <= 0) - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - - ctx::CtxJson1 option; - option.set(NULL, TRIG_KEY_RULE_ID, rule_id); - - int req_id; - ctx::CtxJson1 data_read; - int error = __dbusClient.readSync(SUBJ_TRIGGER_GET, option, &req_id, &data_read); - - if (error == ERR_NO_DATA) { - return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; - } else if (error != ERR_NONE) { - return error; - } - - *rule = new(std::nothrow) _context_trigger_rule_h(); - (*rule)->jrule = data_read; - - return ERR_NONE; -} - -// Rule creation -SO_EXPORT int context_trigger_rule_create(context_trigger_logical_type_e logical_type, context_trigger_rule_h* rule) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(rule); - - std::string logical_str = convert_logical_type_to_string(logical_type); - if (logical_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } - - *rule = new(std::nothrow) _context_trigger_rule_h(); - (*rule)->jold_rule.set(NULL, OLD_TRIG_RULE_KEY_OPERATOR, logical_str); - - (*rule)->jrule.set(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_RULE_LOGICAL_OP, logical_str); - - return ERR_NONE; -} - -// Rule deletion -SO_EXPORT int context_trigger_rule_destroy(context_trigger_rule_h rule) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(rule); - delete rule; - - return CONTEXT_TRIGGER_ERROR_NONE; -} - - -SO_EXPORT int context_trigger_rule_add_entry(context_trigger_rule_h rule, context_trigger_rule_entry_h entry) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(rule && entry); - - // Check if rule handle is created - ctx::CtxJson1 extra; - bool ret = (rule->jrule).get(NULL, _TRIG_RULE_KEY_EXTRA, &extra); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER); - - if (entry->type == TYPE_EVENT) { - // Err: More than one event - ctx::CtxJson1 elem; - if ((rule->jold_rule).get(NULL, OLD_TRIG_RULE_KEY_EVENT, &elem)) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - - // Err: Check if all the mandatory options are added - ret = ctx::rule_validator::check_option(entry->jentry); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - // Err: If referential conditions are registered priviously, check them - std::string ename; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &ename); - ret = ctx::rule_validator::check_referential_data(ename, rule->jref); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - ctx::CtxJson1 temp = (entry->jentry).str(); - ret = (rule->jold_rule).set(NULL, OLD_TRIG_RULE_KEY_EVENT, temp); - - int error = ctx::rule_util::setEvent(entry->jentry, &(rule->jrule)); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to add event entry"); - } else if (entry->type == TYPE_CONDITION) { - // Err: Condition without comparison data - if ((entry->jentry).getSize(NULL, OLD_TRIG_RULE_KEY_DATA_ARR) < 1) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - - ctx::CtxJson1 elem; - for (int i = 0; (entry->jentry).getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { - int val_arr_size = elem.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR); - int op_arr_size = elem.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR); - - // Err: Condition without comparison data - if (val_arr_size != op_arr_size || val_arr_size < 1 || op_arr_size < 1) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - - // Err: Check if all the mandatory options are added - ret = ctx::rule_validator::check_option(entry->jentry); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - // If event is already added .... - std::string ename; - ret = (rule->jold_rule).get(OLD_TRIG_RULE_KEY_EVENT, OLD_TRIG_RULE_KEY_EVENT_ITEM, &ename); - if (ret) { - // Err: Check referential information if exists - ret = ctx::rule_validator::check_referential_data(ename, entry->jref); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - } else { - // If not, copy referential information to rule entry - ctx::CtxJson1 info; - for (int j = 0; (entry->jref).getAt(NULL, TYPE_OPTION, j, &info); j++) { - (rule->jref).append(NULL, TYPE_OPTION, info); - } - - for (int j = 0; (entry->jref).getAt(NULL, TYPE_ATTRIBUTE, j, &info); j++) { - (rule->jref).append(NULL, TYPE_ATTRIBUTE, info); - } - } - } - - ctx::CtxJson1 temp = (entry->jentry).str(); - ret = (rule->jold_rule).append(NULL, OLD_TRIG_RULE_KEY_CONDITION, temp); - - ctx::rule_util::addCondition(entry->jentry, &(rule->jrule)); - } else { - // Entry is not created - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } - - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_OPERATION_FAILED); - return CONTEXT_TRIGGER_ERROR_NONE; -} - -static bool is_call_operation(app_control_h app_control) -{ - char *op = NULL; - int err = app_control_get_operation(app_control, &op); - IF_FAIL_RETURN_TAG(err == APP_CONTROL_ERROR_NONE, false, _W, "Getting operation of app control failed"); - - bool ret = STR_EQ(op, APP_CONTROL_OPERATION_CALL); - g_free(op); - - return ret; -} - -SO_EXPORT int context_trigger_rule_set_action_app_control(context_trigger_rule_h rule, app_control_h app_control) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(rule && app_control); - int error; - - // Privilege check - error = __dbusClient.call(METHOD_CHK_PRIV_APPLAUNCH); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Privilege checking failed (%#x)", error); - - if (is_call_operation(app_control)) { - error = __dbusClient.call(METHOD_CHK_PRIV_CALL); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Privilege checking failed (%#x)", error); - } - - // Err: if action arleady exists - if (ctx::rule_util::isActionSet(rule->jrule)) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - - // Err: service app - char* app_id = NULL; - error = app_control_get_app_id(app_control, &app_id); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to get app id"); - - pkgmgrinfo_appinfo_h app_info; - error = pkgmgrinfo_appinfo_get_usr_appinfo(app_id, getuid(), &app_info); - g_free(app_id); - IF_FAIL_RETURN_TAG(error == PMINFO_R_OK, CONTEXT_TRIGGER_ERROR_INVALID_RULE, _E, "No such app"); - - // Service apps are not allowed to be launched (Mobile & Wearable) - char *app_type = NULL; - pkgmgrinfo_appinfo_get_component_type(app_info, &app_type); - if (!strcmp(app_type, "svcapp")) { - _E("Service application is restricted"); - pkgmgrinfo_appinfo_destroy_appinfo(app_info); - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - pkgmgrinfo_appinfo_destroy_appinfo(app_info); - - // Set app control - bundle* appctl_bundle = NULL; - error = app_control_to_bundle(app_control, &appctl_bundle); - IF_FAIL_RETURN_TAG(error == ERR_NONE, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "App_control to bundle failed"); - - bundle_raw* appctl_raw; - int raw_length; - error = bundle_encode(appctl_bundle, &appctl_raw, &raw_length); - IF_FAIL_RETURN_TAG(error == ERR_NONE, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Bundle encode failed"); - - std::string appctl_str = reinterpret_cast(appctl_raw); - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_APP_LAUNCH, TRIG_RULE_KEY_APP_LAUNCH_APP_CONTROL, appctl_str); - bundle_free_encoded_rawdata(&appctl_raw); - - return CONTEXT_TRIGGER_ERROR_NONE; -} - -SO_EXPORT int context_trigger_rule_set_action_notification(context_trigger_rule_h rule, const char* title, const char* content, const char* icon_path, app_control_h app_control) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(rule && title && content); - - // Privilege check - int error = __dbusClient.call(METHOD_CHK_PRIV_NOTIFICATION); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Privilege checking failed (%#x)", error); - - // if action arleady exists - if (ctx::rule_util::isActionSet(rule->jrule)) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - - // Err: App control check - if (app_control) { - char* app_id = NULL; - error = app_control_get_app_id(app_control, &app_id); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to get app id"); - - pkgmgrinfo_appinfo_h app_info; - error = pkgmgrinfo_appinfo_get_usr_appinfo(app_id, getuid(), &app_info); - g_free(app_id); - IF_FAIL_RETURN_TAG(error == PMINFO_R_OK, CONTEXT_TRIGGER_ERROR_INVALID_RULE, _E, "No such app"); - - pkgmgrinfo_appinfo_destroy_appinfo(app_info); - } - - // Set title, content - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_TITLE, title); - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_CONTENT, content); - - // Set icon path - if (icon_path) { - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_ICON_PATH, icon_path); - } - - // Set app control - if (app_control) { - bundle* appctl_bundle = NULL; - error = app_control_to_bundle(app_control, &appctl_bundle); - IF_FAIL_RETURN_TAG(error == ERR_NONE, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "App_control to bundle failed"); - - bundle_raw* appctl_raw; - int raw_length; - error = bundle_encode(appctl_bundle, &appctl_raw, &raw_length); - IF_FAIL_RETURN_TAG(error == ERR_NONE, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Bundle encode failed"); - - std::string appctl_str = reinterpret_cast(appctl_raw); - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_APP_CONTROL, appctl_str); - - bundle_free_encoded_rawdata(&appctl_raw); - } - - return CONTEXT_TRIGGER_ERROR_NONE; -} - -SO_EXPORT int context_trigger_rule_set_action_dbus_call(context_trigger_rule_h rule, - const char *bus_name, const char *object_path, const char *interface_name, const char *method_name, GVariant *param) -{ - ASSERT_NOT_NULL(rule && bus_name && object_path && interface_name && method_name); - - /* if action arleady exists */ - if (ctx::rule_util::isActionSet(rule->jrule)) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - - /* Set basic dbus method call info */ - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_NAME, bus_name); - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_OBJECT, object_path); - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_INTERFACE, interface_name); - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_METHOD, method_name); - - /* Set the parameters */ - if (param) - (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_PARAMETER, param); - - return CONTEXT_TRIGGER_ERROR_NONE; -} - -// Set description -SO_EXPORT int context_trigger_rule_set_description(context_trigger_rule_h rule, const char* description) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(rule); - - (rule->jrule).set(NULL, TRIG_RULE_KEY_DESCRIPTION, description); - - return CONTEXT_TRIGGER_ERROR_NONE; -} - -// Get rule description -SO_EXPORT int context_trigger_rule_get_description(context_trigger_rule_h rule, char** description) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(rule && description); - - std::string val; - (rule->jrule).get(NULL, TRIG_RULE_KEY_DESCRIPTION, &val); - - *description = strdup(val.c_str()); - - return CONTEXT_TRIGGER_ERROR_NONE; -} - -// Event creation -SO_EXPORT int context_trigger_rule_event_create(context_trigger_event_e event_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(entry); - - if (event_is_deprecated(event_item)) { - _W(TRIGGER_DEPRECATED_EVENT_MSG); - } - - std::string eitem_str = convert_event_to_string(event_item); - if (eitem_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } - - int error = context_trigger_rule_event_create_internal(eitem_str.c_str(), logical_type, entry); - return error; -} - -SO_EXPORT int context_trigger_rule_custom_event_create(const char* event_item, const char* provider, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(event_item && provider && entry); - - // Err: Invalid provider - pkgmgrinfo_pkginfo_h pkg_info; - int error = pkgmgrinfo_pkginfo_get_usr_pkginfo(provider, getuid(), &pkg_info); - pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_info); - IF_FAIL_RETURN_TAG(error == PMINFO_R_OK, CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "No such package"); - - std::string subject = get_custom_item_subject(provider, event_item); - error = context_trigger_rule_event_create_internal(subject.c_str(), logical_type, entry, true); - - return error; -} - -int context_trigger_rule_event_create_internal(const char* event_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(event_item); - - // Err: Invalid logical operator - std::string logical_str = convert_logical_type_to_string(logical_type); - if (logical_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } - - int error = ctx::rule_validator::request_template(event_item, is_custom); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to request template: %#x", error); - - *entry = new(std::nothrow) _context_trigger_rule_entry_h(TYPE_EVENT); - (*entry)->jentry.set(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, event_item); - (*entry)->jentry.set(NULL, OLD_TRIG_RULE_KEY_EVENT_OPERATOR, logical_str); - - return CONTEXT_TRIGGER_ERROR_NONE; -} - -// Event availability check -SO_EXPORT int context_trigger_rule_event_is_supported(context_trigger_event_e event_item, bool* supported) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(supported); - - if (event_is_deprecated(event_item)) { - _W(TRIGGER_DEPRECATED_EVENT_MSG); - } - - *supported = false; - - std::string eitem_str = convert_event_to_string(event_item); - if (eitem_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } - - int error = __dbusClient.isSupported(eitem_str); - - if (error == ERR_NONE) - *supported = true; - - if (error == ERR_NOT_SUPPORTED) - return ERR_NONE; - - return error; -} - -// Condition creation -SO_EXPORT int context_trigger_rule_condition_create(context_trigger_condition_e condition_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(entry); - - if (condition_is_deprecated(condition_item)) { - _W(TRIGGER_DEPRECATED_CONDITION_MSG); - } - - std::string citem_str = convert_condition_to_string(condition_item); - if (citem_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } - - int error = context_trigger_rule_condition_create_internal(citem_str.c_str(), logical_type, entry); - return error; -} - -SO_EXPORT int context_trigger_rule_custom_condition_create(const char* condition_item, const char* provider, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(condition_item && provider && entry); - - // Err: Invalid provider - pkgmgrinfo_pkginfo_h pkg_info; - int error = pkgmgrinfo_pkginfo_get_usr_pkginfo(provider, getuid(), &pkg_info); - pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_info); - IF_FAIL_RETURN_TAG(error == PMINFO_R_OK, CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "No such package"); - - std::string subject = get_custom_item_subject(provider, condition_item); - error = context_trigger_rule_condition_create_internal(subject.c_str(), logical_type, entry, true); - return error; -} - -int context_trigger_rule_condition_create_internal(const char* condition_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(condition_item); - - std::string logical_str = convert_logical_type_to_string(logical_type); - if (logical_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } - - int error = ctx::rule_validator::request_template(condition_item, is_custom); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to request template: %#x", error); - - *entry = new(std::nothrow) _context_trigger_rule_entry_h(TYPE_CONDITION); - (*entry)->jentry.set(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, condition_item); - (*entry)->jentry.set(NULL, OLD_TRIG_RULE_KEY_CONDITION_OPERATOR, logical_str); - - return CONTEXT_TRIGGER_ERROR_NONE; -} - -// Condition availability check -SO_EXPORT int context_trigger_rule_condition_is_supported(context_trigger_condition_e condition_item, bool* supported) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(supported); - - if (condition_is_deprecated(condition_item)) { - _W(TRIGGER_DEPRECATED_CONDITION_MSG); - } - - *supported = false; - - std::string citem_str = convert_condition_to_string(condition_item); - if (citem_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } - - int error = __dbusClient.isSupported(citem_str); - - if (error == ERR_NONE) - *supported = true; - - if (error == ERR_NOT_SUPPORTED) - return ERR_NONE; - - return error; -} - -// Rule data deletion -SO_EXPORT int context_trigger_rule_entry_destroy(context_trigger_rule_entry_h entry) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(entry); - delete entry; - - return CONTEXT_TRIGGER_ERROR_NONE; -} - -SO_EXPORT int context_trigger_rule_entry_add_option_int(context_trigger_rule_entry_h entry, const char* option_key, int value) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(entry && option_key); - - bool ret = true; - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &name); - ret = ctx::rule_validator::check_option_int(name, option_key, value); - if (!ret) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - - (entry->jentry).set(OLD_TRIG_RULE_KEY_CONDITION_OPTION, option_key, value); - - return CONTEXT_TRIGGER_ERROR_NONE; -} - -SO_EXPORT int context_trigger_rule_entry_add_option_string(context_trigger_rule_entry_h entry, const char* option_key, const char* value) -{ - _D("BEGIN"); - _W(TRIGGER_DEPRECATED_FUNCTION_MSG, __FUNCTION__); - ASSERT_NOT_NULL(entry && option_key && value); - - bool ret = true; - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &name); - ret = ctx::rule_validator::check_option_string(name, option_key, value); - if (!ret) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - - (entry->jentry).set(OLD_TRIG_RULE_KEY_CONDITION_OPTION, option_key, value); - - return CONTEXT_TRIGGER_ERROR_NONE; -} - -SO_EXPORT int context_trigger_rule_entry_add_option(context_trigger_rule_entry_h entry, const char* option_key, const char* event_data_key) -{ - _D("BEGIN"); - _W(TRIGGER_DEPRECATED_FUNCTION_MSG, __FUNCTION__); - ASSERT_NOT_NULL(entry && option_key && event_data_key); - - // Err: Only conditin can reference data from event - if (entry->type != TYPE_CONDITION) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &name); - - // Err: Check if key is valid - bool ret = ctx::rule_validator::check_valid_key(TYPE_OPTION, name, option_key); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - // Set reference information - ret = ctx::rule_validator::set_ref_info(TYPE_OPTION, &(entry->jref), name, option_key, event_data_key); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_OPERATION_FAILED); - - (entry->jentry).set(OLD_TRIG_RULE_KEY_CONDITION_OPTION, option_key, std::string(TRIG_RULE_REF_KEY_PREFIX) + std::string(event_data_key)); - - return CONTEXT_TRIGGER_ERROR_NONE; -} - -SO_EXPORT int context_trigger_rule_entry_add_key(context_trigger_rule_entry_h entry, context_trigger_logical_type_e logical_type, const char* key) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(entry && key); - - std::string logical_str = convert_logical_type_to_string(logical_type); - if (logical_str.empty()) { - return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; - } - - // Err: Check if key is valid - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); - - bool ret = ctx::rule_validator::check_valid_key(TYPE_ATTRIBUTE, name, key); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - // Err: Comparison key is already added - ctx::CtxJson1 elem; - for (int i = 0; (entry->jentry).getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { - std::string elem_item; - elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &elem_item); - // Err: Comparison key is already added - if (elem_item.compare(key) == 0) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - } - - ctx::CtxJson1 data; - data.set(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, key); - data.set(NULL, OLD_TRIG_RULE_KEY_DATA_KEY_OPERATOR, logical_str); - (entry->jentry).append(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, data); - - return CONTEXT_TRIGGER_ERROR_NONE; -} - -static int context_trigger_rule_entry_add_comparison_string_internal(context_trigger_rule_entry_h entry, const char* key, std::string op, std::string value) -{ - ctx::CtxJson1 elem; - for (int i = 0; (entry->jentry).getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { - std::string elem_item; - elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &elem_item); - - if (elem_item.compare(key) == 0) { - std::string elem_val; - std::string elem_op; - for (int j = 0; elem.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, j, &elem_val); j++) { - elem.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, j, &elem_op); - - // Err: Duplicated - if (elem_val.compare(value) == 0 && elem_op.compare(op) == 0) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - } - elem.append(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, value.c_str()); - elem.append(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, op); - (entry->jentry).setAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, elem); - - return CONTEXT_TRIGGER_ERROR_NONE; - } - } - - // Comparison key not exist - return CONTEXT_TRIGGER_ERROR_NO_DATA; -} - -static int context_trigger_rule_entry_add_comparison_int_internal(context_trigger_rule_entry_h entry, const char* key, std::string op, int value) -{ - ctx::CtxJson1 elem; - for (int i = 0; (entry->jentry).getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { - std::string elem_item; - elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &elem_item); - - if (elem_item.compare(key) == 0) { - int elem_val; - std::string elem_op; - for (int j = 0; elem.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, j, &elem_val); j++) { - elem.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, j, &elem_op); - - // Err: Duplicated - if (elem_val == value && elem_op.compare(op) == 0) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - } - elem.append(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, value); - elem.append(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, op); - (entry->jentry).setAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, elem); - - return CONTEXT_TRIGGER_ERROR_NONE; - } - } - - // Comparison key not exist - return CONTEXT_TRIGGER_ERROR_NO_DATA; -} - -SO_EXPORT int context_trigger_rule_entry_add_comparison(context_trigger_rule_entry_h entry, const char* key, const char* op, const char* event_data_key) -{ - _D("BEGIN"); - _W(TRIGGER_DEPRECATED_FUNCTION_MSG, __FUNCTION__); - ASSERT_NOT_NULL(entry && key && op && event_data_key); - - // Err: Only condition can reference data from event - if (entry->type != TYPE_CONDITION) { - return CONTEXT_TRIGGER_ERROR_INVALID_RULE; - } - - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &name); - - // Err: Check if key is valid - bool ret = ctx::rule_validator::check_valid_key(TYPE_ATTRIBUTE, name, key); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - // Err: Invalid operator - std::string type = ctx::rule_validator::get_data_type_from_template(TYPE_ATTRIBUTE, name, key); - ret = ctx::rule_validator::is_valid_operator(type, op); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - int error = context_trigger_rule_entry_add_comparison_string_internal(entry, key, op, std::string(TRIG_RULE_REF_KEY_PREFIX) + std::string(event_data_key)); - IF_FAIL_RETURN(error == ERR_NONE, error); - - // Set reference information - ret = ctx::rule_validator::set_ref_info(TYPE_ATTRIBUTE, &(entry->jref), name, key, event_data_key); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_OPERATION_FAILED); - - return CONTEXT_TRIGGER_ERROR_NONE; -} - -SO_EXPORT int context_trigger_rule_entry_add_comparison_int(context_trigger_rule_entry_h entry, const char* key, const char* op, int value) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(entry && key && op); - - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); - - bool ret = ctx::rule_validator::check_comparison_int(name, key, op, value); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - int error = context_trigger_rule_entry_add_comparison_int_internal(entry, key, op, value); - return error; -} -/* -SO_EXPORT int context_trigger_rule_entry_add_comparison_double(context_trigger_rule_entry_h entry, const char* key, const char* op, double value) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(entry && key && op); - - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); - - // TODO: check_comparison_double() - bool ret = ctx::rule_validator::check_comparison_double(name, key, op, value); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - int error = context_trigger_rule_entry_add_comparison_internal(entry, key, op, double_to_string(value)); - return error; -} -*/ -SO_EXPORT int context_trigger_rule_entry_add_comparison_string(context_trigger_rule_entry_h entry, const char* key, const char* op, const char* value) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(entry && key && op && value); - - std::string name; - (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); - - bool ret = ctx::rule_validator::check_comparison_string(name, key, op, value); - IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); - - int error = context_trigger_rule_entry_add_comparison_string_internal(entry, key, op, value); - return error; -} - -SO_EXPORT int context_trigger_custom_register(const char* name, const char* attr_template) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(name && attr_template); - - // Err: Invalid CtxJson1 - ctx::CtxJson1 jattr_template = attr_template; - IF_FAIL_RETURN_TAG(jattr_template.valid(), CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Failed to parse template"); - - // Err: Invalid template - bool ret = ctx::rule_validator::is_valid_template(jattr_template); - IF_FAIL_RETURN_TAG(ret, CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "Invalid template"); - - ctx::CtxJson1 data; - data.set(NULL, TRIG_CUSTOM_KEY_REQ, TRIG_CUSTOM_REQ_ADD); - data.set(NULL, TRIG_CUSTOM_KEY_NAME, name); - data.set(NULL, TRIG_TMPL_KEY_ATTRIBUTE, jattr_template); - - int error = __dbusClient.write(SUBJ_TRIGGER_CUSTOM, data, NULL); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to add custom item: %#x", error); - - return error; -} - -SO_EXPORT int context_trigger_custom_unregister(const char* name) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(name); - - ctx::CtxJson1 data; - data.set(NULL, TRIG_CUSTOM_KEY_REQ, TRIG_CUSTOM_REQ_REMOVE); - data.set(NULL, TRIG_CUSTOM_KEY_NAME, name); - - ctx::CtxJson1 subj; - int error = __dbusClient.write(SUBJ_TRIGGER_CUSTOM, data, &subj); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to remove custom item: %#x", error); - - std::string subject; - subj.get(NULL, TRIG_TMPL_KEY_SUBJECT, &subject); - ctx::rule_validator::remove_template(subject); - - return error; -} - -SO_EXPORT int context_trigger_custom_publish(const char* name, const char* fact) -{ - _D("BEGIN"); - ASSERT_NOT_NULL(name && fact); - - // Err: Invalid CtxJson1 - ctx::CtxJson1 jfact = fact; - IF_FAIL_RETURN_TAG(jfact.valid(), CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Cannot parse fact CtxJson1"); - - ctx::CtxJson1 data; - data.set(NULL, TRIG_CUSTOM_KEY_REQ, TRIG_CUSTOM_REQ_PUBLISH); - data.set(NULL, TRIG_CUSTOM_KEY_NAME, name); - data.set(NULL, TRIG_CUSTOM_KEY_FACT, jfact); - - int error = __dbusClient.write(SUBJ_TRIGGER_CUSTOM, data, NULL); - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to publish custom data"); - - return error; -} - -std::string convert_event_to_string(context_trigger_event_e item) -{ - std::string str; - switch (item) { - case CONTEXT_TRIGGER_EVENT_TIME: - str = SUBJ_STATE_ALARM; - break; - case CONTEXT_TRIGGER_EVENT_BATTERY: - str = SUBJ_STATE_BATTERY; - break; - case CONTEXT_TRIGGER_EVENT_CHARGER: - str = SUBJ_STATE_CHARGER; - break; - case CONTEXT_TRIGGER_EVENT_GPS: - str = SUBJ_STATE_GPS; - break; - case CONTEXT_TRIGGER_EVENT_HEADPHONE: - str = SUBJ_STATE_HEADPHONE; - break; - case CONTEXT_TRIGGER_EVENT_POWER_SAVING_MODE: - str = SUBJ_STATE_PSMODE; - break; - case CONTEXT_TRIGGER_EVENT_USB: - str = SUBJ_STATE_USB; - break; - case CONTEXT_TRIGGER_EVENT_WIFI: - str = SUBJ_STATE_WIFI; - break; - case CONTEXT_TRIGGER_EVENT_CALL: - str = SUBJ_STATE_CALL; - break; - case CONTEXT_TRIGGER_EVENT_EMAIL: - str = SUBJ_STATE_EMAIL; - break; - case CONTEXT_TRIGGER_EVENT_MESSAGE: - str = SUBJ_STATE_MESSAGE; - break; - case CONTEXT_TRIGGER_EVENT_CONTACTS: - str = SUBJ_STATE_CONTACTS; - break; - case CONTEXT_TRIGGER_EVENT_ACTIVITY_STATIONARY: - str = SUBJ_ACTIVITY_STATIONARY; - break; - case CONTEXT_TRIGGER_EVENT_ACTIVITY_WALKING: - str = SUBJ_ACTIVITY_WALKING; - break; - case CONTEXT_TRIGGER_EVENT_ACTIVITY_RUNNING: - str = SUBJ_ACTIVITY_RUNNING; - break; - case CONTEXT_TRIGGER_EVENT_ACTIVITY_IN_VEHICLE: - str = SUBJ_ACTIVITY_IN_VEHICLE; - break; - case CONTEXT_TRIGGER_EVENT_PLACE: - str = SUBJ_PLACE_GEOFENCE; - break; - default: - break; - } - return str; -} - -std::string convert_condition_to_string(context_trigger_condition_e item) -{ - std::string str; - switch (item) { - case CONTEXT_TRIGGER_CONDITION_TIME: - str = SUBJ_STATE_TIME; - break; - case CONTEXT_TRIGGER_CONDITION_BATTERY: - str = SUBJ_STATE_BATTERY; - break; - case CONTEXT_TRIGGER_CONDITION_CHARGER: - str = SUBJ_STATE_CHARGER; - break; - case CONTEXT_TRIGGER_CONDITION_GPS: - str = SUBJ_STATE_GPS; - break; - case CONTEXT_TRIGGER_CONDITION_HEADPHONE: - str = SUBJ_STATE_HEADPHONE; - break; - case CONTEXT_TRIGGER_CONDITION_POWER_SAVING_MODE: - str = SUBJ_STATE_PSMODE; - break; - case CONTEXT_TRIGGER_CONDITION_USB: - str = SUBJ_STATE_USB; - break; - case CONTEXT_TRIGGER_CONDITION_WIFI: - str = SUBJ_STATE_WIFI; - break; - case CONTEXT_TRIGGER_CONDITION_CALL: - str = SUBJ_STATE_CALL; - break; - case CONTEXT_TRIGGER_CONDITION_APP_USE_FREQUENCY: - str = SUBJ_APP_FREQUENCY; - break; - case CONTEXT_TRIGGER_CONDITION_COMMUNICATION_FREQUENCY: - str = SUBJ_SOCIAL_FREQUENCY; - break; - case CONTEXT_TRIGGER_CONDITION_MUSIC_PLAYBACK_FREQUENCY: - str = SUBJ_MUSIC_FREQUENCY; - break; - case CONTEXT_TRIGGER_CONDITION_VIDEO_PLAYBACK_FREQUENCY: - str = SUBJ_VIDEO_FREQUENCY; - break; - default: - break; - } - return str; -} - -std::string convert_logical_type_to_string(context_trigger_logical_type_e logical_type) -{ - std::string str; - switch (logical_type) { - case CONTEXT_TRIGGER_LOGICAL_CONJUNCTION: - str = TRIG_RULE_LOGICAL_CONJUNCTION; - break; - case CONTEXT_TRIGGER_LOGICAL_DISJUNCTION: - str = TRIG_RULE_LOGICAL_DISJUNCTION; - break; - default: - break; - } - return str; -} - -std::string get_custom_item_subject(const char* provider, const char* item) -{ - std::string subject_name = std::string(TRIG_CUSTOM_PREFIX TRIG_SUBJECT_SEPERATOR) + provider + std::string(TRIG_SUBJECT_SEPERATOR) + item; - return subject_name; -} - -bool event_is_deprecated(context_trigger_event_e item) -{ - bool ret = false; - switch (item) { - case CONTEXT_TRIGGER_EVENT_TIME: - case CONTEXT_TRIGGER_EVENT_POWER_SAVING_MODE: - case CONTEXT_TRIGGER_EVENT_CALL: - case CONTEXT_TRIGGER_EVENT_EMAIL: - case CONTEXT_TRIGGER_EVENT_MESSAGE: - ret = true; - break; - default: - break; - } - return ret; -} - -bool condition_is_deprecated(context_trigger_condition_e item) -{ - bool ret = false; - switch (item) { - case CONTEXT_TRIGGER_CONDITION_POWER_SAVING_MODE: - case CONTEXT_TRIGGER_CONDITION_CALL: - case CONTEXT_TRIGGER_CONDITION_APP_USE_FREQUENCY: - case CONTEXT_TRIGGER_CONDITION_COMMUNICATION_FREQUENCY: - case CONTEXT_TRIGGER_CONDITION_MUSIC_PLAYBACK_FREQUENCY: - case CONTEXT_TRIGGER_CONDITION_VIDEO_PLAYBACK_FREQUENCY: - ret = true; - break; - default: - break; - } - return ret; -} - -/* -std::string int_to_string(int value) -{ - std::ostringstream ostr; - ostr << value; - return ostr.str(); -} - -std::string double_to_string(int value) -{ - std::ostringstream ostr; - ostr.imbue(std::locale("C")); - ostr << std::setprecision(DOUBLE_PRECISION) << std::fixed << value; - return ostr.str(); -}*/ diff --git a/src/history/context_history.cpp b/src/history/context_history.cpp new file mode 100644 index 0000000..3770d2f --- /dev/null +++ b/src/history/context_history.cpp @@ -0,0 +1,605 @@ +/* + * Copyright (c) 2015 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 +#include +#include + +#define HISTORY_DEPRECATED_DATA "DEPRECATION WARNING: This history data type is deprecated and will be removed from next release" +#define HISTORY_DEPRECATED_FILTER "DEPRECATION WARNING: This history filter is deprecated and will be removed from next release" +#define TYPE_NUMERIC 0 +#define TYPE_STRING 1 +#define FILTER_KEY_LIMIT 10 + +#define ASSERT_ALLOC(X) IF_FAIL_RETURN_TAG(X, E_NO_MEM, _E, "Memory allocation failed") +#define ASSERT_NOT_NULL(X) IF_FAIL_RETURN_TAG(X, E_PARAM, _E, "Parameter null") + +// handles +typedef struct _context_history_handle_s { + /* At this point, this handle has no purpose. + But, it will be used to support other functionalities later, + e.g., async read or session management. */ + int tmp; +} _cx_history_handle; + +typedef struct _context_history_filter_handle_s { + Json::Value jfilter; +} _cx_history_filter_handle; + +typedef struct _context_history_list_handle_s { + ctx_history_cursor_h cursor; + + _context_history_list_handle_s() { + cursor = NULL; + } +} _cx_history_list_handle; + +typedef struct _context_history_record_handle_s { + std::vector keys; + std::shared_ptr tuple; +} _cx_history_record_handle; + +static std::string convert_filter_to_string(context_history_filter_e filter_type); +static std::string convert_data_to_string(context_history_data_e data_type); +static bool check_record_key_data_type(int type, std::string key); +static bool check_filter_data_int(context_history_filter_e filter_type, int val); +static bool check_filter_data_string(context_history_filter_e filter_type, const char* val); +static bool check_invalid_filter(context_history_data_e data_type, context_history_filter_h filter); +static int __getIndexOf(context_history_record_h record, const std::string& key); +static bool history_is_deprecated(context_history_data_e data_type); +static bool history_filter_is_deprecated(context_history_filter_e filter_type); + +// life-cycle +EXPORT_API int context_history_create(context_history_h* handle) +{ + ASSERT_NOT_NULL(handle); + + *handle = new(std::nothrow) _cx_history_handle(); + ASSERT_ALLOC(*handle); + + return CONTEXT_HISTORY_ERROR_NONE; +} + +EXPORT_API int context_history_destroy(context_history_h handle) +{ + ASSERT_NOT_NULL(handle); + delete handle; + return CONTEXT_HISTORY_ERROR_NONE; +} + +// Read filter manipulation +EXPORT_API int context_history_filter_create(context_history_filter_h* filter) +{ + ASSERT_NOT_NULL(filter); + + *filter = new(std::nothrow) _cx_history_filter_handle(); + ASSERT_ALLOC(*filter); + + return CONTEXT_HISTORY_ERROR_NONE; +} + +EXPORT_API int context_history_filter_destroy(context_history_filter_h filter) +{ + ASSERT_NOT_NULL(filter); + delete filter; + + return CONTEXT_HISTORY_ERROR_NONE; +} + +EXPORT_API int context_history_filter_set_int(context_history_filter_h filter, context_history_filter_e filter_type, int val) +{ + ASSERT_NOT_NULL(filter); + + if (history_filter_is_deprecated(filter_type)) { + _W(HISTORY_DEPRECATED_FILTER); + } + + std::string filter_str = convert_filter_to_string(filter_type); + if (filter_str.empty()) { + return CONTEXT_HISTORY_ERROR_INVALID_PARAMETER; + } + + // Check filter and its data type + IF_FAIL_RETURN_TAG(check_filter_data_int(filter_type, val), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Filter type mismatched"); + + filter->jfilter[filter_str] = val; + + return CONTEXT_HISTORY_ERROR_NONE; +} + +EXPORT_API int context_history_filter_set_string(context_history_filter_h filter, context_history_filter_e filter_type, const char* val) +{ + ASSERT_NOT_NULL(filter); + ASSERT_NOT_NULL(val); + + _W("DEPRECATION WARNING: context_history_filter_set_string() is deprecated and will be removed from next release."); + if (history_filter_is_deprecated(filter_type)) { + _W(HISTORY_DEPRECATED_FILTER); + } + + std::string filter_str = convert_filter_to_string(filter_type); + if (filter_str.empty()) { + return CONTEXT_HISTORY_ERROR_INVALID_PARAMETER; + } + + // Check filter and its data type + IF_FAIL_RETURN_TAG(check_filter_data_string(filter_type, val), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Filter type mismatched"); + + filter->jfilter[filter_str] = val; + + return CONTEXT_HISTORY_ERROR_NONE; +} + +EXPORT_API int context_history_is_supported(context_history_data_e data_type, bool* supported) +{ + ASSERT_NOT_NULL(supported); + + if (history_is_deprecated(data_type)) { + _W(HISTORY_DEPRECATED_DATA); + } + + std::string data_type_str = convert_data_to_string(data_type); + if (data_type_str.empty()) { + return CONTEXT_HISTORY_ERROR_INVALID_PARAMETER; + } + + return ctx_history_is_supported(data_type_str.c_str(), supported); +} + +EXPORT_API int context_history_get_list(context_history_h handle, context_history_data_e data_type, context_history_filter_h filter, context_history_list_h* list) +{ + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(list); + *list = NULL; + + if (history_is_deprecated(data_type)) { + _W(HISTORY_DEPRECATED_DATA); + } + /*TODO: Boundary check for filter values has to be done*/ + + std::string data_type_str = convert_data_to_string(data_type); + if (data_type_str.empty()) { + return CONTEXT_HISTORY_ERROR_INVALID_PARAMETER; + } + + // Check data type & filter + if (filter) + IF_FAIL_RETURN_TAG(check_invalid_filter(data_type, filter), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Invalid filter key"); + + *list = new(std::nothrow) _cx_history_list_handle(); + ASSERT_ALLOC(*list); + + std::string filterStr; + if (filter) { + Json::FastWriter fw; + fw.omitEndingLineFeed(); + filterStr = fw.write(filter->jfilter); + } + + int err = _ctx_history_query(data_type_str.c_str(), filterStr.c_str(), &((*list)->cursor)); + IF_FAIL_RETURN_TAG(err == E_NONE, err, _E, "Query failed"); + + return CONTEXT_HISTORY_ERROR_NONE; +} + +// Data object manipulation +EXPORT_API int context_history_list_get_count(context_history_list_h list, int* count) +{ + ASSERT_NOT_NULL(list && count); + + unsigned int value; + + int err = ctx_history_cursor_get_count(list->cursor, &value); + IF_FAIL_RETURN_TAG(err == E_NONE, err, _E, "Get count failed"); + + *count = value; + return E_NONE; +} + +EXPORT_API int context_history_list_get_current(context_history_list_h list, context_history_record_h* record) +{ + ASSERT_NOT_NULL(list); + ASSERT_NOT_NULL(record); + *record = NULL; + + unsigned int position = 0; + int err = ctx_history_cursor_get_position(list->cursor, &position); + IF_FAIL_RETURN_TAG(err == E_NONE, err, _E, "Get position failed"); + + *record = new(std::nothrow) _cx_history_record_handle(); + ASSERT_ALLOC(*record); + + (*record)->keys = list->cursor->keys; + (*record)->tuple = list->cursor->tuples[position]; + + return CONTEXT_HISTORY_ERROR_NONE; +} + +EXPORT_API int context_history_list_move_first(context_history_list_h list) +{ + ASSERT_NOT_NULL(list); + return ctx_history_cursor_first(list->cursor); +} + +EXPORT_API int context_history_list_move_next(context_history_list_h list) +{ + ASSERT_NOT_NULL(list); + return ctx_history_cursor_next(list->cursor); +} + +EXPORT_API int context_history_list_destroy(context_history_list_h list) +{ + ASSERT_NOT_NULL(list); + ctx_history_cursor_destroy(list->cursor); + delete list; + + return CONTEXT_HISTORY_ERROR_NONE; +} + +EXPORT_API int context_history_record_get_int(context_history_record_h record, const char* key, int* val) +{ + ASSERT_NOT_NULL(record && val && key); + + // Check key and data type + IF_FAIL_RETURN_TAG(check_record_key_data_type(TYPE_NUMERIC, key), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Data type mismatched"); + + int index = __getIndexOf(record, key); + IF_FAIL_RETURN_TAG(index >= 0, CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Invalid record key"); + + int64_t value; + IF_FAIL_RETURN_TAG(record->tuple->getAt(index, &value), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Invalid data"); + + *val = value; + + return CONTEXT_HISTORY_ERROR_NONE; +} + +EXPORT_API int context_history_record_get_double(context_history_record_h record, const char* key, double* val) +{ + ASSERT_NOT_NULL(record && val && key); + + // Check key and data type + IF_FAIL_RETURN_TAG(check_record_key_data_type(TYPE_NUMERIC, key), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Data type mismatched"); + + int index = __getIndexOf(record, key); + IF_FAIL_RETURN_TAG(index >= 0, CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Invalid record key"); + + IF_FAIL_RETURN_TAG(record->tuple->getAt(index, val), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Invalid data"); + + return CONTEXT_HISTORY_ERROR_NONE; +} + +EXPORT_API int context_history_record_get_string(context_history_record_h record, const char* key, char** val) +{ + ASSERT_NOT_NULL(record && val && key); + + // Check key and data type + IF_FAIL_RETURN_TAG(check_record_key_data_type(TYPE_STRING, key), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Data type mismatched"); + + int index = __getIndexOf(record, key); + IF_FAIL_RETURN_TAG(index >= 0, CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Invalid record key"); + + std::string str; + IF_FAIL_RETURN_TAG(record->tuple->getAt(index, &str), CONTEXT_HISTORY_ERROR_INVALID_PARAMETER, _E, "Invalid data"); + + *val = g_strdup(str.c_str()); + ASSERT_ALLOC(*val); + + return CONTEXT_HISTORY_ERROR_NONE; +} + +EXPORT_API int context_history_record_destroy(context_history_record_h record) +{ + ASSERT_NOT_NULL(record); + delete record; + + return CONTEXT_HISTORY_ERROR_NONE; +} + +std::string convert_filter_to_string(context_history_filter_e filter_type) +{ + std::string str; + switch (filter_type) { + case CONTEXT_HISTORY_FILTER_TIME_SPAN: + str = KEY_TIME_SPAN; + break; + case CONTEXT_HISTORY_FILTER_RESULT_SIZE: + str = KEY_RESULT_SIZE; + break; + case CONTEXT_HISTORY_FILTER_APP_ID: + str = KEY_APP_ID; + break; + case CONTEXT_HISTORY_FILTER_DAY_OF_WEEK: + str = KEY_DAY_OF_WEEK; + break; + case CONTEXT_HISTORY_FILTER_START_TIME: + str = KEY_START_TIME; + break; + case CONTEXT_HISTORY_FILTER_END_TIME: + str = KEY_END_TIME; + break; + case CONTEXT_HISTORY_FILTER_WIFI_BSSID: + str = KEY_BSSID; + break; + case CONTEXT_HISTORY_FILTER_AUDIO_JACK: + str = KEY_AUDIO_JACK; + break; + case CONTEXT_HISTORY_FILTER_COMMUNICATION_TYPE: + str = KEY_COMMUNICATION_TYPE; + break; + default: + break; + } + return str; +} + +std::string convert_data_to_string(context_history_data_e data_type) +{ + std::string str; + switch (data_type) { + case CONTEXT_HISTORY_RECENTLY_USED_APP: + str = SUBJ_APP_RECENTLY_USED; + break; + case CONTEXT_HISTORY_FREQUENTLY_USED_APP: + str = SUBJ_APP_FREQUENTLY_USED; + break; + case CONTEXT_HISTORY_RARELY_USED_APP: + str = SUBJ_APP_RARELY_USED; + break; + case CONTEXT_HISTORY_PEAK_TIME_FOR_APP: + str = SUBJ_APP_PEAK_TIME; + break; + case CONTEXT_HISTORY_PEAK_TIME_FOR_MUSIC: + str = SUBJ_MUSIC_PEAK_TIME; + break; + case CONTEXT_HISTORY_PEAK_TIME_FOR_VIDEO: + str = SUBJ_VIDEO_PEAK_TIME; + break; + case CONTEXT_HISTORY_COMMON_SETTING_FOR_APP: + str = SUBJ_APP_COMMON_SETTING; + break; + case CONTEXT_HISTORY_COMMON_SETTING_FOR_MUSIC: + str = SUBJ_MUSIC_COMMON_SETTING; + break; + case CONTEXT_HISTORY_COMMON_SETTING_FOR_VIDEO: + str = SUBJ_VIDEO_COMMON_SETTING; + break; + case CONTEXT_HISTORY_FREQUENTLY_COMMUNICATED_ADDRESS: + str = SUBJ_SOCIAL_FREQ_ADDRESS; + break; + case CONTEXT_HISTORY_BATTERY_USAGE: + str = SUBJ_BATTERY_USAGE; + break; + case CONTEXT_HISTORY_RECENT_BATTERY_USAGE: + str = SUBJ_BATTERY_RECENT_USAGE; + break; + default: + break; + } + return str; +} + +bool check_record_key_data_type(int type, std::string key) +{ + if ((key.compare(CONTEXT_HISTORY_APP_ID) == 0) || + key.compare(CONTEXT_HISTORY_ADDRESS) == 0) { + return (type == TYPE_STRING); + } + + if ((key.compare(CONTEXT_HISTORY_TOTAL_COUNT) == 0) || + key.compare(CONTEXT_HISTORY_TOTAL_AMOUNT) == 0 || + key.compare(CONTEXT_HISTORY_TOTAL_DURATION) == 0 || + key.compare(CONTEXT_HISTORY_LAST_TIME) == 0 || + key.compare(CONTEXT_HISTORY_HOUR_OF_DAY) == 0 || + key.compare(CONTEXT_HISTORY_AUDIO_JACK) == 0 || + key.compare(CONTEXT_HISTORY_SYSTEM_VOLUME) == 0 || + key.compare(CONTEXT_HISTORY_MEDIA_VOLUME) == 0 || + key.compare(KEY_USED_TIME) == 0) { // Internal use for RecentBatteryUsage + return (type == TYPE_NUMERIC); + } + + return false; +} + +bool check_filter_data_int(context_history_filter_e filter_type, int val) +{ + switch (filter_type) { + case CONTEXT_HISTORY_FILTER_TIME_SPAN: + case CONTEXT_HISTORY_FILTER_RESULT_SIZE: + case CONTEXT_HISTORY_FILTER_START_TIME: + case CONTEXT_HISTORY_FILTER_END_TIME: + if (val > 0) + return true; + break; + case CONTEXT_HISTORY_FILTER_DAY_OF_WEEK: + if (val == CONTEXT_HISTORY_FILTER_DAY_OF_WEEK_WEEKDAYS || + val == CONTEXT_HISTORY_FILTER_DAY_OF_WEEK_WEEKENDS || + val == CONTEXT_HISTORY_FILTER_DAY_OF_WEEK_ALL) + return true; + break; + case CONTEXT_HISTORY_FILTER_AUDIO_JACK: + if (val == CONTEXT_HISTORY_FILTER_AUDIO_JACK_NOT_CONNECTED || + val == CONTEXT_HISTORY_FILTER_AUDIO_JACK_CONNECTED) + return true; + break; + case CONTEXT_HISTORY_FILTER_COMMUNICATION_TYPE: + if (val == CONTEXT_HISTORY_FILTER_COMMUNICATION_TYPE_CALL || + val == CONTEXT_HISTORY_FILTER_COMMUNICATION_TYPE_MESSAGE || + val == CONTEXT_HISTORY_FILTER_COMMUNICATION_TYPE_ALL) + return true; + break; + default: + return false; + } + return false; +} + +bool check_filter_data_string(context_history_filter_e filter_type, const char* val) +{ + IF_FAIL_RETURN(val, false); + + switch (filter_type) { + case CONTEXT_HISTORY_FILTER_APP_ID: + case CONTEXT_HISTORY_FILTER_WIFI_BSSID: + return (g_strstr_len(val, -1, ";") == NULL); + + default: + return false; + } +} + +bool check_invalid_filter(context_history_data_e data_type, context_history_filter_h filter) +{ + /* This should be aligned with context_history_filter_e */ + static const char *filter_key[FILTER_KEY_LIMIT] = { + NULL, + KEY_TIME_SPAN, + KEY_RESULT_SIZE, + KEY_APP_ID, + KEY_DAY_OF_WEEK, + KEY_START_TIME, + KEY_END_TIME, + KEY_BSSID, + KEY_AUDIO_JACK, + KEY_COMMUNICATION_TYPE, + }; + + bool allowed[FILTER_KEY_LIMIT] = {false}; + + allowed[CONTEXT_HISTORY_FILTER_TIME_SPAN] = true; + allowed[CONTEXT_HISTORY_FILTER_START_TIME] = true; + allowed[CONTEXT_HISTORY_FILTER_END_TIME] = true; + allowed[CONTEXT_HISTORY_FILTER_RESULT_SIZE] = true; + + switch (data_type) { + case CONTEXT_HISTORY_RECENTLY_USED_APP: + case CONTEXT_HISTORY_FREQUENTLY_USED_APP: + allowed[CONTEXT_HISTORY_FILTER_WIFI_BSSID] = true; + allowed[CONTEXT_HISTORY_FILTER_AUDIO_JACK] = true; + break; + + case CONTEXT_HISTORY_RARELY_USED_APP: + break; + + case CONTEXT_HISTORY_PEAK_TIME_FOR_APP: + allowed[CONTEXT_HISTORY_FILTER_APP_ID] = true; + allowed[CONTEXT_HISTORY_FILTER_DAY_OF_WEEK] = true; + break; + + case CONTEXT_HISTORY_PEAK_TIME_FOR_MUSIC: + case CONTEXT_HISTORY_PEAK_TIME_FOR_VIDEO: + allowed[CONTEXT_HISTORY_FILTER_DAY_OF_WEEK] = true; + break; + + case CONTEXT_HISTORY_COMMON_SETTING_FOR_APP: + allowed[CONTEXT_HISTORY_FILTER_RESULT_SIZE] = false; + allowed[CONTEXT_HISTORY_FILTER_APP_ID] = true; + break; + + case CONTEXT_HISTORY_COMMON_SETTING_FOR_MUSIC: + case CONTEXT_HISTORY_COMMON_SETTING_FOR_VIDEO: + allowed[CONTEXT_HISTORY_FILTER_RESULT_SIZE] = false; + break; + + case CONTEXT_HISTORY_FREQUENTLY_COMMUNICATED_ADDRESS: + allowed[CONTEXT_HISTORY_FILTER_COMMUNICATION_TYPE] = true; + break; + + case CONTEXT_HISTORY_BATTERY_USAGE: + break; + + case CONTEXT_HISTORY_RECENT_BATTERY_USAGE: + allowed[CONTEXT_HISTORY_FILTER_TIME_SPAN] = false; + allowed[CONTEXT_HISTORY_FILTER_START_TIME] = false; + allowed[CONTEXT_HISTORY_FILTER_END_TIME] = false; + break; + + default: + return false; + } + + bool found = true; + std::vector keys = filter->jfilter.getMemberNames(); + + for (auto& key : keys) { + found = false; + for (int i = 1; i < FILTER_KEY_LIMIT; ++i) { + if (allowed[i] && key == filter_key[i]) { + found = true; + break; + } + } + if (found == true) + continue; + + return false; + } + + return true; +} + +int __getIndexOf(context_history_record_h record, const std::string& key) +{ + unsigned int i = 0; + + for (i = 0; i < record->keys.size(); ++i) { + if (record->keys[i] == key) { + return i; + } + } + return -1; +} + +bool history_is_deprecated(context_history_data_e data_type) +{ + bool ret = false; + switch (data_type) { + case CONTEXT_HISTORY_RARELY_USED_APP: + case CONTEXT_HISTORY_PEAK_TIME_FOR_APP: + case CONTEXT_HISTORY_PEAK_TIME_FOR_MUSIC: + case CONTEXT_HISTORY_PEAK_TIME_FOR_VIDEO: + case CONTEXT_HISTORY_COMMON_SETTING_FOR_APP: + case CONTEXT_HISTORY_COMMON_SETTING_FOR_MUSIC: + case CONTEXT_HISTORY_COMMON_SETTING_FOR_VIDEO: + case CONTEXT_HISTORY_FREQUENTLY_COMMUNICATED_ADDRESS: + ret = true; + break; + default: + break; + } + return ret; +} + +bool history_filter_is_deprecated(context_history_filter_e filter_type) +{ + bool ret = false; + switch (filter_type) { + case CONTEXT_HISTORY_FILTER_APP_ID: + case CONTEXT_HISTORY_FILTER_DAY_OF_WEEK: + case CONTEXT_HISTORY_FILTER_WIFI_BSSID: + case CONTEXT_HISTORY_FILTER_COMMUNICATION_TYPE: + ret = true; + break; + default: + break; + } + return ret; +} diff --git a/src/rule_util.cpp b/src/rule_util.cpp deleted file mode 100644 index f57de01..0000000 --- a/src/rule_util.cpp +++ /dev/null @@ -1,254 +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 -#include -#include -#include -#include -#include -#include -#include -#include "rule_validator.h" -#include "rule_util.h" -#include "ComparisonConverter.h" -#include "IntComparisonConverter.h" -#include "StringComparisonConverter.h" - -using namespace ctx; - -static bool __handleTimerEvent(CtxJson1& event); -static int __arrangeDayOfWeek(CtxJson1& dayInfo); - -int ctx::rule_util::setEvent(CtxJson1& entry, CtxJson1* rule) -{ - CtxJson1 tempEvent; - std::string subject; - entry.get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &subject); - - CtxJson1 option; - entry.get(NULL, OLD_TRIG_RULE_KEY_EVENT_OPTION, &option); - tempEvent.set(subject.c_str(), TRIG_RULE_KEY_OPTION, option); - - CtxJson1 elem; - for (int i = 0; entry.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { - CtxJson1 newElem; - - std::string key; - elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &key); - - std::string type = ctx::rule_validator::get_data_type_from_template(TRIG_TMPL_KEY_ATTRIBUTE, subject, key); - - ComparisonConverter* converter = NULL; - if (type == TRIG_TMPL_TYPE_INTEGER) { - converter = new(std::nothrow) IntComparisonConverter(elem); - } else if (type == TRIG_TMPL_TYPE_STRING || type == TRIG_TMPL_TYPE_ENUM) { - converter = new(std::nothrow) StringComparisonConverter(elem); - } - IF_FAIL_RETURN_TAG(converter, ERR_OUT_OF_MEMORY, _E, "Failed to create comparison converter"); - converter->getResult(&newElem); - - CtxJson1 detail; - newElem.get(NULL, key.c_str(), &detail); - - std::string path = subject + "." + TRIG_RULE_KEY_COMPARISON; - tempEvent.set(path.c_str(), key.c_str(), detail); - delete converter; - } - - // Handle Timer Event - if (subject.compare(SUBJ_STATE_ALARM) == 0) { - IF_FAIL_RETURN(__handleTimerEvent(tempEvent), ERR_INVALID_RULE); - } - - rule->set(NULL, TRIG_RULE_KEY_EVENT, tempEvent); - - // Save event entry's logical to extra info (default and) - std::string eventOp = TRIG_RULE_LOGICAL_CONJUNCTION; - if (entry.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_ARR) > 1) { - entry.get(NULL, OLD_TRIG_RULE_KEY_EVENT_OPERATOR, &eventOp); - } - rule->set(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_EVENT_LOGICAL_OP, eventOp); - - return ERR_NONE; -} - -int ctx::rule_util::addCondition(CtxJson1& entry, CtxJson1* rule) -{ - CtxJson1 tempCond; - std::string subject; - entry.get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &subject); - - CtxJson1 option; - entry.get(NULL, OLD_TRIG_RULE_KEY_CONDITION_OPTION, &option); - tempCond.set(subject.c_str(), TRIG_RULE_KEY_OPTION, option); - - CtxJson1 elem; - for (int i = 0; entry.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { - CtxJson1 newElem; - - std::string key; - elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &key); - - std::string type = ctx::rule_validator::get_data_type_from_template(TRIG_TMPL_KEY_ATTRIBUTE, subject, key); - - ComparisonConverter* converter = NULL; - if (type == TRIG_TMPL_TYPE_INTEGER) { - converter = new(std::nothrow) IntComparisonConverter(elem); - } else if (type == TRIG_TMPL_TYPE_STRING || type == TRIG_TMPL_TYPE_ENUM) { - converter = new(std::nothrow) StringComparisonConverter(elem); - } - IF_FAIL_RETURN_TAG(converter, ERR_OUT_OF_MEMORY, _E, "Failed to create comparison converter"); - converter->getResult(&newElem); - - tempCond.set(subject.c_str(), TRIG_RULE_KEY_COMPARISON, newElem); - delete converter; - } - - rule->append(NULL, TRIG_RULE_KEY_CONDITION, tempCond); - - // Save event entry's logical to extra info (default and) - std::string condOp = TRIG_RULE_LOGICAL_CONJUNCTION; - if (entry.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_ARR) > 1) { - entry.get(NULL, OLD_TRIG_RULE_KEY_CONDITION_OPERATOR, &condOp); - } - rule->append(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_CONDITION_LOGICAL_OP, condOp); - - return ERR_NONE; -} - -bool __handleTimerEvent(CtxJson1& event) -{ - CtxJson1 alarmComp; - bool ret = event.get(SUBJ_STATE_ALARM, TRIG_RULE_KEY_COMPARISON, &alarmComp); - IF_FAIL_RETURN_TAG(ret, false, _E, "Invalid EVENT_TIME event"); - - // Day processing - CtxJson1 dayInfo; - bool daySpecified = alarmComp.get(NULL, KEY_DAY_OF_WEEK, &dayInfo); - - if (daySpecified) { - CtxJson1 newDayInfo; - newDayInfo.set(NULL, TRIG_RULE_KEY_OPERATOR, TRIG_RULE_OP_ONE_OF); - - int dow = __arrangeDayOfWeek(dayInfo); - IF_FAIL_RETURN_TAG(dow > 0, false, _E, "Invalid DayOfWeek info for EVENT_TIME"); - - for (int i = 0 ; i < DAYS_PER_WEEK; i++) { - int d = 0x01 << i; - if (dow & d) { - std::string day = TimerManager::dowToStr(d); - newDayInfo.append(NULL, TRIG_RULE_KEY_VALUE, day); - - // Copy details as option - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, day); - } - } - event.set(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_COMPARISON, KEY_DAY_OF_WEEK, newDayInfo); - } else { - // If DayOfWeek is not specified, regard it as Mon ~ Sun - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_MON); - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_TUE); - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_WED); - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_THU); - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_FRI); - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_SAT); - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_SUN); - } - - // Time processing - CtxJson1 timeInfo; - alarmComp.get(NULL, KEY_TIME_OF_DAY, &timeInfo); - - int time; - std::string timeOp; - timeInfo.get(NULL, TRIG_RULE_KEY_OPERATOR, &timeOp); - - if (timeOp == TRIG_RULE_OP_EQUAL_TO) { - timeInfo.get(NULL, TRIG_RULE_KEY_VALUE, &time); - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_TIME_OF_DAY, time); - } else if (timeOp == TRIG_RULE_OP_ONE_OF) { - for (int i = 0; timeInfo.getAt(NULL, TRIG_RULE_KEY_VALUE, i, &time); i++) { - event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_TIME_OF_DAY, time); - } - } - - return true; -} - -int __arrangeDayOfWeek(CtxJson1& dayInfo) -{ - std::string dayOp; - if (!dayInfo.get(NULL, TRIG_RULE_KEY_OPERATOR, &dayOp)) { - return TimerManager::dowToInt(DOW_EVERYDAY); - } - - int result = 0; - if (dayOp == TRIG_RULE_OP_NOT_EQUAL_TO || dayOp == TRIG_RULE_OP_NOT_IN) { - result = TimerManager::dowToInt(DOW_EVERYDAY); - } - - int dow; - std::string day; - if (dayOp == TRIG_RULE_OP_EQUAL_TO) { - dayInfo.get(NULL, TRIG_RULE_KEY_VALUE, &day); - dow = TimerManager::dowToInt(day); - result |= dow; - } else if (dayOp == TRIG_RULE_OP_NOT_EQUAL_TO) { - dayInfo.get(NULL, TRIG_RULE_KEY_VALUE, &day); - dow = TimerManager::dowToInt(day); - dow = TimerManager::dowToInt(DOW_EVERYDAY) & ~dow; - result &= dow; - } else if (dayOp == TRIG_RULE_OP_ONE_OF) { - for (int i = 0; dayInfo.getAt(NULL, TRIG_RULE_KEY_VALUE, i, &day); i++) { - dow = TimerManager::dowToInt(day); - result |= dow; - } - } else if (dayOp == TRIG_RULE_OP_NONE_OF) { - for (int i = 0; dayInfo.getAt(NULL, TRIG_RULE_KEY_VALUE, i, &day); i++) { - dow = TimerManager::dowToInt(day); - dow = TimerManager::dowToInt(DOW_EVERYDAY) & ~dow; - result &= dow; - } - } - - _D("Requested day of week (%#x)", result); - return result; -} - -bool ctx::rule_util::isEventSet(CtxJson1& rule) -{ - ctx::CtxJson1 event; - if (rule.get(NULL, TRIG_RULE_KEY_EVENT, &event)) { - if (event != EMPTY_JSON_OBJECT) { - return true; - } - } - - return false; -} - -bool ctx::rule_util::isActionSet(CtxJson1& rule) -{ - ctx::CtxJson1 action; - if (rule.get(NULL, TRIG_RULE_KEY_ACTION, &action)) { - if (action != EMPTY_JSON_OBJECT) { - return true; - } - } - - return false; -} diff --git a/src/rule_util.h b/src/rule_util.h deleted file mode 100644 index d4443bb..0000000 --- a/src/rule_util.h +++ /dev/null @@ -1,34 +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_RULE_UTIL_H__ -#define __CONTEXT_RULE_UTIL_H__ - -#include - -namespace ctx { - - namespace rule_util { - - int setEvent(CtxJson1& entry, CtxJson1* rule); - int addCondition(CtxJson1& entry, CtxJson1* rule); - bool isEventSet(CtxJson1& rule); - bool isActionSet(CtxJson1& rule); - - } -} /* namespace ctx */ - -#endif /* __CONTEXT_RULE_UTIL_H__ */ diff --git a/src/rule_validator.cpp b/src/rule_validator.cpp deleted file mode 100644 index 6f37448..0000000 --- a/src/rule_validator.cpp +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Copyright (c) 2015 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 -#include -#include "DBusClient.h" -#include "TriggerOldRuleTypes.h" -#include "rule_validator.h" - -using namespace ctx; - -#define RULE_VALIDATOR_COND_NAME "name" -#define RULE_VALIDATOR_KEY "key" -#define RULE_VALIDATOR_TYPE "type" -#define RULE_VALIDATOR_REF "ref" - -typedef std::map template_map_t; -template_map_t template_map; // - -static int string_to_int(std::string str); -static bool check_value_int(CtxJson1& tmpl, std::string key, int value); -static bool check_value_string(CtxJson1& tmpl, std::string key, std::string value); -static bool check_value_enum(CtxJson1& tmpl, std::string key, std::string value); -static CtxJson1 get_template(std::string name); -static bool check_template_int(CtxJson1& elem); -static bool check_template_string(CtxJson1& elem); -static bool check_template_enum(CtxJson1& elem); -static std::string get_data_type(CtxJson1& elem, std::string& key); -static bool is_equal_type(std::string& type1, std::string& type2); - -int string_to_int(std::string str) -{ - int i; - std::istringstream convert(str); - - if (!(convert >> i)) - i = 0; - - return i; -} - -CtxJson1 get_template(std::string name) -{ - rule_validator::request_template(name); - return template_map[name]; -} - -int rule_validator::request_template(std::string name, bool mandatory) -{ - if (!mandatory) { - template_map_t::iterator it = template_map.find(name); - IF_FAIL_RETURN(it == template_map.end(), ERR_NONE); - } - - // Request template - CtxJson1 request; - request.set(NULL, TRIG_TMPL_KEY_SUBJECT, name); - - int req_id; - CtxJson1 tmpl; - DBusClient dbusClient; - int error = dbusClient.readSync(SUBJ_TRIGGER_GET_TEMPLATE, request, &req_id, &tmpl); - if (error == ERR_NOT_SUPPORTED) { - template_map.erase(name); - _E("Failed to get request: not supported"); - return ERR_NOT_SUPPORTED; - } - IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to get request"); - - template_map[name] = tmpl; - - return ERR_NONE; -} - -void rule_validator::remove_template(std::string name) -{ - template_map.erase(name); -} - -// called by context_trigger_rule_add_entry() -bool rule_validator::check_option(CtxJson1& item) -{ - std::string name; - item.get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); - - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); - - // No option needed - CtxJson1 opt_tmpl; - tmpl.get(NULL, TRIG_TMPL_KEY_OPTION, &opt_tmpl); - - std::list opt_keys; - IF_FAIL_RETURN(opt_tmpl.getKeys(&opt_keys), false); - if (opt_keys.size() <= 0) { - return true; - } - - // Err: Check if mandatory option is missed - std::string val_str; - int val; - if (name == SUBJ_PLACE_GEOFENCE) { - if (!(item.get(OLD_TRIG_RULE_KEY_EVENT_OPTION, CONTEXT_TRIGGER_PLACE_ID, &val))) - return false; - } else if (name == SUBJ_APP_FREQUENCY) { - if (!(item.get(OLD_TRIG_RULE_KEY_CONDITION_OPTION, CONTEXT_TRIGGER_APP_ID, &val_str))) - return false; - } else if (name == SUBJ_SOCIAL_FREQUENCY) { - if (!(item.get(OLD_TRIG_RULE_KEY_CONDITION_OPTION, CONTEXT_TRIGGER_ADDRESS, &val_str))) - return false; - } - - return true; -} - -// called by context_trigger_rule_entry_add_option_int() -bool rule_validator::check_option_int(std::string name, std::string key, int value) -{ - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); - - CtxJson1 opt_tmpl; - tmpl.get(NULL, TRIG_TMPL_KEY_OPTION, &opt_tmpl); - - // Err: Item with no option - std::list opt_keys; - IF_FAIL_RETURN(opt_tmpl.getKeys(&opt_keys), false); - IF_FAIL_RETURN(opt_keys.size() > 0, false); - - // Err: Invalid option key or Invalid value type - std::string t_type = get_data_type(opt_tmpl, key); - IF_FAIL_RETURN(t_type == TRIG_TMPL_TYPE_INTEGER, false); - - // Err: Inappropriate value - // a. normal case - bool ret = check_value_int(opt_tmpl, key, value); - IF_FAIL_RETURN(ret, false); - - return true; -} - -// called by context_trigger_rule_entry_add_option_string() -bool rule_validator::check_option_string(std::string name, std::string key, std::string value) -{ - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); - - CtxJson1 opt_tmpl; - tmpl.get(NULL, TRIG_TMPL_KEY_OPTION, &opt_tmpl); - - // Err: ';' for SQL injection - IF_FAIL_RETURN(value.find(';') == std::string::npos, false); - - // Err: Item with no option - std::list opt_keys; - IF_FAIL_RETURN(opt_tmpl.getKeys(&opt_keys), false); - IF_FAIL_RETURN(opt_keys.size() > 0, false); - - // Err: Invalid option key or Invalid value type - std::string t_type = get_data_type(opt_tmpl, key); - IF_FAIL_RETURN(t_type == TRIG_TMPL_TYPE_STRING || t_type == TRIG_TMPL_TYPE_ENUM, false); - - // Err: Inappropriate value - // a. spacial case - if (t_type == TRIG_TMPL_TYPE_STRING && (name == SUBJ_APP_FREQUENCY || name == SUBJ_SOCIAL_FREQUENCY - || name == SUBJ_MUSIC_FREQUENCY || name == SUBJ_VIDEO_FREQUENCY) - && key == CONTEXT_TRIGGER_TIME_OF_DAY) { - std::size_t found = value.find("-"); - if (found == std::string::npos) { - return false; - } - - int t1 = string_to_int(value.substr(0, found-1)); - int t2 = string_to_int(value.substr(found+1, value.length()-1)); - - if (!(t1 >= 0 && t1 < 24) || !(t2 >= 0 && t2 < 24)) { - return false; - } - - if (t1 >= t2) { - return false; - } - - return true; - } - - // b. normal case - bool ret = false; - if (t_type == TRIG_TMPL_TYPE_STRING) { - ret = check_value_string(opt_tmpl, key, value); - } else if (t_type == TRIG_TMPL_TYPE_ENUM) { - ret = check_value_enum(opt_tmpl, key, value); - } - - return ret; -} - -// called by context_trigger_rule_entry_add_comparison_int() -bool rule_validator::check_comparison_int(std::string name, std::string key, std::string op, int value) -{ - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); - - CtxJson1 attr_tmpl; - tmpl.get(NULL, TRIG_TMPL_KEY_ATTRIBUTE, &attr_tmpl); - - // Err: Invalid attribute key or Invalid value type - std::string t_type = get_data_type(attr_tmpl, key); - IF_FAIL_RETURN(t_type == TRIG_TMPL_TYPE_INTEGER, false); - - // Err: Invalid operator for the value - // a. normal case - bool ret = is_valid_operator(TRIG_TMPL_TYPE_INTEGER, op); - IF_FAIL_RETURN(ret, false); - // b. special case - if (name == SUBJ_STATE_ALARM && key == CONTEXT_TRIGGER_TIME_OF_DAY) { - IF_FAIL_RETURN(op == CONTEXT_TRIGGER_EQUAL_TO, false); - } - - // Err: Inappropriate value - // a. normal case - ret = check_value_int(attr_tmpl, key, value); - IF_FAIL_RETURN(ret, false); - - return true; -} - -// called by context_trigger_rule_entry_add_comparison_string() -bool rule_validator::check_comparison_string(std::string name, std::string key, std::string op, std::string value) -{ - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != CtxJson1(EMPTY_JSON_OBJECT), false); - - CtxJson1 attr_tmpl; - tmpl.get(NULL, TRIG_TMPL_KEY_ATTRIBUTE, &attr_tmpl); - - // Err: ';' for SQL injection - IF_FAIL_RETURN(value.find(';') == std::string::npos, false); - - // Err: Invalid option key or Invalid value type - std::string t_type = get_data_type(attr_tmpl, key); - IF_FAIL_RETURN(t_type == TRIG_TMPL_TYPE_STRING || t_type == TRIG_TMPL_TYPE_ENUM, false); - - // Err: Invalid operator for the value - bool ret = is_valid_operator(t_type, op); - IF_FAIL_RETURN(ret, false); - - // Err: Inappropriate value - // a. normal case - if (t_type == TRIG_TMPL_TYPE_STRING) { - ret = check_value_string(attr_tmpl, key, value); - IF_FAIL_RETURN(ret, false); - } else if (t_type == TRIG_TMPL_TYPE_ENUM) { - ret = check_value_enum(attr_tmpl, key, value); - IF_FAIL_RETURN(ret, false); - } - - return true; -} - -bool rule_validator::check_valid_key(std::string type, std::string name, std::string key) -{ - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); - - // Err: Invalid key - CtxJson1 tmp; - bool ret = tmpl.get(type.c_str(), key.c_str(), &tmp); - IF_FAIL_RETURN(ret, false); - - return true; -} - -bool check_value_int(CtxJson1& tmpl, std::string key, int value) -{ - int min, max; - - if (tmpl.get(key.c_str(), TRIG_TMPL_KEY_MIN, &min)) { - IF_FAIL_RETURN(value >= min, false); - } - - if (tmpl.get(key.c_str(), TRIG_TMPL_KEY_MAX, &max)) { - IF_FAIL_RETURN(value <= max, false); - } - - return true; -} - -bool check_value_string(CtxJson1& tmpl, std::string key, std::string value) -{ - return true; -} - -bool check_value_enum(CtxJson1& tmpl, std::string key, std::string value) -{ - std::string t_val; - for (int i = 0; tmpl.getAt(key.c_str(), TRIG_TMPL_TYPE_ENUM, i, &t_val); i++) { - if (t_val == value) - return true; - } - - return false; -} - -// called by context_trigger_rule_entry_add_comparison() -// called by context_trigger_rule_entry_add_option() -bool rule_validator::set_ref_info(std::string type, CtxJson1* jref, std::string name, std::string key, std::string ref_data) -{ - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); - - CtxJson1 detailed_tmpl; - tmpl.get(NULL, type.c_str(), &detailed_tmpl); - - std::string dt = get_data_type(detailed_tmpl, key); - IF_FAIL_RETURN(dt == TRIG_TMPL_TYPE_INTEGER || dt == TRIG_TMPL_TYPE_STRING || dt == TRIG_TMPL_TYPE_ENUM, false); - - CtxJson1 temp; - temp.set(NULL, RULE_VALIDATOR_COND_NAME, name); - temp.set(NULL, RULE_VALIDATOR_KEY, key); - temp.set(NULL, RULE_VALIDATOR_TYPE, dt); - temp.set(NULL, RULE_VALIDATOR_REF, ref_data); - - if (type == TRIG_TMPL_KEY_OPTION) { - jref->append(NULL, TRIG_TMPL_KEY_OPTION, temp); - } else if (type == TRIG_TMPL_KEY_ATTRIBUTE) { - jref->append(NULL, TRIG_TMPL_KEY_ATTRIBUTE, temp); - } else { - return false; - } - - return true;; -} - -std::string get_data_type(CtxJson1& elem, std::string& key) -{ - std::string data_type; - bool ret = elem.get(key.c_str(), TRIG_TMPL_KEY_TYPE, &data_type); - if (!ret) { - int size = elem.getSize(key.c_str(), TRIG_TMPL_TYPE_ENUM); - IF_FAIL_RETURN(size > 0, ""); - data_type = TRIG_TMPL_TYPE_ENUM; - } - IF_FAIL_RETURN(data_type == TRIG_TMPL_TYPE_INTEGER || data_type == TRIG_TMPL_TYPE_STRING || data_type == TRIG_TMPL_TYPE_ENUM, ""); - - return data_type; -} - -// called by context_trigger_rule_entry_add_comparison() -std::string rule_validator::get_data_type_from_template(std::string type, std::string name, std::string key) -{ - CtxJson1 tmpl = get_template(name); - IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, ""); - - CtxJson1 detailed_tmpl; - tmpl.get(NULL, type.c_str(), &detailed_tmpl); - - return get_data_type(detailed_tmpl, key); -} - -// called by context_trigger_rule_add_entry() -bool rule_validator::check_referential_data(std::string name, CtxJson1& ref_info) -{ - std::map type_map; - - CtxJson1 ref_data; - for (int i = 0; ref_info.getAt(NULL, TRIG_TMPL_KEY_OPTION, i, &ref_data); i++) { - std::string ref_key; - ref_data.get(NULL, RULE_VALIDATOR_REF, &ref_key); - std::string cond_type; - ref_data.get(NULL, RULE_VALIDATOR_TYPE, &cond_type); - - if (type_map.count(ref_key) == 0) { - type_map[ref_key] = get_data_type_from_template(TRIG_TMPL_KEY_ATTRIBUTE, name, ref_key); // "", if invalid key - } - - // Err: Invalid key or Value type not matched - IF_FAIL_RETURN(is_equal_type(cond_type, type_map[ref_key]), false); - } - - for (int i = 0; ref_info.getAt(NULL, TRIG_TMPL_KEY_ATTRIBUTE, i, &ref_data); i++) { - std::string ref_key; - ref_data.get(NULL, RULE_VALIDATOR_REF, &ref_key); - std::string cond_type; - ref_data.get(NULL, RULE_VALIDATOR_TYPE, &cond_type); - - if (type_map.count(ref_key) == 0) { - type_map[ref_key] = get_data_type_from_template(TRIG_TMPL_KEY_ATTRIBUTE, name, ref_key); // "", if invalid key - } - - // Err: Invalid key or Value type not matched - IF_FAIL_RETURN(is_equal_type(cond_type, type_map[ref_key]), false); - } - - return true; -} - -bool is_equal_type(std::string& type1, std::string& type2) -{ - // This function regards TRIG_TMPL_TYPE_ENUM as TRIG_TMPL_TYPE_STRING for referential data - if (type1 == type2) { - return true; - } - - if ((type1 == TRIG_TMPL_TYPE_STRING || type1 == TRIG_TMPL_TYPE_ENUM) && (type2 == TRIG_TMPL_TYPE_STRING || type2 == TRIG_TMPL_TYPE_ENUM)) { - return true; - } - - return false; -} - -bool rule_validator::is_valid_operator(std::string type, std::string op) -{ - if (op == CONTEXT_TRIGGER_EQUAL_TO || op == CONTEXT_TRIGGER_NOT_EQUAL_TO) { - return true; - } - - if (type == TRIG_TMPL_TYPE_INTEGER || type == TRIG_TMPL_TYPE_DOUBLE) { - if (op == CONTEXT_TRIGGER_GREATER_THAN || op == CONTEXT_TRIGGER_GREATER_THAN_OR_EQUAL_TO || - op == CONTEXT_TRIGGER_LESS_THAN || op == CONTEXT_TRIGGER_LESS_THAN_OR_EQUAL_TO) { - return true; - } - } - - return false; -} - -// For custom item template -bool rule_validator::is_valid_template(CtxJson1& attr_template) -{ - IF_FAIL_RETURN_TAG(attr_template != EMPTY_JSON_OBJECT, false, _E, "Custom template: empty CtxJson1"); - - bool ret; - std::list keys; - attr_template.getKeys(&keys); - - for (std::list::iterator it = keys.begin(); it != keys.end(); it++) { - std::string key = *it; - - std::string type = get_data_type(attr_template, key); - IF_FAIL_RETURN_TAG(type == TRIG_TMPL_TYPE_INTEGER || type == TRIG_TMPL_TYPE_STRING || type == TRIG_TMPL_TYPE_ENUM, - false, _E, "Custom template: invalid data type"); - - CtxJson1 elem; - attr_template.get(NULL, key.c_str(), &elem); - if (type == TRIG_TMPL_TYPE_INTEGER) { - ret = check_template_int(elem); - IF_FAIL_RETURN(ret, false); - } else if (type == TRIG_TMPL_TYPE_STRING) { - ret = check_template_string(elem); - IF_FAIL_RETURN(ret, false); - } else if (type == TRIG_TMPL_TYPE_ENUM) { - ret = check_template_enum(elem); - IF_FAIL_RETURN(ret, false); - } - } - - return true; -} - -bool check_template_int(CtxJson1& elem) -{ - std::list elem_keys; - elem.getKeys(&elem_keys); - - bool min = false; - bool max = false; - int min_val = 0; - int max_val = 0; - - for (std::list::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) { - std::string elem_key = *it2; - if (elem_key == TRIG_TMPL_KEY_MIN) { - min = elem.get(NULL, elem_key.c_str(), &min_val); - IF_FAIL_RETURN_TAG(min, false, _E, "Custom template: failed to get integer type value"); - } else if (elem_key == TRIG_TMPL_KEY_MAX) { - max = elem.get(NULL, elem_key.c_str(), &max_val); - IF_FAIL_RETURN_TAG(max, false, _E, "Custom template: failed to get integer type value"); - } else { - IF_FAIL_RETURN_TAG(elem_key == TRIG_TMPL_KEY_TYPE, false, _E, "Custom template: invalid key"); - } - } - - if (min && max) { - IF_FAIL_RETURN_TAG(min_val <= max_val, false, _E, "Custom template: invalid min, max value"); - } - - return true; -} - -bool check_template_string(CtxJson1& elem) -{ - std::list elem_keys; - elem.getKeys(&elem_keys); - - for (std::list::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) { - std::string elem_key = *it2; - IF_FAIL_RETURN_TAG(elem_key == TRIG_TMPL_KEY_TYPE, false, _E, "Custom template: invalid key"); - } - - return true; -} - -bool check_template_enum(CtxJson1& elem) -{ - std::list elem_keys; - elem.getKeys(&elem_keys); - - for (std::list::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) { - std::string elem_key = *it2; - - if (elem_key == TRIG_TMPL_TYPE_ENUM) { - int size = elem.getSize(NULL, TRIG_TMPL_TYPE_ENUM); - IF_FAIL_RETURN_TAG(size > 0, false, _E, "Custom template: invalid enum"); - - std::string val_str; - for (int i = 0; i < size; i++) { - bool ret = elem.getAt(NULL, TRIG_TMPL_TYPE_ENUM, i, &val_str); - IF_FAIL_RETURN_TAG(ret, false, _E, "Custom template: failed to get string type value"); - } - } else { - IF_FAIL_RETURN_TAG(elem_key == TRIG_TMPL_KEY_TYPE, false, _E, "Custom template: invalid key"); - } - } - - return true; -} diff --git a/src/rule_validator.h b/src/rule_validator.h deleted file mode 100644 index 688a295..0000000 --- a/src/rule_validator.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2015 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_RULE_VALIDATOR_H__ -#define __CONTEXT_RULE_VALIDATOR_H__ - -#include - -namespace ctx { - namespace rule_validator { - - int request_template(std::string name, bool mandatory = false); - void remove_template(std::string name); - bool check_option(ctx::CtxJson1 &item); - bool check_option_int(std::string name, std::string key, int value); - bool check_option_string(std::string name, std::string key, std::string value); - bool check_option_reference(std::string event, ctx::CtxJson1 &item); - bool check_comparison_int(std::string name, std::string key, std::string op, int value); - bool check_comparison_string(std::string name, std::string key, std::string op, std::string value); - bool check_valid_key(std::string type, std::string name, std::string key); - - bool set_ref_info(std::string type, ctx::CtxJson1 *jref, std::string name, std::string key, std::string ref_key); - std::string get_data_type_from_template(std::string type, std::string name, std::string key); - bool check_referential_data(std::string name, ctx::CtxJson1 &ref_info); - bool is_valid_operator(std::string type, std::string op); - - bool is_valid_template(ctx::CtxJson1& attr_template); - } -} /* namespace ctx */ - -#endif /* __CONTEXT_RULE_VALIDATOR_H__ */ diff --git a/src/trigger/ComparisonConverter.cpp b/src/trigger/ComparisonConverter.cpp new file mode 100644 index 0000000..3d73626 --- /dev/null +++ b/src/trigger/ComparisonConverter.cpp @@ -0,0 +1,154 @@ +/* + * 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 "ComparisonConverter.h" + +using namespace ctx; + +ComparisonConverter::ComparisonConverter(const char* type, CtxJson1& info) : + __completed(false), + __size(0), + __logicalOp(TRIG_RULE_LOGICAL_DISJUNCTION), + __type(type), + __info(info.str()), + __result(EMPTY_JSON_OBJECT) +{ + __info.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &__key); + __info.get(NULL, OLD_TRIG_RULE_KEY_OPERATOR, &__logicalOp); + __size = __info.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR); +} + +int ComparisonConverter::getResult(CtxJson1* result) +{ + if (__result == EMPTY_JSON_OBJECT) + return ERR_INVALID_RULE; + + *result = __result.str(); + + return ERR_NONE; +} + +void ComparisonConverter::__convertComparison() +{ + IF_FAIL_VOID(!__convertEmptyComparison()); + IF_FAIL_VOID(!__convertSingleComparison()); + IF_FAIL_VOID(!__convertMultipleComparison()); + + _E("Failed to convert comparison as new format"); +} + +bool ComparisonConverter::__convertEmptyComparison() +{ + IF_FAIL_RETURN(__size == 0, false); + + CtxJson1 temp = EMPTY_JSON_OBJECT; + __result.set(NULL, __key.c_str(), temp); + + return true; +} + +bool ComparisonConverter::__convertSingleComparison() +{ + IF_FAIL_RETURN(__size == 1, false); + + std::string op; + __info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, 0, &op); + + __setConvertedOperator(op); + __setComparisonValue(); + + return true; +} + +bool ComparisonConverter::__convertMultipleComparison() +{ + IF_FAIL_RETURN(__size > 1, false); + + if (__checkOneOf()) { + return true; + } else if (__checkNoneOf()) { + return true; + } else if (__checkEtc()) { + return true; + } + + return false; +} + +bool ComparisonConverter::__checkOneOf() +{ + // Or of {==, ...} + IF_FAIL_RETURN(__logicalOp == TRIG_RULE_LOGICAL_DISJUNCTION, false); + IF_FAIL_RETURN(__size == __getOperatorCount(TRIG_RULE_OP_EQUAL_TO), false); + + __setConvertedOperator(TRIG_RULE_OP_ONE_OF); + __setComparisonValueArray(); + + return true; +} + +bool ComparisonConverter::__checkNoneOf() +{ + // And of {!=, ...} + IF_FAIL_RETURN(__logicalOp == TRIG_RULE_LOGICAL_CONJUNCTION, false); + IF_FAIL_RETURN(__size == __getOperatorCount(TRIG_RULE_OP_NOT_EQUAL_TO), false); + + __setConvertedOperator(TRIG_RULE_OP_NONE_OF); + __setComparisonValueArray(); + + return true; +} + +bool ComparisonConverter::__checkEtc() +{ + return false; +} + +void ComparisonConverter::__setConvertedOperator(std::string op) +{ + __result.set(__key.c_str(), TRIG_RULE_KEY_OPERATOR, op); +} + +void ComparisonConverter::__setComparisonValue() +{ + std::string valStr; + int val; + + if (__info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, 0, &valStr)) { + __result.set(__key.c_str(), TRIG_RULE_KEY_VALUE, valStr); + } else if (__info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, 0, &val)) { + __result.set(__key.c_str(), TRIG_RULE_KEY_VALUE, val); + } +} + +void ComparisonConverter::__setComparisonValueArray() +{ + std::string valStr; + int val; + // TODO sort + for (int i = 0; i < __size; i++) { + if (__info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, i, &valStr)) { + __result.append(__key.c_str(), TRIG_RULE_KEY_VALUE, valStr); + } else if (__info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, i, &val)) { + __result.append(__key.c_str(), TRIG_RULE_KEY_VALUE, val); + } + } +} + diff --git a/src/trigger/ComparisonConverter.h b/src/trigger/ComparisonConverter.h new file mode 100644 index 0000000..9cde85c --- /dev/null +++ b/src/trigger/ComparisonConverter.h @@ -0,0 +1,58 @@ +/* + * 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_COMPARISON_CONVERTER_H_ +#define _CONTEXT_COMPARISON_CONVERTER_H_ + +#include +#include "TriggerOldRuleTypes.h" + +namespace ctx { + + class ComparisonConverter { + public: + virtual ~ComparisonConverter() {}; + + int getResult(CtxJson1* result); + + protected: + bool __completed; + int __size; + std::string __logicalOp; + std::string __type; + CtxJson1 __info; + CtxJson1 __result; + std::string __key; + + ComparisonConverter(const char* type, CtxJson1& info); + void __convertComparison(); + virtual int __getOperatorCount(std::string op) = 0; + virtual bool __checkEtc(); + void __setConvertedOperator(std::string op); + + private: + bool __convertEmptyComparison(); + bool __convertSingleComparison(); + bool __convertMultipleComparison(); + bool __checkOneOf(); + bool __checkNoneOf(); + void __setComparisonValue(); + void __setComparisonValueArray(); + }; + +} /* namespace ctx */ + +#endif /* _CONTEXT_COMPARISON_CONVERTER_H_ */ diff --git a/src/trigger/IntComparisonConverter.cpp b/src/trigger/IntComparisonConverter.cpp new file mode 100644 index 0000000..9f1a4e5 --- /dev/null +++ b/src/trigger/IntComparisonConverter.cpp @@ -0,0 +1,130 @@ +/* + * 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 +#include "IntComparisonConverter.h" + +using namespace ctx; + +IntComparisonConverter::IntComparisonConverter(CtxJson1 info) : + ComparisonConverter(TRIG_TMPL_TYPE_INTEGER, info) +{ + if (__size >= 2) { + for (int i = 0; i < __size; i++) { + int val; + std::string op; + __info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, i, &val); + __info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, i, &op); + + __insertComparisonInfo(op, val); + } + __sort(); + } + + __convertComparison(); +} + +void IntComparisonConverter::__insertComparisonInfo(std::string op, int val) +{ + IntComparisonMap::iterator it = __map.find(op); + if (it == __map.end()) { + IntList list; + list.push_back(val); + __map[op] = list; + } else { + it->second.push_back(val); + } +} + +void IntComparisonConverter::__sort() +{ + for (IntComparisonMap::iterator it = __map.begin(); it != __map.end(); it++) { + it->second.sort(); + } +} + +int IntComparisonConverter::__getOperatorCount(std::string op) +{ + return __map[op].size(); +} + +int IntComparisonConverter::__getMaxValue(std::string op) +{ + return __map[op].back(); +} + +int IntComparisonConverter::__getMinValue(std::string op) +{ + return __map[op].front(); +} + +bool IntComparisonConverter::__checkEtc() +{ + // Simple version in, notIn + IF_FAIL_RETURN(!__checkIn(), true); + IF_FAIL_RETURN(!__checkNotIn(), true); + + return false; +} + + +bool IntComparisonConverter::__checkIn() +{ + // And of { >= min, <= max } + IF_FAIL_RETURN(__logicalOp == TRIG_RULE_LOGICAL_CONJUNCTION, false); + IF_FAIL_RETURN(__size == 2, false); + IF_FAIL_RETURN(__getOperatorCount(TRIG_RULE_OP_GREATER_THAN_OR_EQUAL_TO) == 1 + && __getOperatorCount(TRIG_RULE_OP_LESS_THAN_OR_EQUAL_TO) == 1, false); + + int maxOfGE = __getMaxValue(TRIG_RULE_OP_GREATER_THAN_OR_EQUAL_TO); + int minOfLE = __getMinValue(TRIG_RULE_OP_LESS_THAN_OR_EQUAL_TO); + IF_FAIL_RETURN(maxOfGE <= minOfLE, false); + + __setConvertedOperator(TRIG_RULE_OP_IN); + __setComparisonValue(maxOfGE, minOfLE); + + return true; +} + +bool IntComparisonConverter::__checkNotIn() +{ + // Or of { < min, > max } + IF_FAIL_RETURN(__logicalOp == TRIG_RULE_LOGICAL_DISJUNCTION, false); + IF_FAIL_RETURN(__size == 2, false); + IF_FAIL_RETURN(__getOperatorCount(TRIG_RULE_OP_GREATER_THAN) == 1 + && __getOperatorCount(TRIG_RULE_OP_LESS_THAN) == 1, false); + + int maxOfL = __getMaxValue(TRIG_RULE_OP_LESS_THAN); + int minOfG = __getMinValue(TRIG_RULE_OP_GREATER_THAN); + IF_FAIL_RETURN(maxOfL <= minOfG, false); + + __setConvertedOperator(TRIG_RULE_OP_NOT_IN); + __setComparisonValue(maxOfL, minOfG); + + return true; +} + +void IntComparisonConverter::__setComparisonValue(int val1, int val2) +{ + __result.append(__key.c_str(), TRIG_RULE_KEY_VALUE, val1); + __result.append(__key.c_str(), TRIG_RULE_KEY_VALUE, val2); +} + diff --git a/src/trigger/IntComparisonConverter.h b/src/trigger/IntComparisonConverter.h new file mode 100644 index 0000000..f18cd2b --- /dev/null +++ b/src/trigger/IntComparisonConverter.h @@ -0,0 +1,52 @@ +/* + * 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_INT_COMPARISON_CONVERTER_H_ +#define _CONTEXT_INT_COMPARISON_CONVERTER_H_ + +#include +#include +#include "ComparisonConverter.h" + +namespace ctx { + + class IntComparisonConverter : public ComparisonConverter { + typedef std::list IntList; // Integer value list + typedef std::map IntComparisonMap; // { operator, IntList } + + public: + IntComparisonConverter(CtxJson1 info); + ~IntComparisonConverter() {}; + + private: + IntComparisonMap __map; + + void __insertComparisonInfo(std::string op, int val); + void __sort(); + int __getMaxValue(std::string op); + int __getMinValue(std::string op); + + bool __checkIn(); + bool __checkNotIn(); + void __setComparisonValue(int val1, int val2); + /* From CompariconConverter */ + int __getOperatorCount(std::string op); + bool __checkEtc(); + }; + +} /* namespace ctx */ + +#endif /* _CONTEXT_INT_COMPARISON_CONVERTER_H_ */ diff --git a/src/trigger/StringComparisonConverter.cpp b/src/trigger/StringComparisonConverter.cpp new file mode 100644 index 0000000..f4c1757 --- /dev/null +++ b/src/trigger/StringComparisonConverter.cpp @@ -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. + */ + +#include +#include +#include +#include +#include "StringComparisonConverter.h" + +using namespace ctx; + +StringComparisonConverter::StringComparisonConverter(CtxJson1 info) : + ComparisonConverter(TRIG_TMPL_TYPE_STRING, info) +{ + if (__size >= 2) { + for (int i = 0; i < __size; i++) { + std::string op; + __info.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, i, &op); + + __map[op]++; + } + } + + __convertComparison(); +} + + +int StringComparisonConverter::__getOperatorCount(std::string op) +{ + return __map[op]; +} + diff --git a/src/trigger/StringComparisonConverter.h b/src/trigger/StringComparisonConverter.h new file mode 100644 index 0000000..69fb110 --- /dev/null +++ b/src/trigger/StringComparisonConverter.h @@ -0,0 +1,42 @@ +/* + * 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_STRING_COMPARISON_CONVERTER_H_ +#define _CONTEXT_STRING_COMPARISON_CONVERTER_H_ + +#include +#include +#include "ComparisonConverter.h" + +namespace ctx { + + class StringComparisonConverter : public ComparisonConverter { + typedef std::map StringComparisonMap; + + public: + StringComparisonConverter(CtxJson1 info); + ~StringComparisonConverter() {}; + + private: + StringComparisonMap __map; + + /* From CompariconConverter */ + int __getOperatorCount(std::string op); + }; + +} /* namespace ctx */ + +#endif /* _CONTEXT_STRING_COMPARISON_CONVERTER_H_ */ diff --git a/src/trigger/TriggerOldRuleTypes.h b/src/trigger/TriggerOldRuleTypes.h new file mode 100644 index 0000000..fe85d67 --- /dev/null +++ b/src/trigger/TriggerOldRuleTypes.h @@ -0,0 +1,36 @@ +/* + * 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_TRIGGER_OLD_RULE_TYPES_H_ +#define _CONTEXT_TRIGGER_OLD_RULE_TYPES_H_ + +/* Old Rule Keys */ +#define OLD_TRIG_RULE_KEY_EVENT "EVENT" +#define OLD_TRIG_RULE_KEY_EVENT_ITEM "ITEM_NAME" +#define OLD_TRIG_RULE_KEY_EVENT_OPERATOR "ITEM_OPERATOR" +#define OLD_TRIG_RULE_KEY_EVENT_OPTION "OPTION" +#define OLD_TRIG_RULE_KEY_OPERATOR "OPERATOR" +#define OLD_TRIG_RULE_KEY_CONDITION "CONDITION" +#define OLD_TRIG_RULE_KEY_CONDITION_ITEM "ITEM_NAME" +#define OLD_TRIG_RULE_KEY_CONDITION_OPERATOR "ITEM_OPERATOR" +#define OLD_TRIG_RULE_KEY_CONDITION_OPTION "OPTION" +#define OLD_TRIG_RULE_KEY_DATA_ARR "DATA_ARR" +#define OLD_TRIG_RULE_KEY_DATA_KEY "DATA_KEY" +#define OLD_TRIG_RULE_KEY_DATA_KEY_OPERATOR "DATA_KEY_OPERATOR" +#define OLD_TRIG_RULE_KEY_DATA_VALUE_ARR "DATA_VALUE_ARR" +#define OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR "DATA_VALUE_OPER_ARR" + +#endif /* _CONTEXT_TRIGGER_OLD_RULE_TYPES_H_ */ diff --git a/src/trigger/context_trigger.cpp b/src/trigger/context_trigger.cpp new file mode 100644 index 0000000..de50622 --- /dev/null +++ b/src/trigger/context_trigger.cpp @@ -0,0 +1,1206 @@ +/* + * Copyright (c) 2015 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "TriggerOldRuleTypes.h" +#include "rule_validator.h" +#include "rule_util.h" + +#define TRIGGER_DEPRECATED_FUNCTION_MSG "DEPRECATION WARNING: %s is deprecated and will be removed from next release." +#define TRIGGER_DEPRECATED_EVENT_MSG "DEPRECATION WARNING: This event is deprecated and will be removed from next release." +#define TRIGGER_DEPRECATED_CONDITION_MSG "DEPRECATION WARNING: This condition is deprecated and will be removed from next release." + +//#define DOUBLE_PRECISION 2 +#define TYPE_EVENT 1 +#define TYPE_CONDITION 2 +#define TYPE_OPTION TRIG_TMPL_KEY_OPTION +#define TYPE_ATTRIBUTE TRIG_TMPL_KEY_ATTRIBUTE +#define OLD_INITIAL_ENTRY "{ \"" OLD_TRIG_RULE_KEY_DATA_ARR "\" : [ ] }" +#define INITIAL_REF "{ \"" TRIG_TMPL_KEY_OPTION "\" : [ ], \"" TRIG_TMPL_KEY_ATTRIBUTE "\" : [ ] }" +#define INITIAL_RULE \ +"{ \"" TRIG_RULE_KEY_DESCRIPTION "\" : \"\", \"" TRIG_RULE_KEY_EVENT "\" : { }, \"" TRIG_RULE_KEY_CONDITION "\" : [ ], \"" \ +TRIG_RULE_KEY_ACTION "\" : { }, \"" _TRIG_RULE_KEY_EXTRA "\": { } }" +#define INITIAL_ENTRY "{ \"" TRIG_RULE_KEY_OPTION "\": { }, \"" TRIG_RULE_KEY_COMPARISON "\" : { } }" + +static ctx::DBusClient __dbusClient; + +static int context_trigger_rule_event_create_internal(const char* event_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom = false); +static int context_trigger_rule_condition_create_internal(const char* condition_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom = false); +static std::string convert_event_to_string(context_trigger_event_e item); +static std::string convert_condition_to_string(context_trigger_condition_e item); +static std::string convert_logical_type_to_string(context_trigger_logical_type_e logical_type); +static std::string get_custom_item_subject(const char* provider, const char* item); +static bool event_is_deprecated(context_trigger_event_e item); +static bool condition_is_deprecated(context_trigger_condition_e item); + +//static std::string int_to_string(int value); +//static std::string double_to_string(int value); + +typedef struct _context_trigger_rule_s { + ctx::CtxJson1 jold_rule; + ctx::CtxJson1 jrule; // description, event{}, condition[], action{}, _extra{} + ctx::CtxJson1 jref; + + _context_trigger_rule_s() { + jold_rule = EMPTY_JSON_OBJECT; + jrule = INITIAL_RULE; + jref = INITIAL_REF; + } +} _context_trigger_rule_h; + +typedef struct _context_trigger_rule_entry_s { + int type; + ctx::CtxJson1 jentry; + ctx::CtxJson1 jref; + + _context_trigger_rule_entry_s(int t): type(t) { + jentry = OLD_INITIAL_ENTRY; + + if (t == TYPE_CONDITION) { + jref = INITIAL_REF; + } + } +} _context_trigger_rule_entry_h; + +// Add a rule +SO_EXPORT int context_trigger_add_rule(context_trigger_rule_h rule, int* rule_id) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(rule && rule_id); + + // Err: No event + if (!ctx::rule_util::isEventSet(rule->jrule)) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + + // Err: No action + if (!ctx::rule_util::isActionSet(rule->jrule)) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + + // If condition size isn't greater than 1, update logical operator as default + if ((rule->jrule).getSize(NULL, TRIG_RULE_KEY_CONDITION) <= 1) { + (rule->jrule).set(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_RULE_LOGICAL_OP, TRIG_RULE_LOGICAL_CONJUNCTION); + } + + ctx::CtxJson1 jrule_id; + int error = __dbusClient.write(SUBJ_TRIGGER_ADD, rule->jrule, &jrule_id); + + if (error == ERR_NONE) { + jrule_id.get(NULL, TRIG_KEY_RULE_ID, rule_id); + } + + return error; +} + +// Remove a rule +SO_EXPORT int context_trigger_remove_rule(int rule_id) +{ + _D("BEGIN"); + if (rule_id <= 0) + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + + ctx::CtxJson1 jrule_id; + jrule_id.set(NULL, TRIG_KEY_RULE_ID, rule_id); + int error = __dbusClient.write(SUBJ_TRIGGER_REMOVE, jrule_id, NULL); + + if (error == ERR_ALREADY_STARTED) { // Rule is still enabled. + return CONTEXT_TRIGGER_ERROR_RULE_ENABLED; + } else if (error == ERR_NO_DATA) { + return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; + } + + return error; +} + +// Enable a rule +SO_EXPORT int context_trigger_enable_rule(int rule_id) +{ + _D("BEGIN"); + if (rule_id <= 0) + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + + ctx::CtxJson1 jrule_id; + jrule_id.set(NULL, TRIG_KEY_RULE_ID, rule_id); + + int req_id; // Useless in context_trigger + int error = __dbusClient.subscribe(SUBJ_TRIGGER_ENABLE, jrule_id, &req_id, NULL); + + if (error == ERR_NO_DATA) { + return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; + } + + return error; +} + +// Disable a rule +SO_EXPORT int context_trigger_disable_rule(int rule_id) +{ + _D("BEGIN"); + if (rule_id <= 0) + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + + ctx::CtxJson1 jrule_id; + jrule_id.set(NULL, TRIG_KEY_RULE_ID, rule_id); + int error = __dbusClient.write(SUBJ_TRIGGER_DISABLE, jrule_id, NULL); + + if (error == ERR_NO_DATA) { + return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; + } + + return error; +} + +SO_EXPORT int context_trigger_get_own_rule_ids(int** enabled_rule_ids, int* enabled_rule_count, int** disabled_rule_ids, int* disabled_rule_count) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(enabled_rule_ids && enabled_rule_count && disabled_rule_ids && disabled_rule_count); + + int req_id; + ctx::CtxJson1 data_read; + int error = __dbusClient.readSync(SUBJ_TRIGGER_GET_RULE_IDS, NULL, &req_id, &data_read); + + if (error != ERR_NONE) { + return error; + } + + // Enabled rules + int* e_arr = NULL; + *enabled_rule_count = data_read.getSize(NULL, TRIG_KEY_ENABLED_IDS); + + if (*enabled_rule_count > 0) { + e_arr = static_cast(g_malloc((*enabled_rule_count) * sizeof(int))); + IF_FAIL_RETURN_TAG(e_arr, CONTEXT_TRIGGER_ERROR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + + int id; + for (int i = 0; data_read.getAt(NULL, TRIG_KEY_ENABLED_IDS, i, &id); i++) { + *(e_arr + i) = id; + } + } + *enabled_rule_ids = e_arr; + + // Disabled rules + int* d_arr = NULL; + *disabled_rule_count = data_read.getSize(NULL, TRIG_KEY_DISABLED_IDS); + + if (*disabled_rule_count > 0) { + d_arr = static_cast(g_malloc((*disabled_rule_count) * sizeof(int))); + IF_FAIL_RETURN_TAG(d_arr, CONTEXT_TRIGGER_ERROR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + + int id; + for (int i = 0; data_read.getAt(NULL, TRIG_KEY_DISABLED_IDS, i, &id); i++) { + *(d_arr + i) = id; + } + } + *disabled_rule_ids = d_arr; + + return error; +} + + +SO_EXPORT int context_trigger_get_rule_by_id(int rule_id, context_trigger_rule_h* rule) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(rule); + if (rule_id <= 0) + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + + ctx::CtxJson1 option; + option.set(NULL, TRIG_KEY_RULE_ID, rule_id); + + int req_id; + ctx::CtxJson1 data_read; + int error = __dbusClient.readSync(SUBJ_TRIGGER_GET, option, &req_id, &data_read); + + if (error == ERR_NO_DATA) { + return CONTEXT_TRIGGER_ERROR_RULE_NOT_EXIST; + } else if (error != ERR_NONE) { + return error; + } + + *rule = new(std::nothrow) _context_trigger_rule_h(); + (*rule)->jrule = data_read; + + return ERR_NONE; +} + +// Rule creation +SO_EXPORT int context_trigger_rule_create(context_trigger_logical_type_e logical_type, context_trigger_rule_h* rule) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(rule); + + std::string logical_str = convert_logical_type_to_string(logical_type); + if (logical_str.empty()) { + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + } + + *rule = new(std::nothrow) _context_trigger_rule_h(); + (*rule)->jold_rule.set(NULL, OLD_TRIG_RULE_KEY_OPERATOR, logical_str); + + (*rule)->jrule.set(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_RULE_LOGICAL_OP, logical_str); + + return ERR_NONE; +} + +// Rule deletion +SO_EXPORT int context_trigger_rule_destroy(context_trigger_rule_h rule) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(rule); + delete rule; + + return CONTEXT_TRIGGER_ERROR_NONE; +} + + +SO_EXPORT int context_trigger_rule_add_entry(context_trigger_rule_h rule, context_trigger_rule_entry_h entry) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(rule && entry); + + // Check if rule handle is created + ctx::CtxJson1 extra; + bool ret = (rule->jrule).get(NULL, _TRIG_RULE_KEY_EXTRA, &extra); + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER); + + if (entry->type == TYPE_EVENT) { + // Err: More than one event + ctx::CtxJson1 elem; + if ((rule->jold_rule).get(NULL, OLD_TRIG_RULE_KEY_EVENT, &elem)) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + + // Err: Check if all the mandatory options are added + ret = ctx::rule_validator::check_option(entry->jentry); + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + + // Err: If referential conditions are registered priviously, check them + std::string ename; + (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &ename); + ret = ctx::rule_validator::check_referential_data(ename, rule->jref); + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + + ctx::CtxJson1 temp = (entry->jentry).str(); + ret = (rule->jold_rule).set(NULL, OLD_TRIG_RULE_KEY_EVENT, temp); + + int error = ctx::rule_util::setEvent(entry->jentry, &(rule->jrule)); + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to add event entry"); + } else if (entry->type == TYPE_CONDITION) { + // Err: Condition without comparison data + if ((entry->jentry).getSize(NULL, OLD_TRIG_RULE_KEY_DATA_ARR) < 1) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + + ctx::CtxJson1 elem; + for (int i = 0; (entry->jentry).getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { + int val_arr_size = elem.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR); + int op_arr_size = elem.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR); + + // Err: Condition without comparison data + if (val_arr_size != op_arr_size || val_arr_size < 1 || op_arr_size < 1) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + + // Err: Check if all the mandatory options are added + ret = ctx::rule_validator::check_option(entry->jentry); + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + + // If event is already added .... + std::string ename; + ret = (rule->jold_rule).get(OLD_TRIG_RULE_KEY_EVENT, OLD_TRIG_RULE_KEY_EVENT_ITEM, &ename); + if (ret) { + // Err: Check referential information if exists + ret = ctx::rule_validator::check_referential_data(ename, entry->jref); + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + } else { + // If not, copy referential information to rule entry + ctx::CtxJson1 info; + for (int j = 0; (entry->jref).getAt(NULL, TYPE_OPTION, j, &info); j++) { + (rule->jref).append(NULL, TYPE_OPTION, info); + } + + for (int j = 0; (entry->jref).getAt(NULL, TYPE_ATTRIBUTE, j, &info); j++) { + (rule->jref).append(NULL, TYPE_ATTRIBUTE, info); + } + } + } + + ctx::CtxJson1 temp = (entry->jentry).str(); + ret = (rule->jold_rule).append(NULL, OLD_TRIG_RULE_KEY_CONDITION, temp); + + ctx::rule_util::addCondition(entry->jentry, &(rule->jrule)); + } else { + // Entry is not created + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + } + + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_OPERATION_FAILED); + return CONTEXT_TRIGGER_ERROR_NONE; +} + +static bool is_call_operation(app_control_h app_control) +{ + char *op = NULL; + int err = app_control_get_operation(app_control, &op); + IF_FAIL_RETURN_TAG(err == APP_CONTROL_ERROR_NONE, false, _W, "Getting operation of app control failed"); + + bool ret = STR_EQ(op, APP_CONTROL_OPERATION_CALL); + g_free(op); + + return ret; +} + +SO_EXPORT int context_trigger_rule_set_action_app_control(context_trigger_rule_h rule, app_control_h app_control) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(rule && app_control); + int error; + + // Privilege check + error = __dbusClient.call(METHOD_CHK_PRIV_APPLAUNCH); + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Privilege checking failed (%#x)", error); + + if (is_call_operation(app_control)) { + error = __dbusClient.call(METHOD_CHK_PRIV_CALL); + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Privilege checking failed (%#x)", error); + } + + // Err: if action arleady exists + if (ctx::rule_util::isActionSet(rule->jrule)) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + + // Err: service app + char* app_id = NULL; + error = app_control_get_app_id(app_control, &app_id); + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to get app id"); + + pkgmgrinfo_appinfo_h app_info; + error = pkgmgrinfo_appinfo_get_usr_appinfo(app_id, getuid(), &app_info); + g_free(app_id); + IF_FAIL_RETURN_TAG(error == PMINFO_R_OK, CONTEXT_TRIGGER_ERROR_INVALID_RULE, _E, "No such app"); + + // Service apps are not allowed to be launched (Mobile & Wearable) + char *app_type = NULL; + pkgmgrinfo_appinfo_get_component_type(app_info, &app_type); + if (!strcmp(app_type, "svcapp")) { + _E("Service application is restricted"); + pkgmgrinfo_appinfo_destroy_appinfo(app_info); + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + pkgmgrinfo_appinfo_destroy_appinfo(app_info); + + // Set app control + bundle* appctl_bundle = NULL; + error = app_control_to_bundle(app_control, &appctl_bundle); + IF_FAIL_RETURN_TAG(error == ERR_NONE, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "App_control to bundle failed"); + + bundle_raw* appctl_raw; + int raw_length; + error = bundle_encode(appctl_bundle, &appctl_raw, &raw_length); + IF_FAIL_RETURN_TAG(error == ERR_NONE, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Bundle encode failed"); + + std::string appctl_str = reinterpret_cast(appctl_raw); + (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_APP_LAUNCH, TRIG_RULE_KEY_APP_LAUNCH_APP_CONTROL, appctl_str); + bundle_free_encoded_rawdata(&appctl_raw); + + return CONTEXT_TRIGGER_ERROR_NONE; +} + +SO_EXPORT int context_trigger_rule_set_action_notification(context_trigger_rule_h rule, const char* title, const char* content, const char* icon_path, app_control_h app_control) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(rule && title && content); + + // Privilege check + int error = __dbusClient.call(METHOD_CHK_PRIV_NOTIFICATION); + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Privilege checking failed (%#x)", error); + + // if action arleady exists + if (ctx::rule_util::isActionSet(rule->jrule)) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + + // Err: App control check + if (app_control) { + char* app_id = NULL; + error = app_control_get_app_id(app_control, &app_id); + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to get app id"); + + pkgmgrinfo_appinfo_h app_info; + error = pkgmgrinfo_appinfo_get_usr_appinfo(app_id, getuid(), &app_info); + g_free(app_id); + IF_FAIL_RETURN_TAG(error == PMINFO_R_OK, CONTEXT_TRIGGER_ERROR_INVALID_RULE, _E, "No such app"); + + pkgmgrinfo_appinfo_destroy_appinfo(app_info); + } + + // Set title, content + (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_TITLE, title); + (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_CONTENT, content); + + // Set icon path + if (icon_path) { + (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_ICON_PATH, icon_path); + } + + // Set app control + if (app_control) { + bundle* appctl_bundle = NULL; + error = app_control_to_bundle(app_control, &appctl_bundle); + IF_FAIL_RETURN_TAG(error == ERR_NONE, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "App_control to bundle failed"); + + bundle_raw* appctl_raw; + int raw_length; + error = bundle_encode(appctl_bundle, &appctl_raw, &raw_length); + IF_FAIL_RETURN_TAG(error == ERR_NONE, CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Bundle encode failed"); + + std::string appctl_str = reinterpret_cast(appctl_raw); + (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_APP_CONTROL, appctl_str); + + bundle_free_encoded_rawdata(&appctl_raw); + } + + return CONTEXT_TRIGGER_ERROR_NONE; +} + +//LCOV_EXCL_START +SO_EXPORT int context_trigger_rule_set_action_dbus_call(context_trigger_rule_h rule, + const char *bus_name, const char *object_path, const char *interface_name, const char *method_name, GVariant *param) +{ + ASSERT_NOT_NULL(rule && bus_name && object_path && interface_name && method_name); + + /* if action arleady exists */ + if (ctx::rule_util::isActionSet(rule->jrule)) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + + /* Set basic dbus method call info */ + (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_NAME, bus_name); + (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_OBJECT, object_path); + (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_INTERFACE, interface_name); + (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_METHOD, method_name); + + /* Set the parameters */ + if (param) + (rule->jrule).set(TRIG_RULE_KEY_ACTION "." TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_PARAMETER, param); + + return CONTEXT_TRIGGER_ERROR_NONE; +} +//LCOV_EXCL_STOP + +// Set description +SO_EXPORT int context_trigger_rule_set_description(context_trigger_rule_h rule, const char* description) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(rule); + + (rule->jrule).set(NULL, TRIG_RULE_KEY_DESCRIPTION, description); + + return CONTEXT_TRIGGER_ERROR_NONE; +} + +// Get rule description +SO_EXPORT int context_trigger_rule_get_description(context_trigger_rule_h rule, char** description) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(rule && description); + + std::string val; + (rule->jrule).get(NULL, TRIG_RULE_KEY_DESCRIPTION, &val); + + *description = strdup(val.c_str()); + + return CONTEXT_TRIGGER_ERROR_NONE; +} + +// Event creation +SO_EXPORT int context_trigger_rule_event_create(context_trigger_event_e event_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(entry); + + if (event_is_deprecated(event_item)) { + _W(TRIGGER_DEPRECATED_EVENT_MSG); + } + + std::string eitem_str = convert_event_to_string(event_item); + if (eitem_str.empty()) { + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + } + + int error = context_trigger_rule_event_create_internal(eitem_str.c_str(), logical_type, entry); + return error; +} + +SO_EXPORT int context_trigger_rule_custom_event_create(const char* event_item, const char* provider, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(event_item && provider && entry); + + // Err: Invalid provider + pkgmgrinfo_pkginfo_h pkg_info; + int error = pkgmgrinfo_pkginfo_get_usr_pkginfo(provider, getuid(), &pkg_info); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_info); + IF_FAIL_RETURN_TAG(error == PMINFO_R_OK, CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "No such package"); + + std::string subject = get_custom_item_subject(provider, event_item); + error = context_trigger_rule_event_create_internal(subject.c_str(), logical_type, entry, true); + + return error; +} + +int context_trigger_rule_event_create_internal(const char* event_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(event_item); + + // Err: Invalid logical operator + std::string logical_str = convert_logical_type_to_string(logical_type); + if (logical_str.empty()) { + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + } + + int error = ctx::rule_validator::request_template(event_item, is_custom); + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to request template: %#x", error); + + *entry = new(std::nothrow) _context_trigger_rule_entry_h(TYPE_EVENT); + (*entry)->jentry.set(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, event_item); + (*entry)->jentry.set(NULL, OLD_TRIG_RULE_KEY_EVENT_OPERATOR, logical_str); + + return CONTEXT_TRIGGER_ERROR_NONE; +} + +// Event availability check +SO_EXPORT int context_trigger_rule_event_is_supported(context_trigger_event_e event_item, bool* supported) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(supported); + + if (event_is_deprecated(event_item)) { + _W(TRIGGER_DEPRECATED_EVENT_MSG); + } + + *supported = false; + + std::string eitem_str = convert_event_to_string(event_item); + if (eitem_str.empty()) { + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + } + + int error = __dbusClient.isSupported(eitem_str); + + if (error == ERR_NONE) + *supported = true; + + if (error == ERR_NOT_SUPPORTED) + return ERR_NONE; + + return error; +} + +// Condition creation +SO_EXPORT int context_trigger_rule_condition_create(context_trigger_condition_e condition_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(entry); + + if (condition_is_deprecated(condition_item)) { + _W(TRIGGER_DEPRECATED_CONDITION_MSG); + } + + std::string citem_str = convert_condition_to_string(condition_item); + if (citem_str.empty()) { + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + } + + int error = context_trigger_rule_condition_create_internal(citem_str.c_str(), logical_type, entry); + return error; +} + +SO_EXPORT int context_trigger_rule_custom_condition_create(const char* condition_item, const char* provider, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(condition_item && provider && entry); + + // Err: Invalid provider + pkgmgrinfo_pkginfo_h pkg_info; + int error = pkgmgrinfo_pkginfo_get_usr_pkginfo(provider, getuid(), &pkg_info); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_info); + IF_FAIL_RETURN_TAG(error == PMINFO_R_OK, CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "No such package"); + + std::string subject = get_custom_item_subject(provider, condition_item); + error = context_trigger_rule_condition_create_internal(subject.c_str(), logical_type, entry, true); + return error; +} + +int context_trigger_rule_condition_create_internal(const char* condition_item, context_trigger_logical_type_e logical_type, context_trigger_rule_entry_h* entry, bool is_custom) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(condition_item); + + std::string logical_str = convert_logical_type_to_string(logical_type); + if (logical_str.empty()) { + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + } + + int error = ctx::rule_validator::request_template(condition_item, is_custom); + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to request template: %#x", error); + + *entry = new(std::nothrow) _context_trigger_rule_entry_h(TYPE_CONDITION); + (*entry)->jentry.set(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, condition_item); + (*entry)->jentry.set(NULL, OLD_TRIG_RULE_KEY_CONDITION_OPERATOR, logical_str); + + return CONTEXT_TRIGGER_ERROR_NONE; +} + +// Condition availability check +SO_EXPORT int context_trigger_rule_condition_is_supported(context_trigger_condition_e condition_item, bool* supported) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(supported); + + if (condition_is_deprecated(condition_item)) { + _W(TRIGGER_DEPRECATED_CONDITION_MSG); + } + + *supported = false; + + std::string citem_str = convert_condition_to_string(condition_item); + if (citem_str.empty()) { + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + } + + int error = __dbusClient.isSupported(citem_str); + + if (error == ERR_NONE) + *supported = true; + + if (error == ERR_NOT_SUPPORTED) + return ERR_NONE; + + return error; +} + +// Rule data deletion +SO_EXPORT int context_trigger_rule_entry_destroy(context_trigger_rule_entry_h entry) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(entry); + delete entry; + + return CONTEXT_TRIGGER_ERROR_NONE; +} + +SO_EXPORT int context_trigger_rule_entry_add_option_int(context_trigger_rule_entry_h entry, const char* option_key, int value) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(entry && option_key); + + bool ret = true; + std::string name; + (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &name); + ret = ctx::rule_validator::check_option_int(name, option_key, value); + if (!ret) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + + (entry->jentry).set(OLD_TRIG_RULE_KEY_CONDITION_OPTION, option_key, value); + + return CONTEXT_TRIGGER_ERROR_NONE; +} + +SO_EXPORT int context_trigger_rule_entry_add_option_string(context_trigger_rule_entry_h entry, const char* option_key, const char* value) +{ + _D("BEGIN"); + _W(TRIGGER_DEPRECATED_FUNCTION_MSG, __FUNCTION__); + ASSERT_NOT_NULL(entry && option_key && value); + + bool ret = true; + std::string name; + (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &name); + ret = ctx::rule_validator::check_option_string(name, option_key, value); + if (!ret) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + + (entry->jentry).set(OLD_TRIG_RULE_KEY_CONDITION_OPTION, option_key, value); + + return CONTEXT_TRIGGER_ERROR_NONE; +} + +SO_EXPORT int context_trigger_rule_entry_add_option(context_trigger_rule_entry_h entry, const char* option_key, const char* event_data_key) +{ + _D("BEGIN"); + _W(TRIGGER_DEPRECATED_FUNCTION_MSG, __FUNCTION__); + ASSERT_NOT_NULL(entry && option_key && event_data_key); + + // Err: Only conditin can reference data from event + if (entry->type != TYPE_CONDITION) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + + std::string name; + (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &name); + + // Err: Check if key is valid + bool ret = ctx::rule_validator::check_valid_key(TYPE_OPTION, name, option_key); + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + + // Set reference information + ret = ctx::rule_validator::set_ref_info(TYPE_OPTION, &(entry->jref), name, option_key, event_data_key); + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_OPERATION_FAILED); + + (entry->jentry).set(OLD_TRIG_RULE_KEY_CONDITION_OPTION, option_key, std::string(TRIG_RULE_REF_KEY_PREFIX) + std::string(event_data_key)); + + return CONTEXT_TRIGGER_ERROR_NONE; +} + +SO_EXPORT int context_trigger_rule_entry_add_key(context_trigger_rule_entry_h entry, context_trigger_logical_type_e logical_type, const char* key) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(entry && key); + + std::string logical_str = convert_logical_type_to_string(logical_type); + if (logical_str.empty()) { + return CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER; + } + + // Err: Check if key is valid + std::string name; + (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); + + bool ret = ctx::rule_validator::check_valid_key(TYPE_ATTRIBUTE, name, key); + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + + // Err: Comparison key is already added + ctx::CtxJson1 elem; + for (int i = 0; (entry->jentry).getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { + std::string elem_item; + elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &elem_item); + // Err: Comparison key is already added + if (elem_item.compare(key) == 0) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + } + + ctx::CtxJson1 data; + data.set(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, key); + data.set(NULL, OLD_TRIG_RULE_KEY_DATA_KEY_OPERATOR, logical_str); + (entry->jentry).append(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, data); + + return CONTEXT_TRIGGER_ERROR_NONE; +} + +static int context_trigger_rule_entry_add_comparison_string_internal(context_trigger_rule_entry_h entry, const char* key, std::string op, std::string value) +{ + ctx::CtxJson1 elem; + for (int i = 0; (entry->jentry).getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { + std::string elem_item; + elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &elem_item); + + if (elem_item.compare(key) == 0) { + std::string elem_val; + std::string elem_op; + for (int j = 0; elem.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, j, &elem_val); j++) { + elem.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, j, &elem_op); + + // Err: Duplicated + if (elem_val.compare(value) == 0 && elem_op.compare(op) == 0) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + } + elem.append(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, value.c_str()); + elem.append(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, op); + (entry->jentry).setAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, elem); + + return CONTEXT_TRIGGER_ERROR_NONE; + } + } + + // Comparison key not exist + return CONTEXT_TRIGGER_ERROR_NO_DATA; +} + +static int context_trigger_rule_entry_add_comparison_int_internal(context_trigger_rule_entry_h entry, const char* key, std::string op, int value) +{ + ctx::CtxJson1 elem; + for (int i = 0; (entry->jentry).getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { + std::string elem_item; + elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &elem_item); + + if (elem_item.compare(key) == 0) { + int elem_val; + std::string elem_op; + for (int j = 0; elem.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, j, &elem_val); j++) { + elem.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, j, &elem_op); + + // Err: Duplicated + if (elem_val == value && elem_op.compare(op) == 0) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + } + elem.append(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_ARR, value); + elem.append(NULL, OLD_TRIG_RULE_KEY_DATA_VALUE_OPERATOR_ARR, op); + (entry->jentry).setAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, elem); + + return CONTEXT_TRIGGER_ERROR_NONE; + } + } + + // Comparison key not exist + return CONTEXT_TRIGGER_ERROR_NO_DATA; +} + +SO_EXPORT int context_trigger_rule_entry_add_comparison(context_trigger_rule_entry_h entry, const char* key, const char* op, const char* event_data_key) +{ + _D("BEGIN"); + _W(TRIGGER_DEPRECATED_FUNCTION_MSG, __FUNCTION__); + ASSERT_NOT_NULL(entry && key && op && event_data_key); + + // Err: Only condition can reference data from event + if (entry->type != TYPE_CONDITION) { + return CONTEXT_TRIGGER_ERROR_INVALID_RULE; + } + + std::string name; + (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &name); + + // Err: Check if key is valid + bool ret = ctx::rule_validator::check_valid_key(TYPE_ATTRIBUTE, name, key); + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + + // Err: Invalid operator + std::string type = ctx::rule_validator::get_data_type_from_template(TYPE_ATTRIBUTE, name, key); + ret = ctx::rule_validator::is_valid_operator(type, op); + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + + int error = context_trigger_rule_entry_add_comparison_string_internal(entry, key, op, std::string(TRIG_RULE_REF_KEY_PREFIX) + std::string(event_data_key)); + IF_FAIL_RETURN(error == ERR_NONE, error); + + // Set reference information + ret = ctx::rule_validator::set_ref_info(TYPE_ATTRIBUTE, &(entry->jref), name, key, event_data_key); + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_OPERATION_FAILED); + + return CONTEXT_TRIGGER_ERROR_NONE; +} + +SO_EXPORT int context_trigger_rule_entry_add_comparison_int(context_trigger_rule_entry_h entry, const char* key, const char* op, int value) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(entry && key && op); + + std::string name; + (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); + + bool ret = ctx::rule_validator::check_comparison_int(name, key, op, value); + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + + int error = context_trigger_rule_entry_add_comparison_int_internal(entry, key, op, value); + return error; +} +/* +SO_EXPORT int context_trigger_rule_entry_add_comparison_double(context_trigger_rule_entry_h entry, const char* key, const char* op, double value) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(entry && key && op); + + std::string name; + (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); + + // TODO: check_comparison_double() + bool ret = ctx::rule_validator::check_comparison_double(name, key, op, value); + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + + int error = context_trigger_rule_entry_add_comparison_internal(entry, key, op, double_to_string(value)); + return error; +} +*/ +SO_EXPORT int context_trigger_rule_entry_add_comparison_string(context_trigger_rule_entry_h entry, const char* key, const char* op, const char* value) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(entry && key && op && value); + + std::string name; + (entry->jentry).get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); + + bool ret = ctx::rule_validator::check_comparison_string(name, key, op, value); + IF_FAIL_RETURN(ret, CONTEXT_TRIGGER_ERROR_INVALID_RULE); + + int error = context_trigger_rule_entry_add_comparison_string_internal(entry, key, op, value); + return error; +} + +SO_EXPORT int context_trigger_custom_register(const char* name, const char* attr_template) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(name && attr_template); + + // Err: Invalid CtxJson1 + ctx::CtxJson1 jattr_template = attr_template; + IF_FAIL_RETURN_TAG(jattr_template.valid(), CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Failed to parse template"); + + // Err: Invalid template + bool ret = ctx::rule_validator::is_valid_template(jattr_template); + IF_FAIL_RETURN_TAG(ret, CONTEXT_TRIGGER_ERROR_INVALID_DATA, _E, "Invalid template"); + + ctx::CtxJson1 data; + data.set(NULL, TRIG_CUSTOM_KEY_REQ, TRIG_CUSTOM_REQ_ADD); + data.set(NULL, TRIG_CUSTOM_KEY_NAME, name); + data.set(NULL, TRIG_TMPL_KEY_ATTRIBUTE, jattr_template); + + int error = __dbusClient.write(SUBJ_TRIGGER_CUSTOM, data, NULL); + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to add custom item: %#x", error); + + return error; +} + +SO_EXPORT int context_trigger_custom_unregister(const char* name) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(name); + + ctx::CtxJson1 data; + data.set(NULL, TRIG_CUSTOM_KEY_REQ, TRIG_CUSTOM_REQ_REMOVE); + data.set(NULL, TRIG_CUSTOM_KEY_NAME, name); + + ctx::CtxJson1 subj; + int error = __dbusClient.write(SUBJ_TRIGGER_CUSTOM, data, &subj); + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to remove custom item: %#x", error); + + std::string subject; + subj.get(NULL, TRIG_TMPL_KEY_SUBJECT, &subject); + ctx::rule_validator::remove_template(subject); + + return error; +} + +SO_EXPORT int context_trigger_custom_publish(const char* name, const char* fact) +{ + _D("BEGIN"); + ASSERT_NOT_NULL(name && fact); + + // Err: Invalid CtxJson1 + ctx::CtxJson1 jfact = fact; + IF_FAIL_RETURN_TAG(jfact.valid(), CONTEXT_TRIGGER_ERROR_INVALID_PARAMETER, _E, "Cannot parse fact CtxJson1"); + + ctx::CtxJson1 data; + data.set(NULL, TRIG_CUSTOM_KEY_REQ, TRIG_CUSTOM_REQ_PUBLISH); + data.set(NULL, TRIG_CUSTOM_KEY_NAME, name); + data.set(NULL, TRIG_CUSTOM_KEY_FACT, jfact); + + int error = __dbusClient.write(SUBJ_TRIGGER_CUSTOM, data, NULL); + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to publish custom data"); + + return error; +} + +std::string convert_event_to_string(context_trigger_event_e item) +{ + std::string str; + switch (item) { + case CONTEXT_TRIGGER_EVENT_TIME: + str = SUBJ_STATE_ALARM; + break; + case CONTEXT_TRIGGER_EVENT_BATTERY: + str = SUBJ_STATE_BATTERY; + break; + case CONTEXT_TRIGGER_EVENT_CHARGER: + str = SUBJ_STATE_CHARGER; + break; + case CONTEXT_TRIGGER_EVENT_GPS: + str = SUBJ_STATE_GPS; + break; + case CONTEXT_TRIGGER_EVENT_HEADPHONE: + str = SUBJ_STATE_HEADPHONE; + break; + case CONTEXT_TRIGGER_EVENT_POWER_SAVING_MODE: + str = SUBJ_STATE_PSMODE; + break; + case CONTEXT_TRIGGER_EVENT_USB: + str = SUBJ_STATE_USB; + break; + case CONTEXT_TRIGGER_EVENT_WIFI: + str = SUBJ_STATE_WIFI; + break; + case CONTEXT_TRIGGER_EVENT_CALL: + str = SUBJ_STATE_CALL; + break; + case CONTEXT_TRIGGER_EVENT_EMAIL: + str = SUBJ_STATE_EMAIL; + break; + case CONTEXT_TRIGGER_EVENT_MESSAGE: + str = SUBJ_STATE_MESSAGE; + break; + case CONTEXT_TRIGGER_EVENT_CONTACTS: + str = SUBJ_STATE_CONTACTS; + break; + case CONTEXT_TRIGGER_EVENT_ACTIVITY_STATIONARY: + str = SUBJ_ACTIVITY_STATIONARY; + break; + case CONTEXT_TRIGGER_EVENT_ACTIVITY_WALKING: + str = SUBJ_ACTIVITY_WALKING; + break; + case CONTEXT_TRIGGER_EVENT_ACTIVITY_RUNNING: + str = SUBJ_ACTIVITY_RUNNING; + break; + case CONTEXT_TRIGGER_EVENT_ACTIVITY_IN_VEHICLE: + str = SUBJ_ACTIVITY_IN_VEHICLE; + break; + case CONTEXT_TRIGGER_EVENT_PLACE: + str = SUBJ_PLACE_GEOFENCE; + break; + default: + break; + } + return str; +} + +std::string convert_condition_to_string(context_trigger_condition_e item) +{ + std::string str; + switch (item) { + case CONTEXT_TRIGGER_CONDITION_TIME: + str = SUBJ_STATE_TIME; + break; + case CONTEXT_TRIGGER_CONDITION_BATTERY: + str = SUBJ_STATE_BATTERY; + break; + case CONTEXT_TRIGGER_CONDITION_CHARGER: + str = SUBJ_STATE_CHARGER; + break; + case CONTEXT_TRIGGER_CONDITION_GPS: + str = SUBJ_STATE_GPS; + break; + case CONTEXT_TRIGGER_CONDITION_HEADPHONE: + str = SUBJ_STATE_HEADPHONE; + break; + case CONTEXT_TRIGGER_CONDITION_POWER_SAVING_MODE: + str = SUBJ_STATE_PSMODE; + break; + case CONTEXT_TRIGGER_CONDITION_USB: + str = SUBJ_STATE_USB; + break; + case CONTEXT_TRIGGER_CONDITION_WIFI: + str = SUBJ_STATE_WIFI; + break; + case CONTEXT_TRIGGER_CONDITION_CALL: + str = SUBJ_STATE_CALL; + break; + case CONTEXT_TRIGGER_CONDITION_APP_USE_FREQUENCY: + str = SUBJ_APP_FREQUENCY; + break; + case CONTEXT_TRIGGER_CONDITION_COMMUNICATION_FREQUENCY: + str = SUBJ_SOCIAL_FREQUENCY; + break; + case CONTEXT_TRIGGER_CONDITION_MUSIC_PLAYBACK_FREQUENCY: + str = SUBJ_MUSIC_FREQUENCY; + break; + case CONTEXT_TRIGGER_CONDITION_VIDEO_PLAYBACK_FREQUENCY: + str = SUBJ_VIDEO_FREQUENCY; + break; + default: + break; + } + return str; +} + +std::string convert_logical_type_to_string(context_trigger_logical_type_e logical_type) +{ + std::string str; + switch (logical_type) { + case CONTEXT_TRIGGER_LOGICAL_CONJUNCTION: + str = TRIG_RULE_LOGICAL_CONJUNCTION; + break; + case CONTEXT_TRIGGER_LOGICAL_DISJUNCTION: + str = TRIG_RULE_LOGICAL_DISJUNCTION; + break; + default: + break; + } + return str; +} + +std::string get_custom_item_subject(const char* provider, const char* item) +{ + std::string subject_name = std::string(TRIG_CUSTOM_PREFIX TRIG_SUBJECT_SEPERATOR) + provider + std::string(TRIG_SUBJECT_SEPERATOR) + item; + return subject_name; +} + +bool event_is_deprecated(context_trigger_event_e item) +{ + bool ret = false; + switch (item) { + case CONTEXT_TRIGGER_EVENT_TIME: + case CONTEXT_TRIGGER_EVENT_POWER_SAVING_MODE: + case CONTEXT_TRIGGER_EVENT_CALL: + case CONTEXT_TRIGGER_EVENT_EMAIL: + case CONTEXT_TRIGGER_EVENT_MESSAGE: + ret = true; + break; + default: + break; + } + return ret; +} + +bool condition_is_deprecated(context_trigger_condition_e item) +{ + bool ret = false; + switch (item) { + case CONTEXT_TRIGGER_CONDITION_POWER_SAVING_MODE: + case CONTEXT_TRIGGER_CONDITION_CALL: + case CONTEXT_TRIGGER_CONDITION_APP_USE_FREQUENCY: + case CONTEXT_TRIGGER_CONDITION_COMMUNICATION_FREQUENCY: + case CONTEXT_TRIGGER_CONDITION_MUSIC_PLAYBACK_FREQUENCY: + case CONTEXT_TRIGGER_CONDITION_VIDEO_PLAYBACK_FREQUENCY: + ret = true; + break; + default: + break; + } + return ret; +} + +/* +std::string int_to_string(int value) +{ + std::ostringstream ostr; + ostr << value; + return ostr.str(); +} + +std::string double_to_string(int value) +{ + std::ostringstream ostr; + ostr.imbue(std::locale("C")); + ostr << std::setprecision(DOUBLE_PRECISION) << std::fixed << value; + return ostr.str(); +}*/ diff --git a/src/trigger/rule_util.cpp b/src/trigger/rule_util.cpp new file mode 100644 index 0000000..f57de01 --- /dev/null +++ b/src/trigger/rule_util.cpp @@ -0,0 +1,254 @@ +/* + * 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 +#include +#include +#include "rule_validator.h" +#include "rule_util.h" +#include "ComparisonConverter.h" +#include "IntComparisonConverter.h" +#include "StringComparisonConverter.h" + +using namespace ctx; + +static bool __handleTimerEvent(CtxJson1& event); +static int __arrangeDayOfWeek(CtxJson1& dayInfo); + +int ctx::rule_util::setEvent(CtxJson1& entry, CtxJson1* rule) +{ + CtxJson1 tempEvent; + std::string subject; + entry.get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &subject); + + CtxJson1 option; + entry.get(NULL, OLD_TRIG_RULE_KEY_EVENT_OPTION, &option); + tempEvent.set(subject.c_str(), TRIG_RULE_KEY_OPTION, option); + + CtxJson1 elem; + for (int i = 0; entry.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { + CtxJson1 newElem; + + std::string key; + elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &key); + + std::string type = ctx::rule_validator::get_data_type_from_template(TRIG_TMPL_KEY_ATTRIBUTE, subject, key); + + ComparisonConverter* converter = NULL; + if (type == TRIG_TMPL_TYPE_INTEGER) { + converter = new(std::nothrow) IntComparisonConverter(elem); + } else if (type == TRIG_TMPL_TYPE_STRING || type == TRIG_TMPL_TYPE_ENUM) { + converter = new(std::nothrow) StringComparisonConverter(elem); + } + IF_FAIL_RETURN_TAG(converter, ERR_OUT_OF_MEMORY, _E, "Failed to create comparison converter"); + converter->getResult(&newElem); + + CtxJson1 detail; + newElem.get(NULL, key.c_str(), &detail); + + std::string path = subject + "." + TRIG_RULE_KEY_COMPARISON; + tempEvent.set(path.c_str(), key.c_str(), detail); + delete converter; + } + + // Handle Timer Event + if (subject.compare(SUBJ_STATE_ALARM) == 0) { + IF_FAIL_RETURN(__handleTimerEvent(tempEvent), ERR_INVALID_RULE); + } + + rule->set(NULL, TRIG_RULE_KEY_EVENT, tempEvent); + + // Save event entry's logical to extra info (default and) + std::string eventOp = TRIG_RULE_LOGICAL_CONJUNCTION; + if (entry.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_ARR) > 1) { + entry.get(NULL, OLD_TRIG_RULE_KEY_EVENT_OPERATOR, &eventOp); + } + rule->set(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_EVENT_LOGICAL_OP, eventOp); + + return ERR_NONE; +} + +int ctx::rule_util::addCondition(CtxJson1& entry, CtxJson1* rule) +{ + CtxJson1 tempCond; + std::string subject; + entry.get(NULL, OLD_TRIG_RULE_KEY_CONDITION_ITEM, &subject); + + CtxJson1 option; + entry.get(NULL, OLD_TRIG_RULE_KEY_CONDITION_OPTION, &option); + tempCond.set(subject.c_str(), TRIG_RULE_KEY_OPTION, option); + + CtxJson1 elem; + for (int i = 0; entry.getAt(NULL, OLD_TRIG_RULE_KEY_DATA_ARR, i, &elem); i++) { + CtxJson1 newElem; + + std::string key; + elem.get(NULL, OLD_TRIG_RULE_KEY_DATA_KEY, &key); + + std::string type = ctx::rule_validator::get_data_type_from_template(TRIG_TMPL_KEY_ATTRIBUTE, subject, key); + + ComparisonConverter* converter = NULL; + if (type == TRIG_TMPL_TYPE_INTEGER) { + converter = new(std::nothrow) IntComparisonConverter(elem); + } else if (type == TRIG_TMPL_TYPE_STRING || type == TRIG_TMPL_TYPE_ENUM) { + converter = new(std::nothrow) StringComparisonConverter(elem); + } + IF_FAIL_RETURN_TAG(converter, ERR_OUT_OF_MEMORY, _E, "Failed to create comparison converter"); + converter->getResult(&newElem); + + tempCond.set(subject.c_str(), TRIG_RULE_KEY_COMPARISON, newElem); + delete converter; + } + + rule->append(NULL, TRIG_RULE_KEY_CONDITION, tempCond); + + // Save event entry's logical to extra info (default and) + std::string condOp = TRIG_RULE_LOGICAL_CONJUNCTION; + if (entry.getSize(NULL, OLD_TRIG_RULE_KEY_DATA_ARR) > 1) { + entry.get(NULL, OLD_TRIG_RULE_KEY_CONDITION_OPERATOR, &condOp); + } + rule->append(_TRIG_RULE_KEY_EXTRA, _TRIG_RULE_KEY_CONDITION_LOGICAL_OP, condOp); + + return ERR_NONE; +} + +bool __handleTimerEvent(CtxJson1& event) +{ + CtxJson1 alarmComp; + bool ret = event.get(SUBJ_STATE_ALARM, TRIG_RULE_KEY_COMPARISON, &alarmComp); + IF_FAIL_RETURN_TAG(ret, false, _E, "Invalid EVENT_TIME event"); + + // Day processing + CtxJson1 dayInfo; + bool daySpecified = alarmComp.get(NULL, KEY_DAY_OF_WEEK, &dayInfo); + + if (daySpecified) { + CtxJson1 newDayInfo; + newDayInfo.set(NULL, TRIG_RULE_KEY_OPERATOR, TRIG_RULE_OP_ONE_OF); + + int dow = __arrangeDayOfWeek(dayInfo); + IF_FAIL_RETURN_TAG(dow > 0, false, _E, "Invalid DayOfWeek info for EVENT_TIME"); + + for (int i = 0 ; i < DAYS_PER_WEEK; i++) { + int d = 0x01 << i; + if (dow & d) { + std::string day = TimerManager::dowToStr(d); + newDayInfo.append(NULL, TRIG_RULE_KEY_VALUE, day); + + // Copy details as option + event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, day); + } + } + event.set(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_COMPARISON, KEY_DAY_OF_WEEK, newDayInfo); + } else { + // If DayOfWeek is not specified, regard it as Mon ~ Sun + event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_MON); + event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_TUE); + event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_WED); + event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_THU); + event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_FRI); + event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_SAT); + event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_DAY_OF_WEEK, CONTEXT_TRIGGER_SUN); + } + + // Time processing + CtxJson1 timeInfo; + alarmComp.get(NULL, KEY_TIME_OF_DAY, &timeInfo); + + int time; + std::string timeOp; + timeInfo.get(NULL, TRIG_RULE_KEY_OPERATOR, &timeOp); + + if (timeOp == TRIG_RULE_OP_EQUAL_TO) { + timeInfo.get(NULL, TRIG_RULE_KEY_VALUE, &time); + event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_TIME_OF_DAY, time); + } else if (timeOp == TRIG_RULE_OP_ONE_OF) { + for (int i = 0; timeInfo.getAt(NULL, TRIG_RULE_KEY_VALUE, i, &time); i++) { + event.append(SUBJ_STATE_ALARM "." TRIG_RULE_KEY_OPTION, KEY_TIME_OF_DAY, time); + } + } + + return true; +} + +int __arrangeDayOfWeek(CtxJson1& dayInfo) +{ + std::string dayOp; + if (!dayInfo.get(NULL, TRIG_RULE_KEY_OPERATOR, &dayOp)) { + return TimerManager::dowToInt(DOW_EVERYDAY); + } + + int result = 0; + if (dayOp == TRIG_RULE_OP_NOT_EQUAL_TO || dayOp == TRIG_RULE_OP_NOT_IN) { + result = TimerManager::dowToInt(DOW_EVERYDAY); + } + + int dow; + std::string day; + if (dayOp == TRIG_RULE_OP_EQUAL_TO) { + dayInfo.get(NULL, TRIG_RULE_KEY_VALUE, &day); + dow = TimerManager::dowToInt(day); + result |= dow; + } else if (dayOp == TRIG_RULE_OP_NOT_EQUAL_TO) { + dayInfo.get(NULL, TRIG_RULE_KEY_VALUE, &day); + dow = TimerManager::dowToInt(day); + dow = TimerManager::dowToInt(DOW_EVERYDAY) & ~dow; + result &= dow; + } else if (dayOp == TRIG_RULE_OP_ONE_OF) { + for (int i = 0; dayInfo.getAt(NULL, TRIG_RULE_KEY_VALUE, i, &day); i++) { + dow = TimerManager::dowToInt(day); + result |= dow; + } + } else if (dayOp == TRIG_RULE_OP_NONE_OF) { + for (int i = 0; dayInfo.getAt(NULL, TRIG_RULE_KEY_VALUE, i, &day); i++) { + dow = TimerManager::dowToInt(day); + dow = TimerManager::dowToInt(DOW_EVERYDAY) & ~dow; + result &= dow; + } + } + + _D("Requested day of week (%#x)", result); + return result; +} + +bool ctx::rule_util::isEventSet(CtxJson1& rule) +{ + ctx::CtxJson1 event; + if (rule.get(NULL, TRIG_RULE_KEY_EVENT, &event)) { + if (event != EMPTY_JSON_OBJECT) { + return true; + } + } + + return false; +} + +bool ctx::rule_util::isActionSet(CtxJson1& rule) +{ + ctx::CtxJson1 action; + if (rule.get(NULL, TRIG_RULE_KEY_ACTION, &action)) { + if (action != EMPTY_JSON_OBJECT) { + return true; + } + } + + return false; +} diff --git a/src/trigger/rule_util.h b/src/trigger/rule_util.h new file mode 100644 index 0000000..d4443bb --- /dev/null +++ b/src/trigger/rule_util.h @@ -0,0 +1,34 @@ +/* + * 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_RULE_UTIL_H__ +#define __CONTEXT_RULE_UTIL_H__ + +#include + +namespace ctx { + + namespace rule_util { + + int setEvent(CtxJson1& entry, CtxJson1* rule); + int addCondition(CtxJson1& entry, CtxJson1* rule); + bool isEventSet(CtxJson1& rule); + bool isActionSet(CtxJson1& rule); + + } +} /* namespace ctx */ + +#endif /* __CONTEXT_RULE_UTIL_H__ */ diff --git a/src/trigger/rule_validator.cpp b/src/trigger/rule_validator.cpp new file mode 100644 index 0000000..6f37448 --- /dev/null +++ b/src/trigger/rule_validator.cpp @@ -0,0 +1,545 @@ +/* + * Copyright (c) 2015 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 +#include +#include "DBusClient.h" +#include "TriggerOldRuleTypes.h" +#include "rule_validator.h" + +using namespace ctx; + +#define RULE_VALIDATOR_COND_NAME "name" +#define RULE_VALIDATOR_KEY "key" +#define RULE_VALIDATOR_TYPE "type" +#define RULE_VALIDATOR_REF "ref" + +typedef std::map template_map_t; +template_map_t template_map; // + +static int string_to_int(std::string str); +static bool check_value_int(CtxJson1& tmpl, std::string key, int value); +static bool check_value_string(CtxJson1& tmpl, std::string key, std::string value); +static bool check_value_enum(CtxJson1& tmpl, std::string key, std::string value); +static CtxJson1 get_template(std::string name); +static bool check_template_int(CtxJson1& elem); +static bool check_template_string(CtxJson1& elem); +static bool check_template_enum(CtxJson1& elem); +static std::string get_data_type(CtxJson1& elem, std::string& key); +static bool is_equal_type(std::string& type1, std::string& type2); + +int string_to_int(std::string str) +{ + int i; + std::istringstream convert(str); + + if (!(convert >> i)) + i = 0; + + return i; +} + +CtxJson1 get_template(std::string name) +{ + rule_validator::request_template(name); + return template_map[name]; +} + +int rule_validator::request_template(std::string name, bool mandatory) +{ + if (!mandatory) { + template_map_t::iterator it = template_map.find(name); + IF_FAIL_RETURN(it == template_map.end(), ERR_NONE); + } + + // Request template + CtxJson1 request; + request.set(NULL, TRIG_TMPL_KEY_SUBJECT, name); + + int req_id; + CtxJson1 tmpl; + DBusClient dbusClient; + int error = dbusClient.readSync(SUBJ_TRIGGER_GET_TEMPLATE, request, &req_id, &tmpl); + if (error == ERR_NOT_SUPPORTED) { + template_map.erase(name); + _E("Failed to get request: not supported"); + return ERR_NOT_SUPPORTED; + } + IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to get request"); + + template_map[name] = tmpl; + + return ERR_NONE; +} + +void rule_validator::remove_template(std::string name) +{ + template_map.erase(name); +} + +// called by context_trigger_rule_add_entry() +bool rule_validator::check_option(CtxJson1& item) +{ + std::string name; + item.get(NULL, OLD_TRIG_RULE_KEY_EVENT_ITEM, &name); + + CtxJson1 tmpl = get_template(name); + IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); + + // No option needed + CtxJson1 opt_tmpl; + tmpl.get(NULL, TRIG_TMPL_KEY_OPTION, &opt_tmpl); + + std::list opt_keys; + IF_FAIL_RETURN(opt_tmpl.getKeys(&opt_keys), false); + if (opt_keys.size() <= 0) { + return true; + } + + // Err: Check if mandatory option is missed + std::string val_str; + int val; + if (name == SUBJ_PLACE_GEOFENCE) { + if (!(item.get(OLD_TRIG_RULE_KEY_EVENT_OPTION, CONTEXT_TRIGGER_PLACE_ID, &val))) + return false; + } else if (name == SUBJ_APP_FREQUENCY) { + if (!(item.get(OLD_TRIG_RULE_KEY_CONDITION_OPTION, CONTEXT_TRIGGER_APP_ID, &val_str))) + return false; + } else if (name == SUBJ_SOCIAL_FREQUENCY) { + if (!(item.get(OLD_TRIG_RULE_KEY_CONDITION_OPTION, CONTEXT_TRIGGER_ADDRESS, &val_str))) + return false; + } + + return true; +} + +// called by context_trigger_rule_entry_add_option_int() +bool rule_validator::check_option_int(std::string name, std::string key, int value) +{ + CtxJson1 tmpl = get_template(name); + IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); + + CtxJson1 opt_tmpl; + tmpl.get(NULL, TRIG_TMPL_KEY_OPTION, &opt_tmpl); + + // Err: Item with no option + std::list opt_keys; + IF_FAIL_RETURN(opt_tmpl.getKeys(&opt_keys), false); + IF_FAIL_RETURN(opt_keys.size() > 0, false); + + // Err: Invalid option key or Invalid value type + std::string t_type = get_data_type(opt_tmpl, key); + IF_FAIL_RETURN(t_type == TRIG_TMPL_TYPE_INTEGER, false); + + // Err: Inappropriate value + // a. normal case + bool ret = check_value_int(opt_tmpl, key, value); + IF_FAIL_RETURN(ret, false); + + return true; +} + +// called by context_trigger_rule_entry_add_option_string() +bool rule_validator::check_option_string(std::string name, std::string key, std::string value) +{ + CtxJson1 tmpl = get_template(name); + IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); + + CtxJson1 opt_tmpl; + tmpl.get(NULL, TRIG_TMPL_KEY_OPTION, &opt_tmpl); + + // Err: ';' for SQL injection + IF_FAIL_RETURN(value.find(';') == std::string::npos, false); + + // Err: Item with no option + std::list opt_keys; + IF_FAIL_RETURN(opt_tmpl.getKeys(&opt_keys), false); + IF_FAIL_RETURN(opt_keys.size() > 0, false); + + // Err: Invalid option key or Invalid value type + std::string t_type = get_data_type(opt_tmpl, key); + IF_FAIL_RETURN(t_type == TRIG_TMPL_TYPE_STRING || t_type == TRIG_TMPL_TYPE_ENUM, false); + + // Err: Inappropriate value + // a. spacial case + if (t_type == TRIG_TMPL_TYPE_STRING && (name == SUBJ_APP_FREQUENCY || name == SUBJ_SOCIAL_FREQUENCY + || name == SUBJ_MUSIC_FREQUENCY || name == SUBJ_VIDEO_FREQUENCY) + && key == CONTEXT_TRIGGER_TIME_OF_DAY) { + std::size_t found = value.find("-"); + if (found == std::string::npos) { + return false; + } + + int t1 = string_to_int(value.substr(0, found-1)); + int t2 = string_to_int(value.substr(found+1, value.length()-1)); + + if (!(t1 >= 0 && t1 < 24) || !(t2 >= 0 && t2 < 24)) { + return false; + } + + if (t1 >= t2) { + return false; + } + + return true; + } + + // b. normal case + bool ret = false; + if (t_type == TRIG_TMPL_TYPE_STRING) { + ret = check_value_string(opt_tmpl, key, value); + } else if (t_type == TRIG_TMPL_TYPE_ENUM) { + ret = check_value_enum(opt_tmpl, key, value); + } + + return ret; +} + +// called by context_trigger_rule_entry_add_comparison_int() +bool rule_validator::check_comparison_int(std::string name, std::string key, std::string op, int value) +{ + CtxJson1 tmpl = get_template(name); + IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); + + CtxJson1 attr_tmpl; + tmpl.get(NULL, TRIG_TMPL_KEY_ATTRIBUTE, &attr_tmpl); + + // Err: Invalid attribute key or Invalid value type + std::string t_type = get_data_type(attr_tmpl, key); + IF_FAIL_RETURN(t_type == TRIG_TMPL_TYPE_INTEGER, false); + + // Err: Invalid operator for the value + // a. normal case + bool ret = is_valid_operator(TRIG_TMPL_TYPE_INTEGER, op); + IF_FAIL_RETURN(ret, false); + // b. special case + if (name == SUBJ_STATE_ALARM && key == CONTEXT_TRIGGER_TIME_OF_DAY) { + IF_FAIL_RETURN(op == CONTEXT_TRIGGER_EQUAL_TO, false); + } + + // Err: Inappropriate value + // a. normal case + ret = check_value_int(attr_tmpl, key, value); + IF_FAIL_RETURN(ret, false); + + return true; +} + +// called by context_trigger_rule_entry_add_comparison_string() +bool rule_validator::check_comparison_string(std::string name, std::string key, std::string op, std::string value) +{ + CtxJson1 tmpl = get_template(name); + IF_FAIL_RETURN(tmpl != CtxJson1(EMPTY_JSON_OBJECT), false); + + CtxJson1 attr_tmpl; + tmpl.get(NULL, TRIG_TMPL_KEY_ATTRIBUTE, &attr_tmpl); + + // Err: ';' for SQL injection + IF_FAIL_RETURN(value.find(';') == std::string::npos, false); + + // Err: Invalid option key or Invalid value type + std::string t_type = get_data_type(attr_tmpl, key); + IF_FAIL_RETURN(t_type == TRIG_TMPL_TYPE_STRING || t_type == TRIG_TMPL_TYPE_ENUM, false); + + // Err: Invalid operator for the value + bool ret = is_valid_operator(t_type, op); + IF_FAIL_RETURN(ret, false); + + // Err: Inappropriate value + // a. normal case + if (t_type == TRIG_TMPL_TYPE_STRING) { + ret = check_value_string(attr_tmpl, key, value); + IF_FAIL_RETURN(ret, false); + } else if (t_type == TRIG_TMPL_TYPE_ENUM) { + ret = check_value_enum(attr_tmpl, key, value); + IF_FAIL_RETURN(ret, false); + } + + return true; +} + +bool rule_validator::check_valid_key(std::string type, std::string name, std::string key) +{ + CtxJson1 tmpl = get_template(name); + IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); + + // Err: Invalid key + CtxJson1 tmp; + bool ret = tmpl.get(type.c_str(), key.c_str(), &tmp); + IF_FAIL_RETURN(ret, false); + + return true; +} + +bool check_value_int(CtxJson1& tmpl, std::string key, int value) +{ + int min, max; + + if (tmpl.get(key.c_str(), TRIG_TMPL_KEY_MIN, &min)) { + IF_FAIL_RETURN(value >= min, false); + } + + if (tmpl.get(key.c_str(), TRIG_TMPL_KEY_MAX, &max)) { + IF_FAIL_RETURN(value <= max, false); + } + + return true; +} + +bool check_value_string(CtxJson1& tmpl, std::string key, std::string value) +{ + return true; +} + +bool check_value_enum(CtxJson1& tmpl, std::string key, std::string value) +{ + std::string t_val; + for (int i = 0; tmpl.getAt(key.c_str(), TRIG_TMPL_TYPE_ENUM, i, &t_val); i++) { + if (t_val == value) + return true; + } + + return false; +} + +// called by context_trigger_rule_entry_add_comparison() +// called by context_trigger_rule_entry_add_option() +bool rule_validator::set_ref_info(std::string type, CtxJson1* jref, std::string name, std::string key, std::string ref_data) +{ + CtxJson1 tmpl = get_template(name); + IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, false); + + CtxJson1 detailed_tmpl; + tmpl.get(NULL, type.c_str(), &detailed_tmpl); + + std::string dt = get_data_type(detailed_tmpl, key); + IF_FAIL_RETURN(dt == TRIG_TMPL_TYPE_INTEGER || dt == TRIG_TMPL_TYPE_STRING || dt == TRIG_TMPL_TYPE_ENUM, false); + + CtxJson1 temp; + temp.set(NULL, RULE_VALIDATOR_COND_NAME, name); + temp.set(NULL, RULE_VALIDATOR_KEY, key); + temp.set(NULL, RULE_VALIDATOR_TYPE, dt); + temp.set(NULL, RULE_VALIDATOR_REF, ref_data); + + if (type == TRIG_TMPL_KEY_OPTION) { + jref->append(NULL, TRIG_TMPL_KEY_OPTION, temp); + } else if (type == TRIG_TMPL_KEY_ATTRIBUTE) { + jref->append(NULL, TRIG_TMPL_KEY_ATTRIBUTE, temp); + } else { + return false; + } + + return true;; +} + +std::string get_data_type(CtxJson1& elem, std::string& key) +{ + std::string data_type; + bool ret = elem.get(key.c_str(), TRIG_TMPL_KEY_TYPE, &data_type); + if (!ret) { + int size = elem.getSize(key.c_str(), TRIG_TMPL_TYPE_ENUM); + IF_FAIL_RETURN(size > 0, ""); + data_type = TRIG_TMPL_TYPE_ENUM; + } + IF_FAIL_RETURN(data_type == TRIG_TMPL_TYPE_INTEGER || data_type == TRIG_TMPL_TYPE_STRING || data_type == TRIG_TMPL_TYPE_ENUM, ""); + + return data_type; +} + +// called by context_trigger_rule_entry_add_comparison() +std::string rule_validator::get_data_type_from_template(std::string type, std::string name, std::string key) +{ + CtxJson1 tmpl = get_template(name); + IF_FAIL_RETURN(tmpl != EMPTY_JSON_OBJECT, ""); + + CtxJson1 detailed_tmpl; + tmpl.get(NULL, type.c_str(), &detailed_tmpl); + + return get_data_type(detailed_tmpl, key); +} + +// called by context_trigger_rule_add_entry() +bool rule_validator::check_referential_data(std::string name, CtxJson1& ref_info) +{ + std::map type_map; + + CtxJson1 ref_data; + for (int i = 0; ref_info.getAt(NULL, TRIG_TMPL_KEY_OPTION, i, &ref_data); i++) { + std::string ref_key; + ref_data.get(NULL, RULE_VALIDATOR_REF, &ref_key); + std::string cond_type; + ref_data.get(NULL, RULE_VALIDATOR_TYPE, &cond_type); + + if (type_map.count(ref_key) == 0) { + type_map[ref_key] = get_data_type_from_template(TRIG_TMPL_KEY_ATTRIBUTE, name, ref_key); // "", if invalid key + } + + // Err: Invalid key or Value type not matched + IF_FAIL_RETURN(is_equal_type(cond_type, type_map[ref_key]), false); + } + + for (int i = 0; ref_info.getAt(NULL, TRIG_TMPL_KEY_ATTRIBUTE, i, &ref_data); i++) { + std::string ref_key; + ref_data.get(NULL, RULE_VALIDATOR_REF, &ref_key); + std::string cond_type; + ref_data.get(NULL, RULE_VALIDATOR_TYPE, &cond_type); + + if (type_map.count(ref_key) == 0) { + type_map[ref_key] = get_data_type_from_template(TRIG_TMPL_KEY_ATTRIBUTE, name, ref_key); // "", if invalid key + } + + // Err: Invalid key or Value type not matched + IF_FAIL_RETURN(is_equal_type(cond_type, type_map[ref_key]), false); + } + + return true; +} + +bool is_equal_type(std::string& type1, std::string& type2) +{ + // This function regards TRIG_TMPL_TYPE_ENUM as TRIG_TMPL_TYPE_STRING for referential data + if (type1 == type2) { + return true; + } + + if ((type1 == TRIG_TMPL_TYPE_STRING || type1 == TRIG_TMPL_TYPE_ENUM) && (type2 == TRIG_TMPL_TYPE_STRING || type2 == TRIG_TMPL_TYPE_ENUM)) { + return true; + } + + return false; +} + +bool rule_validator::is_valid_operator(std::string type, std::string op) +{ + if (op == CONTEXT_TRIGGER_EQUAL_TO || op == CONTEXT_TRIGGER_NOT_EQUAL_TO) { + return true; + } + + if (type == TRIG_TMPL_TYPE_INTEGER || type == TRIG_TMPL_TYPE_DOUBLE) { + if (op == CONTEXT_TRIGGER_GREATER_THAN || op == CONTEXT_TRIGGER_GREATER_THAN_OR_EQUAL_TO || + op == CONTEXT_TRIGGER_LESS_THAN || op == CONTEXT_TRIGGER_LESS_THAN_OR_EQUAL_TO) { + return true; + } + } + + return false; +} + +// For custom item template +bool rule_validator::is_valid_template(CtxJson1& attr_template) +{ + IF_FAIL_RETURN_TAG(attr_template != EMPTY_JSON_OBJECT, false, _E, "Custom template: empty CtxJson1"); + + bool ret; + std::list keys; + attr_template.getKeys(&keys); + + for (std::list::iterator it = keys.begin(); it != keys.end(); it++) { + std::string key = *it; + + std::string type = get_data_type(attr_template, key); + IF_FAIL_RETURN_TAG(type == TRIG_TMPL_TYPE_INTEGER || type == TRIG_TMPL_TYPE_STRING || type == TRIG_TMPL_TYPE_ENUM, + false, _E, "Custom template: invalid data type"); + + CtxJson1 elem; + attr_template.get(NULL, key.c_str(), &elem); + if (type == TRIG_TMPL_TYPE_INTEGER) { + ret = check_template_int(elem); + IF_FAIL_RETURN(ret, false); + } else if (type == TRIG_TMPL_TYPE_STRING) { + ret = check_template_string(elem); + IF_FAIL_RETURN(ret, false); + } else if (type == TRIG_TMPL_TYPE_ENUM) { + ret = check_template_enum(elem); + IF_FAIL_RETURN(ret, false); + } + } + + return true; +} + +bool check_template_int(CtxJson1& elem) +{ + std::list elem_keys; + elem.getKeys(&elem_keys); + + bool min = false; + bool max = false; + int min_val = 0; + int max_val = 0; + + for (std::list::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) { + std::string elem_key = *it2; + if (elem_key == TRIG_TMPL_KEY_MIN) { + min = elem.get(NULL, elem_key.c_str(), &min_val); + IF_FAIL_RETURN_TAG(min, false, _E, "Custom template: failed to get integer type value"); + } else if (elem_key == TRIG_TMPL_KEY_MAX) { + max = elem.get(NULL, elem_key.c_str(), &max_val); + IF_FAIL_RETURN_TAG(max, false, _E, "Custom template: failed to get integer type value"); + } else { + IF_FAIL_RETURN_TAG(elem_key == TRIG_TMPL_KEY_TYPE, false, _E, "Custom template: invalid key"); + } + } + + if (min && max) { + IF_FAIL_RETURN_TAG(min_val <= max_val, false, _E, "Custom template: invalid min, max value"); + } + + return true; +} + +bool check_template_string(CtxJson1& elem) +{ + std::list elem_keys; + elem.getKeys(&elem_keys); + + for (std::list::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) { + std::string elem_key = *it2; + IF_FAIL_RETURN_TAG(elem_key == TRIG_TMPL_KEY_TYPE, false, _E, "Custom template: invalid key"); + } + + return true; +} + +bool check_template_enum(CtxJson1& elem) +{ + std::list elem_keys; + elem.getKeys(&elem_keys); + + for (std::list::iterator it2 = elem_keys.begin(); it2 != elem_keys.end(); it2++) { + std::string elem_key = *it2; + + if (elem_key == TRIG_TMPL_TYPE_ENUM) { + int size = elem.getSize(NULL, TRIG_TMPL_TYPE_ENUM); + IF_FAIL_RETURN_TAG(size > 0, false, _E, "Custom template: invalid enum"); + + std::string val_str; + for (int i = 0; i < size; i++) { + bool ret = elem.getAt(NULL, TRIG_TMPL_TYPE_ENUM, i, &val_str); + IF_FAIL_RETURN_TAG(ret, false, _E, "Custom template: failed to get string type value"); + } + } else { + IF_FAIL_RETURN_TAG(elem_key == TRIG_TMPL_KEY_TYPE, false, _E, "Custom template: invalid key"); + } + } + + return true; +} diff --git a/src/trigger/rule_validator.h b/src/trigger/rule_validator.h new file mode 100644 index 0000000..688a295 --- /dev/null +++ b/src/trigger/rule_validator.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015 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_RULE_VALIDATOR_H__ +#define __CONTEXT_RULE_VALIDATOR_H__ + +#include + +namespace ctx { + namespace rule_validator { + + int request_template(std::string name, bool mandatory = false); + void remove_template(std::string name); + bool check_option(ctx::CtxJson1 &item); + bool check_option_int(std::string name, std::string key, int value); + bool check_option_string(std::string name, std::string key, std::string value); + bool check_option_reference(std::string event, ctx::CtxJson1 &item); + bool check_comparison_int(std::string name, std::string key, std::string op, int value); + bool check_comparison_string(std::string name, std::string key, std::string op, std::string value); + bool check_valid_key(std::string type, std::string name, std::string key); + + bool set_ref_info(std::string type, ctx::CtxJson1 *jref, std::string name, std::string key, std::string ref_key); + std::string get_data_type_from_template(std::string type, std::string name, std::string key); + bool check_referential_data(std::string name, ctx::CtxJson1 &ref_info); + bool is_valid_operator(std::string type, std::string op); + + bool is_valid_template(ctx::CtxJson1& attr_template); + } +} /* namespace ctx */ + +#endif /* __CONTEXT_RULE_VALIDATOR_H__ */