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