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 16using std::string; 17 18namespace syncer { 19namespace syncable { 20 21Entry::Entry(BaseTransaction* trans, GetById, const Id& id) 22 : basetrans_(trans) { 23 kernel_ = trans->directory()->GetEntryById(id); 24} 25 26Entry::Entry(BaseTransaction* trans, GetByClientTag, const string& tag) 27 : basetrans_(trans) { 28 kernel_ = trans->directory()->GetEntryByClientTag(tag); 29} 30 31Entry::Entry(BaseTransaction* trans, GetTypeRoot, ModelType type) 32 : basetrans_(trans) { 33 const std::string& tag = ModelTypeToRootTag(type); 34 kernel_ = trans->directory()->GetEntryByServerTag(tag); 35} 36 37Entry::Entry(BaseTransaction* trans, GetByHandle, int64 metahandle) 38 : basetrans_(trans) { 39 kernel_ = trans->directory()->GetEntryByHandle(metahandle); 40} 41 42Entry::Entry(BaseTransaction* trans, GetByServerTag, const string& tag) 43 : basetrans_(trans) { 44 kernel_ = trans->directory()->GetEntryByServerTag(tag); 45} 46 47Directory* Entry::dir() const { 48 return basetrans_->directory(); 49} 50 51base::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 65ModelType 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 82ModelType 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 96Id Entry::GetPredecessorId() const { 97 return dir()->GetPredecessorId(kernel_); 98} 99 100Id Entry::GetSuccessorId() const { 101 return dir()->GetSuccessorId(kernel_); 102} 103 104Id Entry::GetFirstChildId() const { 105 return dir()->GetFirstChildId(basetrans_, kernel_); 106} 107 108void Entry::GetChildHandles(std::vector<int64>* result) const { 109 dir()->GetChildHandlesById(basetrans_, GetId(), result); 110} 111 112int Entry::GetTotalNodeCount() const { 113 return dir()->GetTotalNodeCount(basetrans_, kernel_); 114} 115 116int Entry::GetPositionIndex() const { 117 return dir()->GetPositionIndex(basetrans_, kernel_); 118} 119 120bool Entry::ShouldMaintainPosition() const { 121 return kernel_->ShouldMaintainPosition(); 122} 123 124bool Entry::ShouldMaintainHierarchy() const { 125 return kernel_->ShouldMaintainHierarchy(); 126} 127 128std::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 135std::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