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 language governing permissions and
13 * limitations under the License.
14 */
15 #define LOG_TAG "UnifiedData"
16 #include "logger.h"
17 #include "unified_data.h"
18 #include "utd_client.h"
19
20 namespace OHOS {
21 namespace UDMF {
22 static const std::set<std::string> FILE_TYPES = {
23 "general.file", "general.image", "general.video", "general.audio", "general.folder", "general.file-uri" };
24 static const std::set<std::string> FILE_SUB_TYPES = {
25 "general.image", "general.video", "general.audio", "general.folder" };
26 static constexpr const char *RECORDS_TANSFER_TAG = "records_to_entries_data_format";
UnifiedData()27 UnifiedData::UnifiedData()
28 {
29 properties_ = std::make_shared<UnifiedDataProperties>();
30 auto duration = std::chrono::system_clock::now().time_since_epoch();
31 properties_->timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
32 }
33
UnifiedData(std::shared_ptr<UnifiedDataProperties> properties)34 UnifiedData::UnifiedData(std::shared_ptr<UnifiedDataProperties> properties)
35 {
36 if (properties == nullptr) {
37 LOG_ERROR(UDMF_FRAMEWORK, "Invalid properties!");
38 return;
39 }
40 properties_ = properties;
41 auto duration = std::chrono::system_clock::now().time_since_epoch();
42 properties_->timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
43 }
44
GetSize()45 int64_t UnifiedData::GetSize()
46 {
47 int64_t totalSize = 0;
48 for (const auto &record : this->records_) {
49 totalSize += record->GetSize();
50 }
51 return totalSize;
52 }
53
GetGroupId() const54 std::string UnifiedData::GetGroupId() const
55 {
56 return this->runtime_->key.groupId;
57 }
58
GetRuntime() const59 std::shared_ptr<Runtime> UnifiedData::GetRuntime() const
60 {
61 return this->runtime_;
62 }
63
SetRuntime(Runtime & runtime)64 void UnifiedData::SetRuntime(Runtime &runtime)
65 {
66 this->runtime_ = std::make_shared<Runtime>(runtime);
67 this->SetSdkVersion(runtime.sdkVersion);
68 }
69
AddRecord(const std::shared_ptr<UnifiedRecord> & record)70 void UnifiedData::AddRecord(const std::shared_ptr<UnifiedRecord> &record)
71 {
72 if (record == nullptr) {
73 return;
74 }
75 record->SetRecordId(++recordId_);
76 this->records_.push_back(record);
77 }
78
AddRecords(const std::vector<std::shared_ptr<UnifiedRecord>> & records)79 void UnifiedData::AddRecords(const std::vector<std::shared_ptr<UnifiedRecord>> &records)
80 {
81 for (auto &record :records) {
82 if (record == nullptr) {
83 LOG_ERROR(UDMF_FRAMEWORK, "Invalid record, skip!");
84 continue;
85 }
86 record->SetRecordId(++recordId_);
87 this->records_.push_back(record);
88 }
89 }
90
GetRecordAt(std::size_t index) const91 std::shared_ptr<UnifiedRecord> UnifiedData::GetRecordAt(std::size_t index) const
92 {
93 if (records_.size() > index) {
94 return records_[index];
95 }
96 return nullptr;
97 }
98
SetRecords(std::vector<std::shared_ptr<UnifiedRecord>> records)99 void UnifiedData::SetRecords(std::vector<std::shared_ptr<UnifiedRecord>> records)
100 {
101 this->records_ = std::move(records);
102 }
103
GetRecords() const104 std::vector<std::shared_ptr<UnifiedRecord>> UnifiedData::GetRecords() const
105 {
106 return this->records_;
107 }
108
GetTypesLabels() const109 std::vector<std::string> UnifiedData::GetTypesLabels() const
110 {
111 std::vector<std::string> types;
112 for (const std::shared_ptr<UnifiedRecord> &record : records_) {
113 types.push_back(UtdUtils::GetUtdIdFromUtdEnum(record->GetType()));
114 }
115 return types;
116 }
117
HasType(const std::string & type) const118 bool UnifiedData::HasType(const std::string &type) const
119 {
120 for (const std::shared_ptr<UnifiedRecord> &record : records_) {
121 std::vector<std::string> recordTypes = record->GetTypes();
122 if (std::find(recordTypes.begin(), recordTypes.end(), type) != recordTypes.end()) {
123 return true;
124 }
125 }
126 return false;
127 }
128
HasHigherFileType(const std::string & type) const129 bool UnifiedData::HasHigherFileType(const std::string &type) const
130 {
131 std::set<std::string> types = GetTypIds();
132 if (types.find(type) != types.end()) {
133 return true;
134 }
135 auto subTypesIter = FILE_SUB_TYPES.find(type);
136 if (subTypesIter == FILE_SUB_TYPES.end()) {
137 return false;
138 }
139 for (auto it = types.begin(); it != types.end(); ++it) {
140 std::shared_ptr<TypeDescriptor> descriptor;
141 UtdClient::GetInstance().GetTypeDescriptor(*it, descriptor);
142 if (descriptor == nullptr) {
143 continue;
144 }
145 bool isFileType = false;
146 descriptor->BelongsTo(type, isFileType);
147 if (isFileType) {
148 return true;
149 }
150 }
151 return false;
152 }
153
GetEntriesTypes() const154 std::vector<std::string> UnifiedData::GetEntriesTypes() const
155 {
156 std::set<std::string> labels;
157 for (const auto &record : records_) {
158 auto types = record->GetUtdIds();
159 labels.insert(types.begin(), types.end());
160 }
161 return std::vector<std::string>(labels.begin(), labels.end());
162 }
163
HasTypeInEntries(const std::string & type) const164 bool UnifiedData::HasTypeInEntries(const std::string &type) const
165 {
166 for (const auto &record : records_) {
167 if (record == nullptr) {
168 LOG_ERROR(UDMF_FRAMEWORK, "Invalid record, skip!");
169 continue;
170 }
171 auto types = record->GetUtdIds();
172 if (types.find(type) != types.end()) {
173 return true;
174 }
175 }
176 return false;
177 }
178
IsEmpty() const179 bool UnifiedData::IsEmpty() const
180 {
181 return records_.empty();
182 }
183
IsValid()184 bool UnifiedData::IsValid()
185 {
186 if (this->IsEmpty()) {
187 LOG_ERROR(UDMF_FRAMEWORK, "Empty data without any record!");
188 return false;
189 }
190 if (this->GetSize() > MAX_DATA_SIZE) {
191 LOG_ERROR(UDMF_FRAMEWORK, "Exceeded data limit, UnifiedData size: %{public}" PRId64 " !", this->GetSize());
192 return false;
193 }
194 return true;
195 }
196
IsComplete()197 bool UnifiedData::IsComplete()
198 {
199 std::shared_ptr<Runtime> runtime = this->GetRuntime();
200 if (runtime == nullptr) {
201 return false;
202 }
203 if (static_cast<uint32_t>(this->GetRecords().size()) != runtime->recordTotalNum) {
204 LOG_ERROR(UDMF_FRAMEWORK,
205 "The records of unifiedData is incomplete, expected recordsNum is %{public}u, not %{public}zu.",
206 runtime->recordTotalNum, this->GetRecords().size());
207 return false;
208 }
209 return true;
210 }
211
HasFileType() const212 bool UnifiedData::HasFileType() const
213 {
214 auto types = GetTypIds();
215 std::set<std::string> intersection;
216 std::set_intersection(FILE_TYPES.begin(), FILE_TYPES.end(), types.begin(), types.end(),
217 std::inserter(intersection, intersection.begin()));
218 return !intersection.empty();
219 }
220
HasUriInfo() const221 bool UnifiedData::HasUriInfo() const
222 {
223 for (auto record : records_) {
224 if (!record->GetUris().empty()) {
225 return true;
226 }
227 }
228 return false;
229 }
230
ClearUriInfo() const231 void UnifiedData::ClearUriInfo() const
232 {
233 for (auto record : records_) {
234 record->ClearUris();
235 }
236 }
237
SetProperties(std::shared_ptr<UnifiedDataProperties> properties)238 void UnifiedData::SetProperties(std::shared_ptr<UnifiedDataProperties> properties)
239 {
240 if (!properties) {
241 LOG_ERROR(UDMF_FRAMEWORK, "properties is null!");
242 return;
243 }
244 if (properties_ == nullptr) {
245 LOG_ERROR(UDMF_FRAMEWORK, "properties_ is nullptr!");
246 return;
247 }
248 properties->timestamp = properties_->timestamp;
249 properties_ = properties;
250 }
251
GetProperties() const252 std::shared_ptr<UnifiedDataProperties> UnifiedData::GetProperties() const
253 {
254 return properties_;
255 }
256
SetDataId(uint32_t dataId)257 void UnifiedData::SetDataId(uint32_t dataId)
258 {
259 dataId_ = dataId;
260 }
261
GetDataId() const262 uint32_t UnifiedData::GetDataId() const
263 {
264 return dataId_;
265 }
266
SetChannelName(const std::string & name)267 void UnifiedData::SetChannelName(const std::string &name)
268 {
269 channelName_ = std::move(name);
270 }
271
GetTypIds() const272 std::set<std::string> UnifiedData::GetTypIds() const
273 {
274 std::set<std::string> types;
275 for (const auto &record : records_) {
276 std::set<std::string> recordTypes = record->GetUtdIdsWithAddFileType();
277 types.insert(recordTypes.begin(), recordTypes.end());
278 }
279 return types;
280 }
281
GetFileUris() const282 std::vector<std::string> UnifiedData::GetFileUris() const
283 {
284 std::vector<std::string> uris;
285 for (auto record : records_) {
286 std::string oriUri;
287 if (record == nullptr || !record->HasFileType(oriUri)) {
288 continue;
289 }
290 uris.push_back(oriUri);
291 }
292 return uris;
293 }
294
GetSdkVersion() const295 std::string UnifiedData::GetSdkVersion() const
296 {
297 return sdkVersion_;
298 }
299
SetSdkVersion(const std::string & version)300 void UnifiedData::SetSdkVersion(const std::string &version)
301 {
302 sdkVersion_ = version;
303 }
304
IsNeedTransferToEntries() const305 bool UnifiedData::IsNeedTransferToEntries() const
306 {
307 if (records_.size() <= 1) {
308 return false;
309 }
310 if (properties_ == nullptr) {
311 return false;
312 }
313 return properties_->tag == RECORDS_TANSFER_TAG;
314 }
315
ConvertRecordsToEntries()316 void UnifiedData::ConvertRecordsToEntries()
317 {
318 if (!IsNeedTransferToEntries()) {
319 return;
320 }
321 std::shared_ptr<UnifiedRecord> recordFirst = records_[0];
322 if (recordFirst == nullptr) {
323 LOG_ERROR(UDMF_FRAMEWORK, "First record is null");
324 return;
325 }
326 for (size_t i = 1; i < records_.size(); i++) {
327 auto record = records_[i];
328 if (record == nullptr) {
329 continue;
330 }
331 if (record->GetUtdId2() == recordFirst->GetUtdId2()) {
332 continue;
333 }
334 record->InitObject();
335 recordFirst->AddEntry(record->GetUtdId2(), record->GetValue());
336 }
337 records_.erase(records_.begin() + 1, records_.end());
338 LOG_INFO(UDMF_FRAMEWORK, "Convert records to entries finished");
339 }
340 } // namespace UDMF
341 } // namespace OHOS