Add type class for ResourceAttriutes
authorcoderhyme <jhyo.kim@samsung.com>
Wed, 8 Jul 2015 04:00:50 +0000 (13:00 +0900)
committerUze Choi <uzchoi@samsung.com>
Wed, 8 Jul 2015 05:36:52 +0000 (05:36 +0000)
The class helps distinguish types between Values

Change-Id: I7a02c290bb6b1f3fb7d26ef7cb1087268afa36ac
Signed-off-by: coderhyme <jhyo.kim@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/1569
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
Tested-by: Uze Choi <uzchoi@samsung.com>
service/resource-manipulation/modules/common/primitiveResource/include/ResourceAttributes.h
service/resource-manipulation/modules/common/primitiveResource/include/internal/ResourceAttributesUtils.h
service/resource-manipulation/modules/common/primitiveResource/src/ResourceAttributes.cpp
service/resource-manipulation/modules/common/primitiveResource/unittests/ResourceAttributesTest.cpp

index 35219fb..3dda5eb 100755 (executable)
@@ -60,7 +60,7 @@ namespace OIC
         class ResourceAttributes
         {
         private:
-            template< typename T > struct is_supported_type_helper;
+            template< typename T > struct IsSupportedTypeHelper;
 
             using ValueVariant = boost::variant<
                 std::nullptr_t,
@@ -76,11 +76,11 @@ namespace OIC
 
             template< typename T, typename V = void >
             using enable_if_supported = typename std::enable_if<
-                    is_supported_type_helper< T >::type::value, V >::type;
+                    IsSupportedTypeHelper< T >::type::value, V >::type;
 
             template< typename T, typename V = void >
             using enable_if_unsupported = typename std::enable_if<
-                    !is_supported_type_helper< T >::type::value, V >::type;
+                    !IsSupportedTypeHelper< T >::type::value, V >::type;
 
             template< typename VISITOR >
             class KeyValueVisitorHelper: public boost::static_visitor< >
@@ -101,9 +101,52 @@ namespace OIC
                 VISITOR& m_visitor;
             };
 
+            template <typename T> struct IndexOfType;
+
         public:
             template< typename T >
-            using is_supported_type = typename is_supported_type_helper< T >::type;
+            using is_supported_type = typename IsSupportedTypeHelper< T >::type;
+
+            enum class TypeId
+            {
+                NULL_T,
+                INT,
+                DOUBLE,
+                BOOL,
+                STRING,
+                ATTRIBUTES,
+                VECTOR
+            };
+
+            class Type
+            {
+            public:
+                Type(const Type&) = default;
+                Type(Type&&) = default;
+
+                Type& operator=(const Type&) = default;
+                Type& operator=(Type&&) = default;
+
+                TypeId getId() const;
+
+                template < typename T >
+                static Type typeOf(const T& value)
+                {
+                    return Type(value);
+                }
+
+                friend bool operator==(const Type&, const Type&);
+
+            private:
+                template < typename T >
+                explicit Type(const T&) :
+                    m_which{ IndexOfType< T >::value }
+                {
+                }
+
+            private:
+                int m_which;
+            };
 
             class Value
             {
@@ -145,25 +188,7 @@ namespace OIC
                     return checkedGet< T >();
                 }
 
-                bool isTypeEqualWith(const Value& rhs) const
-                {
-                    return m_data->which() == rhs.m_data->which();
-                }
-
-                template< typename T >
-                enable_if_supported< T, bool > isTypeOf() const
-                {
-                    using iter = typename boost::mpl::find< ValueVariant::types, T >::type;
-
-                    return m_data->which()
-                            == boost::mpl::distance< mpl_begin< ValueVariant::types >, iter >::value;
-                }
-
-                template< typename T >
-                enable_if_unsupported< T, bool > isTypeOf() const
-                {
-                    return false;
-                }
+                Type getType() const;
 
                 std::string toString() const;
 
@@ -264,12 +289,23 @@ namespace OIC
             friend class ResourceAttributesConverter;
         };
 
-        template< typename T > struct ResourceAttributes::is_supported_type_helper
+        template< typename T >
+        struct ResourceAttributes::IsSupportedTypeHelper
         {
             using type = boost::mpl::contains<ValueVariant::types, typename std::decay< T >::type>;
         };
 
