[IOT-921]Return correct resource type in /oic/d
[platform/upstream/iotivity.git] / resource / src / OCRepresentation.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 /**
22  * @file
23  *
24  * This file contains the implementation of classes and its members related
25  * to OCRepresentation.
26  */
27
28
29 #include <OCRepresentation.h>
30
31 #include <boost/lexical_cast.hpp>
32 #include <algorithm>
33 #include "ocpayload.h"
34 #include "ocrandom.h"
35 #include "oic_malloc.h"
36 #include "oic_string.h"
37
38 namespace OC
39 {
40     static const char COAP[] = "coap://";
41     static const char COAPS[] = "coaps://";
42     static const char COAP_TCP[] = "coap+tcp://";
43
44     void MessageContainer::setPayload(const OCPayload* rep)
45     {
46         if (rep == nullptr)
47         {
48             return;
49         }
50
51         switch(rep->type)
52         {
53             case PAYLOAD_TYPE_REPRESENTATION:
54                 setPayload(reinterpret_cast<const OCRepPayload*>(rep));
55                 break;
56             case PAYLOAD_TYPE_DEVICE:
57                 setPayload(reinterpret_cast<const OCDevicePayload*>(rep));
58                 break;
59             case PAYLOAD_TYPE_PLATFORM:
60                 setPayload(reinterpret_cast<const OCPlatformPayload*>(rep));
61                 break;
62             default:
63                 throw OC::OCException("Invalid Payload type in setPayload");
64                 break;
65         }
66     }
67
68     void MessageContainer::setPayload(const OCDevicePayload* payload)
69     {
70         if (payload == nullptr)
71         {
72             return;
73         }
74
75         OCRepresentation rep;
76         rep[OC_RSRVD_DEVICE_ID] = (payload->sid) ?
77             std::string(payload->sid) :
78             std::string();
79         rep[OC_RSRVD_DEVICE_NAME] = payload->deviceName ?
80             std::string(payload->deviceName) :
81             std::string();
82         rep[OC_RSRVD_SPEC_VERSION] = payload->specVersion ?
83             std::string(payload->specVersion) :
84             std::string();
85         rep[OC_RSRVD_DATA_MODEL_VERSION] = payload->dataModelVersion ?
86             std::string(payload->dataModelVersion) :
87             std::string();
88         for (OCStringLL *strll = payload->types; strll; strll = strll->next)
89         {
90            rep.addResourceType(strll->value);
91         }
92         m_reps.push_back(std::move(rep));
93     }
94
95     void MessageContainer::setPayload(const OCPlatformPayload* payload)
96     {
97         if (payload == nullptr)
98         {
99             return;
100         }
101
102         OCRepresentation rep;
103         rep[OC_RSRVD_PLATFORM_ID] = payload->info.platformID ?
104             std::string(payload->info.platformID) :
105             std::string();
106         rep[OC_RSRVD_MFG_NAME] = payload->info.manufacturerName ?
107             std::string(payload->info.manufacturerName) :
108             std::string();
109         rep[OC_RSRVD_MFG_URL] = payload->info.manufacturerUrl ?
110             std::string(payload->info.manufacturerUrl) :
111             std::string();
112         rep[OC_RSRVD_MODEL_NUM] = payload->info.modelNumber ?
113             std::string(payload->info.modelNumber) :
114             std::string();
115         rep[OC_RSRVD_MFG_DATE] = payload->info.dateOfManufacture ?
116             std::string(payload->info.dateOfManufacture) :
117             std::string();
118         rep[OC_RSRVD_PLATFORM_VERSION] = payload->info.platformVersion ?
119             std::string(payload->info.platformVersion) :
120             std::string();
121         rep[OC_RSRVD_OS_VERSION] = payload->info.operatingSystemVersion ?
122             std::string(payload->info.operatingSystemVersion) :
123             std::string();
124         rep[OC_RSRVD_HARDWARE_VERSION] = payload->info.hardwareVersion ?
125             std::string(payload->info.hardwareVersion) :
126             std::string();
127         rep[OC_RSRVD_FIRMWARE_VERSION] = payload->info.firmwareVersion ?
128             std::string(payload->info.firmwareVersion) :
129             std::string();
130         rep[OC_RSRVD_SUPPORT_URL] = payload->info.supportUrl ?
131             std::string(payload->info.supportUrl) :
132             std::string();
133         rep[OC_RSRVD_SYSTEM_TIME] = payload->info.systemTime ?
134             std::string(payload->info.systemTime) :
135             std::string();
136
137         m_reps.push_back(std::move(rep));
138     }
139
140     void MessageContainer::setPayload(const OCRepPayload* payload)
141     {
142         const OCRepPayload* pl = payload;
143         while(pl)
144         {
145             OCRepresentation cur;
146             cur.setPayload(pl);
147
148             pl = pl->next;
149             this->addRepresentation(cur);
150         }
151     }
152
153     OCRepPayload* MessageContainer::getPayload() const
154     {
155         OCRepPayload* root = nullptr;
156         for(const auto& r : representations())
157         {
158             if (!root)
159             {
160                 root = r.getPayload();
161             }
162             else
163             {
164                 OCRepPayloadAppend(root, r.getPayload());
165             }
166         }
167
168         return root;
169     }
170
171     const std::vector<OCRepresentation>& MessageContainer::representations() const
172     {
173         return m_reps;
174     }
175
176     void MessageContainer::addRepresentation(const OCRepresentation& rep)
177     {
178         m_reps.push_back(rep);
179     }
180 }
181
182 namespace OC
183 {
184     struct get_payload_array: boost::static_visitor<>
185     {
186         template<typename T>
187         void operator()(T& /*arr*/)
188         {
189             throw std::logic_error("Invalid calc_dimensions_visitor type");
190         }
191
192         template<typename T>
193         void operator()(std::vector<T>& arr)
194         {
195             root_size_calc<T>();
196             dimensions[0] = arr.size();
197             dimensions[1] = 0;
198             dimensions[2] = 0;
199             dimTotal = calcDimTotal(dimensions);
200
201             array = (void*)OICMalloc(dimTotal * root_size);
202
203             for(size_t i = 0; i < dimensions[0]; ++i)
204             {
205                 copy_to_array(arr[i], array, i);
206             }
207
208         }
209         template<typename T>
210         void operator()(std::vector<std::vector<T>>& arr)
211         {
212             root_size_calc<T>();
213             dimensions[0] = arr.size();
214             dimensions[1] = 0;
215             dimensions[2] = 0;
216             for(size_t i = 0; i < arr.size(); ++i)
217             {
218                 dimensions[1] = std::max(dimensions[1], arr[i].size());
219             }
220             dimTotal = calcDimTotal(dimensions);
221             array = (void*)OICCalloc(1, dimTotal * root_size);
222
223             for(size_t i = 0; i < dimensions[0]; ++i)
224             {
225                 for(size_t j = 0; j < dimensions[1] && j < arr[i].size(); ++j)
226                 {
227                     copy_to_array(arr[i][j], array, i*dimensions[1] + j);
228                 }
229             }
230         }
231         template<typename T>
232         void operator()(std::vector<std::vector<std::vector<T>>>& arr)
233         {
234             root_size_calc<T>();
235             dimensions[0] = arr.size();
236             dimensions[1] = 0;
237             dimensions[2] = 0;
238             for(size_t i = 0; i < arr.size(); ++i)
239             {
240                 dimensions[1] = std::max(dimensions[1], arr[i].size());
241
242                 for(size_t j = 0; j < arr[i].size(); ++j)
243                 {
244                     dimensions[2] = std::max(dimensions[2], arr[i][j].size());
245                 }
246             }
247
248             dimTotal = calcDimTotal(dimensions);
249             array = (void*)OICCalloc(1, dimTotal * root_size);
250
251             for(size_t i = 0; i < dimensions[0]; ++i)
252             {
253                 for(size_t j = 0; j < dimensions[1] && j < arr[i].size(); ++j)
254                 {
255                     for(size_t k = 0; k < dimensions[2] && k < arr[i][j].size(); ++k)
256                     {
257                         copy_to_array(arr[i][j][k], array,
258                                 dimensions[2] * j +
259                                 dimensions[2] * dimensions[1] * i +
260                                 k);
261                     }
262                 }
263             }
264         }
265
266         template<typename T>
267         void root_size_calc()
268         {
269             root_size = sizeof(T);
270         }
271
272         template<typename T>
273         void copy_to_array(T item, void* array, size_t pos)
274         {
275             ((T*)array)[pos] = item;
276         }
277
278         size_t dimensions[MAX_REP_ARRAY_DEPTH];
279         size_t root_size;
280         size_t dimTotal;
281         void* array;
282     };
283
284     template<>
285     void get_payload_array::root_size_calc<int>()
286     {
287         root_size = sizeof(int64_t);
288     }
289
290     template<>
291     void get_payload_array::root_size_calc<std::string>()
292     {
293         root_size = sizeof(char*);
294     }
295
296     template<>
297     void get_payload_array::root_size_calc<OC::OCRepresentation>()
298     {
299         root_size = sizeof(OCRepPayload*);
300     }
301
302     template<>
303     void get_payload_array::copy_to_array(int item, void* array, size_t pos)
304     {
305         ((int64_t*)array)[pos] = item;
306     }
307
308     template<>
309     void get_payload_array::copy_to_array(std::_Bit_reference br, void* array, size_t pos)
310     {
311         ((bool*)array)[pos] = static_cast<bool>(br);
312     }
313
314     template<>
315     void get_payload_array::copy_to_array(std::string item, void* array, size_t pos)
316     {
317         ((char**)array)[pos] = OICStrdup(item.c_str());
318     }
319
320     template<>
321     void get_payload_array::copy_to_array(std::string& item, void* array, size_t pos)
322     {
323         ((char**)array)[pos] = OICStrdup(item.c_str());
324     }
325
326     template<>
327     void get_payload_array::copy_to_array(const std::string& item, void* array, size_t pos)
328     {
329         ((char**)array)[pos] = OICStrdup(item.c_str());
330     }
331
332     template<>
333     void get_payload_array::copy_to_array(OC::OCRepresentation item, void* array, size_t pos)
334     {
335         ((OCRepPayload**)array)[pos] = item.getPayload();
336     }
337
338     void OCRepresentation::getPayloadArray(OCRepPayload* payload,
339                     const OCRepresentation::AttributeItem& item) const
340     {
341         get_payload_array vis{};
342         boost::apply_visitor(vis, m_values[item.attrname()]);
343
344
345         switch(item.base_type())
346         {
347             case AttributeType::Integer:
348                 OCRepPayloadSetIntArrayAsOwner(payload, item.attrname().c_str(),
349                         (int64_t*)vis.array,
350                         vis.dimensions);
351                 break;
352             case AttributeType::Double:
353                 OCRepPayloadSetDoubleArrayAsOwner(payload, item.attrname().c_str(),
354                         (double*)vis.array,
355                         vis.dimensions);
356                 break;
357             case AttributeType::Boolean:
358                 OCRepPayloadSetBoolArrayAsOwner(payload, item.attrname().c_str(),
359                         (bool*)vis.array,
360                         vis.dimensions);
361                 break;
362             case AttributeType::String:
363                 OCRepPayloadSetStringArrayAsOwner(payload, item.attrname().c_str(),
364                         (char**)vis.array,
365                         vis.dimensions);
366                 break;
367             case AttributeType::OCRepresentation:
368                 OCRepPayloadSetPropObjectArrayAsOwner(payload, item.attrname().c_str(),
369                         (OCRepPayload**)vis.array, vis.dimensions);
370                 break;
371             default:
372                 throw std::logic_error(std::string("GetPayloadArray: Not Implemented") +
373                         std::to_string((int)item.base_type()));
374         }
375     }
376
377     OCRepPayload* OCRepresentation::getPayload() const
378     {
379         OCRepPayload* root = OCRepPayloadCreate();
380         if (!root)
381         {
382             throw std::bad_alloc();
383         }
384
385         OCRepPayloadSetUri(root, getUri().c_str());
386
387         for(const std::string& type : getResourceTypes())
388         {
389             OCRepPayloadAddResourceType(root, type.c_str());
390         }
391
392         for(const std::string& iface : getResourceInterfaces())
393         {
394             OCRepPayloadAddInterface(root, iface.c_str());
395         }
396
397         for(auto& val : *this)
398         {
399             switch(val.type())
400             {
401                 case AttributeType::Null:
402                     OCRepPayloadSetNull(root, val.attrname().c_str());
403                     break;
404                 case AttributeType::Integer:
405                     OCRepPayloadSetPropInt(root, val.attrname().c_str(), static_cast<int>(val));
406                     break;
407                 case AttributeType::Double:
408                     OCRepPayloadSetPropDouble(root, val.attrname().c_str(),
409                             val.getValue<double>());
410                     break;
411                 case AttributeType::Boolean:
412                     OCRepPayloadSetPropBool(root, val.attrname().c_str(), val.getValue<bool>());
413                     break;
414                 case AttributeType::String:
415                     OCRepPayloadSetPropString(root, val.attrname().c_str(),
416                             static_cast<std::string>(val).c_str());
417                     break;
418                 case AttributeType::OCRepresentation:
419                     OCRepPayloadSetPropObjectAsOwner(root, val.attrname().c_str(),
420                             static_cast<OCRepresentation>(val).getPayload());
421                     break;
422                 case AttributeType::Vector:
423                     getPayloadArray(root, val);
424                     break;
425                 default:
426                     throw std::logic_error(std::string("Getpayload: Not Implemented") +
427                             std::to_string((int)val.type()));
428                     break;
429             }
430         }
431
432         return root;
433     }
434
435     size_t calcArrayDepth(const size_t dimensions[MAX_REP_ARRAY_DEPTH])
436     {
437         if (dimensions[0] == 0)
438         {
439             throw std::logic_error("invalid calcArrayDepth");
440         }
441         else if (dimensions[1] == 0)
442         {
443             return 1;
444         }
445         else if (dimensions[2] == 0)
446         {
447             return 2;
448         }
449         else
450         {
451             return 3;
452         }
453     }
454
455     template<typename T>
456     T OCRepresentation::payload_array_helper_copy(size_t index, const OCRepPayloadValue* pl)
457     {
458         throw std::logic_error("payload_array_helper_copy: unsupported type");
459     }
460     template<>
461     int OCRepresentation::payload_array_helper_copy<int>(size_t index, const OCRepPayloadValue* pl)
462     {
463         return pl->arr.iArray[index];
464     }
465     template<>
466     double OCRepresentation::payload_array_helper_copy<double>(size_t index, const OCRepPayloadValue* pl)
467     {
468         return pl->arr.dArray[index];
469     }
470     template<>
471     bool OCRepresentation::payload_array_helper_copy<bool>(size_t index, const OCRepPayloadValue* pl)
472     {
473         return pl->arr.bArray[index];
474     }
475     template<>
476     std::string OCRepresentation::payload_array_helper_copy<std::string>(
477             size_t index, const OCRepPayloadValue* pl)
478     {
479         if (pl->arr.strArray[index])
480         {
481             return std::string(pl->arr.strArray[index]);
482         }
483         else
484         {
485             return std::string{};
486         }
487     }
488     template<>
489     OCRepresentation OCRepresentation::payload_array_helper_copy<OCRepresentation>(
490             size_t index, const OCRepPayloadValue* pl)
491     {
492         OCRepresentation r;
493         if (pl->arr.objArray[index])
494         {
495             r.setPayload(pl->arr.objArray[index]);
496         }
497         return r;
498     }
499
500     template<typename T>
501     void OCRepresentation::payload_array_helper(const OCRepPayloadValue* pl, size_t depth)
502     {
503         if (depth == 1)
504         {
505             std::vector<T> val(pl->arr.dimensions[0]);
506
507             for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
508             {
509                 val[i] = payload_array_helper_copy<T>(i, pl);
510             }
511             this->setValue(std::string(pl->name), val);
512         }
513         else if (depth == 2)
514         {
515             std::vector<std::vector<T>> val(pl->arr.dimensions[0]);
516             for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
517             {
518                 val[i].resize(pl->arr.dimensions[1]);
519                 for(size_t j = 0; j < pl->arr.dimensions[1]; ++j)
520                 {
521                     val[i][j] = payload_array_helper_copy<T>(
522                             i * pl->arr.dimensions[1] + j, pl);
523                 }
524             }
525             this->setValue(std::string(pl->name), val);
526         }
527         else if (depth == 3)
528         {
529             std::vector<std::vector<std::vector<T>>> val(pl->arr.dimensions[0]);
530             for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
531             {
532                 val[i].resize(pl->arr.dimensions[1]);
533                 for(size_t j = 0; j < pl->arr.dimensions[1]; ++j)
534                 {
535                     val[i][j].resize(pl->arr.dimensions[2]);
536                     for(size_t k = 0; k < pl->arr.dimensions[2]; ++k)
537                     {
538                         val[i][j][k] = payload_array_helper_copy<T>(
539                                 pl->arr.dimensions[2] * j +
540                                 pl->arr.dimensions[2] * pl->arr.dimensions[1] * i +
541                                 k,
542                                 pl);
543                     }
544                 }
545             }
546             this->setValue(std::string(pl->name), val);
547         }
548         else
549         {
550             throw std::logic_error("Invalid depth in payload_array_helper");
551         }
552     }
553
554     void OCRepresentation::setPayloadArray(const OCRepPayloadValue* pl)
555     {
556
557         switch(pl->arr.type)
558         {
559             case OCREP_PROP_INT:
560                 payload_array_helper<int>(pl, calcArrayDepth(pl->arr.dimensions));
561                 break;
562             case OCREP_PROP_DOUBLE:
563                 payload_array_helper<double>(pl, calcArrayDepth(pl->arr.dimensions));
564                 break;
565             case OCREP_PROP_BOOL:
566                 payload_array_helper<bool>(pl, calcArrayDepth(pl->arr.dimensions));
567                 break;
568             case OCREP_PROP_STRING:
569                 payload_array_helper<std::string>(pl, calcArrayDepth(pl->arr.dimensions));
570                 break;
571             case OCREP_PROP_OBJECT:
572                 payload_array_helper<OCRepresentation>(pl, calcArrayDepth(pl->arr.dimensions));
573                 break;
574             default:
575                 throw std::logic_error("setPayload array invalid type");
576                 break;
577         }
578     }
579
580     void OCRepresentation::setPayload(const OCRepPayload* pl)
581     {
582         setUri(pl->uri);
583
584         OCStringLL* ll = pl->types;
585         while(ll)
586         {
587             addResourceType(ll->value);
588             ll = ll->next;
589         }
590
591         ll = pl->interfaces;
592         while(ll)
593         {
594             addResourceInterface(ll->value);
595             ll = ll->next;
596         }
597
598         OCRepPayloadValue* val = pl->values;
599
600         while(val)
601         {
602             switch(val->type)
603             {
604                 case OCREP_PROP_NULL:
605                     setNULL(val->name);
606                     break;
607                 case OCREP_PROP_INT:
608                     setValue<int>(val->name, val->i);
609                     break;
610                 case OCREP_PROP_DOUBLE:
611                     setValue<double>(val->name, val->d);
612                     break;
613                 case OCREP_PROP_BOOL:
614                     setValue<bool>(val->name, val->b);
615                     break;
616                 case OCREP_PROP_STRING:
617                     setValue<std::string>(val->name, val->str);
618                     break;
619                 case OCREP_PROP_OBJECT:
620                     {
621                         OCRepresentation cur;
622                         cur.setPayload(val->obj);
623                         setValue<OCRepresentation>(val->name, cur);
624                     }
625                     break;
626                 case OCREP_PROP_ARRAY:
627                     setPayloadArray(val);
628                     break;
629                 default:
630                     throw std::logic_error(std::string("Not Implemented!") +
631                             std::to_string((int)val->type));
632                     break;
633             }
634             val = val->next;
635         }
636     }
637
638     void OCRepresentation::addChild(const OCRepresentation& rep)
639     {
640         m_children.push_back(rep);
641     }
642
643     void OCRepresentation::clearChildren()
644     {
645         m_children.clear();
646     }
647
648     const std::vector<OCRepresentation>& OCRepresentation::getChildren() const
649     {
650         return m_children;
651     }
652
653     void OCRepresentation::setChildren(const std::vector<OCRepresentation>& children)
654     {
655         m_children = children;
656     }
657
658     void OCRepresentation::setDevAddr(const OCDevAddr m_devAddr)
659     {
660         std::ostringstream ss;
661         if (m_devAddr.flags & OC_SECURE)
662         {
663             ss << COAPS;
664         }
665         else if (m_devAddr.adapter & OC_ADAPTER_TCP)
666         {
667             ss << COAP_TCP;
668         }
669         else
670         {
671             ss << COAP;
672         }
673         if (m_devAddr.flags & OC_IP_USE_V6)
674         {
675             ss << '[' << m_devAddr.addr << ']';
676         }
677         else
678         {
679             ss << m_devAddr.addr;
680         }
681         if (m_devAddr.port)
682         {
683             ss << ':' << m_devAddr.port;
684         }
685         m_host = ss.str();
686     }
687
688     const std::string OCRepresentation::getHost() const
689     {
690         return m_host;
691     }
692
693     void OCRepresentation::setUri(const char* uri)
694     {
695         m_uri = uri ? uri : "";
696     }
697
698     void OCRepresentation::setUri(const std::string& uri)
699     {
700         m_uri = uri;
701     }
702
703     std::string OCRepresentation::getUri() const
704     {
705         return m_uri;
706     }
707
708     const std::vector<std::string>& OCRepresentation::getResourceTypes() const
709     {
710         return m_resourceTypes;
711     }
712
713     void OCRepresentation::setResourceTypes(const std::vector<std::string>& resourceTypes)
714     {
715         m_resourceTypes = resourceTypes;
716     }
717
718     void OCRepresentation::addResourceType(const std::string& str)
719     {
720         m_resourceTypes.push_back(str);
721     }
722
723     const std::vector<std::string>& OCRepresentation::getResourceInterfaces() const
724     {
725         return m_interfaces;
726     }
727
728     void OCRepresentation::addResourceInterface(const std::string& str)
729     {
730         m_interfaces.push_back(str);
731     }
732
733     void OCRepresentation::setResourceInterfaces(const std::vector<std::string>& resourceInterfaces)
734     {
735         m_interfaces = resourceInterfaces;
736     }
737
738     bool OCRepresentation::hasAttribute(const std::string& str) const
739     {
740         return m_values.find(str) != m_values.end();
741     }
742
743     bool OCRepresentation::emptyData() const
744     {
745         // This logic is meant to determine whether based on the JSON serialization rules
746         // if this object will result in empty JSON.  URI is only serialized if there is valid
747         // data, ResourceType and Interfaces are only serialized if we are a nothing, a
748         // child of a default or link item.
749         // Our values array is only printed in the if we are the child of a Batch resource,
750         // the parent in a 'default' situation, or not in a child/parent relationship.
751         if (!m_uri.empty())
752         {
753             return false;
754         }
755         else if ((m_interfaceType == InterfaceType::None
756                         || m_interfaceType==InterfaceType::DefaultChild
757                         || m_interfaceType==InterfaceType::LinkChild)
758                     && (m_resourceTypes.size()>0 || m_interfaces.size()>0))
759         {
760             return false;
761         }
762         else if ((m_interfaceType == InterfaceType::None
763                         || m_interfaceType == InterfaceType::BatchChild
764                         || m_interfaceType == InterfaceType::DefaultParent)
765                     && m_values.size()>0)
766         {
767             return false;
768         }
769
770         if (m_children.size() > 0)
771         {
772             return false;
773         }
774
775         return true;
776     }
777
778     int OCRepresentation::numberOfAttributes() const
779     {
780         return m_values.size();
781     }
782
783     bool OCRepresentation::erase(const std::string& str)
784     {
785         return m_values.erase(str);
786     }
787
788     void OCRepresentation::setNULL(const std::string& str)
789     {
790         m_values[str] = OC::NullType();
791     }
792
793     bool OCRepresentation::isNULL(const std::string& str) const
794     {
795         auto x = m_values.find(str);
796
797         if (m_values.end() != x)
798         {
799             return x->second.which() == AttributeValueNullIndex;
800         }
801         else
802         {
803             throw OCException(OC::Exception::INVALID_ATTRIBUTE+ str);
804         }
805     }
806 }
807
808 namespace OC
809 {
810     std::ostream& operator <<(std::ostream& os, const AttributeType at)
811     {
812         switch(at)
813         {
814             case AttributeType::Null:
815                 os << "Null";
816                 break;
817             case AttributeType::Integer:
818                 os << "Integer";
819                 break;
820             case AttributeType::Double:
821                 os << "Double";
822                 break;
823             case AttributeType::Boolean:
824                 os << "Boolean";
825                 break;
826             case AttributeType::String:
827                 os << "String";
828                 break;
829             case AttributeType::OCRepresentation:
830                 os << "OCRepresentation";
831                 break;
832             case AttributeType::Vector:
833                 os << "Vector";
834                 break;
835         }
836         return os;
837     }
838 }
839
840 // STL Container For OCRepresentation
841 namespace OC
842 {
843     OCRepresentation::AttributeItem::AttributeItem(const std::string& name,
844             std::map<std::string, AttributeValue>& vals):
845             m_attrName(name), m_values(vals){}
846
847     OCRepresentation::AttributeItem OCRepresentation::operator[](const std::string& key)
848     {
849         OCRepresentation::AttributeItem attr{key, m_values};
850         return std::move(attr);
851     }
852
853     const OCRepresentation::AttributeItem OCRepresentation::operator[](const std::string& key) const
854     {
855         OCRepresentation::AttributeItem attr{key, m_values};
856         return std::move(attr);
857     }
858
859     const std::string& OCRepresentation::AttributeItem::attrname() const
860     {
861         return m_attrName;
862     }
863
864     template<typename T, typename = void>
865     struct type_info
866     {
867         // contains the actual type
868         typedef T type;
869         // contains the inner most vector-type
870         typedef T base_type;
871         // contains the AttributeType for this item
872         constexpr static AttributeType enum_type =
873             AttributeTypeConvert<T>::type;
874         // contains the AttributeType for this base-type
875         constexpr static AttributeType enum_base_type =
876             AttributeTypeConvert<T>::type;
877         // depth of the vector
878         constexpr static size_t depth = 0;
879     };
880
881     template<typename T>
882     struct type_info<T, typename std::enable_if<is_vector<T>::value>::type>
883     {
884         typedef T type;
885         typedef typename type_info<typename T::value_type>::base_type base_type;
886         constexpr static AttributeType enum_type = AttributeType::Vector;
887         constexpr static AttributeType enum_base_type =
888             type_info<typename T::value_type>::enum_base_type;
889         constexpr static size_t depth = 1 +
890             type_info<typename T::value_type>::depth;
891     };
892
893     struct type_introspection_visitor : boost::static_visitor<>
894     {
895         AttributeType type;
896         AttributeType base_type;
897         size_t depth;
898
899         type_introspection_visitor() : boost::static_visitor<>(),
900             type(AttributeType::Null), base_type(AttributeType::Null), depth(0){}
901
902         template <typename T>
903         void operator()(T const& /*item*/)
904         {
905             type = type_info<T>::enum_type;
906             base_type = type_info<T>::enum_base_type;
907             depth = type_info<T>::depth;
908         }
909     };
910
911     AttributeType OCRepresentation::AttributeItem::type() const
912     {
913         type_introspection_visitor vis;
914         boost::apply_visitor(vis, m_values[m_attrName]);
915         return vis.type;
916     }
917
918     AttributeType OCRepresentation::AttributeItem::base_type() const
919     {
920         type_introspection_visitor vis;
921         boost::apply_visitor(vis, m_values[m_attrName]);
922         return vis.base_type;
923     }
924
925     size_t OCRepresentation::AttributeItem::depth() const
926     {
927         type_introspection_visitor vis;
928         boost::apply_visitor(vis, m_values[m_attrName]);
929         return vis.depth;
930     }
931
932     OCRepresentation::iterator OCRepresentation::begin()
933     {
934         return OCRepresentation::iterator(m_values.begin(), m_values);
935     }
936
937     OCRepresentation::const_iterator OCRepresentation::begin() const
938     {
939          return OCRepresentation::const_iterator(m_values.begin(), m_values);
940     }
941
942     OCRepresentation::const_iterator OCRepresentation::cbegin() const
943     {
944         return OCRepresentation::const_iterator(m_values.cbegin(), m_values);
945     }
946
947     OCRepresentation::iterator OCRepresentation::end()
948     {
949         return OCRepresentation::iterator(m_values.end(), m_values);
950     }
951
952     OCRepresentation::const_iterator OCRepresentation::end() const
953     {
954         return OCRepresentation::const_iterator(m_values.end(), m_values);
955     }
956
957     OCRepresentation::const_iterator OCRepresentation::cend() const
958     {
959         return OCRepresentation::const_iterator(m_values.cend(), m_values);
960     }
961
962     size_t OCRepresentation::size() const
963     {
964         return m_values.size();
965     }
966
967     bool OCRepresentation::empty() const
968     {
969         return m_values.empty();
970     }
971
972     bool OCRepresentation::iterator::operator==(const OCRepresentation::iterator& rhs) const
973     {
974         return m_iterator == rhs.m_iterator;
975     }
976
977     bool OCRepresentation::iterator::operator!=(const OCRepresentation::iterator& rhs) const
978     {
979         return m_iterator != rhs.m_iterator;
980     }
981
982     bool OCRepresentation::const_iterator::operator==(
983             const OCRepresentation::const_iterator& rhs) const
984     {
985         return m_iterator == rhs.m_iterator;
986     }
987
988     bool OCRepresentation::const_iterator::operator!=(
989             const OCRepresentation::const_iterator& rhs) const
990     {
991         return m_iterator != rhs.m_iterator;
992     }
993
994     OCRepresentation::iterator::reference OCRepresentation::iterator::operator*()
995     {
996         return m_item;
997     }
998
999     OCRepresentation::const_iterator::const_reference
1000         OCRepresentation::const_iterator::operator*() const
1001     {
1002         return m_item;
1003     }
1004
1005     OCRepresentation::iterator::pointer OCRepresentation::iterator::operator->()
1006     {
1007         return &m_item;
1008     }
1009
1010     OCRepresentation::const_iterator::const_pointer
1011         OCRepresentation::const_iterator::operator->() const
1012     {
1013         return &m_item;
1014     }
1015
1016     OCRepresentation::iterator& OCRepresentation::iterator::operator++()
1017     {
1018         m_iterator++;
1019         if (m_iterator != m_item.m_values.end())
1020         {
1021             m_item.m_attrName = m_iterator->first;
1022         }
1023         else
1024         {
1025             m_item.m_attrName = "";
1026         }
1027         return *this;
1028     }
1029
1030     OCRepresentation::const_iterator& OCRepresentation::const_iterator::operator++()
1031     {
1032         m_iterator++;
1033         if (m_iterator != m_item.m_values.end())
1034         {
1035             m_item.m_attrName = m_iterator->first;
1036         }
1037         else
1038         {
1039             m_item.m_attrName = "";
1040         }
1041         return *this;
1042     }
1043
1044     OCRepresentation::iterator OCRepresentation::iterator::operator++(int)
1045     {
1046         OCRepresentation::iterator itr(*this);
1047         ++(*this);
1048         return itr;
1049     }
1050
1051     OCRepresentation::const_iterator OCRepresentation::const_iterator::operator++(int)
1052     {
1053         OCRepresentation::const_iterator itr(*this);
1054         ++(*this);
1055         return itr;
1056     }
1057
1058     struct to_string_visitor : boost::static_visitor<>
1059     {
1060         std::string str;
1061         template <typename T>
1062         void operator()(T const& item)
1063         {
1064             str = boost::lexical_cast<std::string>(item);
1065         }
1066
1067         template <typename T>
1068         void operator()(std::vector<T> const& item)
1069         {
1070             to_string_visitor vis;
1071             std::ostringstream stream;
1072             stream << "[";
1073
1074             for(const auto& i : item)
1075             {
1076                 vis(i);
1077                 stream << vis.str  << " ";
1078             }
1079             stream << "]";
1080             str = stream.str();
1081         }
1082     };
1083
1084     template<>
1085     void to_string_visitor::operator()(bool const& item)
1086     {
1087         str = item ? "true" : "false";
1088     }
1089
1090     template<>
1091     void to_string_visitor::operator()(std::string const& item)
1092     {
1093         str = item;
1094     }
1095
1096     template<>
1097     void to_string_visitor::operator()(NullType const& /*item*/)
1098     {
1099         str = "(null)";
1100     }
1101
1102     template<>
1103     void to_string_visitor::operator()(OCRepresentation const& /*item*/)
1104     {
1105         str = "OC::OCRepresentation";
1106     }
1107
1108     std::string OCRepresentation::getValueToString(const std::string& key) const
1109     {
1110         auto x = m_values.find(key);
1111         if (x != m_values.end())
1112         {
1113             to_string_visitor vis;
1114             boost::apply_visitor(vis, x->second);
1115             return std::move(vis.str);
1116         }
1117
1118         return "";
1119     }
1120
1121     std::string OCRepresentation::AttributeItem::getValueToString() const
1122     {
1123         to_string_visitor vis;
1124         boost::apply_visitor(vis, m_values[m_attrName]);
1125         return std::move(vis.str);
1126     }
1127
1128     std::ostream& operator<<(std::ostream& os, const OCRepresentation::AttributeItem& ai)
1129     {
1130         os << ai.getValueToString();
1131         return os;
1132     }
1133 }