blob: c6b7e9bc26bf504386cdfc9a682f985b91cfd843 [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;
Alex Vakulenko5ef75792015-03-19 15:50:44 -070042
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070043 // Checks if any of the constraint properties/attributes are overridden
44 // from their base schema definition. If the constraint is inherited, then
45 // it will not be written to JSON when saving partial schema.
46 virtual bool HasOverriddenAttributes() const = 0;
Alex Vakulenko5ef75792015-03-19 15:50:44 -070047
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070048 // Validates a parameter against the constraint. Returns true if parameter
49 // value satisfies the constraint, otherwise fills the optional |error| with
50 // the details for the failure.
Alex Vakulenko5f472062014-08-14 17:54:04 -070051 virtual bool Validate(const PropValue& value,
52 chromeos::ErrorPtr* error) const = 0;
Alex Vakulenko5ef75792015-03-19 15:50:44 -070053
54 // Makes a full copy of this Constraint instance.
55 virtual std::unique_ptr<Constraint> Clone() const = 0;
56
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070057 // Makes a copy of the constraint object, marking all the attributes
58 // as inherited from the original definition.
Alex Vakulenko5ef75792015-03-19 15:50:44 -070059 virtual std::unique_ptr<Constraint> CloneAsInherited() const = 0;
60
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070061 // Saves the constraint into the specified JSON |dict| object, representing
62 // the object schema. If |overridden_only| is set to true, then the
63 // inherited constraints will not be added to the schema object.
Alex Vakulenkod94656e2015-03-18 09:54:37 -070064 virtual bool AddToJsonDict(base::DictionaryValue* dict,
65 bool overridden_only,
Alex Vakulenko5f472062014-08-14 17:54:04 -070066 chromeos::ErrorPtr* error) const;
Alex Vakulenko5ef75792015-03-19 15:50:44 -070067
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070068 // Saves the value of constraint to JSON value. E.g., if the numeric
69 // constraint was defined as {"minimum":20} this will create a JSON value
70 // of 20. The current design implies that each constraint has one value
71 // only. If this assumption changes, this interface needs to be updated
72 // accordingly.
Alex Vakulenko5f472062014-08-14 17:54:04 -070073 virtual std::unique_ptr<base::Value> ToJson(
74 chromeos::ErrorPtr* error) const = 0;
Alex Vakulenko5ef75792015-03-19 15:50:44 -070075
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070076 // Overloaded by the concrete class implementation, it should return the
77 // JSON object property name to store the constraint's value as.
78 // E.g., if the numeric constraint was defined as {"minimum":20} this
79 // method should return "minimum".
80 virtual const char* GetDictKey() const = 0;
81
82 protected:
83 // Static helper methods to format common constraint validation errors.
84 // They fill the |error| object with specific error message.
85 // Since these functions could be used by constraint objects for various
86 // data types, the values used in validation are expected to be
87 // send as strings already.
Alex Vakulenko5f472062014-08-14 17:54:04 -070088 static bool ReportErrorLessThan(chromeos::ErrorPtr* error,
89 const std::string& val,
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070090 const std::string& limit);
Alex Vakulenko5f472062014-08-14 17:54:04 -070091 static bool ReportErrorGreaterThan(chromeos::ErrorPtr* error,
92 const std::string& val,
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070093 const std::string& limit);
94
Alex Vakulenko5f472062014-08-14 17:54:04 -070095 static bool ReportErrorNotOneOf(chromeos::ErrorPtr* error,
96 const std::string& val,
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070097 const std::vector<std::string>& values);
98
99 private:
100 DISALLOW_COPY_AND_ASSIGN(Constraint);
101};
102
103// ConstraintMinMaxBase is a base class for numeric Minimum and Maximum
104// constraints.
105template<typename T>
106class ConstraintMinMaxBase : public Constraint {
107 public:
108 explicit ConstraintMinMaxBase(const InheritableAttribute<T>& limit)
109 : limit_(limit) {}
110 explicit ConstraintMinMaxBase(const T& limit)
111 : limit_(limit) {}
112
113 // Implementation of Constraint::HasOverriddenAttributes().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700114 bool HasOverriddenAttributes() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700115 return !limit_.is_inherited;
116 }
117
118 // Implementation of Constraint::ToJson().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700119 std::unique_ptr<base::Value> ToJson(
120 chromeos::ErrorPtr* error) const override {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700121 return TypedValueToJson(limit_.value, error);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700122 }
123
124 // Stores the upper/lower value limit for maximum/minimum constraint.
125 // |limit_.is_inherited| indicates whether the constraint is inherited
126 // from base schema or overridden.
127 InheritableAttribute<T> limit_;
128
129 private:
130 DISALLOW_COPY_AND_ASSIGN(ConstraintMinMaxBase);
131};
132
133// Implementation of Minimum value constraint for Integer/Double types.
134template<typename T>
135class ConstraintMin : public ConstraintMinMaxBase<T> {
136 public:
137 explicit ConstraintMin(const InheritableAttribute<T>& limit)
138 : ConstraintMinMaxBase<T>(limit) {}
139 explicit ConstraintMin(const T& limit)
140 : ConstraintMinMaxBase<T>(limit) {}
141
142 // Implementation of Constraint::GetType().
Yunlian Jiang89a97252015-01-28 13:33:46 -0800143 ConstraintType GetType() const override { return ConstraintType::Min; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700144
145 // Implementation of Constraint::Validate().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700146 bool Validate(const PropValue& value,
147 chromeos::ErrorPtr* error) const override {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700148 T v = value.GetValueAsAny().Get<T>();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700149 if (v < this->limit_.value)
150 return this->ReportErrorLessThan(
Alex Vakulenkob8fc1df2014-08-20 15:38:07 -0700151 error, chromeos::string_utils::ToString(v),
152 chromeos::string_utils::ToString(this->limit_.value));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700153 return true;
154 }
155
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700156 // Implementation of Constraint::Clone().
157 std::unique_ptr<Constraint> Clone() const override {
158 return std::unique_ptr<Constraint>{new ConstraintMin{this->limit_}};
159 }
160
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700161 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700162 std::unique_ptr<Constraint> CloneAsInherited() const override {
163 return std::unique_ptr<Constraint>{new ConstraintMin{this->limit_.value}};
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700164 }
165
166 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700167 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700168 return commands::attributes::kNumeric_Min;
169 }
170
171 private:
172 DISALLOW_COPY_AND_ASSIGN(ConstraintMin);
173};
174
175// Implementation of Maximum value constraint for Integer/Double types.
176template<typename T>
177class ConstraintMax : public ConstraintMinMaxBase<T> {
178 public:
179 explicit ConstraintMax(const InheritableAttribute<T>& limit)
180 : ConstraintMinMaxBase<T>(limit) {}
181 explicit ConstraintMax(const T& limit)
182 : ConstraintMinMaxBase<T>(limit) {}
183
184 // Implementation of Constraint::GetType().
Yunlian Jiang89a97252015-01-28 13:33:46 -0800185 ConstraintType GetType() const override { return ConstraintType::Max; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700186
187 // Implementation of Constraint::Validate().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700188 bool Validate(const PropValue& value,
189 chromeos::ErrorPtr* error) const override {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700190 T v = value.GetValueAsAny().Get<T>();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700191 if (v > this->limit_.value)
192 return this->ReportErrorGreaterThan(
Alex Vakulenkob8fc1df2014-08-20 15:38:07 -0700193 error, chromeos::string_utils::ToString(v),
194 chromeos::string_utils::ToString(this->limit_.value));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700195 return true;
196 }
197
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700198 // Implementation of Constraint::Clone().
199 std::unique_ptr<Constraint> Clone() const override {
200 return std::unique_ptr<Constraint>{new ConstraintMax{this->limit_}};
201 }
202
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700203 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700204 std::unique_ptr<Constraint> CloneAsInherited() const override {
205 return std::unique_ptr<Constraint>{new ConstraintMax{this->limit_.value}};
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700206 }
207
208 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700209 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700210 return commands::attributes::kNumeric_Max;
211 }
212
213 private:
214 DISALLOW_COPY_AND_ASSIGN(ConstraintMax);
215};
216
217// ConstraintStringLength is a base class for Minimum/Maximum string length
218// constraints, similar to ConstraintMinMaxBase of numeric types.
219class ConstraintStringLength : public Constraint {
220 public:
221 explicit ConstraintStringLength(const InheritableAttribute<int>& limit);
222 explicit ConstraintStringLength(int limit);
223
224 // Implementation of Constraint::HasOverriddenAttributes().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700225 bool HasOverriddenAttributes() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700226 // Implementation of Constraint::ToJson().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700227 std::unique_ptr<base::Value> ToJson(chromeos::ErrorPtr* error) const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700228
229 // Stores the upper/lower value limit for string length constraint.
230 // |limit_.is_inherited| indicates whether the constraint is inherited
231 // from base schema or overridden.
232 InheritableAttribute<int> limit_;
233
234 private:
235 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLength);
236};
237
238// Implementation of Minimum string length constraint.
239class ConstraintStringLengthMin : public ConstraintStringLength {
240 public:
241 explicit ConstraintStringLengthMin(const InheritableAttribute<int>& limit);
242 explicit ConstraintStringLengthMin(int limit);
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700243
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700244 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700245 ConstraintType GetType() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700246 return ConstraintType::StringLengthMin;
247 }
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700248
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700249 // Implementation of Constraint::Validate().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700250 bool Validate(const PropValue& value,
251 chromeos::ErrorPtr* error) const override;
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700252
253 // Implementation of Constraint::Clone().
254 std::unique_ptr<Constraint> Clone() const override;
255
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700256 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700257 std::unique_ptr<Constraint> CloneAsInherited() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700258 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700259 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700260 return commands::attributes::kString_MinLength;
261 }
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700262
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700263 private:
264 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLengthMin);
265};
266
267// Implementation of Maximum string length constraint.
268class ConstraintStringLengthMax : public ConstraintStringLength {
269 public:
270 explicit ConstraintStringLengthMax(const InheritableAttribute<int>& limit);
271 explicit ConstraintStringLengthMax(int limit);
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700272
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700273 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700274 ConstraintType GetType() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700275 return ConstraintType::StringLengthMax;
276 }
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700277
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700278 // Implementation of Constraint::Validate().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700279 bool Validate(const PropValue& value,
280 chromeos::ErrorPtr* error) const override;
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700281
282 // Implementation of Constraint::Clone().
283 std::unique_ptr<Constraint> Clone() const override;
284
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700285 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700286 std::unique_ptr<Constraint> CloneAsInherited() const override;
287
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700288 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700289 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700290 return commands::attributes::kString_MaxLength;
291 }
292
293 private:
294 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLengthMax);
295};
296
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700297// Implementation of OneOf constraint for different data types.
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700298class ConstraintOneOf : public Constraint {
299 public:
Alex Vakulenko29e64442015-03-20 13:59:19 -0700300 explicit ConstraintOneOf(InheritableAttribute<native_types::Array> set);
301 explicit ConstraintOneOf(native_types::Array set);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700302
303 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700304 ConstraintType GetType() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700305 return ConstraintType::OneOf;
306 }
307
308 // Implementation of Constraint::HasOverriddenAttributes().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700309 bool HasOverriddenAttributes() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700310 return !set_.is_inherited;
311 }
312
313 // Implementation of Constraint::Validate().
Alex Vakulenko5f472062014-08-14 17:54:04 -0700314 bool Validate(const PropValue& value,
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -0700315 chromeos::ErrorPtr* error) const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700316
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700317 // Implementation of Constraint::Clone().
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -0700318 std::unique_ptr<Constraint> Clone() const override;
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700319
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700320 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -0700321 std::unique_ptr<Constraint> CloneAsInherited() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700322
323 // Implementation of Constraint::ToJson().
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -0700324 std::unique_ptr<base::Value> ToJson(chromeos::ErrorPtr* error) const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700325
326 // Implementation of Constraint::GetDictKey().
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -0700327 const char* GetDictKey() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700328
329 // Stores the list of acceptable values for the parameter.
330 // |set_.is_inherited| indicates whether the constraint is inherited
331 // from base schema or overridden.
Alex Vakulenko29e64442015-03-20 13:59:19 -0700332 InheritableAttribute<native_types::Array> set_;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700333
334 private:
335 DISALLOW_COPY_AND_ASSIGN(ConstraintOneOf);
336};
337
338} // namespace buffet
339
340#endif // BUFFET_COMMANDS_PROP_CONSTRAINTS_H_