blob: 960802bdbea3c61f6e7b6648c02f8e2d70c1652e [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_VALUES_H_
6#define LIBWEAVE_SRC_COMMANDS_PROP_VALUES_H_
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -07007
8#include <map>
9#include <memory>
10#include <string>
11
Vitaly Buka0801a1f2015-08-14 10:03:46 -070012#include <weave/error.h>
Alex Vakulenko5f472062014-08-14 17:54:04 -070013
Stefan Sauer2d16dfa2015-09-25 17:08:35 +020014#include "src/commands/schema_utils.h"
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070015
16namespace base {
17class Value;
18class DictionaryValue;
19} // namespace base
20
Vitaly Bukab6f015a2015-07-09 14:59:23 -070021namespace weave {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070022
23// Enumeration to indicate supported command parameter types.
24enum class ValueType {
25 Int,
26 Double,
27 String,
Alex Vakulenko66ec2922014-06-17 15:30:22 -070028 Boolean,
Alex Vakulenko29e64442015-03-20 13:59:19 -070029 Object,
30 Array,
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070031};
32
Alex Vakulenko66ec2922014-06-17 15:30:22 -070033class PropValue;
34class IntValue;
35class DoubleValue;
36class StringValue;
37class BooleanValue;
38class ObjectValue;
Alex Vakulenko29e64442015-03-20 13:59:19 -070039class ArrayValue;
Alex Vakulenko66ec2922014-06-17 15:30:22 -070040
41class PropType;
42
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070043// Helper methods to get the parameter type enum value for the given
44// native C++ data representation.
45// The generic GetValueType<T>() is undefined, however particular
46// type specializations return the appropriate ValueType.
Vitaly Bukaa647c852015-07-06 14:51:01 -070047template <typename T>
48ValueType GetValueType(); // Undefined.
49template <>
50inline ValueType GetValueType<int>() {
51 return ValueType::Int;
52}
53template <>
54inline ValueType GetValueType<double>() {
55 return ValueType::Double;
56}
57template <>
58inline ValueType GetValueType<std::string>() {
59 return ValueType::String;
60}
61template <>
62inline ValueType GetValueType<bool>() {
63 return ValueType::Boolean;
64}
65template <>
Vitaly Buka774cdf52015-07-21 13:55:00 -070066inline ValueType GetValueType<ValueMap>() {
Alex Vakulenko66ec2922014-06-17 15:30:22 -070067 return ValueType::Object;
68}
Vitaly Bukaa647c852015-07-06 14:51:01 -070069template <>
Vitaly Buka774cdf52015-07-21 13:55:00 -070070inline ValueType GetValueType<ValueVector>() {
Alex Vakulenko29e64442015-03-20 13:59:19 -070071 return ValueType::Array;
72}
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070073
Alex Vakulenko66ec2922014-06-17 15:30:22 -070074// The base class for property values.
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070075// Concrete value classes of various types will be derived from this base.
Alex Vakulenko66ec2922014-06-17 15:30:22 -070076// A property value is the actual command parameter value (or a concrete value
77// that can be used in constraints and presets). The PropValue is mostly
78// just parsed content of base::Value when a command is dispatched, however
79// it does have some additional functionality:
80// - it has a reference to the type definition (PropType) which is used
81// when validating the value, especially for "object" types.
82// - it can be compared with another instances of values of the same type.
83// This is used to validate the values against "enum"/"one of" constraints.
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070084class PropValue {
85 public:
Vitaly Buka79c05e92015-07-29 12:25:37 -070086 // Only CreateDefaultValue should use this constructor.
87 explicit PropValue(const PropType& type);
Alex Vakulenko5ef75792015-03-19 15:50:44 -070088 virtual ~PropValue();
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -070089
90 // Gets the type of the value.
91 virtual ValueType GetType() const = 0;
92
93 // Type conversion methods. Used in lieu of RTTI and dynamic_cast<>.
94 virtual IntValue* GetInt() { return nullptr; }
95 virtual IntValue const* GetInt() const { return nullptr; }
96 virtual DoubleValue* GetDouble() { return nullptr; }
97 virtual DoubleValue const* GetDouble() const { return nullptr; }
98 virtual StringValue* GetString() { return nullptr; }
99 virtual StringValue const* GetString() const { return nullptr; }
100 virtual BooleanValue* GetBoolean() { return nullptr; }
101 virtual BooleanValue const* GetBoolean() const { return nullptr; }
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700102 virtual ObjectValue* GetObject() { return nullptr; }
103 virtual ObjectValue const* GetObject() const { return nullptr; }
Alex Vakulenko29e64442015-03-20 13:59:19 -0700104 virtual ArrayValue* GetArray() { return nullptr; }
105 virtual ArrayValue const* GetArray() const { return nullptr; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700106
107 // Makes a full copy of this value class.
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700108 virtual std::unique_ptr<PropValue> Clone() const = 0;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700109
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700110 // Saves the value as a JSON object. Never fails.
111 virtual std::unique_ptr<base::Value> ToJson() const = 0;
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700112
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700113 // Return the type definition of this value.
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700114 const PropType* GetPropType() const { return type_.get(); }
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700115 // Compares two values and returns true if they are equal.
116 virtual bool IsEqual(const PropValue* value) const = 0;
117
118 protected:
Vitaly Bukac58a8282015-07-29 01:25:20 -0700119 // Special out-of-line constructor to help implement PropValue::Clone().
120 // That method needs to clone the underlying type but can't do this in this
121 // header file since PropType is just forward-declared (it needs PropValue
122 // fully defined in its own inner workings).
123 explicit PropValue(const PropValue& other);
124
125 private:
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700126 std::unique_ptr<const PropType> type_;
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700127};
128
Alex Vakulenko29e64442015-03-20 13:59:19 -0700129// A helper template base class for implementing value classes.
Vitaly Bukac58a8282015-07-29 01:25:20 -0700130template <typename T>
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700131class TypedValueBase : public PropValue {
132 public:
Vitaly Buka52d006a2015-11-21 17:14:51 -0800133 TypedValueBase(const PropType& type) : PropValue(type) {}
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700134
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700135 // Overrides from PropValue base class.
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700136 ValueType GetType() const override { return GetValueType<T>(); }
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700137
Vitaly Buka6942e1f2015-07-28 15:33:55 -0700138 std::unique_ptr<base::Value> ToJson() const override {
139 return TypedValueToJson(value_);
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700140 }
141
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700142 bool IsEqual(const PropValue* value) const override {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700143 if (GetType() != value->GetType())
144 return false;
Vitaly Buka79c05e92015-07-29 12:25:37 -0700145 return CompareValue(GetValue(),
146 static_cast<const TypedValueBase*>(value)->GetValue());
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700147 }
148
149 // Helper methods to get and set the C++ representation of the value.
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700150 const T& GetValue() const { return value_; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700151
152 protected:
Vitaly Bukac58a8282015-07-29 01:25:20 -0700153 explicit TypedValueBase(const TypedValueBase& other)
154 : PropValue(other), value_(other.value_) {}
155
Vitaly Buka79c05e92015-07-29 12:25:37 -0700156 TypedValueBase(const PropType& type, T value)
157 : PropValue(type), value_(value) {}
158
Vitaly Bukac58a8282015-07-29 01:25:20 -0700159 private:
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700160 T value_{}; // The value of the parameter in C++ data representation.
161};
162
Vitaly Bukac58a8282015-07-29 01:25:20 -0700163// A helper template base class for implementing value classes.
164template <typename Derived, typename T>
165class TypedValueWithClone : public TypedValueBase<T> {
166 public:
Vitaly Buka52d006a2015-11-21 17:14:51 -0800167 TypedValueWithClone(const PropType& type) : TypedValueBase<T>(type) {}
168 TypedValueWithClone(const PropType& type, const T& value)
169 : TypedValueBase<T>(type, value) {}
Vitaly Bukac58a8282015-07-29 01:25:20 -0700170
171 std::unique_ptr<PropValue> Clone() const override {
172 return std::unique_ptr<PropValue>{
173 new Derived{*static_cast<const Derived*>(this)}};
174 }
Vitaly Buka79c05e92015-07-29 12:25:37 -0700175
176 static std::unique_ptr<Derived> CreateFromJson(const base::Value& value,
177 const PropType& type,
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700178 ErrorPtr* error) {
Vitaly Buka79c05e92015-07-29 12:25:37 -0700179 T tmp_value;
180 if (!TypedValueFromJson(&value, &type, &tmp_value, error))
181 return nullptr;
182
183 // Only place where invalid value can exist.
Vitaly Buka52d006a2015-11-21 17:14:51 -0800184 std::unique_ptr<Derived> result(new Derived(type, tmp_value));
Vitaly Buka79c05e92015-07-29 12:25:37 -0700185 if (!result->GetPropType()->ValidateConstraints(*result, error))
186 return nullptr;
187
188 return result;
189 }
Vitaly Bukac58a8282015-07-29 01:25:20 -0700190};
191
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700192// Value of type Integer.
Vitaly Bukac58a8282015-07-29 01:25:20 -0700193class IntValue final : public TypedValueWithClone<IntValue, int> {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700194 public:
Vitaly Buka52d006a2015-11-21 17:14:51 -0800195 explicit IntValue(const PropType& type)
196 : TypedValueWithClone<IntValue, int>(type) {}
197 IntValue(const PropType& type, int value)
198 : TypedValueWithClone<IntValue, int>(type, value) {}
199
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700200 IntValue* GetInt() override { return this; }
201 IntValue const* GetInt() const override { return this; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700202};
203
204// Value of type Number.
Vitaly Bukac58a8282015-07-29 01:25:20 -0700205class DoubleValue final : public TypedValueWithClone<DoubleValue, double> {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700206 public:
Vitaly Buka52d006a2015-11-21 17:14:51 -0800207 explicit DoubleValue(const PropType& type)
208 : TypedValueWithClone<DoubleValue, double>(type) {}
209 DoubleValue(const PropType& type, double value)
210 : TypedValueWithClone<DoubleValue, double>(type, value) {}
211
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700212 DoubleValue* GetDouble() override { return this; }
213 DoubleValue const* GetDouble() const override { return this; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700214};
215
216// Value of type String.
Vitaly Bukac58a8282015-07-29 01:25:20 -0700217class StringValue final : public TypedValueWithClone<StringValue, std::string> {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700218 public:
Vitaly Buka52d006a2015-11-21 17:14:51 -0800219 explicit StringValue(const PropType& type)
220 : TypedValueWithClone<StringValue, std::string>(type) {}
221 StringValue(const PropType& type, std::string value)
222 : TypedValueWithClone<StringValue, std::string>(type, value) {}
223
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700224 StringValue* GetString() override { return this; }
225 StringValue const* GetString() const override { return this; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700226};
227
228// Value of type Boolean.
Vitaly Bukac58a8282015-07-29 01:25:20 -0700229class BooleanValue final : public TypedValueWithClone<BooleanValue, bool> {
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700230 public:
Vitaly Buka52d006a2015-11-21 17:14:51 -0800231 explicit BooleanValue(const PropType& type)
232 : TypedValueWithClone<BooleanValue, bool>(type) {}
233 BooleanValue(const PropType& type, bool value)
234 : TypedValueWithClone<BooleanValue, bool>(type, value) {}
235
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700236 BooleanValue* GetBoolean() override { return this; }
237 BooleanValue const* GetBoolean() const override { return this; }
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700238};
239
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700240// Value of type Object.
Vitaly Bukac58a8282015-07-29 01:25:20 -0700241class ObjectValue final : public TypedValueWithClone<ObjectValue, ValueMap> {
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700242 public:
Vitaly Buka52d006a2015-11-21 17:14:51 -0800243 explicit ObjectValue(const PropType& type)
244 : TypedValueWithClone<ObjectValue, ValueMap>(type) {}
245 ObjectValue(const PropType& type, ValueMap value)
246 : TypedValueWithClone<ObjectValue, ValueMap>(type, value) {}
247
Alex Vakulenko5a9e7182014-08-11 15:59:58 -0700248 ObjectValue* GetObject() override { return this; }
249 ObjectValue const* GetObject() const override { return this; }
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700250};
Alex Vakulenko29e64442015-03-20 13:59:19 -0700251
252// Value of type Array.
Vitaly Bukac58a8282015-07-29 01:25:20 -0700253class ArrayValue final : public TypedValueWithClone<ArrayValue, ValueVector> {
Alex Vakulenko29e64442015-03-20 13:59:19 -0700254 public:
Vitaly Buka52d006a2015-11-21 17:14:51 -0800255 explicit ArrayValue(const PropType& type)
256 : TypedValueWithClone<ArrayValue, ValueVector>(type) {}
257 ArrayValue(const PropType& type, ValueVector value)
258 : TypedValueWithClone<ArrayValue, ValueVector>(type, value) {}
259
Alex Vakulenko29e64442015-03-20 13:59:19 -0700260 ArrayValue* GetArray() override { return this; }
261 ArrayValue const* GetArray() const override { return this; }
262};
263
Vitaly Bukab6f015a2015-07-09 14:59:23 -0700264} // namespace weave
Alex Vakulenkoe439a0f2014-05-21 12:26:47 -0700265
Vitaly Buka912b6982015-07-06 11:13:03 -0700266#endif // LIBWEAVE_SRC_COMMANDS_PROP_VALUES_H_