1 /*
2 * Copyright (c) 2021-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 "match_candidate.h"
17
18 #include "candidate.h"
19 #include "common.h"
20 #include "contacts.h"
21 #include "contacts_columns.h"
22 #include "contacts_database.h"
23 #include "hilog_wrapper.h"
24 #include "merge_utils.h"
25
26 namespace OHOS {
27 namespace Contacts {
MatchCandidate()28 MatchCandidate::MatchCandidate()
29 {
30 }
31
~MatchCandidate()32 MatchCandidate::~MatchCandidate()
33 {
34 }
35
36 /**
37 * @brief Query operation for update candidate's merge_mode
38 *
39 * @param store Conditions for query operation
40 * @param rawId Contacts's raw_contact_id to query
41 *
42 * @return The result returned by the update operation
43 */
FindMatchContact(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,int rawId)44 int MatchCandidate::FindMatchContact(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, int rawId)
45 {
46 CandidateStatus candidateStatus;
47 // Query candidates
48 Candidate candidate = candidateStatus.QueryAllForMerge(store, rawId);
49 if (candidate.autoIds_.size() > 1) {
50 int minAutoid = *candidate.autoIds_.begin();
51 if (minAutoid != -1) {
52 std::string updateMergeTarget = "UPDATE ";
53 updateMergeTarget.append(ContactTableName::RAW_CONTACT)
54 .append(" SET ")
55 .append(RawContactColumns::IS_MERGE_TARGET)
56 .append(" = 1 ")
57 .append(" WHERE ")
58 .append(ContactPublicColumns::ID)
59 .append(" = ")
60 .append(std::to_string(minAutoid));
61 int code = store->ExecuteSql(updateMergeTarget);
62 if (code != OHOS::NativeRdb::E_OK) {
63 HILOG_ERROR("update is_merge_target error code is : %{public}d ", code);
64 }
65 }
66 }
67 // update merge_mode
68 int retCode = UpdateMergeMode(store, candidate);
69 HILOG_INFO("MatchCandidate::FindMatchContact retCode : %{public}d ", retCode);
70 return retCode;
71 }
72
73 /**
74 * @brief Split operation for already merged contacts
75 *
76 * @param store Conditions for split operation
77 * @param rawId Contacts's raw_contact_id to split
78 *
79 * @return The result returned by the split operation
80 */
Split(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,int rawId)81 int MatchCandidate::Split(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, int rawId)
82 {
83 if (store == nullptr) {
84 HILOG_ERROR("MatchCandidate::Split store is nullptr");
85 return RDB_OBJECT_EMPTY;
86 }
87 std::set<int> rawIds;
88 MergeUtils mergeUtils;
89 mergeUtils.GetRawIdsByRawId(store, rawId, rawIds);
90 if (rawIds.size() < 1) {
91 HILOG_ERROR("MatchCandidate::Split is error");
92 return OPERATION_ERROR;
93 }
94 int code = RDB_EXECUTE_FAIL;
95 for (auto newRawId = rawIds.begin(); newRawId != rawIds.end(); ++newRawId) {
96 int contactsId = AddNewContact(store, *newRawId);
97 if (contactsId <= 0) {
98 continue;
99 }
100 code = UpdateRawContact(store, *newRawId, contactsId);
101 UpdateSearch(store, *newRawId, contactsId);
102 FindMatchContact(store, *newRawId);
103 }
104 AddHasByRawId(store, rawId);
105 return code;
106 }
107
AddHasByRawId(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,int rawId)108 void MatchCandidate::AddHasByRawId(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, int rawId)
109 {
110 MergeUtils mergeUtils;
111 OHOS::NativeRdb::ValuesBucket values;
112 values.PutInt(ContactColumns::HAS_DISPLAY_NAME, 0);
113 values.PutInt(ContactColumns::HAS_PHONE_NUMBER, 0);
114 values.PutInt(ContactColumns::HAS_EMAIL, 0);
115 values.PutInt(ContactColumns::HAS_GROUP, 0);
116 mergeUtils.AddHasJudgeForRawId(store, rawId, values);
117 Contacts contacts;
118 int contactsRet = contacts.UpdateContact(rawId, store, values);
119 HILOG_INFO("MatchCandidate::AddHasByRawId UpdateContact ret is : %{public}d", contactsRet);
120 }
121
UpdateSearch(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,int rawId,int contactsId)122 int MatchCandidate::UpdateSearch(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, int rawId, int contactsId)
123 {
124 std::string sql = "UPDATE ";
125 sql.append(ContactTableName::SEARCH_CONTACT)
126 .append(" SET ")
127 .append(SearchContactColumns::CONTACT_ID)
128 .append(" = ")
129 .append(std::to_string(contactsId))
130 .append(" WHERE ")
131 .append(SearchContactColumns::RAW_CONTACT_ID)
132 .append(" = ")
133 .append(std::to_string(rawId));
134 int ret = store->ExecuteSql(sql);
135 return ret;
136 }
137
AddNewContact(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,int rawId)138 int64_t MatchCandidate::AddNewContact(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, int rawId)
139 {
140 MergeUtils mergeUtils;
141 std::string sql = "SELECT ";
142 sql.append(ContactColumns::PHOTO_ID)
143 .append(", ")
144 .append(ContactColumns::PHOTO_FILE_ID)
145 .append(", ")
146 .append(ContactColumns::PERSONAL_RINGTONE)
147 .append(", ")
148 .append(ContactColumns::COMPANY)
149 .append(", ")
150 .append(ContactColumns::POSITION)
151 .append(", ")
152 .append(ContactColumns::READ_ONLY)
153 .append(", ")
154 .append(ContactColumns::PERSONAL_NOTIFICATION_RINGTONE)
155 .append(", ")
156 .append(ContactColumns::IS_TRANSFER_VOICEMAIL)
157 .append(" FROM ")
158 .append(ContactTableName::RAW_CONTACT)
159 .append(" WHERE ")
160 .append(ContactPublicColumns::ID)
161 .append(" = ")
162 .append(std::to_string(rawId));
163 std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet = store->QuerySql(sql);
164 std::vector<OHOS::NativeRdb::ValuesBucket> value = ResultSetToValuesBucket(resultSet);
165 value[0].PutInt(ContactColumns::NAME_RAW_CONTACT_ID, rawId);
166 mergeUtils.AddHasJudgeForRawId(store, rawId, value[0]);
167 int64_t rawIdTemp = rawId;
168 int64_t contactsId = 0;
169 Contacts contacts;
170 int contactsRet = contacts.InsertContact(store, rawIdTemp, value[0], contactsId);
171 if (contactsRet != OHOS::NativeRdb::E_OK) {
172 HILOG_ERROR("MatchCandidate AddNewContact is error %{public}d", contactsRet);
173 }
174 return contactsId;
175 }
176
ExecuteUpdateMode(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,std::set<int> Ids,int mode)177 int MatchCandidate::ExecuteUpdateMode(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, std::set<int> Ids, int mode)
178 {
179 int ret = RDB_EXECUTE_FAIL;
180 if (Ids.size() < 1) {
181 HILOG_ERROR("MatchCandidate::ExecuteUpdateMode Ids.size() < 1");
182 return ret;
183 }
184 std::string sql = "UPDATE ";
185 sql.append(ContactTableName::RAW_CONTACT)
186 .append(" SET ")
187 .append(RawContactColumns::MERGE_MODE)
188 .append(" = ")
189 .append(std::to_string(mode))
190 .append(" WHERE ");
191 for (auto it = Ids.begin(); it != Ids.end(); it++) {
192 sql.append("id = ").append(std::to_string(*it));
193 if (*it != *Ids.rbegin()) {
194 sql.append(" OR ");
195 }
196 }
197 ret = store->ExecuteSql(sql);
198 return ret;
199 }
200
UpdateMergeMode(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,Candidate candidate)201 int MatchCandidate::UpdateMergeMode(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, Candidate candidate)
202 {
203 HILOG_INFO("MatchCandidate::UpdateMergeMode is start mode :%{public}d ", candidate.mergeMode_);
204 int error = RDB_EXECUTE_FAIL;
205 switch (candidate.mergeMode_) {
206 case MERGE_MODE_DEFAULT:
207 error = ExecuteUpdateMode(store, candidate.manualIds_, MERGE_MODE_DEFAULT);
208 break;
209 case MERGE_MODE_MANUAL:
210 error = ExecuteUpdateMode(store, candidate.manualIds_, MERGE_MODE_MANUAL);
211 break;
212 case MERGE_MODE_AUTO:
213 error = ExecuteUpdateMode(store, candidate.autoIds_, MERGE_MODE_AUTO);
214 break;
215 default:
216 HILOG_ERROR("UpdateMergeMode mode error");
217 break;
218 }
219 return error;
220 }
221
UpdateRawContact(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,int rawId,int64_t contactsId)222 int MatchCandidate::UpdateRawContact(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, int rawId, int64_t contactsId)
223 {
224 std::string sql = "UPDATE ";
225 sql.append(ContactTableName::RAW_CONTACT)
226 .append(" SET ")
227 .append(RawContactColumns::CONTACT_ID)
228 .append(" = ")
229 .append(std::to_string(contactsId))
230 .append(", ")
231 .append(RawContactColumns::MERGE_MODE)
232 .append(" = 0, ")
233 .append(RawContactColumns::IS_NEED_MERGE)
234 .append(" = 1")
235 .append(" WHERE ")
236 .append(ContactPublicColumns::ID)
237 .append(" = ")
238 .append(std::to_string(rawId));
239 int code = store->ExecuteSql(sql);
240 return code;
241 }
242
ResultSetToValuesBucket(std::shared_ptr<OHOS::NativeRdb::ResultSet> & resultSet)243 std::vector<OHOS::NativeRdb::ValuesBucket> MatchCandidate::ResultSetToValuesBucket(
244 std::shared_ptr<OHOS::NativeRdb::ResultSet> &resultSet)
245 {
246 std::vector<std::string> columnNames;
247 resultSet->GetAllColumnNames(columnNames);
248 std::vector<OHOS::NativeRdb::ValuesBucket> vectorQueryData;
249 int resultSetNum = resultSet->GoToFirstRow();
250 while (resultSetNum == OHOS::NativeRdb::E_OK) {
251 OHOS::NativeRdb::ValuesBucket valuesBucketElement;
252 unsigned int size = columnNames.size();
253 for (unsigned int i = 0; i < size; i++) {
254 std::string typeValue = columnNames[i];
255 int columnIndex = 0;
256 resultSet->GetColumnIndex(typeValue, columnIndex);
257 OHOS::NativeRdb::ColumnType columnType;
258 resultSet->GetColumnType(columnIndex, columnType);
259 if (columnType == OHOS::NativeRdb::ColumnType::TYPE_INTEGER) {
260 int intValue = 0;
261 resultSet->GetInt(columnIndex, intValue);
262 valuesBucketElement.PutInt(typeValue, intValue);
263 } else if (columnType == OHOS::NativeRdb::ColumnType::TYPE_FLOAT) {
264 double doubleValue = 0;
265 resultSet->GetDouble(columnIndex, doubleValue);
266 valuesBucketElement.PutDouble(typeValue, doubleValue);
267 } else if (columnType == OHOS::NativeRdb::ColumnType::TYPE_STRING) {
268 std::string stringValue;
269 resultSet->GetString(columnIndex, stringValue);
270 valuesBucketElement.PutString(typeValue, stringValue);
271 }
272 }
273 vectorQueryData.push_back(valuesBucketElement);
274 resultSetNum = resultSet->GoToNextRow();
275 }
276 resultSet->Close();
277 return vectorQueryData;
278 }
279 } // namespace Contacts
280 } // namespace OHOS