+        template <typename T>
+        struct ResourceAttributes::IndexOfType
+        {
+            using iter = typename boost::mpl::find< ValueVariant::types, T >::type;
+
+            static constexpr int value = boost::mpl::distance< mpl_begin< ValueVariant::types >,
+                    iter >::value;
+        };
 
+        bool operator==(const ResourceAttributes::Type&, const ResourceAttributes::Type&);
+        bool operator!=(const ResourceAttributes::Type&, const ResourceAttributes::Type&);
 
         bool operator!=(const ResourceAttributes::Value&, const ResourceAttributes::Value&);
 
index 8672373..50f3b2d 100644 (file)
@@ -36,7 +36,8 @@ namespace OIC
         bool acceptableAttributeValue(const ResourceAttributes::Value& dest,
                 const ResourceAttributes::Value& value);
 
-        AttrKeyValuePairs replaceAttributes(ResourceAttributes& dest, const ResourceAttributes& attrs);
+        AttrKeyValuePairs replaceAttributes(ResourceAttributes& dest,
+                const ResourceAttributes& attrs);
     }
 }
 
index 95d1746..aa74adb 100755 (executable)
 #include <internal/ResourceAttributesConverter.h>
 
 #include <boost/lexical_cast.hpp>
+#include <boost/mpl/advance.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/deref.hpp>
 
 namespace
 {
 
+    using namespace OIC::Service;
+
     class ToStringVisitor: public boost::static_visitor< std::string >
     {
     public:
@@ -65,6 +70,112 @@ namespace
         }
     };
 
+    class TypeVisitor: public boost::static_visitor< ResourceAttributes::Type >
+    {
+    public:
+        TypeVisitor() = default;
+        TypeVisitor(const TypeVisitor&) = delete;
+        TypeVisitor(TypeVisitor&&) = delete;
+
+        TypeVisitor& operator=(const TypeVisitor&) = delete;
+        TypeVisitor& operator=(TypeVisitor&&) = delete;
+
+        template< typename T >
+        ResourceAttributes::Type operator()(const T& value) const
+        {
+            return ResourceAttributes::Type::typeOf(value);
+        }
+
+    };
+
+    template< int >
+    struct Int2Type {};
+
+    template< typename T >
+    struct TypeInfoConverter;
+
+    template< >
+    struct TypeInfoConverter< int >
+    {
+        static constexpr ResourceAttributes::TypeId typeId = ResourceAttributes::TypeId::INT;
+    };
+
+    template< >
+    struct TypeInfoConverter< std::nullptr_t >
+    {
+        static constexpr ResourceAttributes::TypeId typeId = ResourceAttributes::TypeId::NULL_T;
+    };
+
+    template< >
+    struct TypeInfoConverter< double >
+    {
+        static constexpr ResourceAttributes::TypeId typeId = ResourceAttributes::TypeId::DOUBLE;
+    };
+
+    template< >
+    struct TypeInfoConverter< bool >
+    {
+        static constexpr ResourceAttributes::TypeId typeId = ResourceAttributes::TypeId::BOOL;
+    };
+
+    template< >
+    struct TypeInfoConverter< std::string >
+    {
+        static constexpr ResourceAttributes::TypeId typeId = ResourceAttributes::TypeId::STRING;
+    };
+
+    template< >
+    struct TypeInfoConverter< ResourceAttributes >
+    {
+        static constexpr ResourceAttributes::TypeId typeId = ResourceAttributes::TypeId::ATTRIBUTES;
+    };
+
+    struct TypeInfo
+    {
+        ResourceAttributes::TypeId typeId;
+
+        template< typename TRAIT >
+        constexpr TypeInfo(TRAIT) :
+                typeId{ TRAIT::typeId }
+        {
+        }
+
+        template< typename VARIANT, int POS >
+        static constexpr TypeInfo get()
+        {
+            return TypeInfo(
+                    TypeInfoConverter<
+                            typename boost::mpl::deref<
+                                    typename boost::mpl::advance<
+                                            typename boost::mpl::begin< typename VARIANT::types >::type,
+                                            boost::mpl::int_< POS > >::type >::type >{ });
+        }
+    };
+
+    template< typename VARIANT, int POS >
+    constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< POS >)
+    {
+        auto&& vec = getTypeInfo< VARIANT >(Int2Type< POS - 1 >{ });
+        vec.push_back(TypeInfo::get< VARIANT, POS >());
+        return vec;
+    }
+
+    template< typename VARIANT >
+    constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< 0 >)
+    {
+        return { TypeInfo::get< VARIANT, 0 >() };
+    }
+
+    template< typename VARIANT >
+    inline TypeInfo getTypeInfo(int which)
+    {
+        static constexpr int variantEnd = boost::mpl::size< typename VARIANT::types >::value - 1;
+        static const std::vector< TypeInfo > typeInfos = getTypeInfo< VARIANT >(
+                Int2Type< variantEnd >{ });
+
+        return typeInfos[which];
+    }
+
 } // unnamed namespace
 
 
