• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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