| // Copyright 2015 The Weave Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef LIBWEAVE_SRC_COMMANDS_PROP_VALUES_H_ |
| #define LIBWEAVE_SRC_COMMANDS_PROP_VALUES_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| |
| #include <weave/error.h> |
| |
| #include "src/commands/schema_utils.h" |
| |
| namespace base { |
| class Value; |
| class DictionaryValue; |
| } // namespace base |
| |
| namespace weave { |
| |
| // Enumeration to indicate supported command parameter types. |
| enum class ValueType { |
| Int, |
| Double, |
| String, |
| Boolean, |
| Object, |
| Array, |
| }; |
| |
| class PropValue; |
| class IntValue; |
| class DoubleValue; |
| class StringValue; |
| class BooleanValue; |
| class ObjectValue; |
| class ArrayValue; |
| |
| class PropType; |
| |
| // Helper methods to get the parameter type enum value for the given |
| // native C++ data representation. |
| // The generic GetValueType<T>() is undefined, however particular |
| // type specializations return the appropriate ValueType. |
| template <typename T> |
| ValueType GetValueType(); // Undefined. |
| template <> |
| inline ValueType GetValueType<int>() { |
| return ValueType::Int; |
| } |
| template <> |
| inline ValueType GetValueType<double>() { |
| return ValueType::Double; |
| } |
| template <> |
| inline ValueType GetValueType<std::string>() { |
| return ValueType::String; |
| } |
| template <> |
| inline ValueType GetValueType<bool>() { |
| return ValueType::Boolean; |
| } |
| template <> |
| inline ValueType GetValueType<ValueMap>() { |
| return ValueType::Object; |
| } |
| template <> |
| inline ValueType GetValueType<ValueVector>() { |
| return ValueType::Array; |
| } |
| |
| // The base class for property values. |
| // Concrete value classes of various types will be derived from this base. |
| // A property value is the actual command parameter value (or a concrete value |
| // that can be used in constraints and presets). The PropValue is mostly |
| // just parsed content of base::Value when a command is dispatched, however |
| // it does have some additional functionality: |
| // - it has a reference to the type definition (PropType) which is used |
| // when validating the value, especially for "object" types. |
| // - it can be compared with another instances of values of the same type. |
| // This is used to validate the values against "enum"/"one of" constraints. |
| class PropValue { |
| public: |
| // Only CreateDefaultValue should use this constructor. |
| explicit PropValue(const PropType& type); |
| virtual ~PropValue(); |
| |
| // Gets the type of the value. |
| virtual ValueType GetType() const = 0; |
| |
| // Type conversion methods. Used in lieu of RTTI and dynamic_cast<>. |
| virtual IntValue* GetInt() { return nullptr; } |
| virtual IntValue const* GetInt() const { return nullptr; } |
| virtual DoubleValue* GetDouble() { return nullptr; } |
| virtual DoubleValue const* GetDouble() const { return nullptr; } |
| virtual StringValue* GetString() { return nullptr; } |
| virtual StringValue const* GetString() const { return nullptr; } |
| virtual BooleanValue* GetBoolean() { return nullptr; } |
| virtual BooleanValue const* GetBoolean() const { return nullptr; } |
| virtual ObjectValue* GetObject() { return nullptr; } |
| virtual ObjectValue const* GetObject() const { return nullptr; } |
| virtual ArrayValue* GetArray() { return nullptr; } |
| virtual ArrayValue const* GetArray() const { return nullptr; } |
| |
| // Makes a full copy of this value class. |
| virtual std::unique_ptr<PropValue> Clone() const = 0; |
| |
| // Saves the value as a JSON object. Never fails. |
| virtual std::unique_ptr<base::Value> ToJson() const = 0; |
| |
| // Return the type definition of this value. |
| const PropType* GetPropType() const { return type_.get(); } |
| // Compares two values and returns true if they are equal. |
| virtual bool IsEqual(const PropValue* value) const = 0; |
| |
| protected: |
| // Special out-of-line constructor to help implement PropValue::Clone(). |
| // That method needs to clone the underlying type but can't do this in this |
| // header file since PropType is just forward-declared (it needs PropValue |
| // fully defined in its own inner workings). |
| explicit PropValue(const PropValue& other); |
| |
| private: |
| std::unique_ptr<const PropType> type_; |
| }; |
| |
| // A helper template base class for implementing value classes. |
| template <typename T> |
| class TypedValueBase : public PropValue { |
| public: |
| using PropValue::PropValue; |
| |
| // Overrides from PropValue base class. |
| ValueType GetType() const override { return GetValueType<T>(); } |
| |
| std::unique_ptr<base::Value> ToJson() const override { |
| return TypedValueToJson(value_); |
| } |
| |
| bool IsEqual(const PropValue* value) const override { |
| if (GetType() != value->GetType()) |
| return false; |
| return CompareValue(GetValue(), |
| static_cast<const TypedValueBase*>(value)->GetValue()); |
| } |
| |
| // Helper methods to get and set the C++ representation of the value. |
| const T& GetValue() const { return value_; } |
| |
| protected: |
| explicit TypedValueBase(const TypedValueBase& other) |
| : PropValue(other), value_(other.value_) {} |
| |
| TypedValueBase(const PropType& type, T value) |
| : PropValue(type), value_(value) {} |
| |
| private: |
| T value_{}; // The value of the parameter in C++ data representation. |
| }; |
| |
| // A helper template base class for implementing value classes. |
| template <typename Derived, typename T> |
| class TypedValueWithClone : public TypedValueBase<T> { |
| public: |
| using Base = TypedValueWithClone<Derived, T>; |
| |
| // Expose the custom constructor of the base class. |
| using TypedValueBase<T>::TypedValueBase; |
| using PropValue::GetPropType; |
| |
| std::unique_ptr<PropValue> Clone() const override { |
| return std::unique_ptr<PropValue>{ |
| new Derived{*static_cast<const Derived*>(this)}}; |
| } |
| |
| static std::unique_ptr<Derived> CreateFromJson(const base::Value& value, |
| const PropType& type, |
| ErrorPtr* error) { |
| T tmp_value; |
| if (!TypedValueFromJson(&value, &type, &tmp_value, error)) |
| return nullptr; |
| |
| // Only place where invalid value can exist. |
| std::unique_ptr<Derived> result{new Derived{type, tmp_value}}; |
| if (!result->GetPropType()->ValidateConstraints(*result, error)) |
| return nullptr; |
| |
| return result; |
| } |
| }; |
| |
| // Value of type Integer. |
| class IntValue final : public TypedValueWithClone<IntValue, int> { |
| public: |
| using Base::Base; |
| friend class TypedValueWithClone<IntValue, int>; |
| IntValue* GetInt() override { return this; } |
| IntValue const* GetInt() const override { return this; } |
| }; |
| |
| // Value of type Number. |
| class DoubleValue final : public TypedValueWithClone<DoubleValue, double> { |
| public: |
| using Base::Base; |
| friend class TypedValueWithClone<DoubleValue, double>; |
| DoubleValue* GetDouble() override { return this; } |
| DoubleValue const* GetDouble() const override { return this; } |
| }; |
| |
| // Value of type String. |
| class StringValue final : public TypedValueWithClone<StringValue, std::string> { |
| public: |
| using Base::Base; |
| friend class TypedValueWithClone<StringValue, std::string>; |
| StringValue* GetString() override { return this; } |
| StringValue const* GetString() const override { return this; } |
| }; |
| |
| // Value of type Boolean. |
| class BooleanValue final : public TypedValueWithClone<BooleanValue, bool> { |
| public: |
| using Base::Base; |
| friend class TypedValueWithClone<BooleanValue, bool>; |
| BooleanValue* GetBoolean() override { return this; } |
| BooleanValue const* GetBoolean() const override { return this; } |
| }; |
| |
| // Value of type Object. |
| class ObjectValue final : public TypedValueWithClone<ObjectValue, ValueMap> { |
| public: |
| using Base::Base; |
| friend class TypedValueWithClone<ObjectValue, ValueMap>; |
| ObjectValue* GetObject() override { return this; } |
| ObjectValue const* GetObject() const override { return this; } |
| }; |
| |
| // Value of type Array. |
| class ArrayValue final : public TypedValueWithClone<ArrayValue, ValueVector> { |
| public: |
| using Base::Base; |
| friend class TypedValueWithClone<ArrayValue, ValueVector>; |
| ArrayValue* GetArray() override { return this; } |
| ArrayValue const* GetArray() const override { return this; } |
| }; |
| |
| } // namespace weave |
| |
| #endif // LIBWEAVE_SRC_COMMANDS_PROP_VALUES_H_ |