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