1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific locale governing permissions and
13 * limitations under the License.
14 */
15 #include "rules_engine.h"
16 #include <algorithm>
17 #include "hilog/log.h"
18
19 namespace OHOS {
20 namespace Global {
21 namespace I18n {
22 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD001E00, "RulesEngine" };
23 using namespace OHOS::HiviewDFX;
24
RulesEngine()25 RulesEngine::RulesEngine()
26 {
27 }
28
RulesEngine(DateTimeRule * dateTimeRule,RulesSet & rulesSet)29 RulesEngine::RulesEngine(DateTimeRule* dateTimeRule, RulesSet& rulesSet)
30 {
31 this->dateTimeRule = dateTimeRule;
32 this->rulesMap = rulesSet.rulesMap;
33 this->subRules = rulesSet.subRules;
34 this->param = rulesSet.param;
35 this->paramBackup = rulesSet.paramBackup;
36 Init();
37 }
38
~RulesEngine()39 RulesEngine::~RulesEngine()
40 {
41 }
42
43 // match message based on patterns.
Match(icu::UnicodeString & message)44 std::vector<MatchedDateTimeInfo> RulesEngine::Match(icu::UnicodeString& message)
45 {
46 std::vector<MatchedDateTimeInfo> matches;
47 std::vector<std::string> keys;
48 for (auto& kv : this->patterns) {
49 keys.push_back(kv.first);
50 }
51 std::string res;
52 message.toUTF8String(res);
53 for (auto& key : keys) {
54 UErrorCode status = U_ZERO_ERROR;
55 icu::UnicodeString regex = this->patterns[key];
56 icu::RegexPattern* pattern = icu::RegexPattern::compile(regex,
57 URegexpFlag::UREGEX_CASE_INSENSITIVE, status);
58 if (pattern == nullptr) {
59 HiLog::Error(LABEL, "Match failed because pattern is nullptr.");
60 return matches;
61 }
62 icu::RegexMatcher* matcher = pattern->matcher(message, status);
63 if (matcher == nullptr) {
64 HiLog::Error(LABEL, "Match failed because pattern matcher failed.");
65 delete pattern;
66 return matches;
67 }
68 while (matcher->find(status)) {
69 int begin = matcher->start(status);
70 int end = matcher->end(status);
71 MatchedDateTimeInfo match(begin, end, key);
72 matches.push_back(match);
73 }
74 delete matcher;
75 delete pattern;
76 }
77 return matches;
78 }
79
Init()80 void RulesEngine::Init()
81 {
82 for (const auto& rule : rulesMap) {
83 std::string rulesKey = rule.first;
84 std::string rulesValue = rule.second;
85 rulesValue = InitSubRules(rulesValue);
86 rulesValue = InitOptRules(rulesValue);
87 bool isVaild = InitRules(rulesValue);
88 // replace [param_ ] in the rule with the corresponding regular expression.
89 icu::UnicodeString regex = rulesValue.c_str();
90 if (!regex.trim().isEmpty() && isVaild) {
91 this->patterns.insert({rulesKey, regex});
92 }
93 }
94 }
95
InitRules(std::string & rulesValue)96 bool RulesEngine::InitRules(std::string& rulesValue)
97 {
98 bool isVaild = true;
99 if (this->dateTimeRule == nullptr) {
100 HiLog::Error(LABEL, "InitRules failed because this->dateTimeRule is nullptr.");
101 return false;
102 }
103 icu::RegexPattern* pattern = dateTimeRule->GetPatternsMap()["rules"];
104 if (pattern == nullptr) {
105 HiLog::Error(LABEL, "InitRules failed because pattern is nullptr.");
106 return isVaild;
107 }
108 UErrorCode status = U_ZERO_ERROR;
109 if (param.size() != 0 || paramBackup.size() != 0) {
110 icu::UnicodeString rules = rulesValue.c_str();
111 icu::RegexMatcher* matcher = pattern->matcher(rules, status);
112 if (matcher == nullptr) {
113 HiLog::Error(LABEL, "InitRules failed because pattern matcher failed.");
114 return false;
115 }
116 while (matcher->find(status) && isVaild) {
117 icu::UnicodeString value = matcher->group(1, status);
118 std::string valueStr;
119 value.toUTF8String(valueStr);
120 std::string paramValue = this->dateTimeRule->Get(param, valueStr);
121 std::string paramBackupValue = this->dateTimeRule->Get(paramBackup, valueStr);
122 std::string targetStr =
123 (paramValue.length() == 0 && paramBackupValue.length() != 0) ? paramBackupValue : paramValue;
124 targetStr = (paramValue.length() != 0 && paramBackupValue.length() != 0 &&
125 !DateTimeRule::CompareBeginEnd(paramValue, "]", false) &&
126 !DateTimeRule::CompareBeginEnd(paramValue, "]\\b", false)) ?
127 paramValue + "|" + paramBackupValue : targetStr;
128 isVaild = (targetStr.length() == 0) ? false : true;
129 std::string replaceStr = "[" + valueStr + "]";
130 if (DateTimeRule::trim(paramValue).length() != 0) {
131 rulesValue = DateTimeRule::SubReplace(rulesValue, replaceStr, targetStr);
132 }
133 }
134 delete matcher;
135 }
136 return isVaild;
137 }
138
139 // replace [paramopt_ ] in the rule with the corresponding regular expression.
InitOptRules(std::string & rule)140 std::string RulesEngine::InitOptRules(std::string& rule)
141 {
142 std::string rulesValue = rule;
143 icu::UnicodeString matchedStr = rule.c_str();
144 UErrorCode status = U_ZERO_ERROR;
145 if (this->dateTimeRule == nullptr) {
146 HiLog::Error(LABEL, "InitOptRules failed because this->dateTimeRule is nullptr.");
147 return rulesValue;
148 }
149 icu::RegexPattern* pattern = dateTimeRule->GetPatternsMap()["optrules"];
150 if (pattern == nullptr) {
151 HiLog::Error(LABEL, "InitOptRules failed because pattern is nullptr.");
152 return rulesValue;
153 }
154 if (param.size() != 0 || paramBackup.size() != 0) {
155 icu::RegexMatcher* matcher = pattern->matcher(matchedStr, status);
156 if (matcher == nullptr) {
157 HiLog::Error(LABEL, "InitOptRules failed because pattern matcher failed.");
158 return rulesValue;
159 }
160 while (matcher->find(status)) {
161 icu::UnicodeString key = matcher->group(1, status);
162 std::string keyStr;
163 key.toUTF8String(keyStr);
164 std::string value = "param_" + keyStr;
165 int begin = matcher->start(status);
166 int end = matcher->end(status);
167 std::string paramValue = this->dateTimeRule->Get(param, value);
168 std::string paramBackupValue = this->dateTimeRule->Get(paramBackup, value);
169 std::string targetStr = paramValue;
170 if (paramValue.length() == 0 && paramBackupValue.length() != 0) {
171 targetStr = paramBackupValue;
172 } else if (DateTimeRule::trim(paramValue).length() != 0 &&
173 DateTimeRule::trim(paramBackupValue).length() != 0) {
174 targetStr = paramValue + '|' + paramBackupValue;
175 }
176 // if there is not corresponding regular expression, delete [paramopt_ ].
177 if (paramValue.length() == 0 && paramBackupValue.length() == 0) {
178 int rIndex = (rule.substr(begin - 1, 1) == "|") ? begin - 1 : begin;
179 std::string replaceStr1 = rule.substr(rIndex, end - rIndex);
180 rulesValue = DateTimeRule::SubReplace(rulesValue, replaceStr1, "");
181 }
182 std::string replaceStr2 = "[paramopt_" + keyStr + "]";
183 rulesValue = DateTimeRule::SubReplace(rulesValue, replaceStr2, targetStr);
184 }
185 delete matcher;
186 }
187 return rulesValue;
188 }
189
190 // replace [regex_ ] in the rule with the corresponding regular expression.
InitSubRules(std::string & rule)191 std::string RulesEngine::InitSubRules(std::string& rule)
192 {
193 std::string rulesValue = rule;
194 icu::UnicodeString matchedStr = rule.c_str();
195 UErrorCode status = U_ZERO_ERROR;
196 icu::RegexPattern* pattern = dateTimeRule->GetPatternsMap()["subrules"];
197 if (pattern == nullptr) {
198 HiLog::Error(LABEL, "InitSubRules failed because pattern is nullptr.");
199 return rulesValue;
200 }
201 if (subRules.size() != 0) {
202 icu::RegexMatcher* matcher = pattern->matcher(matchedStr, status);
203 if (matcher == nullptr) {
204 HiLog::Error(LABEL, "InitSubRules failed because pattern matcher failed.");
205 return rulesValue;
206 }
207 while (matcher->find(status)) {
208 icu::UnicodeString text = matcher->group(0, status);
209 icu::UnicodeString value = matcher->group(1, status);
210 std::string valueStr;
211 value.toUTF8String(valueStr);
212 std::string targetStr = subRules[valueStr];
213 std::string replaceStr;
214 text.toUTF8String(replaceStr);
215 rulesValue = DateTimeRule::SubReplace(rulesValue, replaceStr, targetStr);
216 }
217 delete matcher;
218 }
219 return rulesValue;
220 }
221 } // namespace I18n
222 } // namespace Global
223 } // namespace OHOS