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