blob: cd35d659ca838a09d5a817c25b8aa7f11dc2931d [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
12#include <base/basictypes.h>
13#include <base/values.h>
14
Alex Vakulenko66ec2922014-06-17 15:30:22 -070015#include "buffet/commands/prop_values.h"
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070016#include "buffet/commands/schema_constants.h"
Alex Vakulenko66ec2922014-06-17 15:30:22 -070017#include "buffet/commands/schema_utils.h"
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070018#include "buffet/error.h"
19#include "buffet/string_utils.h"
20
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 Vakulenko66ec2922014-06-17 15:30:22 -070049 virtual bool Validate(const PropValue& value, ErrorPtr* error) const = 0;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070050 // Makes a copy of the constraint object, marking all the attributes
51 // as inherited from the original definition.
52 virtual std::shared_ptr<Constraint> CloneAsInherited() const = 0;
53 // Saves the constraint into the specified JSON |dict| object, representing
54 // the object schema. If |overridden_only| is set to true, then the
55 // inherited constraints will not be added to the schema object.
56 virtual bool AddToJsonDict(base::DictionaryValue* dict, bool overridden_only,
57 ErrorPtr* error) const;
58 // Saves the value of constraint to JSON value. E.g., if the numeric
59 // constraint was defined as {"minimum":20} this will create a JSON value
60 // of 20. The current design implies that each constraint has one value
61 // only. If this assumption changes, this interface needs to be updated
62 // accordingly.
63 virtual std::unique_ptr<base::Value> ToJson(ErrorPtr* error) const = 0;
64 // Overloaded by the concrete class implementation, it should return the
65 // JSON object property name to store the constraint's value as.
66 // E.g., if the numeric constraint was defined as {"minimum":20} this
67 // method should return "minimum".
68 virtual const char* GetDictKey() const = 0;
69
70 protected:
71 // Static helper methods to format common constraint validation errors.
72 // They fill the |error| object with specific error message.
73 // Since these functions could be used by constraint objects for various
74 // data types, the values used in validation are expected to be
75 // send as strings already.
76 static bool ReportErrorLessThan(ErrorPtr* error, const std::string& val,
77 const std::string& limit);
78 static bool ReportErrorGreaterThan(ErrorPtr* error, const std::string& val,
79 const std::string& limit);
80
81 static bool ReportErrorNotOneOf(ErrorPtr* error, const std::string& val,
82 const std::vector<std::string>& values);
83
84 private:
85 DISALLOW_COPY_AND_ASSIGN(Constraint);
86};
87
88// ConstraintMinMaxBase is a base class for numeric Minimum and Maximum
89// constraints.
90template<typename T>
91class ConstraintMinMaxBase : public Constraint {
92 public:
93 explicit ConstraintMinMaxBase(const InheritableAttribute<T>& limit)
94 : limit_(limit) {}
95 explicit ConstraintMinMaxBase(const T& limit)
96 : limit_(limit) {}
97
98 // Implementation of Constraint::HasOverriddenAttributes().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -070099 bool HasOverriddenAttributes() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700100 return !limit_.is_inherited;
101 }
102
103 // Implementation of Constraint::ToJson().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700104 std::unique_ptr<base::Value> ToJson(ErrorPtr* error) const override {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700105 return TypedValueToJson(limit_.value, error);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700106 }
107
108 // Stores the upper/lower value limit for maximum/minimum constraint.
109 // |limit_.is_inherited| indicates whether the constraint is inherited
110 // from base schema or overridden.
111 InheritableAttribute<T> limit_;
112
113 private:
114 DISALLOW_COPY_AND_ASSIGN(ConstraintMinMaxBase);
115};
116
117// Implementation of Minimum value constraint for Integer/Double types.
118template<typename T>
119class ConstraintMin : public ConstraintMinMaxBase<T> {
120 public:
121 explicit ConstraintMin(const InheritableAttribute<T>& limit)
122 : ConstraintMinMaxBase<T>(limit) {}
123 explicit ConstraintMin(const T& limit)
124 : ConstraintMinMaxBase<T>(limit) {}
125
126 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700127 ConstraintType GetType() const { return ConstraintType::Min; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700128
129 // Implementation of Constraint::Validate().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700130 bool Validate(const PropValue& value, ErrorPtr* error) const override {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700131 T v = value.GetValueAsAny().Get<T>();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700132 if (v < this->limit_.value)
133 return this->ReportErrorLessThan(
134 error, string_utils::ToString(v),
135 string_utils::ToString(this->limit_.value));
136 return true;
137 }
138
139 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700140 std::shared_ptr<Constraint> CloneAsInherited() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700141 return std::make_shared<ConstraintMin>(this->limit_.value);
142 }
143
144 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700145 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700146 return commands::attributes::kNumeric_Min;
147 }
148
149 private:
150 DISALLOW_COPY_AND_ASSIGN(ConstraintMin);
151};
152
153// Implementation of Maximum value constraint for Integer/Double types.
154template<typename T>
155class ConstraintMax : public ConstraintMinMaxBase<T> {
156 public:
157 explicit ConstraintMax(const InheritableAttribute<T>& limit)
158 : ConstraintMinMaxBase<T>(limit) {}
159 explicit ConstraintMax(const T& limit)
160 : ConstraintMinMaxBase<T>(limit) {}
161
162 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700163 ConstraintType GetType() const { return ConstraintType::Max; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700164
165 // Implementation of Constraint::Validate().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700166 bool Validate(const PropValue& value, ErrorPtr* error) const override {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700167 T v = value.GetValueAsAny().Get<T>();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700168 if (v > this->limit_.value)
169 return this->ReportErrorGreaterThan(
170 error, string_utils::ToString(v),
171 string_utils::ToString(this->limit_.value));
172 return true;
173 }
174
175 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700176 std::shared_ptr<Constraint> CloneAsInherited() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700177 return std::make_shared<ConstraintMax>(this->limit_.value);
178 }
179
180 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700181 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700182 return commands::attributes::kNumeric_Max;
183 }
184
185 private:
186 DISALLOW_COPY_AND_ASSIGN(ConstraintMax);
187};
188
189// ConstraintStringLength is a base class for Minimum/Maximum string length
190// constraints, similar to ConstraintMinMaxBase of numeric types.
191class ConstraintStringLength : public Constraint {
192 public:
193 explicit ConstraintStringLength(const InheritableAttribute<int>& limit);
194 explicit ConstraintStringLength(int limit);
195
196 // Implementation of Constraint::HasOverriddenAttributes().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700197 bool HasOverriddenAttributes() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700198 // Implementation of Constraint::ToJson().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700199 std::unique_ptr<base::Value> ToJson(ErrorPtr* error) const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700200
201 // Stores the upper/lower value limit for string length constraint.
202 // |limit_.is_inherited| indicates whether the constraint is inherited
203 // from base schema or overridden.
204 InheritableAttribute<int> limit_;
205
206 private:
207 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLength);
208};
209
210// Implementation of Minimum string length constraint.
211class ConstraintStringLengthMin : public ConstraintStringLength {
212 public:
213 explicit ConstraintStringLengthMin(const InheritableAttribute<int>& limit);
214 explicit ConstraintStringLengthMin(int limit);
215 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700216 ConstraintType GetType() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700217 return ConstraintType::StringLengthMin;
218 }
219 // Implementation of Constraint::Validate().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700220 bool Validate(const PropValue& value, ErrorPtr* error) const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700221 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700222 std::shared_ptr<Constraint> CloneAsInherited() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700223 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700224 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700225 return commands::attributes::kString_MinLength;
226 }
227 private:
228 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLengthMin);
229};
230
231// Implementation of Maximum string length constraint.
232class ConstraintStringLengthMax : public ConstraintStringLength {
233 public:
234 explicit ConstraintStringLengthMax(const InheritableAttribute<int>& limit);
235 explicit ConstraintStringLengthMax(int limit);
236 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700237 ConstraintType GetType() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700238 return ConstraintType::StringLengthMax;
239 }
240 // Implementation of Constraint::Validate().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700241 bool Validate(const PropValue& value, ErrorPtr* error) const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700242 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700243 std::shared_ptr<Constraint> CloneAsInherited() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700244 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700245 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700246 return commands::attributes::kString_MaxLength;
247 }
248
249 private:
250 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLengthMax);
251};
252
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700253// Implementation of OneOf constraint for different data types.
254template<typename T>
255class ConstraintOneOf : public Constraint {
256 public:
257 explicit ConstraintOneOf(const InheritableAttribute<std::vector<T>>& set)
258 : set_(set) {}
259 explicit ConstraintOneOf(const std::vector<T>& set)
260 : set_(set) {}
261
262 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700263 ConstraintType GetType() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700264 return ConstraintType::OneOf;
265 }
266
267 // Implementation of Constraint::HasOverriddenAttributes().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700268 bool HasOverriddenAttributes() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700269 return !set_.is_inherited;
270 }
271
272 // Implementation of Constraint::Validate().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700273 bool Validate(const PropValue& value, ErrorPtr* error) const override {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700274 using string_utils::ToString;
275 T v = value.GetValueAsAny().Get<T>();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700276 for (const auto& item : set_.value) {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700277 if (CompareValue(v, item))
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700278 return true;
279 }
280 std::vector<std::string> values;
281 values.reserve(set_.value.size());
282 for (const auto& item : set_.value) {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700283 values.push_back(ToString(item));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700284 }
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700285 return ReportErrorNotOneOf(error, ToString(v), values);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700286 }
287
288 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700289 std::shared_ptr<Constraint> CloneAsInherited() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700290 return std::make_shared<ConstraintOneOf>(set_.value);
291 }
292
293 // Implementation of Constraint::ToJson().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700294 std::unique_ptr<base::Value> ToJson(ErrorPtr* error) const override {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700295 return TypedValueToJson(set_.value, error);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700296 }
297
298 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700299 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700300 return commands::attributes::kOneOf_Enum;
301 }
302
303 // Stores the list of acceptable values for the parameter.
304 // |set_.is_inherited| indicates whether the constraint is inherited
305 // from base schema or overridden.
306 InheritableAttribute<std::vector<T>> set_;
307
308 private:
309 DISALLOW_COPY_AND_ASSIGN(ConstraintOneOf);
310};
311
312} // namespace buffet
313
314#endif // BUFFET_COMMANDS_PROP_CONSTRAINTS_H_