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 19 using syncer::Attachment; 20 using syncer::AttachmentIdList; 21 using syncer::AttachmentList; 22 23 namespace { 24 25 sync_pb::AttachmentIdProto AttachmentToProto( 26 const syncer::Attachment& attachment) { 27 return attachment.GetId().GetProto(); 28 } 29 30 sync_pb::AttachmentIdProto IdToProto( 31 const syncer::AttachmentId& attachment_id) { 32 return attachment_id.GetProto(); 33 } 34 35 syncer::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. 41 bool 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 56 namespace syncer { 57 58 void SyncData::ImmutableSyncEntityTraits::InitializeWrapper(Wrapper* wrapper) { 59 *wrapper = new sync_pb::SyncEntity(); 60 } 61 62 void SyncData::ImmutableSyncEntityTraits::DestroyWrapper(Wrapper* wrapper) { 63 delete *wrapper; 64 } 65 66 const sync_pb::SyncEntity& SyncData::ImmutableSyncEntityTraits::Unwrap( 67 const Wrapper& wrapper) { 68 return *wrapper; 69 } 70 71 sync_pb::SyncEntity* SyncData::ImmutableSyncEntityTraits::UnwrapMutable( 72 Wrapper* wrapper) { 73 return *wrapper; 74 } 75 76 void SyncData::ImmutableSyncEntityTraits::Swap(sync_pb::SyncEntity* t1, 77 sync_pb::SyncEntity* t2) { 78 t1->Swap(t2); 79 } 80 81 SyncData::SyncData() : id_(kInvalidId), is_valid_(false) {} 82 83 SyncData::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 95 SyncData::~SyncData() {} 96 97 // Static. 98 SyncData 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. 106 SyncData 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. 115 SyncData 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 ©_of_attachments, 133 base::Time(), 134 AttachmentServiceProxy()); 135 } 136 137 // Static. 138 SyncData 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 156 bool SyncData::IsValid() const { return is_valid_; } 157 158 const sync_pb::EntitySpecifics& SyncData::GetSpecifics() const { 159 return immutable_entity_.Get().specifics(); 160 } 161 162 ModelType SyncData::GetDataType() const { 163 return GetModelTypeFromSpecifics(GetSpecifics()); 164 } 165 166 const 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 172 bool SyncData::IsLocal() const { return id_ == kInvalidId; } 173 174 std::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 198 void PrintTo(const SyncData& sync_data, std::ostream* os) { 199 *os << sync_data.ToString(); 200 } 201 202 AttachmentIdList 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 212 SyncDataLocal::SyncDataLocal(const SyncData& sync_data) : SyncData(sync_data) { 213 DCHECK(sync_data.IsLocal()); 214 } 215 216 SyncDataLocal::~SyncDataLocal() {} 217 218 const AttachmentList& SyncDataLocal::GetLocalAttachmentsForUpload() const { 219 return attachments_.Get(); 220 } 221 222 const std::string& SyncDataLocal::GetTag() const { 223 return immutable_entity_.Get().client_defined_unique_tag(); 224 } 225 226 SyncDataRemote::SyncDataRemote(const SyncData& sync_data) 227 : SyncData(sync_data) { 228 DCHECK(!sync_data.IsLocal()); 229 } 230 231 SyncDataRemote::~SyncDataRemote() {} 232 233 const base::Time& SyncDataRemote::GetModifiedTime() const { 234 return remote_modification_time_; 235 } 236 237 int64 SyncDataRemote::GetId() const { 238 return id_; 239 } 240 241 void SyncDataRemote::GetOrDownloadAttachments( 242 const AttachmentIdList& attachment_ids, 243 const AttachmentService::GetOrDownloadCallback& callback) { 244 attachment_service_.GetOrDownloadAttachments(attachment_ids, callback); 245 } 246 247 void 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