1 /*
2 * Copyright (c) 2022 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 language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "dm_discovery_filter.h"
17
18 #include "dm_anonymous.h"
19 #include "dm_constants.h"
20 #include "dm_log.h"
21 #include "nlohmann/json.hpp"
22
23 namespace OHOS {
24 namespace DistributedHardware {
25 const std::string FILTERS_KEY = "filters";
26 const std::string FILTER_OP_KEY = "filter_op";
27 const std::string FILTERS_TYPE_OR = "OR";
28 const std::string FILTERS_TYPE_AND = "AND";
29
30 enum DmDiscoveryDeviceFilter {
31 DM_OFFLINE_DEVICE = 0,
32 DM_ONLINE_DEVICE = 1,
33 DM_ALL_DEVICE = 2
34 };
35
ParseFilterJson(const std::string & str)36 int32_t DmDeviceFilterOption::ParseFilterJson(const std::string &str)
37 {
38 nlohmann::json jsonObject = nlohmann::json::parse(str, nullptr, false);
39 if (jsonObject.is_discarded()) {
40 LOGE("FilterOptions parse error.");
41 return ERR_DM_INPUT_PARA_INVALID;
42 }
43 if (!jsonObject.contains(FILTERS_KEY) || !jsonObject[FILTERS_KEY].is_array() || jsonObject[FILTERS_KEY].empty()) {
44 LOGE("Filters invalid.");
45 return ERR_DM_INPUT_PARA_INVALID;
46 }
47 if (jsonObject.contains(FILTER_OP_KEY) && !jsonObject[FILTER_OP_KEY].is_string()) {
48 LOGE("Filters_op invalid.");
49 return ERR_DM_INPUT_PARA_INVALID;
50 }
51 if (!jsonObject.contains(FILTER_OP_KEY)) {
52 filterOp_ = FILTERS_TYPE_OR; // filterOp optional, "OR" default
53 } else {
54 jsonObject[FILTER_OP_KEY].get_to(filterOp_);
55 }
56
57 for (const auto &object : jsonObject[FILTERS_KEY]) {
58 if (!object.contains("type") || !object["type"].is_string()) {
59 LOGE("Filters type invalid");
60 return ERR_DM_INPUT_PARA_INVALID;
61 }
62 if (!object.contains("value") || !object["value"].is_number_integer()) {
63 LOGE("Filters value invalid");
64 return ERR_DM_INPUT_PARA_INVALID;
65 }
66 DmDeviceFilters deviceFilters;
67 deviceFilters.type = object["type"];
68 deviceFilters.value = object["value"];
69 filters_.push_back(deviceFilters);
70 }
71 return DM_OK;
72 }
73
TransformToFilter(const std::string & filterOptions)74 int32_t DmDeviceFilterOption::TransformToFilter(const std::string &filterOptions)
75 {
76 if (filterOptions.empty()) {
77 LOGI("DmDeviceFilterOption::filterOptions empty");
78 filterOp_ = FILTERS_TYPE_OR;
79 DmDeviceFilters deviceFilters;
80 deviceFilters.type = "credible";
81 deviceFilters.value = DM_OFFLINE_DEVICE;
82 filters_.push_back(deviceFilters);
83 return DM_OK;
84 }
85 return ParseFilterJson(filterOptions);
86 }
87
FilterByCredible(int32_t value,bool isOnline)88 bool DmDiscoveryFilter::FilterByCredible(int32_t value, bool isOnline)
89 {
90 if (value == DM_OFFLINE_DEVICE) {
91 return !isOnline;
92 }
93 if (value == DM_ONLINE_DEVICE) {
94 return isOnline;
95 }
96 return (value == DM_ALL_DEVICE);
97 }
98
FilterByRange(int32_t value,int range)99 bool DmDiscoveryFilter::FilterByRange(int32_t value, int range)
100 {
101 return ((range > 0) && (range <= value));
102 }
103
FilterByType(const DmDeviceFilters & filters,const DmDeviceFilterPara & filterPara)104 bool DmDiscoveryFilter::FilterByType(const DmDeviceFilters &filters, const DmDeviceFilterPara &filterPara)
105 {
106 LOGI("DmDiscoveryFilter::FilterByType: type: %s, value: %d", filters.type.c_str(), filters.value);
107 if (filters.type == "credible") {
108 return FilterByCredible(filters.value, filterPara.isOnline);
109 }
110 if (filters.type == "range") {
111 return FilterByRange(filters.value, filterPara.range);
112 }
113 return false;
114 }
115
FilterOr(const std::vector<DmDeviceFilters> & filters,const DmDeviceFilterPara & filterPara)116 bool DmDiscoveryFilter::FilterOr(const std::vector<DmDeviceFilters> &filters, const DmDeviceFilterPara &filterPara)
117 {
118 for (auto &iter : filters) {
119 if (FilterByType(iter, filterPara) == true) {
120 return true;
121 }
122 }
123 return false;
124 }
125
FilterAnd(const std::vector<DmDeviceFilters> & filters,const DmDeviceFilterPara & filterPara)126 bool DmDiscoveryFilter::FilterAnd(const std::vector<DmDeviceFilters> &filters, const DmDeviceFilterPara &filterPara)
127 {
128 for (auto &iter : filters) {
129 if (FilterByType(iter, filterPara) == false) {
130 return false;
131 }
132 }
133 return true;
134 }
135
IsValidDevice(const std::string & filterOp,const std::vector<DmDeviceFilters> & filters,const DmDeviceFilterPara & filterPara)136 bool DmDiscoveryFilter::IsValidDevice(const std::string &filterOp, const std::vector<DmDeviceFilters> &filters,
137 const DmDeviceFilterPara &filterPara)
138 {
139 LOGI("DmDiscoveryFilter::IsValidDevice: filterOp: %s, isOnline: %d, range: %d", filterOp.c_str(),
140 filterPara.isOnline, filterPara.range);
141 if (filterOp == FILTERS_TYPE_OR) {
142 return FilterOr(filters, filterPara);
143 }
144 if (filterOp == FILTERS_TYPE_AND) {
145 return FilterAnd(filters, filterPara);
146 }
147 return false;
148 }
149 } // namespace DistributedHardware
150 } // namespace OHOS