blob: da43e862363444824c1cdb0c978b02735b3a16b4 [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().
99 virtual bool HasOverriddenAttributes() const override {
100 return !limit_.is_inherited;
101 }
102
103 // Implementation of Constraint::ToJson().
104 virtual 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().
127 virtual ConstraintType GetType() const { return ConstraintType::Min; }
128
129 // Implementation of Constraint::Validate().
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700130 virtual bool Validate(const PropValue& value,
131 ErrorPtr* error) const override {
132 T v = value.GetValueAsAny().Get<T>();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700133 if (v < this->limit_.value)
134 return this->ReportErrorLessThan(
135 error, string_utils::ToString(v),
136 string_utils::ToString(this->limit_.value));
137 return true;
138 }
139
140 // Implementation of Constraint::CloneAsInherited().
141 virtual std::shared_ptr<Constraint> CloneAsInherited() const override {
142 return std::make_shared<ConstraintMin>(this->limit_.value);
143 }
144
145 // Implementation of Constraint::GetDictKey().
146 virtual const char* GetDictKey() const override {
147 return commands::attributes::kNumeric_Min;
148 }
149
150 private:
151 DISALLOW_COPY_AND_ASSIGN(ConstraintMin);
152};
153
154// Implementation of Maximum value constraint for Integer/Double types.
155template<typename T>
156class ConstraintMax : public ConstraintMinMaxBase<T> {
157 public:
158 explicit ConstraintMax(const InheritableAttribute<T>& limit)
159 : ConstraintMinMaxBase<T>(limit) {}
160 explicit ConstraintMax(const T& limit)
161 : ConstraintMinMaxBase<T>(limit) {}
162
163 // Implementation of Constraint::GetType().
164 virtual ConstraintType GetType() const { return ConstraintType::Max; }
165
166 // Implementation of Constraint::Validate().
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700167 virtual bool Validate(const PropValue& value,
168 ErrorPtr* error) const override {
169 T v = value.GetValueAsAny().Get<T>();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700170 if (v > this->limit_.value)
171 return this->ReportErrorGreaterThan(
172 error, string_utils::ToString(v),
173 string_utils::ToString(this->limit_.value));
174 return true;
175 }
176
177 // Implementation of Constraint::CloneAsInherited().
178 virtual std::shared_ptr<Constraint> CloneAsInherited() const override {
179 return std::make_shared<ConstraintMax>(this->limit_.value);
180 }
181
182 // Implementation of Constraint::GetDictKey().
183 virtual const char* GetDictKey() const override {
184 return commands::attributes::kNumeric_Max;
185 }
186
187 private:
188 DISALLOW_COPY_AND_ASSIGN(ConstraintMax);
189};
190
191// ConstraintStringLength is a base class for Minimum/Maximum string length
192// constraints, similar to ConstraintMinMaxBase of numeric types.
193class ConstraintStringLength : public Constraint {
194 public:
195 explicit ConstraintStringLength(const InheritableAttribute<int>& limit);
196 explicit ConstraintStringLength(int limit);
197
198 // Implementation of Constraint::HasOverriddenAttributes().
199 virtual bool HasOverriddenAttributes() const override;
200 // Implementation of Constraint::ToJson().
201 virtual std::unique_ptr<base::Value> ToJson(ErrorPtr* error) const override;
202
203 // Stores the upper/lower value limit for string length constraint.
204 // |limit_.is_inherited| indicates whether the constraint is inherited
205 // from base schema or overridden.
206 InheritableAttribute<int> limit_;
207
208 private:
209 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLength);
210};
211
212// Implementation of Minimum string length constraint.
213class ConstraintStringLengthMin : public ConstraintStringLength {
214 public:
215 explicit ConstraintStringLengthMin(const InheritableAttribute<int>& limit);
216 explicit ConstraintStringLengthMin(int limit);
217 // Implementation of Constraint::GetType().
218 virtual ConstraintType GetType() const override {
219 return ConstraintType::StringLengthMin;
220 }
221 // Implementation of Constraint::Validate().
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700222 virtual bool Validate(const PropValue& value, ErrorPtr* error) const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700223 // Implementation of Constraint::CloneAsInherited().
224 virtual std::shared_ptr<Constraint> CloneAsInherited() const override;
225 // Implementation of Constraint::GetDictKey().
226 virtual const char* GetDictKey() const override {
227 return commands::attributes::kString_MinLength;
228 }
229 private:
230 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLengthMin);
231};
232
233// Implementation of Maximum string length constraint.
234class ConstraintStringLengthMax : public ConstraintStringLength {
235 public:
236 explicit ConstraintStringLengthMax(const InheritableAttribute<int>& limit);
237 explicit ConstraintStringLengthMax(int limit);
238 // Implementation of Constraint::GetType().
239 virtual ConstraintType GetType() const override {
240 return ConstraintType::StringLengthMax;
241 }
242 // Implementation of Constraint::Validate().
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700243 virtual bool Validate(const PropValue& value, ErrorPtr* error) const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700244 // Implementation of Constraint::CloneAsInherited().
245 virtual std::shared_ptr<Constraint> CloneAsInherited() const override;
246 // Implementation of Constraint::GetDictKey().
247 virtual const char* GetDictKey() const override {
248 return commands::attributes::kString_MaxLength;
249 }
250
251 private:
252 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLengthMax);
253};
254
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700255// Implementation of OneOf constraint for different data types.
256template<typename T>
257class ConstraintOneOf : public Constraint {
258 public:
259 explicit ConstraintOneOf(const InheritableAttribute<std::vector<T>>& set)
260 : set_(set) {}
261 explicit ConstraintOneOf(const std::vector<T>& set)
262 : set_(set) {}
263
264 // Implementation of Constraint::GetType().
265 virtual ConstraintType GetType() const override {
266 return ConstraintType::OneOf;
267 }
268
269 // Implementation of Constraint::HasOverriddenAttributes().
270 virtual bool HasOverriddenAttributes() const override {
271 return !set_.is_inherited;
272 }
273
274 // Implementation of Constraint::Validate().
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700275 virtual bool Validate(const PropValue& value,
276 ErrorPtr* error) const override {
277 using string_utils::ToString;
278 T v = value.GetValueAsAny().Get<T>();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700279 for (const auto& item : set_.value) {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700280 if (CompareValue(v, item))
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700281 return true;
282 }
283 std::vector<std::string> values;
284 values.reserve(set_.value.size());
285 for (const auto& item : set_.value) {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700286 values.push_back(ToString(item));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700287 }
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700288 return ReportErrorNotOneOf(error, ToString(v), values);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700289 }
290
291 // Implementation of Constraint::CloneAsInherited().
292 virtual std::shared_ptr<Constraint> CloneAsInherited() const override {
293 return std::make_shared<ConstraintOneOf>(set_.value);
294 }
295
296 // Implementation of Constraint::ToJson().
297 virtual std::unique_ptr<base::Value> ToJson(ErrorPtr* error) const override {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700298 return TypedValueToJson(set_.value, error);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700299 }
300
301 // Implementation of Constraint::GetDictKey().
302 virtual const char* GetDictKey() const override {
303 return commands::attributes::kOneOf_Enum;
304 }
305
306 // Stores the list of acceptable values for the parameter.
307 // |set_.is_inherited| indicates whether the constraint is inherited
308 // from base schema or overridden.
309 InheritableAttribute<std::vector<T>> set_;
310
311 private:
312 DISALLOW_COPY_AND_ASSIGN(ConstraintOneOf);
313};
314
315} // namespace buffet
316
317#endif // BUFFET_COMMANDS_PROP_CONSTRAINTS_H_