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