blob: 4054f30fd6a193a9a561f2624e63fbb825b7db76 [file] [log] [blame]
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07001// Copyright 2014 The Chromium OS 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#ifndef BUFFET_COMMANDS_PROP_CONSTRAINTS_H_
6#define BUFFET_COMMANDS_PROP_CONSTRAINTS_H_
7
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07008#include <string>
9#include <type_traits>
10#include <vector>
11
Alex Vakulenko132617a2014-09-04 08:59:43 -070012#include <base/macros.h>
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070013#include <base/values.h>
Alex Vakulenkoa8b95bc2014-08-27 11:00:57 -070014#include <chromeos/errors/error.h>
15#include <chromeos/strings/string_utils.h>
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070016
Alex Vakulenko66ec2922014-06-17 15:30:22 -070017#include "buffet/commands/prop_values.h"
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070018#include "buffet/commands/schema_constants.h"
Alex Vakulenko66ec2922014-06-17 15:30:22 -070019#include "buffet/commands/schema_utils.h"
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070020
21namespace buffet {
22
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070023enum class ConstraintType {
24 Min,
25 Max,
26 StringLengthMin,
27 StringLengthMax,
28 OneOf
29};
30
31// Abstract base class for all parameter constraints. Many constraints are
32// type-dependent. Thus, a numeric parameter could have "minimum" and/or
33// "maximum" constraints specified. Some constraints, such as "OneOf" apply to
34// any data type.
35class Constraint {
36 public:
37 Constraint() = default;
38 virtual ~Constraint();
39
40 // Gets the constraint type.
41 virtual ConstraintType GetType() const = 0;
42 // Checks if any of the constraint properties/attributes are overridden
43 // from their base schema definition. If the constraint is inherited, then
44 // it will not be written to JSON when saving partial schema.
45 virtual bool HasOverriddenAttributes() const = 0;
46 // Validates a parameter against the constraint. Returns true if parameter
47 // value satisfies the constraint, otherwise fills the optional |error| with
48 // the details for the failure.
Alex Vakulenko5f472062014-08-14 17:54:04 -070049 virtual bool Validate(const PropValue& value,
50 chromeos::ErrorPtr* error) const = 0;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070051 // Makes a copy of the constraint object, marking all the attributes
52 // as inherited from the original definition.
53 virtual std::shared_ptr<Constraint> CloneAsInherited() const = 0;
54 // Saves the constraint into the specified JSON |dict| object, representing
55 // the object schema. If |overridden_only| is set to true, then the
56 // inherited constraints will not be added to the schema object.
57 virtual bool AddToJsonDict(base::DictionaryValue* dict, bool overridden_only,
Alex Vakulenko5f472062014-08-14 17:54:04 -070058 chromeos::ErrorPtr* error) const;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070059 // Saves the value of constraint to JSON value. E.g., if the numeric
60 // constraint was defined as {"minimum":20} this will create a JSON value
61 // of 20. The current design implies that each constraint has one value
62 // only. If this assumption changes, this interface needs to be updated
63 // accordingly.
Alex Vakulenko5f472062014-08-14 17:54:04 -070064 virtual std::unique_ptr<base::Value> ToJson(
65 chromeos::ErrorPtr* error) const = 0;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070066 // Overloaded by the concrete class implementation, it should return the
67 // JSON object property name to store the constraint's value as.
68 // E.g., if the numeric constraint was defined as {"minimum":20} this
69 // method should return "minimum".
70 virtual const char* GetDictKey() const = 0;
71
72 protected:
73 // Static helper methods to format common constraint validation errors.
74 // They fill the |error| object with specific error message.
75 // Since these functions could be used by constraint objects for various
76 // data types, the values used in validation are expected to be
77 // send as strings already.
Alex Vakulenko5f472062014-08-14 17:54:04 -070078 static bool ReportErrorLessThan(chromeos::ErrorPtr* error,
79 const std::string& val,
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070080 const std::string& limit);
Alex Vakulenko5f472062014-08-14 17:54:04 -070081 static bool ReportErrorGreaterThan(chromeos::ErrorPtr* error,
82 const std::string& val,
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070083 const std::string& limit);
84
Alex Vakulenko5f472062014-08-14 17:54:04 -070085 static bool ReportErrorNotOneOf(chromeos::ErrorPtr* error,
86 const std::string& val,
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070087 const std::vector<std::string>& values);
88
89 private:
90 DISALLOW_COPY_AND_ASSIGN(Constraint);
91};
92
93// ConstraintMinMaxBase is a base class for numeric Minimum and Maximum
94// constraints.
95template<typename T>
96class ConstraintMinMaxBase : public Constraint {
97 public:
98 explicit ConstraintMinMaxBase(const InheritableAttribute<T>& limit)
99 : limit_(limit) {}
100 explicit ConstraintMinMaxBase(const T& limit)
101 : limit_(limit) {}
102
103 // Implementation of Constraint::HasOverriddenAttributes().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700104 bool HasOverriddenAttributes() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700105 return !limit_.is_inherited;
106 }
107
108 // Implementation of Constraint::ToJson().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700109 std::unique_ptr<base::Value> ToJson(
110 chromeos::ErrorPtr* error) const override {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700111 return TypedValueToJson(limit_.value, error);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700112 }
113
114 // Stores the upper/lower value limit for maximum/minimum constraint.
115 // |limit_.is_inherited| indicates whether the constraint is inherited
116 // from base schema or overridden.
117 InheritableAttribute<T> limit_;
118
119 private:
120 DISALLOW_COPY_AND_ASSIGN(ConstraintMinMaxBase);
121};
122
123// Implementation of Minimum value constraint for Integer/Double types.
124template<typename T>
125class ConstraintMin : public ConstraintMinMaxBase<T> {
126 public:
127 explicit ConstraintMin(const InheritableAttribute<T>& limit)
128 : ConstraintMinMaxBase<T>(limit) {}
129 explicit ConstraintMin(const T& limit)
130 : ConstraintMinMaxBase<T>(limit) {}
131
132 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700133 ConstraintType GetType() const { return ConstraintType::Min; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700134
135 // Implementation of Constraint::Validate().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700136 bool Validate(const PropValue& value,
137 chromeos::ErrorPtr* error) const override {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700138 T v = value.GetValueAsAny().Get<T>();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700139 if (v < this->limit_.value)
140 return this->ReportErrorLessThan(
Alex Vakulenkob8fc1df2014-08-20 15:38:07 -0700141 error, chromeos::string_utils::ToString(v),
142 chromeos::string_utils::ToString(this->limit_.value));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700143 return true;
144 }
145
146 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700147 std::shared_ptr<Constraint> CloneAsInherited() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700148 return std::make_shared<ConstraintMin>(this->limit_.value);
149 }
150
151 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700152 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700153 return commands::attributes::kNumeric_Min;
154 }
155
156 private:
157 DISALLOW_COPY_AND_ASSIGN(ConstraintMin);
158};
159
160// Implementation of Maximum value constraint for Integer/Double types.
161template<typename T>
162class ConstraintMax : public ConstraintMinMaxBase<T> {
163 public:
164 explicit ConstraintMax(const InheritableAttribute<T>& limit)
165 : ConstraintMinMaxBase<T>(limit) {}
166 explicit ConstraintMax(const T& limit)
167 : ConstraintMinMaxBase<T>(limit) {}
168
169 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700170 ConstraintType GetType() const { return ConstraintType::Max; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700171
172 // Implementation of Constraint::Validate().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700173 bool Validate(const PropValue& value,
174 chromeos::ErrorPtr* error) const override {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700175 T v = value.GetValueAsAny().Get<T>();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700176 if (v > this->limit_.value)
177 return this->ReportErrorGreaterThan(
Alex Vakulenkob8fc1df2014-08-20 15:38:07 -0700178 error, chromeos::string_utils::ToString(v),
179 chromeos::string_utils::ToString(this->limit_.value));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700180 return true;
181 }
182
183 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700184 std::shared_ptr<Constraint> CloneAsInherited() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700185 return std::make_shared<ConstraintMax>(this->limit_.value);
186 }
187
188 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700189 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700190 return commands::attributes::kNumeric_Max;
191 }
192
193 private:
194 DISALLOW_COPY_AND_ASSIGN(ConstraintMax);
195};
196
197// ConstraintStringLength is a base class for Minimum/Maximum string length
198// constraints, similar to ConstraintMinMaxBase of numeric types.
199class ConstraintStringLength : public Constraint {
200 public:
201 explicit ConstraintStringLength(const InheritableAttribute<int>& limit);
202 explicit ConstraintStringLength(int limit);
203
204 // Implementation of Constraint::HasOverriddenAttributes().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700205 bool HasOverriddenAttributes() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700206 // Implementation of Constraint::ToJson().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700207 std::unique_ptr<base::Value> ToJson(chromeos::ErrorPtr* error) const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700208
209 // Stores the upper/lower value limit for string length constraint.
210 // |limit_.is_inherited| indicates whether the constraint is inherited
211 // from base schema or overridden.
212 InheritableAttribute<int> limit_;
213
214 private:
215 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLength);
216};
217
218// Implementation of Minimum string length constraint.
219class ConstraintStringLengthMin : public ConstraintStringLength {
220 public:
221 explicit ConstraintStringLengthMin(const InheritableAttribute<int>& limit);
222 explicit ConstraintStringLengthMin(int limit);
223 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700224 ConstraintType GetType() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700225 return ConstraintType::StringLengthMin;
226 }
227 // Implementation of Constraint::Validate().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700228 bool Validate(const PropValue& value,
229 chromeos::ErrorPtr* error) const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700230 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700231 std::shared_ptr<Constraint> CloneAsInherited() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700232 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700233 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700234 return commands::attributes::kString_MinLength;
235 }
236 private:
237 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLengthMin);
238};
239
240// Implementation of Maximum string length constraint.
241class ConstraintStringLengthMax : public ConstraintStringLength {
242 public:
243 explicit ConstraintStringLengthMax(const InheritableAttribute<int>& limit);
244 explicit ConstraintStringLengthMax(int limit);
245 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700246 ConstraintType GetType() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700247 return ConstraintType::StringLengthMax;
248 }
249 // Implementation of Constraint::Validate().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700250 bool Validate(const PropValue& value,
251 chromeos::ErrorPtr* error) const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700252 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700253 std::shared_ptr<Constraint> CloneAsInherited() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700254 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700255 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700256 return commands::attributes::kString_MaxLength;
257 }
258
259 private:
260 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLengthMax);
261};
262
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700263// Implementation of OneOf constraint for different data types.
264template<typename T>
265class ConstraintOneOf : public Constraint {
266 public:
267 explicit ConstraintOneOf(const InheritableAttribute<std::vector<T>>& set)
268 : set_(set) {}
269 explicit ConstraintOneOf(const std::vector<T>& set)
270 : set_(set) {}
271
272 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700273 ConstraintType GetType() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700274 return ConstraintType::OneOf;
275 }
276
277 // Implementation of Constraint::HasOverriddenAttributes().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700278 bool HasOverriddenAttributes() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700279 return !set_.is_inherited;
280 }
281
282 // Implementation of Constraint::Validate().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700283 bool Validate(const PropValue& value,
284 chromeos::ErrorPtr* error) const override {
Alex Vakulenkob8fc1df2014-08-20 15:38:07 -0700285 using chromeos::string_utils::ToString;
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700286 T v = value.GetValueAsAny().Get<T>();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700287 for (const auto& item : set_.value) {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700288 if (CompareValue(v, item))
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700289 return true;
290 }
291 std::vector<std::string> values;
292 values.reserve(set_.value.size());
293 for (const auto& item : set_.value) {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700294 values.push_back(ToString(item));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700295 }
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700296 return ReportErrorNotOneOf(error, ToString(v), values);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700297 }
298
299 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700300 std::shared_ptr<Constraint> CloneAsInherited() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700301 return std::make_shared<ConstraintOneOf>(set_.value);
302 }
303
304 // Implementation of Constraint::ToJson().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700305 std::unique_ptr<base::Value> ToJson(
306 chromeos::ErrorPtr* error) const override {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700307 return TypedValueToJson(set_.value, error);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700308 }
309
310 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700311 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700312 return commands::attributes::kOneOf_Enum;
313 }
314
315 // Stores the list of acceptable values for the parameter.
316 // |set_.is_inherited| indicates whether the constraint is inherited
317 // from base schema or overridden.
318 InheritableAttribute<std::vector<T>> set_;
319
320 private:
321 DISALLOW_COPY_AND_ASSIGN(ConstraintOneOf);
322};
323
324} // namespace buffet
325
326#endif // BUFFET_COMMANDS_PROP_CONSTRAINTS_H_