1 /*
2 * Copyright (C) 2024 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 MLOG_TAG "PhotoBurstOperation"
16
17 #include "photo_burst_operation.h"
18
19 #include <string>
20 #include <uuid.h>
21 #include <sstream>
22 #include <vector>
23 #include <numeric>
24 #include <algorithm>
25
26 #include "rdb_store.h"
27 #include "result_set_utils.h"
28 #include "userfile_manager_types.h"
29 #include "media_column.h"
30 #include "media_log.h"
31
32 namespace OHOS::Media {
SetTargetPhotoInfo(const PhotoAssetInfo & photoAssetInfo)33 PhotoBurstOperation &PhotoBurstOperation::SetTargetPhotoInfo(const PhotoAssetInfo &photoAssetInfo)
34 {
35 this->photoAssetInfo_ = photoAssetInfo;
36 this->photoAssetInfo_.burstGroupName = this->FindBurstGroupName(photoAssetInfo.displayName);
37 return *this;
38 }
39
40 /**
41 * @brief Find burstKey from the given albumId, only for BURST photo.
42 * @return burstKey, if found; empty string, otherwise.
43 */
FindBurstKey(const std::shared_ptr<MediaLibraryRdbStore> & rdbStore)44 std::string PhotoBurstOperation::FindBurstKey(const std::shared_ptr<MediaLibraryRdbStore> &rdbStore)
45 {
46 return this->FindBurstKey(rdbStore, this->photoAssetInfo_);
47 }
48
49 /**
50 * @brief Find burstKey from the given albumId, only for BURST photo.
51 * @return burstKey, if found; empty string, otherwise.
52 */
FindBurstKey(const std::shared_ptr<MediaLibraryRdbStore> & rdbStore,const PhotoAssetInfo & photoAssetInfo)53 std::string PhotoBurstOperation::FindBurstKey(
54 const std::shared_ptr<MediaLibraryRdbStore> &rdbStore, const PhotoAssetInfo &photoAssetInfo)
55 {
56 if (photoAssetInfo.ownerAlbumId <= 0 || photoAssetInfo.burstGroupName.empty() ||
57 photoAssetInfo.subtype != static_cast<int32_t>(PhotoSubType::BURST) || rdbStore == nullptr) {
58 return "";
59 }
60 std::string burstKey = this->QueryBurstKeyFromDB(rdbStore, photoAssetInfo);
61 if (burstKey.empty()) {
62 burstKey = this->GenerateUuid();
63 MEDIA_INFO_LOG("Media_Operation: burstKey is empty, create a new one [%{public}s]. Object: %{public}s",
64 burstKey.c_str(),
65 photoAssetInfo.ToString().c_str());
66 }
67 return burstKey;
68 }
69
ToString(const std::vector<NativeRdb::ValueObject> & values)70 std::string PhotoBurstOperation::ToString(const std::vector<NativeRdb::ValueObject> &values)
71 {
72 std::vector<std::string> result;
73 for (auto &value : values) {
74 std::string str;
75 value.GetString(str);
76 result.emplace_back(str + ", ");
77 }
78 return std::accumulate(result.begin(), result.end(), std::string());
79 }
80
81 /**
82 * @brief generate a uuid
83 *
84 * @return std::string uuid with 37 characters
85 */
GenerateUuid()86 std::string PhotoBurstOperation::GenerateUuid()
87 {
88 uuid_t uuid;
89 uuid_generate(uuid);
90 char str[UUID_STR_LENGTH] = {};
91 uuid_unparse(uuid, str);
92 return str;
93 }
94
95 /**
96 * @brief find prefix contains "_BURST" of displayName
97 *
98 * @return std::string prefix including "_BURST" of displayName
99 */
FindBurstGroupName(const std::string & displayName)100 std::string PhotoBurstOperation::FindBurstGroupName(const std::string &displayName)
101 {
102 auto pos = displayName.find(this->TITLE_KEY_WORDS_OF_BURST);
103 if (pos == std::string::npos) {
104 MEDIA_ERR_LOG("Media_Operation: FindBurstGroupName: cannot find _BURST in displayName. displayName: %{public}s",
105 displayName.c_str());
106 return "";
107 }
108 return displayName.substr(0, std::min<int32_t>(pos, DISPLAY_NAME_PREFIX_LENGTH) + 1);
109 }
110
QueryBurstKeyFromDB(const std::shared_ptr<MediaLibraryRdbStore> & rdbStore,const PhotoAssetInfo & photoAssetInfo)111 std::string PhotoBurstOperation::QueryBurstKeyFromDB(
112 const std::shared_ptr<MediaLibraryRdbStore> &rdbStore, const PhotoAssetInfo &photoAssetInfo)
113 {
114 int32_t ownerAlbumId = photoAssetInfo.ownerAlbumId;
115 std::string burstGroupName = photoAssetInfo.burstGroupName;
116 // Avoid full table scan: if the burstGroupName is empty, return empty string.
117 if (ownerAlbumId <= 0 || burstGroupName.empty() || rdbStore == nullptr) {
118 MEDIA_ERR_LOG("Media_Operation: object invalid. Object: %{public}s", photoAssetInfo.ToString().c_str());
119 return "";
120 }
121 std::string querySql = this->SQL_PHOTOS_TABLE_QUERY_BURST_KEY;
122 std::string burstGroupNameCondition = burstGroupName + "%";
123 const std::vector<NativeRdb::ValueObject> bindArgs = {ownerAlbumId, burstGroupNameCondition};
124 auto resultSet = rdbStore->QuerySql(querySql, bindArgs);
125 if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
126 MEDIA_WARN_LOG("Media_Operation: resultSet is null or no data found! "
127 "querySql: %{public}s, bindArgs: %{public}s",
128 querySql.c_str(),
129 this->ToString(bindArgs).c_str());
130 return "";
131 }
132 std::string burstKey = GetStringVal(PhotoColumn::PHOTO_BURST_KEY, resultSet);
133 return burstKey;
134 }
135 } // namespace OHOS::Media