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