1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
24 * This file contains the implementation of classes and its members related
25 * to OCRepresentation.
29 #include <OCRepresentation.h>
31 #include <boost/lexical_cast.hpp>
33 #include "ocpayload.h"
35 #include "oic_malloc.h"
36 #include "oic_string.h"
41 void MessageContainer::setPayload(const OCPayload* rep)
45 case PAYLOAD_TYPE_REPRESENTATION:
46 setPayload(reinterpret_cast<const OCRepPayload*>(rep));
48 case PAYLOAD_TYPE_DEVICE:
49 setPayload(reinterpret_cast<const OCDevicePayload*>(rep));
51 case PAYLOAD_TYPE_PLATFORM:
52 setPayload(reinterpret_cast<const OCPlatformPayload*>(rep));
55 throw OC::OCException("Invalid Payload type in setPayload");
60 void MessageContainer::setPayload(const OCDevicePayload* payload)
63 rep.setUri(payload->uri);
64 char uuidString[UUID_STRING_SIZE];
65 if(payload->sid && RAND_UUID_OK == OCConvertUuidToString(payload->sid, uuidString))
67 rep[OC_RSRVD_DEVICE_ID] = std::string(uuidString);
71 rep[OC_RSRVD_DEVICE_ID] = std::string();
73 rep[OC_RSRVD_DEVICE_NAME] = payload->deviceName ?
74 std::string(payload->deviceName) :
76 rep[OC_RSRVD_SPEC_VERSION] = payload->specVersion ?
77 std::string(payload->specVersion) :
79 rep[OC_RSRVD_DATA_MODEL_VERSION] = payload->dataModelVersion ?
80 std::string(payload->dataModelVersion) :
82 m_reps.push_back(std::move(rep));
85 void MessageContainer::setPayload(const OCPlatformPayload* payload)
88 rep.setUri(payload->uri);
90 rep[OC_RSRVD_PLATFORM_ID] = payload->info.platformID ?
91 std::string(payload->info.platformID) :
93 rep[OC_RSRVD_MFG_NAME] = payload->info.manufacturerName ?
94 std::string(payload->info.manufacturerName) :
96 rep[OC_RSRVD_MFG_URL] = payload->info.manufacturerUrl ?
97 std::string(payload->info.manufacturerUrl) :
99 rep[OC_RSRVD_MODEL_NUM] = payload->info.modelNumber ?
100 std::string(payload->info.modelNumber) :
102 rep[OC_RSRVD_MFG_DATE] = payload->info.dateOfManufacture ?
103 std::string(payload->info.dateOfManufacture) :
105 rep[OC_RSRVD_PLATFORM_VERSION] = payload->info.platformVersion ?
106 std::string(payload->info.platformVersion) :
108 rep[OC_RSRVD_OS_VERSION] = payload->info.operatingSystemVersion ?
109 std::string(payload->info.operatingSystemVersion) :
111 rep[OC_RSRVD_HARDWARE_VERSION] = payload->info.hardwareVersion ?
112 std::string(payload->info.hardwareVersion) :
114 rep[OC_RSRVD_FIRMWARE_VERSION] = payload->info.firmwareVersion ?
115 std::string(payload->info.firmwareVersion) :
117 rep[OC_RSRVD_SUPPORT_URL] = payload->info.supportUrl ?
118 std::string(payload->info.supportUrl) :
120 rep[OC_RSRVD_SYSTEM_TIME] = payload->info.systemTime ?
121 std::string(payload->info.systemTime) :
124 m_reps.push_back(std::move(rep));
127 void MessageContainer::setPayload(const OCRepPayload* payload)
129 const OCRepPayload* pl = payload;
132 OCRepresentation cur;
136 this->addRepresentation(cur);
140 OCRepPayload* MessageContainer::getPayload() const
142 OCRepPayload* root = nullptr;
143 for(const auto& r : representations())
147 root = r.getPayload();
151 OCRepPayloadAppend(root, r.getPayload());
158 const std::vector<OCRepresentation>& MessageContainer::representations() const
163 void MessageContainer::addRepresentation(const OCRepresentation& rep)
165 m_reps.push_back(rep);
171 struct get_payload_array: boost::static_visitor<>
174 void operator()(T& arr)
176 throw std::logic_error("Invalid calc_dimensions_visitor type");
180 void operator()(std::vector<T>& arr)
183 dimensions[0] = arr.size();
184 dimTotal = calcDimTotal(dimensions);
186 array = (void*)OICMalloc(dimTotal * root_size);
188 for(size_t i = 0; i < dimensions[0]; ++i)
190 copy_to_array(arr[i], array, i);
195 void operator()(std::vector<std::vector<T>>& arr)
198 dimensions[0] = arr.size();
199 for(size_t i = 0; i < arr.size(); ++i)
201 dimensions[1] = std::max(dimensions[1], arr[i].size());
203 dimTotal = calcDimTotal(dimensions);
204 array = (void*)OICCalloc(1, dimTotal * root_size);
206 for(size_t i = 0; i < dimensions[0]; ++i)
208 for(size_t j = 0; j < dimensions[1] && j < arr[i].size(); ++j)
210 copy_to_array(arr[i][j], array, i*dimensions[1] + j);
215 void operator()(std::vector<std::vector<std::vector<T>>>& arr)
218 dimensions[0] = arr.size();
219 for(size_t i = 0; i < arr.size(); ++i)
221 dimensions[1] = std::max(dimensions[1], arr[i].size());
223 for(size_t j = 0; j < arr[i].size(); ++j)
225 dimensions[2] = std::max(dimensions[2], arr[i][j].size());
229 dimTotal = calcDimTotal(dimensions);
230 array = (void*)OICCalloc(1, dimTotal * root_size);
232 for(size_t i = 0; i < dimensions[0]; ++i)
234 for(size_t j = 0; j < dimensions[1] && j < arr[i].size(); ++j)
236 for(size_t k = 0; k < dimensions[2] && k < arr[i][j].size(); ++k)
238 copy_to_array(arr[i][j][k], array,
240 dimensions[2] * dimensions[1] * i +
248 void root_size_calc()
250 root_size = sizeof(T);
254 void copy_to_array(T item, void* array, size_t pos)
256 ((T*)array)[pos] = item;
259 size_t dimensions[MAX_REP_ARRAY_DEPTH];
266 void get_payload_array::root_size_calc<int>()
268 root_size = sizeof(int64_t);
272 void get_payload_array::root_size_calc<std::string>()
274 root_size = sizeof(char*);
278 void get_payload_array::root_size_calc<OC::OCRepresentation>()
280 root_size = sizeof(OCRepPayload*);
284 void get_payload_array::copy_to_array(int item, void* array, size_t pos)
286 ((int64_t*)array)[pos] = item;
290 void get_payload_array::copy_to_array(std::_Bit_reference br, void* array, size_t pos)
292 ((bool*)array)[pos] = static_cast<bool>(br);
296 void get_payload_array::copy_to_array(const std::string& item, void* array, size_t pos)
298 ((char**)array)[pos] = OICStrdup(item.c_str());
302 void get_payload_array::copy_to_array(OC::OCRepresentation item, void* array, size_t pos)
304 ((OCRepPayload**)array)[pos] = item.getPayload();
307 void OCRepresentation::getPayloadArray(OCRepPayload* payload,
308 const OCRepresentation::AttributeItem& item) const
310 get_payload_array vis{};
311 boost::apply_visitor(vis, m_values[item.attrname()]);
314 switch(item.base_type())
316 case AttributeType::Integer:
317 OCRepPayloadSetIntArrayAsOwner(payload, item.attrname().c_str(),
321 case AttributeType::Double:
322 OCRepPayloadSetDoubleArrayAsOwner(payload, item.attrname().c_str(),
326 case AttributeType::Boolean:
327 OCRepPayloadSetBoolArrayAsOwner(payload, item.attrname().c_str(),
331 case AttributeType::String:
332 OCRepPayloadSetStringArrayAsOwner(payload, item.attrname().c_str(),
336 case AttributeType::OCRepresentation:
337 OCRepPayloadSetPropObjectArrayAsOwner(payload, item.attrname().c_str(),
338 (OCRepPayload**)vis.array, vis.dimensions);
341 throw std::logic_error(std::string("GetPayloadArray: Not Implemented") +
342 std::to_string((int)item.base_type()));
346 OCRepPayload* OCRepresentation::getPayload() const
348 OCRepPayload* root = OCRepPayloadCreate();
351 throw std::bad_alloc();
354 OCRepPayloadSetUri(root, getUri().c_str());
356 for(const std::string& type : getResourceTypes())
358 OCRepPayloadAddResourceType(root, type.c_str());
361 for(const std::string& iface : getResourceInterfaces())
363 OCRepPayloadAddInterface(root, iface.c_str());
366 for(auto& val : *this)
370 case AttributeType::Null:
371 OCRepPayloadSetNull(root, val.attrname().c_str());
373 case AttributeType::Integer:
374 OCRepPayloadSetPropInt(root, val.attrname().c_str(), static_cast<int>(val));
376 case AttributeType::Double:
377 OCRepPayloadSetPropDouble(root, val.attrname().c_str(), val);
379 case AttributeType::Boolean:
380 OCRepPayloadSetPropBool(root, val.attrname().c_str(), val);
382 case AttributeType::String:
383 OCRepPayloadSetPropString(root, val.attrname().c_str(),
384 static_cast<std::string>(val).c_str());
386 case AttributeType::OCRepresentation:
387 OCRepPayloadSetPropObjectAsOwner(root, val.attrname().c_str(),
388 static_cast<OCRepresentation>(val).getPayload());
390 case AttributeType::Vector:
391 getPayloadArray(root, val);
394 throw std::logic_error(std::string("Getpayload: Not Implemented") +
395 std::to_string((int)val.type()));
400 OCRepPayload* cur = root;
401 for(auto& child : this->getChildren())
403 cur->next = child.getPayload();
410 size_t calcArrayDepth(const size_t dimensions[MAX_REP_ARRAY_DEPTH])
412 if(dimensions[0] == 0)
414 throw std::logic_error("invalid calcArrayDepth");
416 else if(dimensions[1] == 0)
420 else if (dimensions[2] == 0)
431 T OCRepresentation::payload_array_helper_copy(size_t index, const OCRepPayloadValue* pl)
433 throw std::logic_error("payload_array_helper_copy: unsupported type");
436 int OCRepresentation::payload_array_helper_copy<int>(size_t index, const OCRepPayloadValue* pl)
438 return pl->arr.iArray[index];
441 double OCRepresentation::payload_array_helper_copy<double>(size_t index, const OCRepPayloadValue* pl)
443 return pl->arr.dArray[index];
446 bool OCRepresentation::payload_array_helper_copy<bool>(size_t index, const OCRepPayloadValue* pl)
448 return pl->arr.bArray[index];
451 std::string OCRepresentation::payload_array_helper_copy<std::string>(
452 size_t index, const OCRepPayloadValue* pl)
454 return std::string(pl->arr.strArray[index]);
457 OCRepresentation OCRepresentation::payload_array_helper_copy<OCRepresentation>(
458 size_t index, const OCRepPayloadValue* pl)
461 r.setPayload(pl->arr.objArray[index]);
466 void OCRepresentation::payload_array_helper(const OCRepPayloadValue* pl, size_t depth)
470 std::vector<T> val(pl->arr.dimensions[0]);
472 for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
474 val[i] = payload_array_helper_copy<T>(i, pl);
476 this->setValue(std::string(pl->name), val);
480 std::vector<std::vector<T>> val(pl->arr.dimensions[0]);
481 for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
483 val[i].reserve(pl->arr.dimensions[1]);
484 for(size_t j = 0; j < pl->arr.dimensions[1]; ++j)
486 val[i][j] = payload_array_helper_copy<T>(
487 i * pl->arr.dimensions[1] + j, pl);
490 this->setValue(std::string(pl->name), val);
494 std::vector<std::vector<std::vector<T>>> val;
495 for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
497 val[i].reserve(pl->arr.dimensions[1]);
498 for(size_t j = 0; j < pl->arr.dimensions[1]; ++j)
500 val[i][j].reserve(pl->arr.dimensions[2]);
501 for(size_t k = 0; k < pl->arr.dimensions[2]; ++k)
503 val[i][j][k] = payload_array_helper_copy<T>(
504 pl->arr.dimensions[2] * j +
505 pl->arr.dimensions[2] * pl->arr.dimensions[1] * i +
511 this->setValue(std::string(pl->name), val);
515 throw std::logic_error("Invalid depth in payload_array_helper");
519 void OCRepresentation::setPayloadArray(const OCRepPayloadValue* pl)
525 payload_array_helper<int>(pl, calcArrayDepth(pl->arr.dimensions));
527 case OCREP_PROP_DOUBLE:
528 payload_array_helper<double>(pl, calcArrayDepth(pl->arr.dimensions));
530 case OCREP_PROP_BOOL:
531 payload_array_helper<bool>(pl, calcArrayDepth(pl->arr.dimensions));
533 case OCREP_PROP_STRING:
534 payload_array_helper<std::string>(pl, calcArrayDepth(pl->arr.dimensions));
536 case OCREP_PROP_OBJECT:
537 payload_array_helper<OCRepresentation>(pl, calcArrayDepth(pl->arr.dimensions));
540 throw std::logic_error("setPayload array invalid type");
545 void OCRepresentation::setPayload(const OCRepPayload* pl)
549 OCStringLL* ll = pl->types;
552 addResourceType(ll->value);
559 addResourceInterface(ll->value);
563 OCRepPayloadValue* val = pl->values;
569 case OCREP_PROP_NULL:
573 setValue<int>(val->name, val->i);
575 case OCREP_PROP_DOUBLE:
576 setValue<double>(val->name, val->d);
578 case OCREP_PROP_BOOL:
579 setValue<bool>(val->name, val->b);
581 case OCREP_PROP_STRING:
582 setValue<std::string>(val->name, val->str);
584 case OCREP_PROP_OBJECT:
586 OCRepresentation cur;
587 cur.setPayload(val->obj);
588 setValue<OCRepresentation>(val->name, cur);
591 case OCREP_PROP_ARRAY:
592 setPayloadArray(val);
595 throw std::logic_error(std::string("Not Implemented!") +
596 std::to_string((int)val->type));
603 void OCRepresentation::addChild(const OCRepresentation& rep)
605 m_children.push_back(rep);
608 void OCRepresentation::clearChildren()
613 const std::vector<OCRepresentation>& OCRepresentation::getChildren() const
618 void OCRepresentation::setChildren(const std::vector<OCRepresentation>& children)
620 m_children = children;
622 void OCRepresentation::setUri(const char* uri)
624 m_uri = uri ? uri : "";
627 void OCRepresentation::setUri(const std::string& uri)
632 std::string OCRepresentation::getUri() const
637 const std::vector<std::string>& OCRepresentation::getResourceTypes() const
639 return m_resourceTypes;
642 void OCRepresentation::setResourceTypes(const std::vector<std::string>& resourceTypes)
644 m_resourceTypes = resourceTypes;
647 void OCRepresentation::addResourceType(const std::string& str)
649 m_resourceTypes.push_back(str);
652 const std::vector<std::string>& OCRepresentation::getResourceInterfaces() const
657 void OCRepresentation::addResourceInterface(const std::string& str)
659 m_interfaces.push_back(str);
662 void OCRepresentation::setResourceInterfaces(const std::vector<std::string>& resourceInterfaces)
664 m_interfaces = resourceInterfaces;
667 bool OCRepresentation::hasAttribute(const std::string& str) const
669 return m_values.find(str) != m_values.end();
672 bool OCRepresentation::emptyData() const
674 // This logic is meant to determine whether based on the JSON serialization rules
675 // if this object will result in empty JSON. URI is only serialized if there is valid
676 // data, ResourceType and Interfaces are only serialized if we are a nothing, a
677 // child of a default or link item.
678 // Our values array is only printed in the if we are the child of a Batch resource,
679 // the parent in a 'default' situation, or not in a child/parent relationship.
684 else if ((m_interfaceType == InterfaceType::None
685 || m_interfaceType==InterfaceType::DefaultChild
686 || m_interfaceType==InterfaceType::LinkChild)
687 && (m_resourceTypes.size()>0 || m_interfaces.size()>0))
691 else if((m_interfaceType == InterfaceType::None
692 || m_interfaceType == InterfaceType::BatchChild
693 || m_interfaceType == InterfaceType::DefaultParent)
694 && m_values.size()>0)
699 if(m_children.size() > 0)
707 int OCRepresentation::numberOfAttributes() const
709 return m_values.size();
712 bool OCRepresentation::erase(const std::string& str)
714 return m_values.erase(str);
717 void OCRepresentation::setNULL(const std::string& str)
719 m_values[str] = OC::NullType();
722 bool OCRepresentation::isNULL(const std::string& str) const
724 auto x = m_values.find(str);
726 if(m_values.end() != x)
728 return x->second.which() == AttributeValueNullIndex;
732 throw OCException(OC::Exception::INVALID_ATTRIBUTE+ str);
739 std::ostream& operator <<(std::ostream& os, const AttributeType at)
743 case AttributeType::Null:
746 case AttributeType::Integer:
749 case AttributeType::Double:
752 case AttributeType::Boolean:
755 case AttributeType::String:
758 case AttributeType::OCRepresentation:
759 os << "OCRepresentation";
761 case AttributeType::Vector:
769 // STL Container For OCRepresentation
772 OCRepresentation::AttributeItem::AttributeItem(const std::string& name,
773 std::map<std::string, AttributeValue>& vals):
774 m_attrName(name), m_values(vals){}
776 OCRepresentation::AttributeItem OCRepresentation::operator[](const std::string& key)
778 OCRepresentation::AttributeItem attr{key, m_values};
779 return std::move(attr);
782 const OCRepresentation::AttributeItem OCRepresentation::operator[](const std::string& key) const
784 OCRepresentation::AttributeItem attr{key, m_values};
785 return std::move(attr);
788 const std::string& OCRepresentation::AttributeItem::attrname() const
793 template<typename T, typename = void>
796 // contains the actual type
798 // contains the inner most vector-type
800 // contains the AttributeType for this item
801 constexpr static AttributeType enum_type =
802 AttributeTypeConvert<T>::type;
803 // contains the AttributeType for this base-type
804 constexpr static AttributeType enum_base_type =
805 AttributeTypeConvert<T>::type;
806 // depth of the vector
807 constexpr static size_t depth = 0;
811 struct type_info<T, typename std::enable_if<is_vector<T>::value>::type>
814 typedef typename type_info<typename T::value_type>::base_type base_type;
815 constexpr static AttributeType enum_type = AttributeType::Vector;
816 constexpr static AttributeType enum_base_type =
817 type_info<typename T::value_type>::enum_base_type;
818 constexpr static size_t depth = 1 +
819 type_info<typename T::value_type>::depth;
822 struct type_introspection_visitor : boost::static_visitor<>
825 AttributeType base_type;
828 type_introspection_visitor() : boost::static_visitor<>(),
829 type(AttributeType::Null), base_type(AttributeType::Null), depth(0){}
831 template <typename T>
832 void operator()(T const& item)
834 type = type_info<T>::enum_type;
835 base_type = type_info<T>::enum_base_type;
836 depth = type_info<T>::depth;
840 AttributeType OCRepresentation::AttributeItem::type() const
842 type_introspection_visitor vis;
843 boost::apply_visitor(vis, m_values[m_attrName]);
847 AttributeType OCRepresentation::AttributeItem::base_type() const
849 type_introspection_visitor vis;
850 boost::apply_visitor(vis, m_values[m_attrName]);
851 return vis.base_type;
854 size_t OCRepresentation::AttributeItem::depth() const
856 type_introspection_visitor vis;
857 boost::apply_visitor(vis, m_values[m_attrName]);
861 OCRepresentation::iterator OCRepresentation::begin()
863 return OCRepresentation::iterator(m_values.begin(), m_values);
866 OCRepresentation::const_iterator OCRepresentation::begin() const
868 return OCRepresentation::const_iterator(m_values.begin(), m_values);
871 OCRepresentation::const_iterator OCRepresentation::cbegin() const
873 return OCRepresentation::const_iterator(m_values.cbegin(), m_values);
876 OCRepresentation::iterator OCRepresentation::end()
878 return OCRepresentation::iterator(m_values.end(), m_values);
881 OCRepresentation::const_iterator OCRepresentation::end() const
883 return OCRepresentation::const_iterator(m_values.end(), m_values);
886 OCRepresentation::const_iterator OCRepresentation::cend() const
888 return OCRepresentation::const_iterator(m_values.cend(), m_values);
891 size_t OCRepresentation::size() const
893 return m_values.size();
896 bool OCRepresentation::empty() const
898 return m_values.empty();
901 bool OCRepresentation::iterator::operator==(const OCRepresentation::iterator& rhs) const
903 return m_iterator == rhs.m_iterator;
906 bool OCRepresentation::iterator::operator!=(const OCRepresentation::iterator& rhs) const
908 return m_iterator != rhs.m_iterator;
911 bool OCRepresentation::const_iterator::operator==(
912 const OCRepresentation::const_iterator& rhs) const
914 return m_iterator == rhs.m_iterator;
917 bool OCRepresentation::const_iterator::operator!=(
918 const OCRepresentation::const_iterator& rhs) const
920 return m_iterator != rhs.m_iterator;
923 OCRepresentation::iterator::reference OCRepresentation::iterator::operator*()
928 OCRepresentation::const_iterator::const_reference
929 OCRepresentation::const_iterator::operator*() const
934 OCRepresentation::iterator::pointer OCRepresentation::iterator::operator->()
939 OCRepresentation::const_iterator::const_pointer
940 OCRepresentation::const_iterator::operator->() const
945 OCRepresentation::iterator& OCRepresentation::iterator::operator++()
948 if(m_iterator != m_item.m_values.end())
950 m_item.m_attrName = m_iterator->first;
954 m_item.m_attrName = "";
959 OCRepresentation::const_iterator& OCRepresentation::const_iterator::operator++()
962 if(m_iterator != m_item.m_values.end())
964 m_item.m_attrName = m_iterator->first;
968 m_item.m_attrName = "";
973 OCRepresentation::iterator OCRepresentation::iterator::operator++(int)
975 OCRepresentation::iterator itr(*this);
980 OCRepresentation::const_iterator OCRepresentation::const_iterator::operator++(int)
982 OCRepresentation::const_iterator itr(*this);
987 struct to_string_visitor : boost::static_visitor<>
990 template <typename T>
991 void operator()(T const& item)
993 str = boost::lexical_cast<std::string>(item);
996 template <typename T>
997 void operator()(std::vector<T> const& item)
999 to_string_visitor vis;
1000 std::ostringstream stream;
1003 for(const auto& i : item)
1006 stream << vis.str << " ";
1014 void to_string_visitor::operator()(bool const& item)
1016 str = item ? "true" : "false";
1020 void to_string_visitor::operator()(std::string const& item)
1026 void to_string_visitor::operator()(NullType const& item)
1032 void to_string_visitor::operator()(OCRepresentation const& item)
1034 str = "OC::OCRepresentation";
1037 std::string OCRepresentation::getValueToString(const std::string& key) const
1039 auto x = m_values.find(key);
1040 if(x != m_values.end())
1042 to_string_visitor vis;
1043 boost::apply_visitor(vis, x->second);
1044 return std::move(vis.str);
1050 std::string OCRepresentation::AttributeItem::getValueToString() const
1052 to_string_visitor vis;
1053 boost::apply_visitor(vis, m_values[m_attrName]);
1054 return std::move(vis.str);
1057 std::ostream& operator<<(std::ostream& os, const OCRepresentation::AttributeItem& ai)
1059 os << ai.getValueToString();