blob: 53a4d9399e9f13f20ce177bb27a749a98039b89f [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Vitaly Buka912b6982015-07-06 11:13:03 -07005#ifndef LIBWEAVE_SRC_COMMANDS_PROP_CONSTRAINTS_H_
6#define LIBWEAVE_SRC_COMMANDS_PROP_CONSTRAINTS_H_
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07007
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>
Vitaly Buka0801a1f2015-08-14 10:03:46 -070014#include <weave/error.h>
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070015
Stefan Sauer2d16dfa2015-09-25 17:08:35 +020016#include "src/commands/prop_values.h"
17#include "src/commands/schema_constants.h"
18#include "src/commands/schema_utils.h"
19#include "src/string_utils.h"
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070020
Vitaly Bukab6f015a2015-07-09 14:59:23 -070021namespace weave {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070022
Vitaly Bukaa647c852015-07-06 14:51:01 -070023enum class ConstraintType { Min, Max, StringLengthMin, StringLengthMax, OneOf };
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070024
25// Abstract base class for all parameter constraints. Many constraints are
26// type-dependent. Thus, a numeric parameter could have "minimum" and/or
27// "maximum" constraints specified. Some constraints, such as "OneOf" apply to
28// any data type.
29class Constraint {
30 public:
31 Constraint() = default;
32 virtual ~Constraint();
33
34 // Gets the constraint type.
35 virtual ConstraintType GetType() const = 0;
Alex Vakulenko5ef75792015-03-19 15:50:44 -070036
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070037 // Checks if any of the constraint properties/attributes are overridden
38 // from their base schema definition. If the constraint is inherited, then
39 // it will not be written to JSON when saving partial schema.
40 virtual bool HasOverriddenAttributes() const = 0;
Alex Vakulenko5ef75792015-03-19 15:50:44 -070041
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070042 // Validates a parameter against the constraint. Returns true if parameter
43 // value satisfies the constraint, otherwise fills the optional |error| with
44 // the details for the failure.
Vitaly Buka0801a1f2015-08-14 10:03:46 -070045 virtual bool Validate(const PropValue& value, ErrorPtr* error) const = 0;
Alex Vakulenko5ef75792015-03-19 15:50:44 -070046
47 // Makes a full copy of this Constraint instance.
48 virtual std::unique_ptr<Constraint> Clone() const = 0;
49
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.
Alex Vakulenko5ef75792015-03-19 15:50:44 -070052 virtual std::unique_ptr<Constraint> CloneAsInherited() const = 0;
53
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070054 // 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.
Vitaly Buka6942e1f2015-07-28 15:33:55 -070057 virtual void AddToJsonDict(base::DictionaryValue* dict,
58 bool overridden_only) const;
Alex Vakulenko5ef75792015-03-19 15:50:44 -070059
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070060 // Saves the value of constraint to JSON value. E.g., if the numeric
61 // constraint was defined as {"minimum":20} this will create a JSON value
62 // of 20. The current design implies that each constraint has one value
63 // only. If this assumption changes, this interface needs to be updated
64 // accordingly.
Vitaly Buka6942e1f2015-07-28 15:33:55 -070065 virtual std::unique_ptr<base::Value> ToJson() const = 0;
Alex Vakulenko5ef75792015-03-19 15:50:44 -070066
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070067 // Overloaded by the concrete class implementation, it should return the
68 // JSON object property name to store the constraint's value as.
69 // E.g., if the numeric constraint was defined as {"minimum":20} this
70 // method should return "minimum".
71 virtual const char* GetDictKey() const = 0;
72
73 protected:
74 // Static helper methods to format common constraint validation errors.
75 // They fill the |error| object with specific error message.
76 // Since these functions could be used by constraint objects for various
77 // data types, the values used in validation are expected to be
78 // send as strings already.
Vitaly Buka0801a1f2015-08-14 10:03:46 -070079 static bool ReportErrorLessThan(ErrorPtr* error,
Alex Vakulenko5f472062014-08-14 17:54:04 -070080 const std::string& val,
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070081 const std::string& limit);
Vitaly Buka0801a1f2015-08-14 10:03:46 -070082 static bool ReportErrorGreaterThan(ErrorPtr* error,
Alex Vakulenko5f472062014-08-14 17:54:04 -070083 const std::string& val,
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070084 const std::string& limit);
85
Vitaly Buka0801a1f2015-08-14 10:03:46 -070086 static bool ReportErrorNotOneOf(ErrorPtr* error,
Alex Vakulenko5f472062014-08-14 17:54:04 -070087 const std::string& val,
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070088 const std::vector<std::string>& values);
89
90 private:
91 DISALLOW_COPY_AND_ASSIGN(Constraint);
92};
93
94// ConstraintMinMaxBase is a base class for numeric Minimum and Maximum
95// constraints.
Vitaly Bukaa647c852015-07-06 14:51:01 -070096template <typename T>
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070097class ConstraintMinMaxBase : public Constraint {
98 public:
99 explicit ConstraintMinMaxBase(const InheritableAttribute<T>& limit)
100 : limit_(limit) {}
Vitaly Bukaa647c852015-07-06 14:51:01 -0700101 explicit ConstraintMinMaxBase(const T& limit) : limit_(limit) {}
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700102
103 // Implementation of Constraint::HasOverriddenAttributes().
Vitaly Bukaa647c852015-07-06 14:51:01 -0700104 bool HasOverriddenAttributes() const override { return !limit_.is_inherited; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700105
106 // Implementation of Constraint::ToJson().
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700107 std::unique_ptr<base::Value> ToJson() const override {
108 return TypedValueToJson(limit_.value);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700109 }
110
111 // Stores the upper/lower value limit for maximum/minimum constraint.
112 // |limit_.is_inherited| indicates whether the constraint is inherited
113 // from base schema or overridden.
114 InheritableAttribute<T> limit_;
115
116 private:
117 DISALLOW_COPY_AND_ASSIGN(ConstraintMinMaxBase);
118};
119
120// Implementation of Minimum value constraint for Integer/Double types.
Vitaly Bukaa647c852015-07-06 14:51:01 -0700121template <typename T>
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700122class ConstraintMin : public ConstraintMinMaxBase<T> {
123 public:
124 explicit ConstraintMin(const InheritableAttribute<T>& limit)
125 : ConstraintMinMaxBase<T>(limit) {}
Vitaly Bukaa647c852015-07-06 14:51:01 -0700126 explicit ConstraintMin(const T& limit) : ConstraintMinMaxBase<T>(limit) {}
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700127
128 // Implementation of Constraint::GetType().
Yunlian Jiang89a97252015-01-28 13:33:46 -0800129 ConstraintType GetType() const override { return ConstraintType::Min; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700130
131 // Implementation of Constraint::Validate().
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700132 bool Validate(const PropValue& value, ErrorPtr* error) const override {
Vitaly Bukac58a8282015-07-29 01:25:20 -0700133 const T& v = static_cast<const TypedValueBase<T>&>(value).GetValue();
134 if (v < this->limit_.value) {
Vitaly Buka24d6fd52015-08-13 23:22:48 -0700135 return this->ReportErrorLessThan(error, std::to_string(v),
136 std::to_string(this->limit_.value));
Vitaly Bukac58a8282015-07-29 01:25:20 -0700137 }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700138 return true;
139 }
140
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700141 // Implementation of Constraint::Clone().
142 std::unique_ptr<Constraint> Clone() const override {
143 return std::unique_ptr<Constraint>{new ConstraintMin{this->limit_}};
144 }
145
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700146 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700147 std::unique_ptr<Constraint> CloneAsInherited() const override {
148 return std::unique_ptr<Constraint>{new ConstraintMin{this->limit_.value}};
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700149 }
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.
Vitaly Bukaa647c852015-07-06 14:51:01 -0700161template <typename T>
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700162class ConstraintMax : public ConstraintMinMaxBase<T> {
163 public:
164 explicit ConstraintMax(const InheritableAttribute<T>& limit)
165 : ConstraintMinMaxBase<T>(limit) {}
Vitaly Bukaa647c852015-07-06 14:51:01 -0700166 explicit ConstraintMax(const T& limit) : ConstraintMinMaxBase<T>(limit) {}
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700167
168 // Implementation of Constraint::GetType().
Yunlian Jiang89a97252015-01-28 13:33:46 -0800169 ConstraintType GetType() const override { return ConstraintType::Max; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700170
171 // Implementation of Constraint::Validate().
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700172 bool Validate(const PropValue& value, ErrorPtr* error) const override {
Vitaly Bukac58a8282015-07-29 01:25:20 -0700173 const T& v = static_cast<const TypedValueBase<T>&>(value).GetValue();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700174 if (v > this->limit_.value)
Vitaly Buka24d6fd52015-08-13 23:22:48 -0700175 return this->ReportErrorGreaterThan(error, std::to_string(v),
176 std::to_string(this->limit_.value));
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700177 return true;
178 }
179
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700180 // Implementation of Constraint::Clone().
181 std::unique_ptr<Constraint> Clone() const override {
182 return std::unique_ptr<Constraint>{new ConstraintMax{this->limit_}};
183 }
184
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700185 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700186 std::unique_ptr<Constraint> CloneAsInherited() const override {
187 return std::unique_ptr<Constraint>{new ConstraintMax{this->limit_.value}};
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700188 }
189
190 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700191 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700192 return commands::attributes::kNumeric_Max;
193 }
194
195 private:
196 DISALLOW_COPY_AND_ASSIGN(ConstraintMax);
197};
198
199// ConstraintStringLength is a base class for Minimum/Maximum string length
200// constraints, similar to ConstraintMinMaxBase of numeric types.
201class ConstraintStringLength : public Constraint {
202 public:
203 explicit ConstraintStringLength(const InheritableAttribute<int>& limit);
204 explicit ConstraintStringLength(int limit);
205
206 // Implementation of Constraint::HasOverriddenAttributes().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700207 bool HasOverriddenAttributes() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700208 // Implementation of Constraint::ToJson().
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700209 std::unique_ptr<base::Value> ToJson() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700210
211 // Stores the upper/lower value limit for string length constraint.
212 // |limit_.is_inherited| indicates whether the constraint is inherited
213 // from base schema or overridden.
214 InheritableAttribute<int> limit_;
215
216 private:
217 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLength);
218};
219
220// Implementation of Minimum string length constraint.
221class ConstraintStringLengthMin : public ConstraintStringLength {
222 public:
223 explicit ConstraintStringLengthMin(const InheritableAttribute<int>& limit);
224 explicit ConstraintStringLengthMin(int limit);
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700225
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700226 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700227 ConstraintType GetType() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700228 return ConstraintType::StringLengthMin;
229 }
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700230
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700231 // Implementation of Constraint::Validate().
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700232 bool Validate(const PropValue& value, ErrorPtr* error) const override;
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700233
234 // Implementation of Constraint::Clone().
235 std::unique_ptr<Constraint> Clone() const override;
236
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700237 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700238 std::unique_ptr<Constraint> CloneAsInherited() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700239 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700240 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700241 return commands::attributes::kString_MinLength;
242 }
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700243
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700244 private:
245 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLengthMin);
246};
247
248// Implementation of Maximum string length constraint.
249class ConstraintStringLengthMax : public ConstraintStringLength {
250 public:
251 explicit ConstraintStringLengthMax(const InheritableAttribute<int>& limit);
252 explicit ConstraintStringLengthMax(int limit);
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700253
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700254 // Implementation of Constraint::GetType().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700255 ConstraintType GetType() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700256 return ConstraintType::StringLengthMax;
257 }
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700258
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700259 // Implementation of Constraint::Validate().
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700260 bool Validate(const PropValue& value, ErrorPtr* error) const override;
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700261
262 // Implementation of Constraint::Clone().
263 std::unique_ptr<Constraint> Clone() const override;
264
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700265 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700266 std::unique_ptr<Constraint> CloneAsInherited() const override;
267
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700268 // Implementation of Constraint::GetDictKey().
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700269 const char* GetDictKey() const override {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700270 return commands::attributes::kString_MaxLength;
271 }
272
273 private:
274 DISALLOW_COPY_AND_ASSIGN(ConstraintStringLengthMax);
275};
276
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700277// Implementation of OneOf constraint for different data types.
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700278class ConstraintOneOf : public Constraint {
279 public:
Vitaly Buka774cdf52015-07-21 13:55:00 -0700280 explicit ConstraintOneOf(InheritableAttribute<ValueVector> set);
281 explicit ConstraintOneOf(ValueVector set);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700282
283 // Implementation of Constraint::GetType().
Vitaly Bukaa647c852015-07-06 14:51:01 -0700284 ConstraintType GetType() const override { return ConstraintType::OneOf; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700285
286 // Implementation of Constraint::HasOverriddenAttributes().
Vitaly Bukaa647c852015-07-06 14:51:01 -0700287 bool HasOverriddenAttributes() const override { return !set_.is_inherited; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700288
289 // Implementation of Constraint::Validate().
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700290 bool Validate(const PropValue& value, ErrorPtr* error) const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700291
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700292 // Implementation of Constraint::Clone().
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -0700293 std::unique_ptr<Constraint> Clone() const override;
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700294
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700295 // Implementation of Constraint::CloneAsInherited().
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -0700296 std::unique_ptr<Constraint> CloneAsInherited() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700297
298 // Implementation of Constraint::ToJson().
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700299 std::unique_ptr<base::Value> ToJson() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700300
301 // Implementation of Constraint::GetDictKey().
Alex Vakulenko9e25ecd2015-03-20 09:43:10 -0700302 const char* GetDictKey() const override;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700303
304 // Stores the list of acceptable values for the parameter.
305 // |set_.is_inherited| indicates whether the constraint is inherited
306 // from base schema or overridden.
Vitaly Buka774cdf52015-07-21 13:55:00 -0700307 InheritableAttribute<ValueVector> set_;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700308
309 private:
310 DISALLOW_COPY_AND_ASSIGN(ConstraintOneOf);
311};
312
Vitaly Bukab6f015a2015-07-09 14:59:23 -0700313} // namespace weave
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700314
Vitaly Buka912b6982015-07-06 11:13:03 -0700315#endif // LIBWEAVE_SRC_COMMANDS_PROP_CONSTRAINTS_H_