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