Implement [] and iteration for OCRepresentation
authorErich Keane <erich.keane@intel.com>
Wed, 7 Jan 2015 21:09:55 +0000 (13:09 -0800)
committerSashi Penta <sashi.kumar.penta@intel.com>
Sat, 14 Feb 2015 07:15:26 +0000 (07:15 +0000)
Multiple requests have come in to be able to access the contents
of OCRepresentation in an easier to use manner.  This fix allows
OCRepresentation to be indexed using the [] operator and also
be iterated in an STL compliant fashion.

Additionally, this adds more than 40 tests for this functionality

Change-Id: Ibfc4bc61493324e118c4a6b67efc1d66e8b66b04
Signed-off-by: Erich Keane <erich.keane@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/116
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Sashi Penta <sashi.kumar.penta@intel.com>
(cherry picked from commit 529bb98b884ca4db27b7659f966075a8680fa3c3)
Reviewed-on: https://gerrit.iotivity.org/gerrit/325
Tested-by: Sashi Penta <sashi.kumar.penta@intel.com>
resource/examples/garageclient.cpp
resource/examples/garageserver.cpp
resource/include/AttributeValue.h
resource/include/OCRepresentation.h
resource/include/OCUtilities.h
resource/src/OCRepresentation.cpp
resource/unittests/OCRepresentationTest.cpp [new file with mode: 0644]
resource/unittests/makefile

index 2976aba..a03c742 100644 (file)
@@ -43,6 +43,7 @@ public:
     std::vector<int> m_lightPowers;
     OCRepresentation m_lightRep;
     std::vector<OCRepresentation> m_reps;
+    std::vector<std::vector<int>> m_hingeStates;
 
     Garage() : m_state(false), m_name("")
     {
@@ -57,7 +58,7 @@ void printRepresentation(const OCRepresentation& rep)
         // Check if attribute "name" exists, and then getValue
         if(rep.hasAttribute("name"))
         {
-            myGarage.m_name = rep.getValue<std::string>("name");
+            myGarage.m_name = rep["name"];
         }
         std::cout << "\tname: " << myGarage.m_name << std::endl;
 
@@ -92,10 +93,10 @@ void printRepresentation(const OCRepresentation& rep)
             std::cout << "\tnullAttribute is not null." << std::endl;
         }
 
-        rep.getValue("light", myGarage.m_lightRep);
+        myGarage.m_lightRep = rep["light"];
 
-        myGarage.m_lightRep.getValue("states", myGarage.m_lightStates);
-        myGarage.m_lightRep.getValue("powers", myGarage.m_lightPowers);
+        myGarage.m_lightStates = myGarage.m_lightRep["states"];
+        myGarage.m_lightPowers = myGarage.m_lightRep["powers"];
 
         std::cout << "\tlightRep: states: ";
 
@@ -131,13 +132,26 @@ void printRepresentation(const OCRepresentation& rep)
         std::cout << std::endl;
 
         // Get vector of representations
-        rep.getValue("reps", myGarage.m_reps);
-        // Client know that server is sending two representations
-        // and has key1 and key2 repsectively
-        std::cout << "\treps[0].key1: " << myGarage.m_reps[0].getValue<int>("key1") << std::endl;
-        std::cout << "\treps[0].key2: " << myGarage.m_reps[1].getValue<int>("key2") << std::endl;
+        myGarage.m_reps = rep["reps"];
+
+        int ct = 0;
+        for(auto& rep : myGarage.m_reps)
+        {
+            for(auto& attribute : rep)
+            {
+                std::cout<< "\treps["<<ct<<"]."<<attribute.attrname()<<":"
+                    << attribute.type()<<" with value " <<attribute.getValueToString() <<std::endl;
+            }
+            ++ct;
+        }
+
+        std::cout << "\tjson: " << rep["json"] << std::endl;
+        myGarage.m_hingeStates = rep["hinges"];
+
+        std::cout<< "\tHinge parameter is type: " << rep["hinges"].type() << " with depth "<<
+            rep["hinges"].depth() << " and a base type of "<< rep["hinges"].base_type()<<std::endl;
+
 
-        std::cout << "\tjson: " << rep.getValue<std::string>("json") << std::endl;
 }
 // callback handler on PUT request
 void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
@@ -166,7 +180,7 @@ void putLightRepresentation(std::shared_ptr<OCResource> resource)
 
         myGarage.m_state = true;
 
-        rep.setValue("state", myGarage.m_state);
+        rep["state"] = myGarage.m_state;
 
         // Create QueryParameters Map and add query params (if any)
         QueryParamsMap queryParamsMap;
index e2a57d8..1b2dfde 100644 (file)
@@ -53,25 +53,22 @@ public:
     // array of lights representation with in GarageResource
     OCRepresentation m_lightRep;
     std::vector<OCRepresentation> m_reps;
+    std::vector<std::vector<int>> m_hingeStates;
 
 public:
     /// Constructor
