| // 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_ |