Home | History | Annotate | Download | only in syncable
      1 // Copyright 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/syncable/entry.h"
      6 
      7 #include <iomanip>
      8 
      9 #include "base/json/string_escape.h"
     10 #include "base/strings/string_util.h"
     11 #include "sync/syncable/blob.h"
     12 #include "sync/syncable/directory.h"
     13 #include "sync/syncable/syncable_base_transaction.h"
     14 #include "sync/syncable/syncable_columns.h"
     15 
     16 using std::string;
     17 
     18 namespace syncer {
     19 namespace syncable {
     20 
     21 Entry::Entry(BaseTransaction* trans, GetById, const Id& id)
     22     : basetrans_(trans) {
     23   kernel_ = trans->directory()->GetEntryById(id);
     24 }
     25 
     26 Entry::Entry(BaseTransaction* trans, GetByClientTag, const string& tag)
     27     : basetrans_(trans) {
     28   kernel_ = trans->directory()->GetEntryByClientTag(tag);
     29 }
     30 
     31 Entry::Entry(BaseTransaction* trans, GetTypeRoot, ModelType type)
     32     : basetrans_(trans) {
     33   const std::string& tag = ModelTypeToRootTag(type);
     34   kernel_ = trans->directory()->GetEntryByServerTag(tag);
     35 }
     36 
     37 Entry::Entry(BaseTransaction* trans, GetByHandle, int64 metahandle)
     38     : basetrans_(trans) {
     39   kernel_ = trans->directory()->GetEntryByHandle(metahandle);
     40 }
     41 
     42 Entry::Entry(BaseTransaction* trans, GetByServerTag, const string& tag)
     43     : basetrans_(trans) {
     44   kernel_ = trans->directory()->GetEntryByServerTag(tag);
     45 }
     46 
     47 Directory* Entry::dir() const {
     48   return basetrans_->directory();
     49 }
     50 
     51 base::DictionaryValue* Entry::ToValue(Cryptographer* cryptographer) const {
     52   base::DictionaryValue* entry_info = new base::DictionaryValue();
     53   entry_info->SetBoolean("good", good());
     54   if (good()) {
     55     entry_info->Set("kernel", kernel_->ToValue(cryptographer));
     56     entry_info->Set("modelType",
     57                     ModelTypeToValue(GetModelType()));
     58     entry_info->SetBoolean("existsOnClientBecauseNameIsNonEmpty",
     59                            ExistsOnClientBecauseNameIsNonEmpty());
     60     entry_info->SetBoolean("isRoot", IsRoot());
     61   }
     62   return entry_info;
     63 }
     64 
     65 ModelType Entry::GetServerModelType() const {
     66   ModelType specifics_type = kernel_->GetServerModelType();
     67   if (specifics_type != UNSPECIFIED)
     68     return specifics_type;
     69 
     70   // Otherwise, we don't have a server type yet.  That should only happen
     71   // if the item is an uncommitted locally created item.
     72   // It's possible we'll need to relax these checks in the future; they're
     73   // just here for now as a safety measure.
     74   DCHECK(GetIsUnsynced());
     75   DCHECK_EQ(GetServerVersion(), 0);
     76   DCHECK(GetServerIsDel());
     77   // Note: can't enforce !GetId().ServerKnows() here because that could
     78   // actually happen if we hit AttemptReuniteLostCommitResponses.
     79   return UNSPECIFIED;
     80 }
     81 
     82 ModelType Entry::GetModelType() const {
     83   ModelType specifics_type = GetModelTypeFromSpecifics(GetSpecifics());
     84   if (specifics_type != UNSPECIFIED)
     85     return specifics_type;
     86   if (IsRoot())
     87     return TOP_LEVEL_FOLDER;
     88   // Loose check for server-created top-level folders that aren't
     89   // bound to a particular model type.
     90   if (!GetUniqueServerTag().empty() && GetIsDir())
     91     return TOP_LEVEL_FOLDER;
     92 
     93   return UNSPECIFIED;
     94 }
     95 
     96 Id Entry::GetPredecessorId() const {
     97   return dir()->GetPredecessorId(kernel_);
     98 }
     99 
    100 Id Entry::GetSuccessorId() const {
    101   return dir()->GetSuccessorId(kernel_);
    102 }
    103 
    104 Id Entry::GetFirstChildId() const {
    105   return dir()->GetFirstChildId(basetrans_, kernel_);
    106 }
    107 
    108 void Entry::GetChildHandles(std::vector<int64>* result) const {
    109   dir()->GetChildHandlesById(basetrans_, GetId(), result);
    110 }
    111 
    112 int Entry::GetTotalNodeCount() const {
    113   return dir()->GetTotalNodeCount(basetrans_, kernel_);
    114 }
    115 
    116 int Entry::GetPositionIndex() const {
    117   return dir()->GetPositionIndex(basetrans_, kernel_);
    118 }
    119 
    120 bool Entry::ShouldMaintainPosition() const {
    121   return kernel_->ShouldMaintainPosition();
    122 }
    123 
    124 bool Entry::ShouldMaintainHierarchy() const {
    125   return kernel_->ShouldMaintainHierarchy();
    126 }
    127 
    128 std::ostream& operator<<(std::ostream& s, const Blob& blob) {
    129   for (Blob::const_iterator i = blob.begin(); i != blob.end(); ++i)
    130     s << std::hex << std::setw(2)
    131       << std::setfill('0') << static_cast<unsigned int>(*i);
    132   return s << std::dec;
    133 }
    134 
    135 std::ostream& operator<<(std::ostream& os, const Entry& entry) {
    136   int i;
    137   EntryKernel* const kernel = entry.kernel_;
    138   for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) {
    139     os << g_metas_columns[i].name << ": "
    140        << kernel->ref(static_cast<Int64Field>(i)) << ", ";
    141   }
    142   for ( ; i < TIME_FIELDS_END; ++i) {
    143     os << g_metas_columns[i].name << ": "
    144        << GetTimeDebugString(kernel->ref(static_cast<TimeField>(i))) << ", ";
    145   }
    146   for ( ; i < ID_FIELDS_END; ++i) {
    147     os << g_metas_columns[i].name << ": "
    148        << kernel->ref(static_cast<IdField>(i)) << ", ";
    149   }
    150   os << "Flags: ";
    151   for ( ; i < BIT_FIELDS_END; ++i) {
    152     if (kernel->ref(static_cast<BitField>(i)))
    153       os << g_metas_columns[i].name << ", ";
    154   }
    155   for ( ; i < STRING_FIELDS_END; ++i) {
    156     const std::string& field = kernel->ref(static_cast<StringField>(i));
    157     os << g_metas_columns[i].name << ": " << field << ", ";
    158   }
    159   for ( ; i < PROTO_FIELDS_END; ++i) {
    160     std::string escaped_str = base::EscapeBytesAsInvalidJSONString(
    161         kernel->ref(static_cast<ProtoField>(i)).SerializeAsString(),
    162         false);
    163     os << g_metas_columns[i].name << ": " << escaped_str << ", ";
    164   }
    165   for ( ; i < UNIQUE_POSITION_FIELDS_END; ++i) {
    166     os << g_metas_columns[i].name << ": "
    167        << kernel->ref(static_cast<UniquePositionField>(i)).ToDebugString()
    168        << ", ";
    169   }
    170   for ( ; i < ATTACHMENT_METADATA_FIELDS_END; ++i) {
    171     std::string escaped_str = base::EscapeBytesAsInvalidJSONString(
    172         kernel->ref(static_cast<AttachmentMetadataField>(i))
    173             .SerializeAsString(),
    174         false);
    175     os << g_metas_columns[i].name << ": " << escaped_str << ", ";
    176   }
    177   os << "TempFlags: ";
    178   for ( ; i < BIT_TEMPS_END; ++i) {
    179     if (kernel->ref(static_cast<BitTemp>(i)))
    180       os << "#" << i - BIT_TEMPS_BEGIN << ", ";
    181   }
    182   return os;
    183 }
    184 
    185 }  // namespace syncable
    186 }  // namespace syncer
    187