Home | History | Annotate | Download | only in api
      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                   &copy_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