• 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 language governing permissions and
13  * limitations under the License.
14  */
15 #define LOG_TAG "UnifiedRecord"
16 #include "unified_record.h"
17 
18 #include "file.h"
19 #include "getter_system.h"
20 #include "logger.h"
21 #include "utd_client.h"
22 
23 namespace OHOS {
24 namespace UDMF {
25 static constexpr UDType FILE_TYPES[] = {FILE, AUDIO, FOLDER, IMAGE, VIDEO};
26 static constexpr const char *FILE_SCHEME = "file";
27 static constexpr UDType UDC_RECORDS[] = {APPLICATION_DEFINED_RECORD, AUDIO, FILE, FOLDER, HTML, IMAGE, HYPERLINK,
28     PLAIN_TEXT, SYSTEM_DEFINED_APP_ITEM, SYSTEM_DEFINED_FORM, SYSTEM_DEFINED_PIXEL_MAP, SYSTEM_DEFINED_RECORD,
29     TEXT, VIDEO};
30 
UnifiedRecord()31 UnifiedRecord::UnifiedRecord()
32 {
33     dataType_ = UD_BUTT;
34 }
35 
UnifiedRecord(UDType type)36 UnifiedRecord::UnifiedRecord(UDType type)
37 {
38     dataType_ = type;
39     utdId_ = UtdUtils::GetUtdIdFromUtdEnum(type);
40     utdId2_ = utdId_;
41 }
42 
UnifiedRecord(UDType type,ValueType value)43 UnifiedRecord::UnifiedRecord(UDType type, ValueType value)
44 {
45     dataType_ = type;
46     utdId_ = UtdUtils::GetUtdIdFromUtdEnum(type);
47     utdId2_ = utdId_;
48     value_ = value;
49     if (std::holds_alternative<std::shared_ptr<Object>>(value_)) {
50         if (utdId_ == GENERAL_FILE_URI) {
51             ObjectUtils::ProcessFileUriType(dataType_, value_);
52         }
53     }
54 }
55 
GetType() const56 UDType UnifiedRecord::GetType() const
57 {
58     return this->dataType_;
59 }
60 
GetTypes() const61 std::vector<std::string> UnifiedRecord::GetTypes() const
62 {
63     std::vector<std::string> types;
64     for (auto it = entries_->begin(); it != entries_->end(); it++) {
65         types.push_back(it->first);
66     }
67     types.push_back(utdId2_);
68     return types;
69 }
70 
SetType(const UDType & type)71 void UnifiedRecord::SetType(const UDType &type)
72 {
73     dataType_ = type;
74     utdId_ = UtdUtils::GetUtdIdFromUtdEnum(type);
75     utdId2_ = utdId_;
76 }
77 
GetSize()78 int64_t UnifiedRecord::GetSize()
79 {
80     if (std::holds_alternative<std::shared_ptr<Object>>(value_)) {
81         auto value = std::get<std::shared_ptr<Object>>(value_);
82         if (value->value_.size() == 1) {
83             return ObjectUtils::GetValueSize(value_, true) + GetInnerEntriesSize();
84         }
85     }
86     return ObjectUtils::GetValueSize(value_, false) + GetInnerEntriesSize();
87 }
88 
GetUid() const89 std::string UnifiedRecord::GetUid() const
90 {
91     return this->uid_;
92 }
93 
SetUid(const std::string & id)94 void UnifiedRecord::SetUid(const std::string &id)
95 {
96     this->uid_ = id;
97 }
98 
GetValue()99 ValueType UnifiedRecord::GetValue()
100 {
101     return value_;
102 }
103 
SetValue(const ValueType & value)104 void UnifiedRecord::SetValue(const ValueType &value)
105 {
106     value_ = value;
107 }
108 
GetOriginValue() const109 ValueType UnifiedRecord::GetOriginValue() const
110 {
111     return value_;
112 }
113 
HasType(const std::string & utdId) const114 bool UnifiedRecord::HasType(const std::string &utdId) const
115 {
116     if (entries_->find(utdId) != entries_->end()) {
117         return true;
118     }
119     return utdId == utdId2_;
120 }
121 
AddEntry(const std::string & utdId,ValueType && value)122 void UnifiedRecord::AddEntry(const std::string &utdId, ValueType &&value)
123 {
124     std::lock_guard<std::recursive_mutex> lock(mutex_);
125     if (utdId == utdId2_ || utdId2_.empty()) {
126         utdId_ = utdId;
127         utdId2_ = utdId_;
128         value_ = std::move(value);
129         auto udType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(utdId2_));
130         if (udType == UD_BUTT) {
131             dataType_ = APPLICATION_DEFINED_RECORD;
132             return;
133         }
134         if (utdId == GENERAL_FILE_URI && std::holds_alternative<std::shared_ptr<Object>>(value_)) {
135             ObjectUtils::ProcessFileUriType(udType, value_);
136         }
137         dataType_ = udType;
138     } else {
139         entries_->insert_or_assign(utdId, std::move(value));
140     }
141 }
142 
GetEntry(const std::string & utdId)143 ValueType UnifiedRecord::GetEntry(const std::string &utdId)
144 {
145     std::lock_guard<std::recursive_mutex> lock(mutex_);
146     if (utdId2_ == utdId && !(std::holds_alternative<std::monostate>(value_))) {
147         auto value = value_;
148         if (!std::holds_alternative<std::shared_ptr<Object>>(value_)
149             && std::find(std::begin(UDC_RECORDS), std::end(UDC_RECORDS), dataType_) != std::end(UDC_RECORDS)) {
150             InitObject();
151             value = value_;
152             auto obj = std::get<std::shared_ptr<Object>>(value_);
153             value_ = obj->value_[VALUE_TYPE];
154         }
155         return value;
156     }
157     auto it = entries_->find(utdId);
158     if (it != entries_->end() && !(std::holds_alternative<std::monostate>(it->second))) {
159         return it->second;
160     }
161     auto getter = GetterSystem::GetInstance().GetGetter(channelName_);
162     if (getter != nullptr && (utdId2_ == utdId || it != entries_->end())) {
163         auto value = getter->GetValueByType(dataId_, recordId_, utdId);
164         if (std::holds_alternative<std::monostate>(value)) {
165             LOG_ERROR(UDMF_FRAMEWORK, "get value failed, utdId: %{public}s", utdId.c_str());
166             return std::monostate();
167         }
168         AddEntry(utdId, ValueType(value));
169         return value;
170     }
171     if (utdId2_ == utdId && std::holds_alternative<std::monostate>(value_)) {
172         InitObject();
173         auto value = value_;
174         auto obj = std::get<std::shared_ptr<Object>>(value_);
175         value_ = obj->value_[VALUE_TYPE];
176         if (obj->value_.size() == 1) { // value_ size equals 1 means there are no datas
177             return std::monostate();
178         } else {
179             return value;
180         }
181     }
182     return std::monostate();
183 }
184 
GetEntries()185 std::shared_ptr<std::map<std::string, ValueType>> UnifiedRecord::GetEntries()
186 {
187     auto res = std::make_shared<std::map<std::string, ValueType>>(*entries_);
188     if (!utdId2_.empty()) {
189         if (!std::holds_alternative<std::shared_ptr<Object>>(value_)) {
190             InitObject();
191             ValueType value = value_;
192             res->insert_or_assign(utdId2_, std::move(value));
193             auto object = std::get<std::shared_ptr<Object>>(value_);
194             value_ = object->value_[VALUE_TYPE];   // restore value_
195         } else {
196             res->insert_or_assign(utdId2_, value_);
197         }
198     }
199     return res;
200 }
201 
GetInnerEntries() const202 std::shared_ptr<std::map<std::string, ValueType>> UnifiedRecord::GetInnerEntries() const
203 {
204     return entries_;
205 }
206 
SetInnerEntries(std::shared_ptr<std::map<std::string,ValueType>> entries)207 void UnifiedRecord::SetInnerEntries(std::shared_ptr<std::map<std::string, ValueType>> entries)
208 {
209     entries_ = entries;
210 }
211 
GetInnerEntriesSize() const212 int64_t UnifiedRecord::GetInnerEntriesSize() const
213 {
214     if (entries_ == nullptr) {
215         return 0;
216     }
217     int64_t size = 0;
218     for (auto &entry : *entries_) {
219         size += ObjectUtils::GetValueSize(entry.second, false);
220     }
221     return size;
222 }
223 
GetUtdIds() const224 std::set<std::string> UnifiedRecord::GetUtdIds() const
225 {
226     std::set<std::string> utdIds;
227     if (!utdId_.empty()) {
228         utdIds.emplace(utdId_);
229     }
230     for (const auto& [key, value] : *entries_) {
231         utdIds.emplace(key);
232     }
233     return utdIds;
234 }
235 
GetUtdIdsWithAddFileType(bool isSpecific) const236 std::set<std::string> UnifiedRecord::GetUtdIdsWithAddFileType(bool isSpecific) const
237 {
238     std::set<std::string> utdIds;
239     if (!utdId2_.empty()) {
240         utdIds.emplace(utdId2_);
241         if (utdId2_ == GENERAL_FILE_URI && std::holds_alternative<std::shared_ptr<Object>>(value_)) {
242             auto fileUri = std::get<std::shared_ptr<Object>>(value_);
243             AddFileUriType(utdIds, fileUri, isSpecific);
244         }
245     }
246     for (const auto& [key, value] : *entries_) {
247         utdIds.emplace(key);
248         if (key == GENERAL_FILE_URI && std::holds_alternative<std::shared_ptr<Object>>(value)) {
249             auto fileUri = std::get<std::shared_ptr<Object>>(value);
250             AddFileUriType(utdIds, fileUri, isSpecific);
251         }
252     }
253     return utdIds;
254 }
255 
SetUtdId(const std::string & utdId)256 void UnifiedRecord::SetUtdId(const std::string& utdId)
257 {
258     utdId_ = utdId;
259     utdId2_ = utdId;
260 }
261 
GetUtdId() const262 std::string UnifiedRecord::GetUtdId() const
263 {
264     return utdId_;
265 }
266 
SetUtdId2(const std::string & utdId)267 void UnifiedRecord::SetUtdId2(const std::string& utdId)
268 {
269     utdId2_ = utdId;
270 }
271 
GetUtdId2() const272 std::string UnifiedRecord::GetUtdId2() const
273 {
274     return utdId2_;
275 }
276 
SetDataId(uint32_t dataId)277 void UnifiedRecord::SetDataId(uint32_t dataId)
278 {
279     dataId_ = dataId;
280 }
281 
GetDataId() const282 uint32_t UnifiedRecord::GetDataId() const
283 {
284     return dataId_;
285 }
286 
SetRecordId(uint32_t recordId)287 void UnifiedRecord::SetRecordId(uint32_t recordId)
288 {
289     recordId_ = recordId;
290 }
291 
GetRecordId() const292 uint32_t UnifiedRecord::GetRecordId() const
293 {
294     return recordId_;
295 }
296 
SetEntryGetter(const std::vector<std::string> & utdIds,const std::shared_ptr<EntryGetter> & entryGetter)297 void UnifiedRecord::SetEntryGetter(
298     const std::vector<std::string> &utdIds,
299     const std::shared_ptr<EntryGetter> &entryGetter)
300 {
301     for (auto const &utdId : utdIds) {
302         if (HasType(utdId)) {
303             LOG_WARN(UDMF_FRAMEWORK, "already has the utdId: %{public}s", utdId.c_str());
304             continue;
305         }
306         AddEntry(utdId, ValueType());
307     }
308     entryGetter_ = entryGetter;
309 }
310 
GetEntryGetter()311 std::shared_ptr<EntryGetter> UnifiedRecord::GetEntryGetter()
312 {
313     return entryGetter_;
314 }
315 
SetChannelName(const std::string & channelName)316 void UnifiedRecord::SetChannelName(const std::string &channelName)
317 {
318     channelName_ = channelName;
319 }
320 
InitObject()321 void UnifiedRecord::InitObject()
322 {
323     if (!std::holds_alternative<std::shared_ptr<Object>>(value_)) {
324         auto value = value_;
325         value_ = std::make_shared<Object>();
326         auto object = std::get<std::shared_ptr<Object>>(value_);
327         object->value_.insert_or_assign(VALUE_TYPE, std::move(value));
328     }
329 }
330 
HasFileType(std::string & fileUri) const331 bool UnifiedRecord::HasFileType(std::string &fileUri) const
332 {
333     fileUri.clear();
334     if (std::holds_alternative<std::shared_ptr<Object>>(GetOriginValue())) {
335         auto obj = std::get<std::shared_ptr<Object>>(GetOriginValue());
336         if (obj->value_.find(ORI_URI) != obj->value_.end()) {
337             obj->GetValue(ORI_URI, fileUri);
338         }
339     } else if (std::find(std::begin(FILE_TYPES), std::end(FILE_TYPES), GetType()) != std::end(FILE_TYPES)) {
340         auto file = static_cast<const File*>(this);
341         fileUri = file->GetUri();
342     } else {
343         return false;
344     }
345 
346     if (fileUri.empty()) {
347         LOG_ERROR(UDMF_FRAMEWORK, "Get uri empty, plase check the uri.");
348         return false;
349     }
350 #ifndef CROSS_PLATFORM
351     Uri uri(fileUri);
352     std::string scheme = uri.GetScheme();
353     std::transform(scheme.begin(), scheme.end(), scheme.begin(), ::tolower);
354     if (uri.GetAuthority().empty() || scheme != FILE_SCHEME) {
355         LOG_INFO(UDMF_FRAMEWORK, "Get uri authority empty or uri scheme not equals to file.");
356         return false;
357     }
358 #endif
359     return true;
360 }
361 
SetFileUri(const std::string & fileUri)362 void UnifiedRecord::SetFileUri(const std::string &fileUri)
363 {
364     if (std::find(std::begin(FILE_TYPES), std::end(FILE_TYPES), GetType()) != std::end(FILE_TYPES)) {
365         auto file = static_cast<File*>(this);
366         file->SetUri(fileUri);
367     } else if (std::holds_alternative<std::shared_ptr<Object>>(GetOriginValue())) {
368         auto obj = std::get<std::shared_ptr<Object>>(GetOriginValue());
369         obj->value_[ORI_URI] = fileUri;
370     } else {
371         LOG_ERROR(UDMF_FRAMEWORK, "Record has no uri.");
372     }
373 }
374 
GetUris() const375 std::vector<UriInfo> UnifiedRecord::GetUris() const
376 {
377     return uris_;
378 }
379 
SetUris(std::vector<UriInfo> uris)380 void UnifiedRecord::SetUris(std::vector<UriInfo> uris)
381 {
382     uris_ = std::move(uris);
383 }
384 
ClearUris()385 void UnifiedRecord::ClearUris()
386 {
387     uris_.clear();
388 }
389 
ComputeUris(const std::function<bool (UriInfo &)> & action)390 void UnifiedRecord::ComputeUris(const std::function<bool(UriInfo &)> &action)
391 {
392     for (auto &uri : uris_) {
393         if (!action(uri)) {
394             break;
395         }
396     }
397 }
398 
AddFileUriType(std::set<std::string> & utdIds,const std::shared_ptr<Object> & fileUri,bool isSpecific) const399 void UnifiedRecord::AddFileUriType(std::set<std::string> &utdIds,
400     const std::shared_ptr<Object> &fileUri, bool isSpecific) const
401 {
402     if (fileUri == nullptr) {
403         return;
404     }
405     std::string uniformDataType;
406     if (fileUri->GetValue(UNIFORM_DATA_TYPE, uniformDataType) && uniformDataType == GENERAL_FILE_URI) {
407         std::string fileType;
408         if (fileUri->GetValue(FILE_TYPE, fileType) && !fileType.empty()) {
409             if (isSpecific) {
410                 utdIds.emplace(fileType);
411                 return;
412             }
413             std::string fileTypeStr = UnifiedDataUtils::GetBelongsToFileType(fileType);
414             if (!fileTypeStr.empty()) {
415                 utdIds.emplace(fileTypeStr);
416             }
417         }
418     }
419 }
420 } // namespace UDMF
421 } // namespace OHOS