12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SYNC_SYNCABLE_SYNCABLE_ID_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SYNC_SYNCABLE_SYNCABLE_ID_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iosfwd>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sstream>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/containers/hash_tables.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/base/sync_export.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockConnectionManager;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StringValue;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sql {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Statement;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncer {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncable {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct EntryKernel;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Id;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SYNC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, const Id& id);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For historical reasons, 3 concepts got everloaded into the Id:
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1. A unique, opaque identifier for the object.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2. Flag specifing whether server know about this object.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3. Flag for root.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We originally wrapped an integer for this information, but now we use a
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// string. It will have one of three forms:
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1. c<client only opaque id> for client items that have not been committed.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2. r for the root item.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3. s<server provided opaque id> for items that the server knows about.
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SYNC_EXPORT Id {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This constructor will be handy even when we move away from int64s, just
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for unit tests.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Id() : s_("r") { }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Id(const Id& that) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Copy(that);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Id& operator = (const Id& that) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Copy(that);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *this;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void Copy(const Id& that) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->s_ = that.s_;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool IsRoot() const {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "r" == s_;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool ServerKnows() const {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return s_[0] == 's' || s_ == "r";
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sync): We could use null here, but to ease conversion we use "r".
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fix this, this is madness :)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool IsNull() const {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return IsRoot();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void Clear() {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s_ = "r";
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int compare(const Id& that) const {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return s_.compare(that.s_);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator == (const Id& that) const {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return s_ == that.s_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator != (const Id& that) const {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return s_ != that.s_;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator < (const Id& that) const {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return s_ < that.s_;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator > (const Id& that) const {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return s_ > that.s_;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& value() const {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return s_;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return the next highest ID in the lexicographic ordering.  This is
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // useful for computing upper bounds on std::sets that are ordered
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by operator<.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Id GetLexicographicSuccessor() const;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Dumps the ID as a value and returns it.  Transfers ownership of
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the StringValue to the caller.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringValue* ToValue() const;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Three functions are used to work with our proto buffers.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetServerId() const;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static Id CreateFromServerId(const std::string& server_id);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should only be used if you get back a reference to a local
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // id from the server. Returns a client only opaque id.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static Id CreateFromClientString(const std::string& local_id);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This method returns an ID that will compare less than any valid ID.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The returned ID is not a valid ID itself.  This is useful for
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // computing lower bounds on std::sets that are ordered by operator<.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static Id GetLeastIdForLexicographicComparison();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend scoped_ptr<EntryKernel> UnpackEntry(sql::Statement* statement);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend void BindFields(const EntryKernel& entry,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         sql::Statement* statement);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SYNC_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& out,
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                      const Id& id);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class MockConnectionManager;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class SyncableIdTest;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string s_;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SYNC_EXPORT_PRIVATE Id GetNullId();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace syncable
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace syncer
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // SYNC_SYNCABLE_SYNCABLE_ID_H_
133