| // Copyright 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "sync/syncable/entry.h" |
| |
| #include <iomanip> |
| |
| #include "base/json/string_escape.h" |
| #include "base/strings/string_util.h" |
| #include "sync/syncable/blob.h" |
| #include "sync/syncable/directory.h" |
| #include "sync/syncable/syncable_base_transaction.h" |
| #include "sync/syncable/syncable_columns.h" |
| |
| using std::string; |
| |
| namespace syncer { |
| namespace syncable { |
| |
| Entry::Entry(BaseTransaction* trans, GetById, const Id& id) |
| : basetrans_(trans) { |
| kernel_ = trans->directory()->GetEntryById(id); |
| } |
| |
| Entry::Entry(BaseTransaction* trans, GetByClientTag, const string& tag) |
| : basetrans_(trans) { |
| kernel_ = trans->directory()->GetEntryByClientTag(tag); |
| } |
| |
| Entry::Entry(BaseTransaction* trans, GetTypeRoot, ModelType type) |
| : basetrans_(trans) { |
| const std::string& tag = ModelTypeToRootTag(type); |
| kernel_ = trans->directory()->GetEntryByServerTag(tag); |
| } |
| |
| Entry::Entry(BaseTransaction* trans, GetByHandle, int64 metahandle) |
| : basetrans_(trans) { |
| kernel_ = trans->directory()->GetEntryByHandle(metahandle); |
| } |
| |
| Entry::Entry(BaseTransaction* trans, GetByServerTag, const string& tag) |
| : basetrans_(trans) { |
| kernel_ = trans->directory()->GetEntryByServerTag(tag); |
| } |
| |
| Directory* Entry::dir() const { |
| return basetrans_->directory(); |
| } |
| |
| base::DictionaryValue* Entry::ToValue(Cryptographer* cryptographer) const { |
| base::DictionaryValue* entry_info = new base::DictionaryValue(); |
| entry_info->SetBoolean("good", good()); |
| if (good()) { |
| entry_info->Set("kernel", kernel_->ToValue(cryptographer)); |
| entry_info->Set("modelType", |
| ModelTypeToValue(GetModelType())); |
| entry_info->SetBoolean("existsOnClientBecauseNameIsNonEmpty", |
| ExistsOnClientBecauseNameIsNonEmpty()); |
| entry_info->SetBoolean("isRoot", IsRoot()); |
| } |
| return entry_info; |
| } |
| |
| ModelType Entry::GetServerModelType() const { |
| ModelType specifics_type = kernel_->GetServerModelType(); |
| if (specifics_type != UNSPECIFIED) |
| return specifics_type; |
| |
| // Otherwise, we don't have a server type yet. That should only happen |
| // if the item is an uncommitted locally created item. |
| // It's possible we'll need to relax these checks in the future; they're |
| // just here for now as a safety measure. |
| DCHECK(GetIsUnsynced()); |
| DCHECK_EQ(GetServerVersion(), 0); |
| DCHECK(GetServerIsDel()); |
| // Note: can't enforce !GetId().ServerKnows() here because that could |
| // actually happen if we hit AttemptReuniteLostCommitResponses. |
| return UNSPECIFIED; |
| } |
| |
| ModelType Entry::GetModelType() const { |
| ModelType specifics_type = GetModelTypeFromSpecifics(GetSpecifics()); |
| if (specifics_type != UNSPECIFIED) |
| return specifics_type; |
| if (IsRoot()) |
| return TOP_LEVEL_FOLDER; |
| // Loose check for server-created top-level folders that aren't |
| // bound to a particular model type. |
| if (!GetUniqueServerTag().empty() && GetIsDir()) |
| return TOP_LEVEL_FOLDER; |
| |
| return UNSPECIFIED; |
| } |
| |
| Id Entry::GetPredecessorId() const { |
| return dir()->GetPredecessorId(kernel_); |
| } |
| |
| Id Entry::GetSuccessorId() const { |
| return dir()->GetSuccessorId(kernel_); |
| } |
| |
| Id Entry::GetFirstChildId() const { |
| return dir()->GetFirstChildId(basetrans_, kernel_); |
| } |
| |
| void Entry::GetChildHandles(std::vector<int64>* result) const { |
| dir()->GetChildHandlesById(basetrans_, GetId(), result); |
| } |
| |
| int Entry::GetTotalNodeCount() const { |
| return dir()->GetTotalNodeCount(basetrans_, kernel_); |
| } |
| |
| int Entry::GetPositionIndex() const { |
| return dir()->GetPositionIndex(basetrans_, kernel_); |
| } |
| |
| bool Entry::ShouldMaintainPosition() const { |
| return kernel_->ShouldMaintainPosition(); |
| } |
| |
| bool Entry::ShouldMaintainHierarchy() const { |
| return kernel_->ShouldMaintainHierarchy(); |
| } |
| |
| std::ostream& operator<<(std::ostream& s, const Blob& blob) { |
| for (Blob::const_iterator i = blob.begin(); i != blob.end(); ++i) |
| s << std::hex << std::setw(2) |
| << std::setfill('0') << static_cast<unsigned int>(*i); |
| return s << std::dec; |
| } |
| |
| std::ostream& operator<<(std::ostream& os, const Entry& entry) { |
| int i; |
| EntryKernel* const kernel = entry.kernel_; |
| for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) { |
| os << g_metas_columns[i].name << ": " |
| << kernel->ref(static_cast<Int64Field>(i)) << ", "; |
| } |
| for ( ; i < TIME_FIELDS_END; ++i) { |
| os << g_metas_columns[i].name << ": " |
| << GetTimeDebugString(kernel->ref(static_cast<TimeField>(i))) << ", "; |
| } |
| for ( ; i < ID_FIELDS_END; ++i) { |
| os << g_metas_columns[i].name << ": " |
| << kernel->ref(static_cast<IdField>(i)) << ", "; |
| } |
| os << "Flags: "; |
| for ( ; i < BIT_FIELDS_END; ++i) { |
| if (kernel->ref(static_cast<BitField>(i))) |
| os << g_metas_columns[i].name << ", "; |
| } |
| for ( ; i < STRING_FIELDS_END; ++i) { |
| const std::string& field = kernel->ref(static_cast<StringField>(i)); |
| os << g_metas_columns[i].name << ": " << field << ", "; |
| } |
| for ( ; i < PROTO_FIELDS_END; ++i) { |
| std::string escaped_str = base::EscapeBytesAsInvalidJSONString( |
| kernel->ref(static_cast<ProtoField>(i)).SerializeAsString(), |
| false); |
| os << g_metas_columns[i].name << ": " << escaped_str << ", "; |
| } |
| for ( ; i < UNIQUE_POSITION_FIELDS_END; ++i) { |
| os << g_metas_columns[i].name << ": " |
| << kernel->ref(static_cast<UniquePositionField>(i)).ToDebugString() |
| << ", "; |
| } |
| for ( ; i < ATTACHMENT_METADATA_FIELDS_END; ++i) { |
| std::string escaped_str = base::EscapeBytesAsInvalidJSONString( |
| kernel->ref(static_cast<AttachmentMetadataField>(i)) |
| .SerializeAsString(), |
| false); |
| os << g_metas_columns[i].name << ": " << escaped_str << ", "; |
| } |
| os << "TempFlags: "; |
| for ( ; i < BIT_TEMPS_END; ++i) { |
| if (kernel->ref(static_cast<BitTemp>(i))) |
| os << "#" << i - BIT_TEMPS_BEGIN << ", "; |
| } |
| return os; |
| } |
| |
| } // namespace syncable |
| } // namespace syncer |