1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_INTERNAL_COMMON_METADATA_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_INTERNAL_COMMON_METADATA_H
17 
18 #include "google/cloud/storage/version.h"
19 #include "google/cloud/status_or.h"
20 #include "absl/types/optional.h"
21 #include <chrono>
22 #include <map>
23 #include <utility>
24 #include <vector>
25 
26 namespace google {
27 namespace cloud {
28 namespace storage {
29 inline namespace STORAGE_CLIENT_NS {
30 /// A simple wrapper for the `owner` field in `internal::CommonMetadata`.
31 struct Owner {
32   std::string entity;
33   std::string entity_id;
34 };
35 
36 inline bool operator==(Owner const& lhs, Owner const& rhs) {
37   return std::tie(lhs.entity, lhs.entity_id) ==
38          std::tie(rhs.entity, rhs.entity_id);
39 }
40 
41 inline bool operator<(Owner const& lhs, Owner const& rhs) {
42   return std::tie(lhs.entity, lhs.entity_id) <
43          std::tie(rhs.entity, rhs.entity_id);
44 }
45 
46 inline bool operator!=(Owner const& lhs, Owner const& rhs) {
47   return std::rel_ops::operator!=(lhs, rhs);
48 }
49 
50 inline bool operator>(Owner const& lhs, Owner const& rhs) {
51   return std::rel_ops::operator>(lhs, rhs);
52 }
53 
54 inline bool operator<=(Owner const& lhs, Owner const& rhs) {
55   return std::rel_ops::operator<=(lhs, rhs);
56 }
57 
58 inline bool operator>=(Owner const& lhs, Owner const& rhs) {
59   return std::rel_ops::operator>=(lhs, rhs);
60 }
61 
62 namespace internal {
63 class GrpcClient;
64 template <typename Derived>
65 struct CommonMetadataParser;
66 
67 /**
68  * Defines common attributes to both `BucketMetadata` and `ObjectMetadata`.
69  *
70  * @tparam Derived a class derived from CommonMetadata<Derived>. This class uses
71  *     the Curiously recurring template pattern.
72  *
73  * @see https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
74  */
75 template <typename Derived>
76 class CommonMetadata {
77  public:
78   CommonMetadata() = default;
79 
etag()80   std::string const& etag() const { return etag_; }
id()81   std::string const& id() const { return id_; }
kind()82   std::string const& kind() const { return kind_; }
metageneration()83   std::int64_t metageneration() const { return metageneration_; }
84 
name()85   std::string const& name() const { return name_; }
86   // NOLINTNEXTLINE(performance-unnecessary-value-param)  TODO(#4112)
set_name(std::string value)87   void set_name(std::string value) { name_ = std::move(value); }
88 
has_owner()89   bool has_owner() const { return owner_.has_value(); }
owner()90   Owner const& owner() const { return owner_.value(); }
91 
self_link()92   std::string const& self_link() const { return self_link_; }
93 
storage_class()94   std::string const& storage_class() const { return storage_class_; }
95   // NOLINTNEXTLINE(performance-unnecessary-value-param)  TODO(#4112)
set_storage_class(std::string value)96   void set_storage_class(std::string value) {
97     storage_class_ = std::move(value);
98   }
99 
time_created()100   std::chrono::system_clock::time_point time_created() const {
101     return time_created_;
102   }
updated()103   std::chrono::system_clock::time_point updated() const { return updated_; }
104 
105  private:
106   friend class GrpcClient;
107   template <typename ParserDerived>
108   friend struct CommonMetadataParser;
109 
110   // Keep the fields in alphabetical order.
111   std::string etag_;
112   std::string id_;
113   std::string kind_;
114   std::int64_t metageneration_{0};
115   std::string name_;
116   absl::optional<Owner> owner_;
117   std::string self_link_;
118   std::string storage_class_;
119   std::chrono::system_clock::time_point time_created_;
120   std::chrono::system_clock::time_point updated_;
121 };
122 
123 template <typename T>
124 inline bool operator==(CommonMetadata<T> const& lhs,
125                        CommonMetadata<T> const& rhs) {
126   // etag changes each time the metadata changes, so that is the best field
127   // to short-circuit this comparison.  The check the name, project number,
128   // and metadata generation, which have the next best chance to
129   // short-circuit.  The rest just put in alphabetical order.
130   return lhs.name() == rhs.name() &&
131          lhs.metageneration() == rhs.metageneration() && lhs.id() == rhs.id() &&
132          lhs.etag() == rhs.etag() && lhs.kind() == rhs.kind() &&
133          lhs.self_link() == rhs.self_link() &&
134          lhs.storage_class() == rhs.storage_class() &&
135          lhs.time_created() == rhs.time_created() &&
136          lhs.updated() == rhs.updated() && lhs.has_owner() == rhs.has_owner() &&
137          (!lhs.has_owner() || lhs.owner() == rhs.owner());
138 }
139 
140 template <typename T>
141 inline bool operator!=(CommonMetadata<T> const& lhs,
142                        CommonMetadata<T> const& rhs) {
143   return std::rel_ops::operator!=(lhs, rhs);
144 }
145 
146 }  // namespace internal
147 }  // namespace STORAGE_CLIENT_NS
148 }  // namespace storage
149 }  // namespace cloud
150 }  // namespace google
151 
152 #endif  // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_INTERNAL_COMMON_METADATA_H
153