@@ -73,6 +184,16 @@ namespace OIC
     namespace Service
     {
 
+        bool operator==(const ResourceAttributes::Type& lhs, const ResourceAttributes::Type& rhs)
+        {
+            return lhs.m_which == rhs.m_which;
+        }
+
+        bool operator!=(const ResourceAttributes::Type& lhs, const ResourceAttributes::Type& rhs)
+        {
+            return !(lhs == rhs);
+        }
+
         bool operator!=(const ResourceAttributes::Value& lhs, const ResourceAttributes::Value& rhs)
         {
             return !(lhs == rhs);
@@ -83,7 +204,6 @@ namespace OIC
             return !(rhs == lhs);
         }
 
-
         bool operator==(const char* lhs, const ResourceAttributes::Value& rhs)
         {
             return rhs == lhs;
@@ -104,6 +224,11 @@ namespace OIC
             return !(lhs == rhs);
         }
 
+        auto ResourceAttributes::Type::getId() const -> TypeId
+        {
+            return ::getTypeInfo< ValueVariant >(m_which).typeId;
+        }
+
         ResourceAttributes::Value::Value() :
                 m_data{ new ValueVariant{} }
         {
@@ -155,6 +280,11 @@ namespace OIC
             return equals< std::string >(rhs);
         }
 
+        auto ResourceAttributes::Value::getType() const -> Type
+        {
+            return boost::apply_visitor(TypeVisitor(), *m_data);
+        }
+
         std::string ResourceAttributes::Value::toString() const
         {
             return boost::apply_visitor(ToStringVisitor(), *m_data);
@@ -211,7 +341,6 @@ namespace OIC
             return boost::apply_visitor(m_valueVisitor, m_iterRef);
         }
 
-
         ResourceAttributes::KeyValuePair::KeyValuePair(boost::variant<iterator*,
                 const_iterator*>&& ref) :
                 m_iterRef{ ref }
@@ -406,7 +535,7 @@ namespace OIC
         bool acceptableAttributeValue(const ResourceAttributes::Value& dest,
                 const ResourceAttributes::Value& value)
         {
-            if (!dest.isTypeEqualWith(value))
+            if (dest.getType() != value.getType())
             {
                 return false;
             }
@@ -414,7 +543,7 @@ namespace OIC
             static_assert(ResourceAttributes::is_supported_type< ResourceAttributes >::value,
                     "ResourceAttributes doesn't have ResourceAttributes recursively.");
 
-            if (dest.isTypeOf< ResourceAttributes >()
+            if (dest.getType().getId() == ResourceAttributes::TypeId::ATTRIBUTES
                     && !acceptableAttributes(dest.get< ResourceAttributes >(),
                             value.get< ResourceAttributes >()))
             {
index 3066a5f..b8f593c 100644 (file)
@@ -272,6 +272,22 @@ TEST(ResourceAttributesValueTest, ValuesCanBeSwapped)
     ASSERT_EQ(i, strValue);
 }
 
+TEST(ResourceAttributesTypeTest, TypeIdMatchesTypeOfValue)
+{
+    ResourceAttributes::Value intValue { 1 };
+
+    ASSERT_EQ(intValue.getType().getId(), ResourceAttributes::TypeId::INT);
+}
+
+TEST(ResourceAttributesTypeTest, TypeCanBeConstructedFromValue)
+{
+    ResourceAttributes::Value intValue { 1 };
+
+    ResourceAttributes::Type t = ResourceAttributes::Type::typeOf(0);
+
+    ASSERT_EQ(intValue.getType(), t);
+}
+
 TEST(ResourceAttributesConverterTest, OCRepresentationCanBeConvertedIntoResourceAttributes)
 {
     constexpr double value = 9876;