entry.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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
124std::ostream& operator<<(std::ostream& s, const Blob& blob) {
125  for (Blob::const_iterator i = blob.begin(); i != blob.end(); ++i)
126    s << std::hex << std::setw(2)
127      << std::setfill('0') << static_cast<unsigned int>(*i);
128  return s << std::dec;
129}
130
131std::ostream& operator<<(std::ostream& os, const Entry& entry) {
132  int i;
133  EntryKernel* const kernel = entry.kernel_;
134  for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) {
135    os << g_metas_columns[i].name << ": "
136       << kernel->ref(static_cast<Int64Field>(i)) << ", ";
137  }
138  for ( ; i < TIME_FIELDS_END; ++i) {
139    os << g_metas_columns[i].name << ": "
140       << GetTimeDebugString(kernel->ref(static_cast<TimeField>(i))) << ", ";
141  }
142  for ( ; i < ID_FIELDS_END; ++i) {
143    os << g_metas_columns[i].name << ": "
144       << kernel->ref(static_cast<IdField>(i)) << ", ";
145  }
146  os << "Flags: ";
147  for ( ; i < BIT_FIELDS_END; ++i) {
148    if (kernel->ref(static_cast<BitField>(i)))
149      os << g_metas_columns[i].name << ", ";
150  }
151  for ( ; i < STRING_FIELDS_END; ++i) {
152    const std::string& field = kernel->ref(static_cast<StringField>(i));
153    os << g_metas_columns[i].name << ": " << field << ", ";
154  }
155  for ( ; i < PROTO_FIELDS_END; ++i) {
156    std::string escaped_str = base::EscapeBytesAsInvalidJSONString(
157        kernel->ref(static_cast<ProtoField>(i)).SerializeAsString(),
158        false);
159    os << g_metas_columns[i].name << ": " << escaped_str << ", ";
160  }
161  for ( ; i < UNIQUE_POSITION_FIELDS_END; ++i) {
162    os << g_metas_columns[i].name << ": "
163       << kernel->ref(static_cast<UniquePositionField>(i)).ToDebugString()
164       << ", ";
165  }
166  for ( ; i < ATTACHMENT_METADATA_FIELDS_END; ++i) {
167    std::string escaped_str = base::EscapeBytesAsInvalidJSONString(
168        kernel->ref(static_cast<AttachmentMetadataField>(i))
169            .SerializeAsString(),
170        false);
171    os << g_metas_columns[i].name << ": " << escaped_str << ", ";
172  }
173  os << "TempFlags: ";
174  for ( ; i < BIT_TEMPS_END; ++i) {
175    if (kernel->ref(static_cast<BitTemp>(i)))
176      os << "#" << i - BIT_TEMPS_BEGIN << ", ";
177  }
178  return os;
179}
180
181}  // namespace syncable
182}  // namespace syncer
183