/* * Copyright (c) 2023 Huawei Device 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 locale governing permissions and * limitations under the License. */ #include "rules_engine.h" #include #include "hilog/log.h" namespace OHOS { namespace Global { namespace I18n { static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD001E00, "RulesEngine" }; using namespace OHOS::HiviewDFX; RulesEngine::RulesEngine() { } RulesEngine::RulesEngine(DateTimeRule* dateTimeRule, RulesSet& rulesSet) { this->dateTimeRule = dateTimeRule; this->rulesMap = rulesSet.rulesMap; this->subRules = rulesSet.subRules; this->param = rulesSet.param; this->paramBackup = rulesSet.paramBackup; Init(); } RulesEngine::~RulesEngine() { } // match message based on patterns. std::vector RulesEngine::Match(icu::UnicodeString& message) { std::vector matches; std::vector keys; for (auto& kv : this->patterns) { keys.push_back(kv.first); } std::string res; message.toUTF8String(res); for (auto& key : keys) { UErrorCode status = U_ZERO_ERROR; icu::UnicodeString regex = this->patterns[key]; icu::RegexPattern* pattern = icu::RegexPattern::compile(regex, URegexpFlag::UREGEX_CASE_INSENSITIVE, status); if (pattern == nullptr) { HiLog::Error(LABEL, "Match failed because pattern is nullptr."); return matches; } icu::RegexMatcher* matcher = pattern->matcher(message, status); if (matcher == nullptr) { HiLog::Error(LABEL, "Match failed because pattern matcher failed."); delete pattern; return matches; } while (matcher->find(status)) { int begin = matcher->start(status); int end = matcher->end(status); MatchedDateTimeInfo match(begin, end, key); matches.push_back(match); } delete matcher; delete pattern; } return matches; } void RulesEngine::Init() { for (const auto& rule : rulesMap) { std::string rulesKey = rule.first; std::string rulesValue = rule.second; rulesValue = InitSubRules(rulesValue); rulesValue = InitOptRules(rulesValue); bool isVaild = InitRules(rulesValue); // replace [param_ ] in the rule with the corresponding regular expression. icu::UnicodeString regex = rulesValue.c_str(); if (!regex.trim().isEmpty() && isVaild) { this->patterns.insert({rulesKey, regex}); } } } bool RulesEngine::InitRules(std::string& rulesValue) { bool isVaild = true; if (this->dateTimeRule == nullptr) { HiLog::Error(LABEL, "InitRules failed because this->dateTimeRule is nullptr."); return false; } icu::RegexPattern* pattern = dateTimeRule->GetPatternsMap()["rules"]; if (pattern == nullptr) { HiLog::Error(LABEL, "InitRules failed because pattern is nullptr."); return isVaild; } UErrorCode status = U_ZERO_ERROR; if (param.size() != 0 || paramBackup.size() != 0) { icu::UnicodeString rules = rulesValue.c_str(); icu::RegexMatcher* matcher = pattern->matcher(rules, status); if (matcher == nullptr) { HiLog::Error(LABEL, "InitRules failed because pattern matcher failed."); return false; } while (matcher->find(status) && isVaild) { icu::UnicodeString value = matcher->group(1, status); std::string valueStr; value.toUTF8String(valueStr); std::string paramValue = this->dateTimeRule->Get(param, valueStr); std::string paramBackupValue = this->dateTimeRule->Get(paramBackup, valueStr); std::string targetStr = (paramValue.length() == 0 && paramBackupValue.length() != 0) ? paramBackupValue : paramValue; targetStr = (paramValue.length() != 0 && paramBackupValue.length() != 0 && !DateTimeRule::CompareBeginEnd(paramValue, "]", false) && !DateTimeRule::CompareBeginEnd(paramValue, "]\\b", false)) ? paramValue + "|" + paramBackupValue : targetStr; isVaild = (targetStr.length() == 0) ? false : true; std::string replaceStr = "[" + valueStr + "]"; if (DateTimeRule::trim(paramValue).length() != 0) { rulesValue = DateTimeRule::SubReplace(rulesValue, replaceStr, targetStr); } } delete matcher; } return isVaild; } // replace [paramopt_ ] in the rule with the corresponding regular expression. std::string RulesEngine::InitOptRules(std::string& rule) { std::string rulesValue = rule; icu::UnicodeString matchedStr = rule.c_str(); UErrorCode status = U_ZERO_ERROR; if (this->dateTimeRule == nullptr) { HiLog::Error(LABEL, "InitOptRules failed because this->dateTimeRule is nullptr."); return rulesValue; } icu::RegexPattern* pattern = dateTimeRule->GetPatternsMap()["optrules"]; if (pattern == nullptr) { HiLog::Error(LABEL, "InitOptRules failed because pattern is nullptr."); return rulesValue; } if (param.size() != 0 || paramBackup.size() != 0) { icu::RegexMatcher* matcher = pattern->matcher(matchedStr, status); if (matcher == nullptr) { HiLog::Error(LABEL, "InitOptRules failed because pattern matcher failed."); return rulesValue; } while (matcher->find(status)) { icu::UnicodeString key = matcher->group(1, status); std::string keyStr; key.toUTF8String(keyStr); std::string value = "param_" + keyStr; int begin = matcher->start(status); int end = matcher->end(status); std::string paramValue = this->dateTimeRule->Get(param, value); std::string paramBackupValue = this->dateTimeRule->Get(paramBackup, value); std::string targetStr = paramValue; if (paramValue.length() == 0 && paramBackupValue.length() != 0) { targetStr = paramBackupValue; } else if (DateTimeRule::trim(paramValue).length() != 0 && DateTimeRule::trim(paramBackupValue).length() != 0) { targetStr = paramValue + '|' + paramBackupValue; } // if there is not corresponding regular expression, delete [paramopt_ ]. if (paramValue.length() == 0 && paramBackupValue.length() == 0) { int rIndex = (rule.substr(begin - 1, 1) == "|") ? begin - 1 : begin; std::string replaceStr1 = rule.substr(rIndex, end - rIndex); rulesValue = DateTimeRule::SubReplace(rulesValue, replaceStr1, ""); } std::string replaceStr2 = "[paramopt_" + keyStr + "]"; rulesValue = DateTimeRule::SubReplace(rulesValue, replaceStr2, targetStr); } delete matcher; } return rulesValue; } // replace [regex_ ] in the rule with the corresponding regular expression. std::string RulesEngine::InitSubRules(std::string& rule) { std::string rulesValue = rule; icu::UnicodeString matchedStr = rule.c_str(); UErrorCode status = U_ZERO_ERROR; icu::RegexPattern* pattern = dateTimeRule->GetPatternsMap()["subrules"]; if (pattern == nullptr) { HiLog::Error(LABEL, "InitSubRules failed because pattern is nullptr."); return rulesValue; } if (subRules.size() != 0) { icu::RegexMatcher* matcher = pattern->matcher(matchedStr, status); if (matcher == nullptr) { HiLog::Error(LABEL, "InitSubRules failed because pattern matcher failed."); return rulesValue; } while (matcher->find(status)) { icu::UnicodeString text = matcher->group(0, status); icu::UnicodeString value = matcher->group(1, status); std::string valueStr; value.toUTF8String(valueStr); std::string targetStr = subRules[valueStr]; std::string replaceStr; text.toUTF8String(replaceStr); rulesValue = DateTimeRule::SubReplace(rulesValue, replaceStr, targetStr); } delete matcher; } return rulesValue; } } // namespace I18n } // namespace Global } // namespace OHOS