sync_data.cc revision 010d83a9304c5a91596085d917d248abff47903a
1// Copyright (c) 2012 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.
4
5#include "sync/api/sync_data.h"
6
7#include <ostream>
8
9#include "base/json/json_writer.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/strings/string_number_conversions.h"
12#include "base/values.h"
13#include "sync/api/attachments/attachment_service_proxy.h"
14#include "sync/internal_api/public/base/model_type.h"
15#include "sync/internal_api/public/base_node.h"
16#include "sync/protocol/proto_value_conversions.h"
17#include "sync/protocol/sync.pb.h"
18
19using syncer::Attachment;
20using syncer::AttachmentIdList;
21using syncer::AttachmentList;
22
23namespace {
24
25sync_pb::AttachmentIdProto AttachmentToProto(
26    const syncer::Attachment& attachment) {
27  return attachment.GetId().GetProto();
28}
29
30sync_pb::AttachmentIdProto IdToProto(
31    const syncer::AttachmentId& attachment_id) {
32  return attachment_id.GetProto();
33}
34
35syncer::AttachmentId ProtoToId(const sync_pb::AttachmentIdProto& proto) {
36  return syncer::AttachmentId::CreateFromProto(proto);
37}
38
39// Return true iff |attachments| contains one or more elements with the same
40// AttachmentId.
41bool ContainsDuplicateAttachments(const syncer::AttachmentList& attachments) {
42  std::set<syncer::AttachmentId> id_set;
43  AttachmentList::const_iterator iter = attachments.begin();
44  AttachmentList::const_iterator end = attachments.end();
45  for (; iter != end; ++iter) {
46    if (id_set.find(iter->GetId()) != id_set.end()) {
47      return true;
48    }
49    id_set.insert(iter->GetId());
50  }
51  return false;
52}
53
54}  // namespace
55
56namespace syncer {
57
58void SyncData::ImmutableSyncEntityTraits::InitializeWrapper(Wrapper* wrapper) {
59  *wrapper = new sync_pb::SyncEntity();
60}
61
62void SyncData::ImmutableSyncEntityTraits::DestroyWrapper(Wrapper* wrapper) {
63  delete *wrapper;
64}
65
66const sync_pb::SyncEntity& SyncData::ImmutableSyncEntityTraits::Unwrap(
67    const Wrapper& wrapper) {
68  return *wrapper;
69}
70
71sync_pb::SyncEntity* SyncData::ImmutableSyncEntityTraits::UnwrapMutable(
72    Wrapper* wrapper) {
73  return *wrapper;
74}
75
76void SyncData::ImmutableSyncEntityTraits::Swap(sync_pb::SyncEntity* t1,
77                                               sync_pb::SyncEntity* t2) {
78  t1->Swap(t2);
79}
80
81SyncData::SyncData() : id_(kInvalidId), is_valid_(false) {}
82
83SyncData::SyncData(int64 id,
84                   sync_pb::SyncEntity* entity,
85                   AttachmentList* attachments,
86                   const base::Time& remote_modification_time,
87                   const syncer::AttachmentServiceProxy& attachment_service)
88    : id_(id),
89      remote_modification_time_(remote_modification_time),
90      immutable_entity_(entity),
91      attachments_(attachments),
92      attachment_service_(attachment_service),
93      is_valid_(true) {}
94
95SyncData::~SyncData() {}
96
97// Static.
98SyncData SyncData::CreateLocalDelete(const std::string& sync_tag,
99                                     ModelType datatype) {
100  sync_pb::EntitySpecifics specifics;
101  AddDefaultFieldValue(datatype, &specifics);
102  return CreateLocalData(sync_tag, std::string(), specifics);
103}
104
105// Static.
106SyncData SyncData::CreateLocalData(const std::string& sync_tag,
107                                   const std::string& non_unique_title,
108                                   const sync_pb::EntitySpecifics& specifics) {
109  syncer::AttachmentList attachments;
110  return CreateLocalDataWithAttachments(
111      sync_tag, non_unique_title, specifics, attachments);
112}
113
114// Static.
115SyncData SyncData::CreateLocalDataWithAttachments(
116    const std::string& sync_tag,
117    const std::string& non_unique_title,
118    const sync_pb::EntitySpecifics& specifics,
119    const AttachmentList& attachments) {
120  DCHECK(!ContainsDuplicateAttachments(attachments));
121  sync_pb::SyncEntity entity;
122  entity.set_client_defined_unique_tag(sync_tag);
123  entity.set_non_unique_name(non_unique_title);
124  entity.mutable_specifics()->CopyFrom(specifics);
125  std::transform(attachments.begin(),
126                 attachments.end(),
127                 RepeatedFieldBackInserter(entity.mutable_attachment_id()),
128                 AttachmentToProto);
129  AttachmentList copy_of_attachments(attachments);
130  return SyncData(kInvalidId,
131                  &entity,
132                  &copy_of_attachments,
133                  base::Time(),
134                  AttachmentServiceProxy());
135}
136
137// Static.
138SyncData SyncData::CreateRemoteData(
139    int64 id,
140    const sync_pb::EntitySpecifics& specifics,
141    const base::Time& modification_time,
142    const AttachmentIdList& attachment_ids,
143    const AttachmentServiceProxy& attachment_service) {
144  DCHECK_NE(id, kInvalidId);
145  sync_pb::SyncEntity entity;
146  entity.mutable_specifics()->CopyFrom(specifics);
147  std::transform(attachment_ids.begin(),
148                 attachment_ids.end(),
149                 RepeatedFieldBackInserter(entity.mutable_attachment_id()),
150                 IdToProto);
151  AttachmentList attachments;
152  return SyncData(
153      id, &entity, &attachments, modification_time, attachment_service);
154}
155
156bool SyncData::IsValid() const { return is_valid_; }
157
158const sync_pb::EntitySpecifics& SyncData::GetSpecifics() const {
159  return immutable_entity_.Get().specifics();
160}
161
162ModelType SyncData::GetDataType() const {
163  return GetModelTypeFromSpecifics(GetSpecifics());
164}
165
166const std::string& SyncData::GetTitle() const {
167  // TODO(zea): set this for data coming from the syncer too.
168  DCHECK(immutable_entity_.Get().has_non_unique_name());
169  return immutable_entity_.Get().non_unique_name();
170}
171
172bool SyncData::IsLocal() const { return id_ == kInvalidId; }
173
174std::string SyncData::ToString() const {
175  if (!IsValid())
176    return "<Invalid SyncData>";
177
178  std::string type = ModelTypeToString(GetDataType());
179  std::string specifics;
180  scoped_ptr<base::DictionaryValue> value(
181      EntitySpecificsToValue(GetSpecifics()));
182  base::JSONWriter::WriteWithOptions(
183      value.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &specifics);
184
185  if (IsLocal()) {
186    SyncDataLocal sync_data_local(*this);
187    return "{ isLocal: true, type: " + type + ", tag: " +
188           sync_data_local.GetTag() + ", title: " + GetTitle() +
189           ", specifics: " + specifics + "}";
190  }
191
192  SyncDataRemote sync_data_remote(*this);
193  std::string id = base::Int64ToString(sync_data_remote.GetId());
194  return "{ isLocal: false, type: " + type + ", specifics: " + specifics +
195         ", id: " + id + "}";
196}
197
198void PrintTo(const SyncData& sync_data, std::ostream* os) {
199  *os << sync_data.ToString();
200}
201
202AttachmentIdList SyncData::GetAttachmentIds() const {
203  AttachmentIdList result;
204  const sync_pb::SyncEntity& entity = immutable_entity_.Get();
205  std::transform(entity.attachment_id().begin(),
206                 entity.attachment_id().end(),
207                 std::back_inserter(result),
208                 ProtoToId);
209  return result;
210}
211
212SyncDataLocal::SyncDataLocal(const SyncData& sync_data) : SyncData(sync_data) {
213  DCHECK(sync_data.IsLocal());
214}
215
216SyncDataLocal::~SyncDataLocal() {}
217
218const AttachmentList& SyncDataLocal::GetLocalAttachmentsForUpload() const {
219  return attachments_.Get();
220}
221
222const std::string& SyncDataLocal::GetTag() const {
223  return immutable_entity_.Get().client_defined_unique_tag();
224}
225
226SyncDataRemote::SyncDataRemote(const SyncData& sync_data)
227    : SyncData(sync_data) {
228  DCHECK(!sync_data.IsLocal());
229}
230
231SyncDataRemote::~SyncDataRemote() {}
232
233const base::Time& SyncDataRemote::GetModifiedTime() const {
234  return remote_modification_time_;
235}
236
237int64 SyncDataRemote::GetId() const {
238  return id_;
239}
240
241void SyncDataRemote::GetOrDownloadAttachments(
242    const AttachmentIdList& attachment_ids,
243    const AttachmentService::GetOrDownloadCallback& callback) {
244  attachment_service_.GetOrDownloadAttachments(attachment_ids, callback);
245}
246
247void SyncDataRemote::DropAttachments(
248    const AttachmentIdList& attachment_ids,
249    const AttachmentService::DropCallback& callback) {
250  attachment_service_.DropAttachments(attachment_ids, callback);
251}
252
253}  // namespace syncer
254