1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/dom_distiller/core/dom_distiller_model.h"
9 using syncer::SyncChange
;
10 using syncer::SyncChangeList
;
11 using syncer::SyncData
;
12 using syncer::SyncDataList
;
14 namespace dom_distiller
{
16 DomDistillerModel::DomDistillerModel()
19 DomDistillerModel::DomDistillerModel(
20 const std::vector
<ArticleEntry
>& initial_data
)
22 for (size_t i
= 0; i
< initial_data
.size(); ++i
) {
23 AddEntry(initial_data
[i
]);
27 DomDistillerModel::~DomDistillerModel() {}
29 bool DomDistillerModel::GetEntryById(const std::string
& entry_id
,
30 ArticleEntry
* entry
) const {
32 if (!GetKeyById(entry_id
, &key
)) {
35 GetEntryByKey(key
, entry
);
39 bool DomDistillerModel::GetEntryByUrl(const GURL
& url
,
40 ArticleEntry
* entry
) const {
42 if (!GetKeyByUrl(url
, &key
)) {
45 GetEntryByKey(key
, entry
);
49 bool DomDistillerModel::GetKeyById(const std::string
& entry_id
,
51 StringToKeyMap::const_iterator it
= entry_id_to_key_map_
.find(entry_id
);
52 if (it
== entry_id_to_key_map_
.end()) {
61 bool DomDistillerModel::GetKeyByUrl(const GURL
& url
, KeyType
* key
) const {
62 StringToKeyMap::const_iterator it
= url_to_key_map_
.find(url
.spec());
63 if (it
== url_to_key_map_
.end()) {
72 void DomDistillerModel::GetEntryByKey(KeyType key
, ArticleEntry
* entry
) const {
74 EntryMap::const_iterator it
= entries_
.find(key
);
75 DCHECK(it
!= entries_
.end());
80 size_t DomDistillerModel::GetNumEntries() const {
81 return entries_
.size();
84 std::vector
<ArticleEntry
> DomDistillerModel::GetEntries() const {
85 std::vector
<ArticleEntry
> entries_list
;
86 for (EntryMap::const_iterator it
= entries_
.begin(); it
!= entries_
.end();
88 entries_list
.push_back(it
->second
);
93 SyncDataList
DomDistillerModel::GetAllSyncData() const {
95 for (EntryMap::const_iterator it
= entries_
.begin(); it
!= entries_
.end();
97 data
.push_back(CreateLocalData(it
->second
));
102 void DomDistillerModel::CalculateChangesForMerge(
103 const SyncDataList
& data
,
104 SyncChangeList
* changes_to_apply
,
105 SyncChangeList
* changes_missing
) {
106 typedef base::hash_set
<std::string
> StringSet
;
107 StringSet entries_to_change
;
108 for (SyncDataList::const_iterator it
= data
.begin(); it
!= data
.end(); ++it
) {
109 std::string entry_id
= GetEntryIdFromSyncData(*it
);
110 std::pair
<StringSet::iterator
, bool> insert_result
=
111 entries_to_change
.insert(entry_id
);
113 DCHECK(insert_result
.second
);
115 SyncChange::SyncChangeType change_type
= SyncChange::ACTION_ADD
;
116 if (GetEntryById(entry_id
, NULL
)) {
117 change_type
= SyncChange::ACTION_UPDATE
;
119 changes_to_apply
->push_back(SyncChange(FROM_HERE
, change_type
, *it
));
122 for (EntryMap::const_iterator it
= entries_
.begin(); it
!= entries_
.end();
124 if (entries_to_change
.find(it
->second
.entry_id()) ==
125 entries_to_change
.end()) {
126 changes_missing
->push_back(SyncChange(
127 FROM_HERE
, SyncChange::ACTION_ADD
, CreateLocalData(it
->second
)));
132 void DomDistillerModel::ApplyChangesToModel(
133 const SyncChangeList
& changes
,
134 SyncChangeList
* changes_applied
,
135 SyncChangeList
* changes_missing
) {
136 DCHECK(changes_applied
);
137 DCHECK(changes_missing
);
139 for (SyncChangeList::const_iterator it
= changes
.begin(); it
!= changes
.end();
141 ApplyChangeToModel(*it
, changes_applied
, changes_missing
);
145 void DomDistillerModel::AddEntry(const ArticleEntry
& entry
) {
146 const std::string
& entry_id
= entry
.entry_id();
147 KeyType key
= next_key_
++;
148 DCHECK(!GetKeyById(entry_id
, NULL
));
149 entries_
.insert(std::make_pair(key
, entry
));
150 entry_id_to_key_map_
.insert(std::make_pair(entry_id
, key
));
151 for (int i
= 0; i
< entry
.pages_size(); ++i
) {
152 url_to_key_map_
.insert(std::make_pair(entry
.pages(i
).url(), key
));
156 void DomDistillerModel::RemoveEntry(const ArticleEntry
& entry
) {
157 const std::string
& entry_id
= entry
.entry_id();
159 bool success
= GetKeyById(entry_id
, &key
);
163 entry_id_to_key_map_
.erase(entry_id
);
164 for (int i
= 0; i
< entry
.pages_size(); ++i
) {
165 url_to_key_map_
.erase(entry
.pages(i
).url());
169 void DomDistillerModel::ApplyChangeToModel(
170 const SyncChange
& change
,
171 SyncChangeList
* changes_applied
,
172 SyncChangeList
* changes_missing
) {
173 DCHECK(change
.IsValid());
174 DCHECK(changes_applied
);
175 DCHECK(changes_missing
);
177 const std::string
& entry_id
= GetEntryIdFromSyncData(change
.sync_data());
179 if (change
.change_type() == SyncChange::ACTION_DELETE
) {
180 ArticleEntry current_entry
;
181 if (GetEntryById(entry_id
, ¤t_entry
)) {
182 RemoveEntry(current_entry
);
183 changes_applied
->push_back(SyncChange(
184 change
.location(), SyncChange::ACTION_DELETE
, change
.sync_data()));
186 // If we couldn't find in sync db, we were deleting anyway so swallow the
191 ArticleEntry entry
= GetEntryFromChange(change
);
192 ArticleEntry current_entry
;
193 if (!GetEntryById(entry_id
, ¤t_entry
)) {
195 changes_applied
->push_back(SyncChange(
196 change
.location(), SyncChange::ACTION_ADD
, change
.sync_data()));
198 if (!AreEntriesEqual(current_entry
, entry
)) {
199 // Currently, conflicts are simply resolved by accepting the last one to
201 RemoveEntry(current_entry
);
203 changes_applied
->push_back(SyncChange(
204 change
.location(), SyncChange::ACTION_UPDATE
, change
.sync_data()));
209 } // namespace dom_distiller