-    GarageResource(): m_name("John's Garage"), m_state(false), m_garageUri("/a/garage") {
+    GarageResource(): m_name("John's Garage"), m_state(false), m_garageUri("/a/garage"),
+        m_hingeStates{{1,2,3},{4,5,6}}
+    {
         // Initialize representation
         m_garageRep.setUri(m_garageUri);
 
-        m_garageRep.setValue("state", m_state);
-        m_garageRep.setValue("name", m_name);
+        m_garageRep["state"] = m_state;
+        m_garageRep["name"] = m_name;
 
         // For demonstration purpose we are setting x to nullptr here.
         // In reality it may happen else where.
-        int* x = nullptr;
-
-        // Check for nullptr and set null for that attribute
-        if(x == nullptr)
-        {
-            m_garageRep.setNULL("nullAttribute");
-        }
+        m_garageRep["nullAttribute"] = nullptr;
 
         std::vector<bool> lightStates;
         std::vector<int>  lightPowers;
@@ -82,30 +79,32 @@ public:
             lightPowers.push_back(i);
         }
 
-        m_lightRep.setValue("states", lightStates);
-        m_lightRep.setValue("powers", lightPowers);
+        m_lightRep["states"] = lightStates;
+        m_lightRep["powers"] = lightPowers;
 
         // Storing another representation within a representation
-        m_garageRep.setValue("light", m_lightRep);
+        m_garageRep["light"] = m_lightRep;
 
         OCRepresentation rep1;
         int value1 = 5;
-        rep1.setValue("key1", value1);
+        rep1["key1"] = value1;
         OCRepresentation rep2;
         int value2 = 10;
-        rep2.setValue("key2", value2);
+        rep2["key2"] = value2;
 
         m_reps.push_back(rep1);
         m_reps.push_back(rep2);
 
         // storing array of representations
-        m_garageRep.setValue("reps", m_reps);
+        m_garageRep["reps"] =  m_reps;
 
 
         // setting json string
         std::string json = "{\"num\":10,\"rno\":23.5,\"aoa\":[[1,2],[3]],\"str\":\"john\",\
 \"object\":{\"bl1\":false,\"ar\":[2,3]}, \"objects\":[{\"bl2\":true,\"nl\":null},{\"ar1\":[1,2]}]}";
-        m_garageRep.setValue("json", json);
+        m_garageRep["json"] = json;
+
+        m_garageRep["hinges"] = m_hingeStates;
     }
 
     /* Note that this does not need to be a member function: for classes you do not have
@@ -164,7 +163,7 @@ public:
     // sending out.
     OCRepresentation get()
     {
-        m_garageRep.setValue("state", m_state);
+        m_garageRep["state"] = m_state;
 
         return m_garageRep;
     }
index 5d0d524..be07173 100644 (file)
 #define BOOST_MPL_LIMIT_LIST_SIZE 30
 #define BOOST_MPL_LIMIT_VECTOR_SIZE 30
 #include <boost/variant.hpp>
-
+#include <iosfwd>
+#include <OCUtilities.h>
 namespace OC
 {
     class OCRepresentation;
 
     struct NullType{};
+
     // Since null needs to be encoded in a special fashion in JSON, the encoder
     // needs to know the index of the NullType Sentinel  Any time the code does a special
     // case for the NullType, we use the AttributeValueNullIndex.  This MUST be kept up to date
     // with the variant's which() for NullType.
     static const int AttributeValueNullIndex = 0;
     typedef boost::variant<
-
-        // Base values:
         NullType, // Note: this handles the null-type and must match the above static const
         int,
         double,
@@ -78,5 +78,56 @@ namespace OC
         std::vector<std::vector<std::vector<OC::OCRepresentation>>>
     > AttributeValue;
 
+    enum class AttributeType
+    {
+        Null,
+        Integer,
+        Double,
+        Boolean,
+        String,
+        OCRepresentation,
+        Vector
+    };
+
+    template<typename T>
+    struct AttributeTypeConvert{};
+
+    template<>
+    struct AttributeTypeConvert<NullType>
+    {
+        constexpr static AttributeType type = AttributeType::Null;
+    };
+
+    template<>
+    struct AttributeTypeConvert<int>
+    {
+        constexpr static AttributeType type = AttributeType::Integer;
+    };
+
+    template<>
+    struct AttributeTypeConvert<double>
+    {
+        constexpr static AttributeType type = AttributeType::Double;
+    };
+
+    template<>
+    struct AttributeTypeConvert<bool>
+    {
+        constexpr static AttributeType type = AttributeType::Boolean;
+    };
+
+    template<>
+    struct AttributeTypeConvert<std::string>
+    {
+        constexpr static AttributeType type = AttributeType::String;
+    };
+
+    template<>
+    struct AttributeTypeConvert<OCRepresentation>
+    {
+        constexpr static AttributeType type = AttributeType::OCRepresentation;
+    };
+
+    std::ostream& operator << (std::ostream& os, const AttributeType at);
 }
 #endif // __ATTRIBUTEVALUE_H
index 3a1746b..287d42e 100644 (file)
@@ -121,7 +121,7 @@ namespace OC
 
             void setResourceInterfaces(const std::vector<std::string>& resourceInterfaces);
 
-            bool empty() const;
+            bool emptyData() const;
 
             int numberOfAttributes() const;
 
@@ -162,11 +162,172 @@ namespace OC
                 return val;
             }
 
+            std::string getValueToString(const std::string& key) const;
             bool hasAttribute(const std::string& str) const;
 
             void setNULL(const std::string& str);
 
             bool isNULL(const std::string& str) const;
+
+            // STL Container stuff
+        public:
+            class iterator;
+            class const_iterator;
+            // Shim class to allow iterating and indexing of the OCRepresentation
+            // object.
+            class AttributeItem
+            {
+                friend class OCRepresentation;
+                friend class iterator;
+                friend class const_iterator;
+                public:
+                    const std::string& attrname() const;
+                    AttributeType type() const;
+                    AttributeType base_type() const;
+                    size_t depth() const;
+                    template<typename T>
+                    T getValue() const
+                    {
+                        return boost::get<T>(m_values[m_attrName]);
+                    }
+
+                    std::string getValueToString() const;
+
+                    template<typename T>
+                    AttributeItem& operator=(T&& rhs)
+                    {
+                        m_values[m_attrName] = std::forward<T>(rhs);
+                        return *this;
+                    }
+
+                    AttributeItem& operator=(std::nullptr_t rhs)
+                    {
+                        NullType t;
+                        m_values[m_attrName] = t;
+                        return *this;
+                    }
+
+                    // Enable-if required to prevent conversions to alternate types.  This prevents
+                    // ambigious conversions in the case where conversions can include a number of
+                    // types, such as the string constructor.
+                    template<typename T, typename= typename std::enable_if<
+                     std::is_same<T, int>::value ||
+                     std::is_same<T, double>::value ||
+                     std::is_same<T, bool>::value ||
+                     std::is_same<T, std::string>::value ||
+                     std::is_same<T, OCRepresentation>::value ||
+                     std::is_same<T, std::vector<int>>::value ||
+                     std::is_same<T, std::vector<std::vector<int>>>::value ||
+                     std::is_same<T, std::vector<std::vector<std::vector<int>>>>::value ||
+                     std::is_same<T, std::vector<double>>::value ||
+                     std::is_same<T, std::vector<std::vector<double>>>::value ||
+                     std::is_same<T, std::vector<std::vector<std::vector<double>>>>::value ||
+                     std::is_same<T, std::vector<bool>>::value ||
+                     std::is_same<T, std::vector<std::vector<bool>>>::value ||
+                     std::is_same<T, std::vector<std::vector<std::vector<bool>>>>::value ||
+                     std::is_same<T, std::vector<std::string>>::value ||
+                     std::is_same<T, std::vector<std::vector<std::string>>>::value ||
+                     std::is_same<T, std::vector<std::vector<std::vector<std::string>>>>::value ||
+                     std::is_same<T, std::vector<OCRepresentation>>::value ||
+                     std::is_same<T, std::vector<std::vector<OCRepresentation>>>::value ||
+                     std::is_same<T, std::vector<std::vector<std::vector<OCRepresentation>>>>::value
+                     >::type // enable_if
+                    >
+                    operator T() const
+                    {
+                        return this->getValue<T>();
+                    }
+
+                    operator std::nullptr_t() const
+                    {
+                        this->getValue<NullType>();
+                        return nullptr;
+                    }
+
+                private:
+                    AttributeItem(const std::string& name,
+                            std::map<std::string, AttributeValue>& vals);
+                    AttributeItem(const AttributeItem&) = default;
+                    std::string m_attrName;
+                    std::map<std::string, AttributeValue>& m_values;
+            };
+
+            // Iterator to allow iteration via STL containers/methods
+            class iterator
+            {
+                friend class OCRepresentation;
+                public:
+                    typedef iterator self_type;
+                    typedef AttributeItem value_type;
+                    typedef value_type& reference;
+                    typedef value_type* pointer;
+                    typedef std::forward_iterator_tag iterator_category;
+                    typedef int difference_type;
+
+                    iterator(const iterator&) = default;
+                    ~iterator() = default;
+
+                    bool operator ==(const iterator&) const;
+                    bool operator !=(const iterator&) const;
+
+                    iterator& operator++();
+                    iterator operator++(int);
+
+                    reference operator*();
+                    pointer operator->();
+                private:
+                    iterator(std::map<std::string, AttributeValue>::iterator&& itr,
+                            std::map<std::string, AttributeValue>& vals)
+                        : m_iterator(std::move(itr)),
+                        m_item(m_iterator != vals.end() ? m_iterator->first:"", vals){}
+                    std::map<std::string, AttributeValue>::iterator m_iterator;
+                    AttributeItem m_item;
+            };
+
+            class const_iterator
+            {
+                friend class OCRepresentation;
+                public:
+                    typedef iterator self_type;
+                    typedef const AttributeItem value_type;
+                    typedef value_type& const_reference;
+                    typedef value_type* const_pointer;
+                    typedef std::forward_iterator_tag iterator_category;
+                    typedef int difference_type;
+
+                    const_iterator(const iterator& rhs)
+                        :m_iterator(rhs.m_iterator), m_item(rhs.m_item){}
+                    const_iterator(const const_iterator&) = default;
+                    ~const_iterator() = default;
+
+                    bool operator ==(const const_iterator&) const;
+                    bool operator !=(const const_iterator&) const;
+
+                    const_iterator& operator++();
+                    const_iterator operator++(int);
+
+                    const_reference operator*() const;
+                    const_pointer operator->() const;
+                private:
+                    const_iterator(std::map<std::string, AttributeValue>::const_iterator&& itr,
+                            std::map<std::string, AttributeValue>& vals)
+                        : m_iterator(std::move(itr)),
+                        m_item(m_iterator != vals.end() ? m_iterator->first: "", vals){}
+                    std::map<std::string, AttributeValue>::const_iterator m_iterator;
+                    AttributeItem m_item;
+            };
+
+            iterator begin();
+            const_iterator begin() const;
+            const_iterator cbegin() const;
+            iterator end();
+            const_iterator end() const;
+            const_iterator cend() const;
+            size_t size() const;
+            bool empty() const;
+
+            AttributeItem operator[](const std::string& key);
+            const AttributeItem operator[](const std::string& key) const;
         private:
             friend class OCResourceResponse;
             friend class cereal::access;
@@ -217,12 +378,14 @@ namespace OC
         private:
             std::string m_uri;
             std::vector<OCRepresentation> m_children;
-            std::map<std::string, AttributeValue> m_values;
+            mutable std::map<std::string, AttributeValue> m_values;
             std::vector<std::string> m_resourceTypes;
             std::vector<std::string> m_interfaces;
 
             InterfaceType m_interfaceType;
     };
+
+    std::ostream& operator <<(std::ostream& os, const OCRepresentation::AttributeItem& ai);
 } // namespace OC
 
 
index aca25e9..cf01b8d 100644 (file)
@@ -27,7 +27,8 @@
 #include <utility>
 #include <exception>
 
-#include "OCException.h"
+#include <OCException.h>
+#include <StringConstants.h>
 
 namespace OC {
     namespace Utilities {
@@ -96,4 +97,23 @@ namespace OC {
 
 } // namespace OC
 
+namespace OC
+{
+    template<typename T, typename = void>
+    struct is_vector
+    {
+        constexpr static bool value = false;
+    };
+
+    template<typename T>
+    struct is_vector<T,
+        typename std::enable_if<
+            std::is_same<T, std::vector<typename T::value_type, typename T::allocator_type>>::value
+        >::type
+    >
+    {
+        constexpr static bool value = true;
+    };
+} // namespace OC
+
 #endif
index 71487cd..a91fd72 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <OCRepresentation.h>
 
+#include <boost/lexical_cast.hpp>
 #include <cereal/cereal.hpp>
 #include <cereal/types/map.hpp>
 #include <cereal/types/vector.hpp>
@@ -132,7 +133,7 @@ namespace OC
                 bool firstPrinted = false;
                 for(std::vector<OCRepresentation>::size_type i = 0; i< m_reps.size();++i)
                 {
-                    if(!m_reps[i].empty())
+                    if(!m_reps[i].emptyData())
                     {
                         if(firstPrinted)
                         {
@@ -165,7 +166,7 @@ namespace OC
     { }
     std::string OCRepresentation::getJSONRepresentation() const
     {
-        if(empty())
+        if(emptyData())
         {
             return "{}";
         }
@@ -233,7 +234,7 @@ namespace OC
         return m_values.find(str) != m_values.end();
     }
 
-    bool OCRepresentation::empty() const
+    bool OCRepresentation::emptyData() const
     {
         // This logic is meant to determine whether based on the JSON serialization rules
         // if this object will result in empty JSON.  URI is only serialized if there is valid
@@ -646,3 +647,330 @@ namespace cereal
        }
    }
 }
+
+namespace OC
+{
+    std::ostream& operator <<(std::ostream& os, const AttributeType at)
+    {
+        switch(at)
+        {
+            case AttributeType::Null:
+                os << "Null";
+                break;
+            case AttributeType::Integer:
+                os << "Integer";
+                break;
+            case AttributeType::Double:
+                os << "Double";
+                break;
+            case AttributeType::Boolean:
+                os << "Boolean";
+                break;
+            case AttributeType::String:
+                os << "String";
+                break;
+            case AttributeType::OCRepresentation:
+                os << "OCRepresentation";
+                break;
+            case AttributeType::Vector:
+                os << "Vector";
+                break;
+        }
+        return os;
+    }
+}
+
+// STL Container For OCRepresentation
+namespace OC
+{
+    OCRepresentation::AttributeItem::AttributeItem(const std::string& name,
+            std::map<std::string, AttributeValue>& vals):
+            m_attrName(name), m_values(vals){}
+
+    OCRepresentation::AttributeItem OCRepresentation::operator[](const std::string& key)
+    {
+        OCRepresentation::AttributeItem attr{key, m_values};
+        return std::move(attr);
+    }
+
+    const OCRepresentation::AttributeItem OCRepresentation::operator[](const std::string& key) const
+    {
+        OCRepresentation::AttributeItem attr{key, m_values};
+        return std::move(attr);
+    }
+
+    const std::string& OCRepresentation::AttributeItem::attrname() const
+    {
+        return m_attrName;
+    }
+
+    template<typename T, typename = void>
+    struct type_info
+    {
+        // contains the actual type
+        typedef T type;
+        // contains the inner most vector-type
+        typedef T base_type;
+        // contains the AttributeType for this item
+        constexpr static AttributeType enum_type =
+            AttributeTypeConvert<T>::type;
+        // contains the AttributeType for this base-type
+        constexpr static AttributeType enum_base_type =
+            AttributeTypeConvert<T>::type;
+        // depth of the vector
+        constexpr static size_t depth = 0;
+    };
+
+    template<typename T>
+    struct type_info<T, typename std::enable_if<is_vector<T>::value>::type>
+    {
+        typedef T type;
+        typedef typename type_info<typename T::value_type>::base_type base_type;
+        constexpr static AttributeType enum_type = AttributeType::Vector;
+        constexpr static AttributeType enum_base_type =
+            type_info<typename T::value_type>::enum_base_type;
+        constexpr static size_t depth = 1 +
+            type_info<typename T::value_type>::depth;
+    };
+
+    struct type_introspection_visitor : boost::static_visitor<>
+    {
+        AttributeType type;
+        AttributeType base_type;
+        size_t depth;
+
+        type_introspection_visitor() : boost::static_visitor<>(),
+            type(AttributeType::Null), base_type(AttributeType::Null), depth(0){}
+
+        template <typename T>
+        void operator()(T const& item)
+        {
+            type = type_info<T>::enum_type;
+            base_type = type_info<T>::enum_base_type;
+            depth = type_info<T>::depth;
+        }
+    };
+
+    AttributeType OCRepresentation::AttributeItem::type() const
+    {
+        type_introspection_visitor vis;
+        boost::apply_visitor(vis, m_values[m_attrName]);
+        return vis.type;
+    }
+
+    AttributeType OCRepresentation::AttributeItem::base_type() const
+    {
+        type_introspection_visitor vis;
+        boost::apply_visitor(vis, m_values[m_attrName]);
+        return vis.base_type;
+    }
+
+    size_t OCRepresentation::AttributeItem::depth() const
+    {
+        type_introspection_visitor vis;
+        boost::apply_visitor(vis, m_values[m_attrName]);
+        return vis.depth;
+    }
+
+    OCRepresentation::iterator OCRepresentation::begin()
+    {
+        return OCRepresentation::iterator(m_values.begin(), m_values);
+    }
+
+    OCRepresentation::const_iterator OCRepresentation::begin() const
+    {
+         return OCRepresentation::const_iterator(m_values.begin(), m_values);
+    }
+
+    OCRepresentation::const_iterator OCRepresentation::cbegin() const
+    {
+        return OCRepresentation::const_iterator(m_values.cbegin(), m_values);
+    }
+
+    OCRepresentation::iterator OCRepresentation::end()
+    {
+        return OCRepresentation::iterator(m_values.end(), m_values);
+    }
+
+    OCRepresentation::const_iterator OCRepresentation::end() const
+    {
+        return OCRepresentation::const_iterator(m_values.end(), m_values);
+    }
+
+    OCRepresentation::const_iterator OCRepresentation::cend() const
+    {
+        return OCRepresentation::const_iterator(m_values.cend(), m_values);
+    }
+
+    size_t OCRepresentation::size() const
+    {
+        return m_values.size();
+    }
+
+    bool OCRepresentation::empty() const
+    {
+        return m_values.empty();
+    }
+
+    bool OCRepresentation::iterator::operator==(const OCRepresentation::iterator& rhs) const
+    {
+        return m_iterator == rhs.m_iterator;
+    }
+
+    bool OCRepresentation::iterator::operator!=(const OCRepresentation::iterator& rhs) const
+    {
+        return m_iterator != rhs.m_iterator;
+    }
+
+    bool OCRepresentation::const_iterator::operator==(
+            const OCRepresentation::const_iterator& rhs) const
+    {
+        return m_iterator == rhs.m_iterator;
+    }
+
+    bool OCRepresentation::const_iterator::operator!=(
+            const OCRepresentation::const_iterator& rhs) const
+    {
+        return m_iterator != rhs.m_iterator;
+    }
+
+    OCRepresentation::iterator::reference OCRepresentation::iterator::operator*()
+    {
+        return m_item;
+    }
+
+    OCRepresentation::const_iterator::const_reference
+        OCRepresentation::const_iterator::operator*() const
+    {
+        return m_item;
+    }
+
+    OCRepresentation::iterator::pointer OCRepresentation::iterator::operator->()
+    {
+        return &m_item;
+    }
+
+    OCRepresentation::const_iterator::const_pointer
+        OCRepresentation::const_iterator::operator->() const
+    {
+        return &m_item;
+    }
+
+    OCRepresentation::iterator& OCRepresentation::iterator::operator++()
+    {
+        m_iterator++;
+        if(m_iterator != m_item.m_values.end())
+        {
+            m_item.m_attrName = m_iterator->first;
+        }
+        else
+        {
+            m_item.m_attrName = "";
+        }
+        return *this;
+    }
+
+    OCRepresentation::const_iterator& OCRepresentation::const_iterator::operator++()
+    {
+        m_iterator++;
+        if(m_iterator != m_item.m_values.end())
+        {
+            m_item.m_attrName = m_iterator->first;
+        }
+        else
+        {
+            m_item.m_attrName = "";
+        }
+        return *this;
+    }
+
+    OCRepresentation::iterator OCRepresentation::iterator::operator++(int)
+    {
+        OCRepresentation::iterator itr(*this);
+        ++(*this);
+        return itr;
+    }
+
+    OCRepresentation::const_iterator OCRepresentation::const_iterator::operator++(int)
+    {
+        OCRepresentation::const_iterator itr(*this);
+        ++(*this);
+        return itr;
+    }
+
+    struct to_string_visitor : boost::static_visitor<>
+    {
+        std::string str;
+        template <typename T>
+        void operator()(T const& item)
+        {
+            str = boost::lexical_cast<std::string>(item);
+        }
+
+        template <typename T>
+        void operator()(std::vector<T> const& item)
+        {
+            to_string_visitor vis;
+            std::ostringstream stream;
+            stream << "[";
+
+            for(const auto& i : item)
+            {
+                vis(i);
+                stream << vis.str  << " ";
+            }
+            stream << "]";
+            str = stream.str();
+        }
+    };
+
+    template<>
+    void to_string_visitor::operator()(bool const& item)
+    {
+        str = item ? "true" : "false";
+    }
+
+    template<>
+    void to_string_visitor::operator()(std::string const& item)
+    {
+        str = item;
+    }
+
+    template<>
+    void to_string_visitor::operator()(NullType const& item)
+    {
+        str = "(null)";
+    }
+
+    template<>
+    void to_string_visitor::operator()(OCRepresentation const& item)
+    {
+        str = "OC::OCRepresentation";
+    }
+
+    std::string OCRepresentation::getValueToString(const std::string& key) const
+    {
+        auto x = m_values.find(key);
+        if(x != m_values.end())
+        {
+            to_string_visitor vis;
+            boost::apply_visitor(vis, x->second);
+            return std::move(vis.str);
+        }
+
+        return "";
+    }
+
+    std::string OCRepresentation::AttributeItem::getValueToString() const
+    {
+        to_string_visitor vis;
+        boost::apply_visitor(vis, m_values[m_attrName]);
+        return std::move(vis.str);
+    }
+
+    std::ostream& operator<<(std::ostream& os, const OCRepresentation::AttributeItem& ai)
+    {
+        os << ai.getValueToString();
+        return os;
+    }
+}
diff --git a/resource/unittests/OCRepresentationTest.cpp b/resource/unittests/OCRepresentationTest.cpp
new file mode 100644 (file)
index 0000000..629b989
--- /dev/null
@@ -0,0 +1,1311 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <gtest/gtest.h>
+#include <OCApi.h>
+#include <string>
+#include <limits>
+#include <boost/lexical_cast.hpp>
+namespace OCRepresentationTest
+{
+    using namespace OC;
+    using std::string;
+    using std::vector;
+
+    template<typename T>
+    void parsedEqual(T expected, const std::string& actualStr)
+    {
+        T actual = boost::lexical_cast<T>(actualStr);
+        EXPECT_LT(std::abs(expected - actual), std::numeric_limits<T>::epsilon());
+    }
+
+    // getValueToString(all types)
+    TEST(OCRepresentationValueToString, Null)
+    {
+        static const std::string AttrName = "NullTest";
+        OCRepresentation rep;
+        rep.setNULL(AttrName);
+
+        EXPECT_TRUE(rep.isNULL(AttrName));
+        EXPECT_EQ("(null)", rep.getValueToString(AttrName));
+        EXPECT_EQ("(null)", rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, Integer)
+    {
+        static const std::string AttrName = "IntTest";
+        OCRepresentation rep;
+
+        rep.setValue(AttrName, -5);
+        EXPECT_EQ("-5", rep.getValueToString(AttrName));
+        EXPECT_EQ("-5", rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, 0);
+        EXPECT_EQ("0", rep.getValueToString(AttrName));
+        EXPECT_EQ("0", rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, 5);
+        EXPECT_EQ("5", rep.getValueToString(AttrName));
+        EXPECT_EQ("5", rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, 54321);
+        EXPECT_EQ("54321", rep.getValueToString(AttrName));
+        EXPECT_EQ("54321", rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, Double)
+    {
+        static const std::string AttrName = "DoubleTest";
+        OCRepresentation rep;
+
+        rep.setValue(AttrName, -5.0);
+        parsedEqual(-5.0, rep.getValueToString(AttrName));
+        parsedEqual(-5.0, rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, 0.0);
+        parsedEqual(0.0, rep.getValueToString(AttrName));
+        parsedEqual(0.0, rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, 5.0);
+        parsedEqual(5.0, rep.getValueToString(AttrName));
+        parsedEqual(5.0, rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, 54321.0);
+        parsedEqual(54321.0, rep.getValueToString(AttrName));
+        parsedEqual(54321.0, rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, 3.55);
+        parsedEqual(3.55, rep.getValueToString(AttrName));
+        parsedEqual(3.55, rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, -4.95);
+        parsedEqual(-4.95, rep.getValueToString(AttrName));
+        parsedEqual(-4.95, rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, 99999.5555);
+        parsedEqual(99999.5555, rep.getValueToString(AttrName));
+        parsedEqual(99999.5555, rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, Boolean)
+    {
+        static const std::string AttrName = "BooleanTest";
+        OCRepresentation rep;
+
+        rep.setValue(AttrName, false);
+        EXPECT_EQ("false", rep.getValueToString(AttrName));
+        EXPECT_EQ("false", rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, true);
+        EXPECT_EQ("true", rep.getValueToString(AttrName));
+        EXPECT_EQ("true", rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, String)
+    {
+        static const std::string AttrName = "StringTest";
+        OCRepresentation rep;
+
+        rep.setValue(AttrName, std::string("test 1"));
+        EXPECT_EQ("test 1", rep.getValueToString(AttrName));
+        EXPECT_EQ("test 1", rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, std::string("test 2"));
+        EXPECT_EQ("test 2", rep.getValueToString(AttrName));
+        EXPECT_EQ("test 2", rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, SubRepresentation)
+    {
+        static const std::string AttrName = "SubRepTest";
+        OCRepresentation rep;
+        OCRepresentation sub1;
+        OCRepresentation sub2;
+
+        rep.setValue(AttrName, sub1);
+        EXPECT_EQ("OC::OCRepresentation", rep.getValueToString(AttrName));
+        EXPECT_EQ("OC::OCRepresentation", rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, sub2);
+        EXPECT_EQ("OC::OCRepresentation", rep.getValueToString(AttrName));
+        EXPECT_EQ("OC::OCRepresentation", rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, IntegerVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        vector<int> vect {1,2,3,4,5,6,7,8,9};
+        vector<int> vect2 {-5,-3,-1,0,5,3,2};
+        rep.setValue(AttrName, vect);
+        EXPECT_EQ("[1 2 3 4 5 6 7 8 9 ]", rep.getValueToString(AttrName));
+        EXPECT_EQ("[1 2 3 4 5 6 7 8 9 ]", rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, vect2);
+        EXPECT_EQ("[-5 -3 -1 0 5 3 2 ]", rep.getValueToString(AttrName));
+        EXPECT_EQ("[-5 -3 -1 0 5 3 2 ]", rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, IntegerVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        vector<int> vect1 {1,2,3,4,5,6,7,8,9};
+        vector<int> vect2 {-5,-3,-1,0,5,3,2};
+        vector<vector<int>> vect{vect1, vect2};
+
+        rep.setValue(AttrName, vect);
+        static const string Expected = "[[1 2 3 4 5 6 7 8 9 ] [-5 -3 -1 0 5 3 2 ] ]";
+        EXPECT_EQ(Expected, rep.getValueToString(AttrName));
+        EXPECT_EQ(Expected, rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, IntegerVectorVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        vector<int> vect11 {1,2,3,4,5,6,7,8,9};
+        vector<int> vect12 {-5,-3,-1,0,5,3,2};
+        vector<vector<int>> vect1{vect11, vect12};
+        vector<int> vect21 {2,0,1,6,9,3,8};
+        vector<int> vect22 {9,7,8,100003};
+        vector<vector<int>> vect2{vect21, vect22};
+        vector<vector<vector<int>>> vect{vect1, vect2};
+        rep.setValue(AttrName, vect);
+        static const std::string Expected =
+            "[[[1 2 3 4 5 6 7 8 9 ] [-5 -3 -1 0 5 3 2 ] ] [[2 0 1 6 9 3 8 ] [9 7 8 100003 ] ] ]";
+        EXPECT_EQ(Expected, rep.getValueToString(AttrName));
+        EXPECT_EQ(Expected, rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, DoubleVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        vector<double> vect {3.12, -5.3, 7.5, 1.110};
+        vector<double> vect2 {2.1, -555.5, 0.0001, -0.2};
+        rep.setValue(AttrName, vect);
+        EXPECT_EQ(rep.getValueToString(AttrName), rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, vect2);
+        EXPECT_EQ(rep.getValueToString(AttrName), rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, DoubleVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        vector<double> vect1 {30.1,5.88,-22.0,0};
+        vector<double> vect2 {2.1,-55.5,0.1100,-.2};
+        vector<vector<double>> vect{vect1, vect2};
+
+        rep.setValue(AttrName, vect);
+        EXPECT_EQ(rep.getValueToString(AttrName), rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, DoubleVectorVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        vector<double> vect11 {3.01, 5.88, -22.0, 0.0};
+        vector<double> vect12 {99.3,8.0,.01236,-.22};
+        vector<vector<double>> vect1{vect11, vect12};
+        vector<double> vect21 {9.0,-1};
+        vector<double> vect22 {-99.2};
+        vector<vector<double>> vect2{vect21, vect22};
+        vector<vector<vector<double>>> vect{vect1, vect2};
+        rep.setValue(AttrName, vect);
+        EXPECT_EQ(rep.getValueToString(AttrName), rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, BooleanVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        vector<bool> vect {true, false, false, true};
+        vector<bool> vect2 {false, false, false, true};
+        rep.setValue(AttrName, vect);
+        EXPECT_EQ("[true false false true ]", rep.getValueToString(AttrName));
+        EXPECT_EQ("[true false false true ]", rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, vect2);
+        EXPECT_EQ("[false false false true ]", rep.getValueToString(AttrName));
+        EXPECT_EQ("[false false false true ]", rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, BooleanVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        vector<bool> vect1 {true, false, false, true};
+        vector<bool> vect2 {false, false, false, true};
+        vector<vector<bool>> vect{vect1, vect2};
+
+        rep.setValue(AttrName, vect);
+        static const string Expected="[[true false false true ] [false false false true ] ]";
+
+        EXPECT_EQ(Expected, rep.getValueToString(AttrName));
+        EXPECT_EQ(Expected, rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, BooleanVectorVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        vector<bool> vect11 {true, false, false, true};
+        vector<bool> vect12 {false, false, false, true};
+        vector<vector<bool>> vect1{vect11, vect12};
+        vector<bool> vect21 {false, true, true, false};
+        vector<bool> vect22 {true, true, true, false};
+        vector<vector<bool>> vect2{vect21, vect22};
+        vector<vector<vector<bool>>> vect{vect1, vect2};
+        rep.setValue(AttrName, vect);
+        static const std::string Expected =
+            "[[[true false false true ] [false false false true ] ]"
+            " [[false true true false ] [true true true false ] ] ]";
+        EXPECT_EQ(Expected, rep.getValueToString(AttrName));
+        EXPECT_EQ(Expected, rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, StringVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        vector<string> vect {"s1", "s2", "s3"};
+        vector<string> vect2 {"s4", "s5", "s6"};
+        rep.setValue(AttrName, vect);
+        EXPECT_EQ("[s1 s2 s3 ]", rep.getValueToString(AttrName));
+        EXPECT_EQ("[s1 s2 s3 ]", rep[AttrName].getValueToString());
+
+        rep.setValue(AttrName, vect2);
+        EXPECT_EQ("[s4 s5 s6 ]", rep.getValueToString(AttrName));
+        EXPECT_EQ("[s4 s5 s6 ]", rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, StringVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        vector<string> vect1 {"s1", "s2", "s3"};
+        vector<string> vect2 {"s4", "s5", "s6"};
+        vector<vector<string>> vect{vect1, vect2};
+
+        rep.setValue(AttrName, vect);
+        static const string Expected="[[s1 s2 s3 ] [s4 s5 s6 ] ]";
+
+        EXPECT_EQ(Expected, rep.getValueToString(AttrName));
+        EXPECT_EQ(Expected, rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, StringVectorVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        vector<string> vect11 {"s1", "s2", "s3"};
+        vector<string> vect12 {"s4", "s5", "s6"};
+        vector<vector<string>> vect1{vect11, vect12};
+        vector<string> vect21 {"s7", "s8"};
+        vector<string> vect22 {"s9"};
+        vector<vector<string>> vect2{vect21, vect22};
+        vector<vector<vector<string>>> vect{vect1, vect2};
+        rep.setValue(AttrName, vect);
+        static const std::string Expected =
+            "[[[s1 s2 s3 ] [s4 s5 s6 ] ]"
+            " [[s7 s8 ] [s9 ] ] ]";
+        EXPECT_EQ(Expected, rep.getValueToString(AttrName));
+        EXPECT_EQ(Expected, rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, SubRepresentationVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        OCRepresentation sub1;
+        OCRepresentation sub2;
+        vector<OCRepresentation> vect {sub1, sub2};
+        rep.setValue(AttrName, vect);
+        EXPECT_EQ("[OC::OCRepresentation OC::OCRepresentation ]", rep.getValueToString(AttrName));
+        EXPECT_EQ("[OC::OCRepresentation OC::OCRepresentation ]", rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, SubRepresentationVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        OCRepresentation sub1;
+        OCRepresentation sub2;
+        OCRepresentation sub3;
+        OCRepresentation sub4;
+        vector<OCRepresentation> vect1 {sub1, sub2};
+        vector<OCRepresentation> vect2 {sub3, sub4};
+        vector<vector<OCRepresentation>> vect{vect1, vect2};
+        rep.setValue(AttrName, vect);
+        static const string Expected = "[[OC::OCRepresentation OC::OCRepresentation ]"
+            " [OC::OCRepresentation OC::OCRepresentation ] ]";
+        EXPECT_EQ(Expected, rep.getValueToString(AttrName));
+        EXPECT_EQ(Expected, rep[AttrName].getValueToString());
+    }
+
+    TEST(OCRepresentationValueToString, SubRepresentationVectorVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+
+        OCRepresentation sub1;
+        OCRepresentation sub2;
+        OCRepresentation sub3;
+        OCRepresentation sub4;
+        OCRepresentation sub5;
+        OCRepresentation sub6;
+
+        vector<OCRepresentation> vect11 {sub1, sub2};
+        vector<OCRepresentation> vect12 {sub3, sub4};
+        vector<vector<OCRepresentation>> vect1{vect11, vect12};
+        vector<OCRepresentation> vect21 {sub5};
+        vector<OCRepresentation> vect22 {sub6};
+        vector<vector<OCRepresentation>> vect2{vect21, vect22};
+        vector<vector<vector<OCRepresentation>>> vect{vect1, vect2};
+
+        rep.setValue(AttrName, vect);
+        static const string Expected =
+            "[[[OC::OCRepresentation OC::OCRepresentation ] "
+            "[OC::OCRepresentation OC::OCRepresentation ] ] "
+            "[[OC::OCRepresentation ] [OC::OCRepresentation ] ] ]";
+        EXPECT_EQ(Expected, rep.getValueToString(AttrName));
+        EXPECT_EQ(Expected, rep[AttrName].getValueToString());
+    }
+
+    // Subscript get/set (all types)
+    TEST(OCRepresentationSubscript, NullPtr)
+    {
+        static const std::string AttrName = "NullTest";
+        OCRepresentation rep;
+        rep[AttrName] = nullptr;
+        EXPECT_TRUE(rep.isNULL(AttrName));
+
+        std::nullptr_t repout = rep[AttrName];
+        std::nullptr_t repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(nullptr, repout);
+        EXPECT_EQ(nullptr, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, Integer)
+    {
+        static const std::string AttrName = "IntTest";
+        OCRepresentation rep;
+        int repsource = -5;
+        rep[AttrName] = repsource;
+        int repout = rep[AttrName];
+        int repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, Double)
+    {
+        static const std::string AttrName = "DoubleTest";
+        OCRepresentation rep;
+        double repsource = -5.33;
+        rep[AttrName] = repsource;
+        double repout = rep[AttrName];
+        double repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        int badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, Boolean)
+    {
+        static const std::string AttrName = "BooleanTest";
+        OCRepresentation rep;
+        bool repsource = true;
+        rep[AttrName] = repsource;
+        bool repout = rep[AttrName];
+        bool repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        repsource = false;
+        rep[AttrName] = repsource;
+        repout = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+
+        int badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, String)
+    {
+        static const std::string AttrName = "StringTest";
+        OCRepresentation rep;
+        string repsource = "This is a string!";
+        rep[AttrName] = repsource;
+        string repout = rep[AttrName];
+        string repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        (void)badout;
+    }
+
+    TEST(OCRepresentationSubscript, SubRepresentation)
+    {
+        static const std::string AttrName = "SubRepresentationTest";
+        OCRepresentation rep;
+        OCRepresentation repsource;
+        repsource.setUri("This is a uri");
+
+        rep[AttrName] = repsource;
+        OCRepresentation repout = rep[AttrName];
+        OCRepresentation repout2;
+        repout2 = rep[AttrName];
+
+        //OCRepresentation doesn't overload equality, so this just compares
+        //the value we set to ensure we got the same one out;
+        EXPECT_EQ(repsource.getUri(), repout.getUri());
+        EXPECT_EQ(repsource.getUri(), repout2.getUri());
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, IntegerVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        vector<int> repsource {1,2,3,4};
+        rep[AttrName] = repsource;
+        vector<int> repout = rep[AttrName];
+        vector<int> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, IntegerVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        vector<vector<int>> repsource {{1,2,3,4},{5,6,7,8}};
+        rep[AttrName] = repsource;
+        vector<vector<int>> repout = rep[AttrName];
+        vector<vector<int>> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, IntegerVectorVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        vector<vector<vector<int>>> repsource {{{1,2,3,4},{5,6,7,8}},{{9,10,11},{21,13}}};
+        rep[AttrName] = repsource;
+        vector<vector<vector<int>>> repout = rep[AttrName];
+        vector<vector<vector<int>>> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, DoubleVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        vector<double> repsource {1.1,2.2,3.2,4.2};
+        rep[AttrName] = repsource;
+        vector<double> repout = rep[AttrName];
+        vector<double> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, DoubleVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        vector<vector<double>> repsource {{1.1,2.2,3.2,4.3},{5.5,6.6,7.8,.8}};
+        rep[AttrName] = repsource;
+        vector<vector<double>> repout = rep[AttrName];
+        vector<vector<double>> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, DoubleVectorVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        vector<vector<vector<double>>> repsource {{{1.1,2.5,3.5,4.4},{.5,.6,7.8,8.9}},
+            {{9.8,10.8,11.8},{2.1,1.3}}};
+        rep[AttrName] = repsource;
+        vector<vector<vector<double>>> repout = rep[AttrName];
+        vector<vector<vector<double>>> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, BooleanVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        vector<bool> repsource {false, false, true};
+        rep[AttrName] = repsource;
+        vector<bool> repout = rep[AttrName];
+        vector<bool> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, BooleanVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        vector<vector<bool>> repsource {{true, true},{false, true}};
+        rep[AttrName] = repsource;
+        vector<vector<bool>> repout = rep[AttrName];
+        vector<vector<bool>> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, BooleanVectorVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        vector<vector<vector<bool>>> repsource {{{true, true, false},{true}},
+            {{true, false, false},{false, true, true}}};
+        rep[AttrName] = repsource;
+        vector<vector<vector<bool>>> repout = rep[AttrName];
+        vector<vector<vector<bool>>> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, StringVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        vector<string> repsource {"str1", "str2"};
+        rep[AttrName] = repsource;
+        vector<string> repout = rep[AttrName];
+        vector<string> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, StringVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        vector<vector<string>> repsource {{"str1", "str2"},{"str3", "str4"}};
+        rep[AttrName] = repsource;
+        vector<vector<string>> repout = rep[AttrName];
+        vector<vector<string>> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, StringVectorVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        vector<vector<vector<string>>> repsource {{{"str1", "str2"},{"str3", "str4"}},
+            {{"str5"},{"str6"}}};
+        rep[AttrName] = repsource;
+        vector<vector<vector<string>>> repout = rep[AttrName];
+        vector<vector<vector<string>>> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(repsource, repout);
+        EXPECT_EQ(repsource, repout2);
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, SubRepresentationVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        OCRepresentation inner1, inner2;
+        inner1.setUri("inner1");
+        inner2.setUri("inner2");
+        vector<OCRepresentation> repsource {inner1, inner2};
+        rep[AttrName] = repsource;
+        vector<OCRepresentation> repout = rep[AttrName];
+        vector<OCRepresentation> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(2, repout.size());
+        EXPECT_EQ(inner1.getUri(), repout[0].getUri());
+        EXPECT_EQ(inner2.getUri(), repout[1].getUri());
+        EXPECT_EQ(2, repout2.size());
+        EXPECT_EQ(inner1.getUri(), repout2[0].getUri());
+        EXPECT_EQ(inner2.getUri(), repout2[1].getUri());
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, SubRepresentationVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        OCRepresentation inner1, inner2, inner3, inner4;
+        inner1.setUri("inner1");
+        inner2.setUri("inner2");
+        inner3.setUri("inner3");
+        inner4.setUri("inner4");
+
+        vector<vector<OCRepresentation>> repsource {{inner1, inner2}, {inner3, inner4}};
+        rep[AttrName] = repsource;
+        vector<vector<OCRepresentation>> repout = rep[AttrName];
+        vector<vector<OCRepresentation>> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(2, repout.size());
+        EXPECT_EQ(2, repout[0].size());
+        EXPECT_EQ(inner1.getUri(), repout[0][0].getUri());
+        EXPECT_EQ(inner2.getUri(), repout[0][1].getUri());
+        EXPECT_EQ(2, repout.size());
+        EXPECT_EQ(2, repout[1].size());
+        EXPECT_EQ(inner3.getUri(), repout[1][0].getUri());
+        EXPECT_EQ(inner4.getUri(), repout[1][1].getUri());
+
+        EXPECT_EQ(2, repout2.size());
+        EXPECT_EQ(2, repout2[0].size());
+        EXPECT_EQ(inner1.getUri(), repout2[0][0].getUri());
+        EXPECT_EQ(inner2.getUri(), repout2[0][1].getUri());
+        EXPECT_EQ(2, repout2.size());
+        EXPECT_EQ(2, repout2[1].size());
+        EXPECT_EQ(inner3.getUri(), repout2[1][0].getUri());
+        EXPECT_EQ(inner4.getUri(), repout2[1][1].getUri());
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationSubscript, SubRepresentationVectorVectorVector)
+    {
+        static const std::string AttrName = "VectorTest";
+        OCRepresentation rep;
+        OCRepresentation inner1, inner2, inner3, inner4, inner5, inner6, inner7, inner8;
+        inner1.setUri("inner1");
+        inner2.setUri("inner2");
+        inner3.setUri("inner3");
+        inner4.setUri("inner4");
+        inner5.setUri("inner5");
+        inner6.setUri("inner6");
+        inner7.setUri("inner7");
+        inner8.setUri("inner8");
+
+        vector<vector<vector<OCRepresentation>>> repsource
+            {{{inner1, inner2},{inner3, inner4}},{{inner5, inner6},{inner7,inner8}}};
+
+        rep[AttrName] = repsource;
+        vector<vector<vector<OCRepresentation>>> repout = rep[AttrName];
+        vector<vector<vector<OCRepresentation>>> repout2;
+        repout2 = rep[AttrName];
+
+        EXPECT_EQ(2, repout.size());
+        EXPECT_EQ(2, repout[0].size());
+        EXPECT_EQ(2, repout[0][0].size());
+        EXPECT_EQ(inner1.getUri(), repout[0][0][0].getUri());
+        EXPECT_EQ(inner2.getUri(), repout[0][0][1].getUri());
+        EXPECT_EQ(2, repout[0][1].size());
+        EXPECT_EQ(inner3.getUri(), repout[0][1][0].getUri());
+        EXPECT_EQ(inner4.getUri(), repout[0][1][1].getUri());
+        EXPECT_EQ(2, repout[1].size());
+        EXPECT_EQ(2, repout[1][0].size());
+        EXPECT_EQ(inner5.getUri(), repout[1][0][0].getUri());
+        EXPECT_EQ(inner6.getUri(), repout[1][0][1].getUri());
+        EXPECT_EQ(2, repout[1][1].size());
+        EXPECT_EQ(inner7.getUri(), repout[1][1][0].getUri());
+        EXPECT_EQ(inner8.getUri(), repout[1][1][1].getUri());
+
+        EXPECT_EQ(2, repout2.size());
+        EXPECT_EQ(2, repout2[0].size());
+        EXPECT_EQ(2, repout2[0][0].size());
+        EXPECT_EQ(inner1.getUri(), repout2[0][0][0].getUri());
+        EXPECT_EQ(inner2.getUri(), repout2[0][0][1].getUri());
+        EXPECT_EQ(2, repout[0][1].size());
+        EXPECT_EQ(inner3.getUri(), repout2[0][1][0].getUri());
+        EXPECT_EQ(inner4.getUri(), repout2[0][1][1].getUri());
+        EXPECT_EQ(2, repout[1].size());
+        EXPECT_EQ(2, repout[1][0].size());
+        EXPECT_EQ(inner5.getUri(), repout2[1][0][0].getUri());
+        EXPECT_EQ(inner6.getUri(), repout2[1][0][1].getUri());
+        EXPECT_EQ(2, repout[1][1].size());
+        EXPECT_EQ(inner7.getUri(), repout2[1][1][0].getUri());
+        EXPECT_EQ(inner8.getUri(), repout2[1][1][1].getUri());
+
+        double badout;
+        EXPECT_THROW(badout = rep[AttrName], boost::bad_get);
+        string badoutstr;
+        EXPECT_THROW(badoutstr = rep[AttrName], boost::bad_get);
+        (void)badout;
+        (void)badoutstr;
+    }
+
+    TEST(OCRepresentationIterator, constiterator)
+    {
+        OCRepresentation rep;
+
+        EXPECT_TRUE(rep.empty());
+        rep.setValue("int", 8);
+        EXPECT_FALSE(rep.empty());
+        rep.setValue("double", 8.8);
+        rep.setValue("bool", true);
+        rep.setValue("string", std::string("this is a string"));
+
+        EXPECT_EQ(4, rep.size());
+        EXPECT_FALSE(rep.empty());
+
+        OCRepresentation::const_iterator itr = rep.cbegin();
+        OCRepresentation::const_iterator endItr = rep.cend();
+        for(;itr!=endItr;++itr);
+
+        const OCRepresentation& rep2(rep);
+        OCRepresentation::const_iterator itr2 = rep2.begin();
+        OCRepresentation::const_iterator endItr2 = rep2.end();
+        for(;itr2!=endItr2;++itr2);
+
+    }
+
+    TEST(OCRepresentationIterator, constautoiterator)
+    {
+        OCRepresentation rep;
+
+        EXPECT_TRUE(rep.empty());
+        rep.setValue("int", 8);
+        EXPECT_FALSE(rep.empty());
+        rep.setValue("double", 8.8);
+        rep.setValue("bool", true);
+        rep.setValue("string", std::string("this is a string"));
+
+        EXPECT_EQ(4, rep.size());
+        EXPECT_FALSE(rep.empty());
+
+        for(const auto& a : rep)
+        {
+            (void)a;
+        }
+
+        const OCRepresentation& rep2(rep);
+        for(const auto& a : rep2)
+        {
+            (void)a;
+        }
+    }
+    TEST(OCRepresentationIterator, autoiterator)
+    {
+        OCRepresentation rep;
+
+        EXPECT_TRUE(rep.empty());
+        rep.setValue("int", 8);
+        EXPECT_FALSE(rep.empty());
+        rep.setValue("double", 8.8);
+        rep.setValue("bool", true);
+        rep.setValue("string", std::string("this is a string"));
+
+        EXPECT_EQ(4, rep.size());
+        EXPECT_FALSE(rep.empty());
+
+        for(auto& cur : rep)
+        {
+            if(cur.attrname() == "int")
+            {
+                EXPECT_EQ("int", cur.attrname());
+                EXPECT_EQ(AttributeType::Integer, cur.type());
+                EXPECT_EQ(AttributeType::Integer, cur.base_type());
+                EXPECT_EQ(0, cur.depth());
+                int curInt = cur.getValue<int>();
+                EXPECT_EQ(8, curInt);
+            }
+            if(cur.attrname() == "double")
+            {
+                EXPECT_EQ("double", cur.attrname());
+                EXPECT_EQ(AttributeType::Double, cur.type());
+                EXPECT_EQ(AttributeType::Double, cur.base_type());
+                EXPECT_EQ(0, cur.depth());
+                double curDouble = cur.getValue<double>();
+                EXPECT_EQ(8.8, curDouble);
+            }
+            if(cur.attrname() == "bool")
+            {
+                EXPECT_EQ("bool", cur.attrname());
+                EXPECT_EQ(AttributeType::Boolean, cur.type());
+                EXPECT_EQ(AttributeType::Boolean, cur.base_type());
+                EXPECT_EQ(0, cur.depth());
+                bool curBool = cur.getValue<bool>();
+                EXPECT_EQ(true, curBool);
+            }
+            if(cur.attrname() == "string")
+            {
+                EXPECT_EQ("string", cur.attrname());
+                EXPECT_EQ(AttributeType::String, cur.type());
+                EXPECT_EQ(AttributeType::String, cur.base_type());
+                EXPECT_EQ(0, cur.depth());
+                string curStr = cur.getValue<string>();
+                EXPECT_EQ("this is a string", curStr);
+            }
+        }
+    }
+    // Iterator usage
+    TEST(OCRepresentationIterator, iterator)
+    {
+        OCRepresentation rep;
+        OCRepresentation sub1;
+        sub1.setUri("sub rep1 URI");
+        OCRepresentation sub2;
+        sub2.setUri("sub rep2 URI");
+        OCRepresentation sub3;
+        sub3.setUri("sub rep3 URI");
+        OCRepresentation sub4;
+        sub4.setUri("sub rep4 URI");
+        OCRepresentation sub5;
+        sub5.setUri("sub rep5 URI");
+        OCRepresentation sub6;
+        sub6.setUri("sub rep6 URI");
+
+
+        EXPECT_TRUE(rep.empty());
+        rep.setValue("int", 8);
+        EXPECT_FALSE(rep.empty());
+        rep.setValue("double", 8.8);
+        rep.setValue("bool", true);
+        rep.setValue("string", std::string("this is a string"));
+        rep.setValue("rep", sub1);
+
+        vector<int> intv {1,2,3,4};
+        rep.setValue("intv", intv);
+        vector<double> doublev {1.1,2.2,3.3,4.4};
+        rep.setValue("doublev", doublev);
+        vector<bool> boolv{false, false, true};
+        rep.setValue("boolv", boolv);
+        vector<string> strv{"abc", "def", "ghi"};
+        rep.setValue("strv", strv);
+        vector<OCRepresentation> repv { sub1, sub2 };
+        rep.setValue("repv", repv);
+
+        vector<vector<int>> intvv{{1,2,3},{4,5,6}};
+        rep.setValue("intvv", intvv);
+        vector<vector<vector<int>>> intvvv{{{1,2},{3,4}},{{5,6},{8,7}}};
+        rep.setValue("intvvv", intvvv);
+
+        vector<vector<double>> doublevv{{1.1,2.1,3},{4.4,5.4,6.4}};
+        rep.setValue("doublevv", doublevv);
+        vector<vector<vector<double>>> doublevvv{{{1.1,2.1},{3.1,4.1}},{{5.1,6.1},{8.1,7.1}}};
+        rep.setValue("doublevvv", doublevvv);
+
+        vector<vector<bool>> boolvv{{false, true},{true, false}};
+        rep.setValue("boolvv", boolvv);
+        vector<vector<vector<bool>>> boolvvv{{{true, false},{true}},{{false},{true}}};
+        rep.setValue("boolvvv", boolvvv);
+
+        vector<vector<string>> strvv{{"abc", "def"},{"wer", "qwer"}};
+        rep.setValue("strvv", strvv);
+        vector<vector<vector<string>>> strvvv{{{"wqr", "xcv"},{"234"}},{{"we"},{"wert"}}};
+        rep.setValue("strvvv", strvvv);
+
+        vector<vector<OCRepresentation>> repvv{{sub1, sub2},{sub3, sub4}};
+        rep.setValue("repvv", repvv);
+        vector<vector<vector<OCRepresentation>>> repvvv{{{sub5},{sub6}},{{sub3},{sub2}}};
+        rep.setValue("repvvv", repvvv);
+
+        EXPECT_EQ(20, rep.size());
+        EXPECT_FALSE(rep.empty());
+
+        OCRepresentation::iterator itr= rep.begin();
+        OCRepresentation::iterator endItr = rep.end();
+
+        for(;itr!=endItr;++itr)
+        {
+            if(itr->attrname() == "int")
+            {
+                EXPECT_EQ("int", itr->attrname());
+                EXPECT_EQ(AttributeType::Integer, itr->type());
+                EXPECT_EQ(AttributeType::Integer, itr->base_type());
+                EXPECT_EQ(0, itr->depth());
+                int curInt = (*itr).getValue<int>();
+                EXPECT_EQ(8, curInt);
+            }
+            else if (itr->attrname() == "double")
+            {
+                EXPECT_EQ("double", itr->attrname());
+                EXPECT_EQ(AttributeType::Double, itr->type());
+                EXPECT_EQ(AttributeType::Double, itr->base_type());
+                EXPECT_EQ(0, itr->depth());
+                double curDouble = (*itr).getValue<double>();
+                EXPECT_EQ(8.8, curDouble);
+            }
+            else if (itr->attrname() == "bool")
+            {
+                EXPECT_EQ("bool", itr->attrname());
+                EXPECT_EQ(AttributeType::Boolean, itr->type());
+                EXPECT_EQ(AttributeType::Boolean, itr->base_type());
+                EXPECT_EQ(0, itr->depth());
+                bool curBool = (*itr).getValue<bool>();
+                EXPECT_EQ(true, curBool);
+            }
+            else if (itr->attrname() == "string")
+            {
+                EXPECT_EQ("string", itr->attrname());
+                EXPECT_EQ(AttributeType::String, itr->type());
+                EXPECT_EQ(AttributeType::String, itr->base_type());
+                EXPECT_EQ(0, itr->depth());
+                string curString = (*itr).getValue<string>();
+                EXPECT_EQ("this is a string", curString);
+            }
+            else if (itr->attrname() == "rep")
+            {
+                EXPECT_EQ("rep", itr->attrname());
+                EXPECT_EQ(AttributeType::OCRepresentation, itr->type());
+                EXPECT_EQ(AttributeType::OCRepresentation, itr->base_type());
+                EXPECT_EQ(0, itr->depth());
+                OCRepresentation curRep = (*itr).getValue<OCRepresentation>();
+                EXPECT_EQ(sub1.getUri(), curRep.getUri());
+            }
+            else if (itr->attrname() == "intv")
+            {
+                EXPECT_EQ("intv", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::Integer, itr->base_type());
+                EXPECT_EQ(1, itr->depth());
+                vector<int> curv = (*itr).getValue<vector<int>>();
+                EXPECT_EQ(intv, curv);
+            }
+            else if (itr->attrname() == "doublev")
+            {
+                EXPECT_EQ("doublev", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::Double, itr->base_type());
+                EXPECT_EQ(1, itr->depth());
+                vector<double> curv = (*itr).getValue<vector<double>>();
+                EXPECT_EQ(doublev, curv);
+            }
+            else if (itr->attrname() == "boolv")
+            {
+                EXPECT_EQ("boolv", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::Boolean, itr->base_type());
+                EXPECT_EQ(1, itr->depth());
+                vector<bool> curv = (*itr).getValue<vector<bool>>();
+                EXPECT_EQ(boolv, curv);
+            }
+            else if (itr->attrname() == "strv")
+            {
+                EXPECT_EQ("strv", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::String, itr->base_type());
+                EXPECT_EQ(1, itr->depth());
+                vector<string> curv = (*itr).getValue<vector<string>>();
+                EXPECT_EQ(strv, curv);
+            }
+            else if (itr->attrname() == "repv")
+            {
+                EXPECT_EQ("repv", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::OCRepresentation, itr->base_type());
+                EXPECT_EQ(1, itr->depth());
+                vector<OCRepresentation> curv = (*itr).getValue<vector<OCRepresentation>>();
+                EXPECT_EQ(2, repv.size());
+                EXPECT_EQ(sub1.getUri(), repv[0].getUri());
+                EXPECT_EQ(sub2.getUri(), repv[1].getUri());
+            }
+            else if (itr->attrname() == "intvv")
+            {
+                EXPECT_EQ("intvv", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::Integer, itr->base_type());
+                EXPECT_EQ(2, itr->depth());
+                vector<vector<int>> curv = (*itr).getValue<vector<vector<int>>>();
+                EXPECT_EQ(intvv, curv);
+            }
+            else if (itr->attrname() == "intvvv")
+            {
+                EXPECT_EQ("intvvv", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::Integer, itr->base_type());
+                EXPECT_EQ(3, itr->depth());
+                vector<vector<vector<int>>> curv = (*itr).getValue<vector<vector<vector<int>>>>();
+                EXPECT_EQ(intvvv, curv);
+            }
+            else if (itr->attrname() == "doublevv")
+            {
+                EXPECT_EQ("doublevv", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::Double, itr->base_type());
+                EXPECT_EQ(2, itr->depth());
+                vector<vector<double>> curv = (*itr).getValue<vector<vector<double>>>();
+                EXPECT_EQ(doublevv, curv);
+            }
+            else if (itr->attrname() == "doublevvv")
+            {
+                EXPECT_EQ("doublevvv", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::Double, itr->base_type());
+                EXPECT_EQ(3, itr->depth());
+                vector<vector<vector<double>>> curv =
+                    (*itr).getValue<vector<vector<vector<double>>>>();
+                EXPECT_EQ(doublevvv, curv);
+            }
+            else if (itr->attrname() == "boolvv")
+            {
+                EXPECT_EQ("boolvv", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::Boolean, itr->base_type());
+                EXPECT_EQ(2, itr->depth());
+                vector<vector<bool>> curv = (*itr).getValue<vector<vector<bool>>>();
+                EXPECT_EQ(boolvv, curv);
+            }
+            else if (itr->attrname() == "boolvvv")
+            {
+                EXPECT_EQ("boolvvv", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::Boolean, itr->base_type());
+                EXPECT_EQ(3, itr->depth());
+                vector<vector<vector<bool>>> curv = (*itr).getValue<vector<vector<vector<bool>>>>();
+                EXPECT_EQ(boolvvv, curv);
+            }
+            else if (itr->attrname() == "strvv")
+            {
+                EXPECT_EQ("strvv", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::String, itr->base_type());
+                EXPECT_EQ(2, itr->depth());
+                vector<vector<string>> curv = (*itr).getValue<vector<vector<string>>>();
+                EXPECT_EQ(strvv, curv);
+            }
+            else if (itr->attrname() == "strvvv")
+            {
+                EXPECT_EQ("strvvv", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::String, itr->base_type());
+                EXPECT_EQ(3, itr->depth());
+                vector<vector<vector<string>>> curv =
+                    (*itr).getValue<vector<vector<vector<string>>>>();
+                EXPECT_EQ(strvvv, curv);
+            }
+            else if (itr->attrname() == "repvv")
+            {
+                EXPECT_EQ("repvv", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::OCRepresentation, itr->base_type());
+                EXPECT_EQ(2, itr->depth());
+                vector<vector<OCRepresentation>> curv =
+                    (*itr).getValue<vector<vector<OCRepresentation>>>();
+                EXPECT_EQ(2, curv.size());
+                EXPECT_EQ(2, curv[0].size());
+                EXPECT_EQ(sub1.getUri(), curv[0][0].getUri());
+                EXPECT_EQ(sub2.getUri(), curv[0][1].getUri());
+                EXPECT_EQ(2, curv[1].size());
+                EXPECT_EQ(sub3.getUri(), curv[1][0].getUri());
+                EXPECT_EQ(sub4.getUri(), curv[1][1].getUri());
+            }
+            else if (itr->attrname() == "repvvv")
+            {
+                EXPECT_EQ("repvvv", itr->attrname());
+                EXPECT_EQ(AttributeType::Vector, itr->type());
+                EXPECT_EQ(AttributeType::OCRepresentation, itr->base_type());
+                EXPECT_EQ(3, itr->depth());
+                vector<vector<vector<OCRepresentation>>> curv =
+                    (*itr).getValue<vector<vector<vector<OCRepresentation>>>>();
+                EXPECT_EQ(2, curv.size());
+                EXPECT_EQ(2, curv[0].size());
+                EXPECT_EQ(1, curv[0][0].size());
+                EXPECT_EQ(sub5.getUri(), curv[0][0][0].getUri());
+                EXPECT_EQ(1, curv[0][1].size());
+                EXPECT_EQ(sub6.getUri(), curv[0][1][0].getUri());
+                EXPECT_EQ(1, curv[1][0].size());
+                EXPECT_EQ(sub3.getUri(), curv[1][0][0].getUri());
+                EXPECT_EQ(1, curv[1][1].size());
+                EXPECT_EQ(sub2.getUri(), curv[1][1][0].getUri());
+            }
+            else
+            {
+                EXPECT_TRUE(false) << itr->attrname();
+            }
+        }
+    }
+}
index 7587c04..7b38234 100644 (file)
@@ -67,7 +67,7 @@ all: prep_dirs $(MOCKS_DIR) unittests
 prep_dirs:
        -mkdir -p $(OUT_DIR)
 
-unittests: OCPlatformTest.cpp OCResourceTest.cpp ConstructResourceTest.cpp $(GTEST_LIBS)
+unittests: OCPlatformTest.cpp OCResourceTest.cpp ConstructResourceTest.cpp OCRepresentationTest.cpp $(GTEST_LIBS)
        $(CXX) $^ $(CPPFLAGS) -o $(OUT_DIR)/$@
        
 $(GTEST_DIR):