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