Merge branch 'master' into windows-port
[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                 case AttributeType::Binary:
437                     OCRepPayloadSetPropByteString(root, val.attrname().c_str(),
438                             OCByteString{const_cast<uint8_t*>(val.getValue<std::vector<uint8_t>>().data()),
439                             val.getValue<std::vector<uint8_t>>().size()});
440                     break;
441                 default:
442                     throw std::logic_error(std::string("Getpayload: Not Implemented") +
443                             std::to_string((int)val.type()));
444                     break;
445             }
446         }
447
448         return root;
449     }
450
451     size_t calcArrayDepth(const size_t dimensions[MAX_REP_ARRAY_DEPTH])
452     {
453         if (dimensions[0] == 0)
454         {
455             throw std::logic_error("invalid calcArrayDepth");
456         }
457         else if (dimensions[1] == 0)
458         {
459             return 1;
460         }
461         else if (dimensions[2] == 0)
462         {
463             return 2;
464         }
465         else
466         {
467             return 3;
468         }
469     }
470
471     template<typename T>
472     T OCRepresentation::payload_array_helper_copy(size_t index, const OCRepPayloadValue* pl)
473     {
474         throw std::logic_error("payload_array_helper_copy: unsupported type");
475     }
476     template<>
477     int OCRepresentation::payload_array_helper_copy<int>(size_t index, const OCRepPayloadValue* pl)
478     {
479         return pl->arr.iArray[index];
480     }
481     template<>
482     double OCRepresentation::payload_array_helper_copy<double>(size_t index, const OCRepPayloadValue* pl)
483     {
484         return pl->arr.dArray[index];
485     }
486     template<>
487     bool OCRepresentation::payload_array_helper_copy<bool>(size_t index, const OCRepPayloadValue* pl)
488     {
489         return pl->arr.bArray[index];
490     }
491     template<>
492     std::string OCRepresentation::payload_array_helper_copy<std::string>(
493             size_t index, const OCRepPayloadValue* pl)
494     {
495         if (pl->arr.strArray[index])
496         {
497             return std::string(pl->arr.strArray[index]);
498         }
499         else
500         {
501             return std::string{};
502         }
503     }
504     template<>
505     OCRepresentation OCRepresentation::payload_array_helper_copy<OCRepresentation>(
506             size_t index, const OCRepPayloadValue* pl)
507     {
508         OCRepresentation r;
509         if (pl->arr.objArray[index])
510         {
511             r.setPayload(pl->arr.objArray[index]);
512         }
513         return r;
514     }
515
516     template<typename T>
517     void OCRepresentation::payload_array_helper(const OCRepPayloadValue* pl, size_t depth)
518     {
519         if (depth == 1)
520         {
521             std::vector<T> val(pl->arr.dimensions[0]);
522
523             for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
524             {
525                 val[i] = payload_array_helper_copy<T>(i, pl);
526             }
527             this->setValue(std::string(pl->name), val);
528         }
529         else if (depth == 2)
530         {
531             std::vector<std::vector<T>> val(pl->arr.dimensions[0]);
532             for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
533             {
534                 val[i].resize(pl->arr.dimensions[1]);
535                 for(size_t j = 0; j < pl->arr.dimensions[1]; ++j)
536                 {
537                     val[i][j] = payload_array_helper_copy<T>(
538                             i * pl->arr.dimensions[1] + j, pl);
539                 }
540             }
541             this->setValue(std::string(pl->name), val);
542         }
543         else if (depth == 3)
544         {
545             std::vector<std::vector<std::vector<T>>> val(pl->arr.dimensions[0]);
546             for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
547             {
548                 val[i].resize(pl->arr.dimensions[1]);
549                 for(size_t j = 0; j < pl->arr.dimensions[1]; ++j)
550                 {
551                     val[i][j].resize(pl->arr.dimensions[2]);
552                     for(size_t k = 0; k < pl->arr.dimensions[2]; ++k)
553                     {
554                         val[i][j][k] = payload_array_helper_copy<T>(
555                                 pl->arr.dimensions[2] * j +
556                                 pl->arr.dimensions[2] * pl->arr.dimensions[1] * i +
557                                 k,
558                                 pl);
559                     }
560                 }
561             }
562             this->setValue(std::string(pl->name), val);
563         }
564         else
565         {
566             throw std::logic_error("Invalid depth in payload_array_helper");
567         }
568     }
569
570     void OCRepresentation::setPayloadArray(const OCRepPayloadValue* pl)
571     {
572
573         switch(pl->arr.type)
574         {
575             case OCREP_PROP_INT:
576                 payload_array_helper<int>(pl, calcArrayDepth(pl->arr.dimensions));
577                 break;
578             case OCREP_PROP_DOUBLE:
579                 payload_array_helper<double>(pl, calcArrayDepth(pl->arr.dimensions));
580                 break;
581             case OCREP_PROP_BOOL:
582                 payload_array_helper<bool>(pl, calcArrayDepth(pl->arr.dimensions));
583                 break;
584             case OCREP_PROP_STRING:
585                 payload_array_helper<std::string>(pl, calcArrayDepth(pl->arr.dimensions));
586                 break;
587             case OCREP_PROP_OBJECT:
588                 payload_array_helper<OCRepresentation>(pl, calcArrayDepth(pl->arr.dimensions));
589                 break;
590             default:
591                 throw std::logic_error("setPayload array invalid type");
592                 break;
593         }
594     }
595
596     void OCRepresentation::setPayload(const OCRepPayload* pl)
597     {
598         setUri(pl->uri);
599
600         OCStringLL* ll = pl->types;
601         while(ll)
602         {
603             addResourceType(ll->value);
604             ll = ll->next;
605         }
606
607         ll = pl->interfaces;
608         while(ll)
609         {
610             addResourceInterface(ll->value);
611             ll = ll->next;
612         }
613
614         OCRepPayloadValue* val = pl->values;
615
616         while(val)
617         {
618             switch(val->type)
619             {
620                 case OCREP_PROP_NULL:
621                     setNULL(val->name);
622                     break;
623                 case OCREP_PROP_INT:
624                     setValue<int>(val->name, val->i);
625                     break;
626                 case OCREP_PROP_DOUBLE:
627                     setValue<double>(val->name, val->d);
628                     break;
629                 case OCREP_PROP_BOOL:
630                     setValue<bool>(val->name, val->b);
631                     break;
632                 case OCREP_PROP_STRING:
633                     setValue<std::string>(val->name, val->str);
634                     break;
635                 case OCREP_PROP_OBJECT:
636                     {
637                         OCRepresentation cur;
638                         cur.setPayload(val->obj);
639                         setValue<OCRepresentation>(val->name, cur);
640                     }
641                     break;
642                 case OCREP_PROP_ARRAY:
643                     setPayloadArray(val);
644                     break;
645                 case OCREP_PROP_BYTE_STRING:
646                     setValue(val->name,
647                             std::vector<uint8_t>
648                             (val->ocByteStr.bytes, val->ocByteStr.bytes + val->ocByteStr.len)
649                             );
650                     break;
651                 default:
652                     throw std::logic_error(std::string("Not Implemented!") +
653                             std::to_string((int)val->type));
654                     break;
655             }
656             val = val->next;
657         }
658     }
659
660     void OCRepresentation::addChild(const OCRepresentation& rep)
661     {
662         m_children.push_back(rep);
663     }
664
665     void OCRepresentation::clearChildren()
666     {
667         m_children.clear();
668     }
669
670     const std::vector<OCRepresentation>& OCRepresentation::getChildren() const
671     {
672         return m_children;
673     }
674
675     void OCRepresentation::setChildren(const std::vector<OCRepresentation>& children)
676     {
677         m_children = children;
678     }
679
680     void OCRepresentation::setDevAddr(const OCDevAddr m_devAddr)
681     {
682         std::ostringstream ss;
683         if (m_devAddr.flags & OC_SECURE)
684         {
685             ss << COAPS;
686         }
687         else if (m_devAddr.adapter & OC_ADAPTER_TCP)
688         {
689             ss << COAP_TCP;
690         }
691         else
692         {
693             ss << COAP;
694         }
695         if (m_devAddr.flags & OC_IP_USE_V6)
696         {
697             ss << '[' << m_devAddr.addr << ']';
698         }
699         else
700         {
701             ss << m_devAddr.addr;
702         }
703         if (m_devAddr.port)
704         {
705             ss << ':' << m_devAddr.port;
706         }
707         m_host = ss.str();
708     }
709
710     const std::string OCRepresentation::getHost() const
711     {
712         return m_host;
713     }
714
715     void OCRepresentation::setUri(const char* uri)
716     {
717         m_uri = uri ? uri : "";
718     }
719
720     void OCRepresentation::setUri(const std::string& uri)
721     {
722         m_uri = uri;
723     }
724
725     std::string OCRepresentation::getUri() const
726     {
727         return m_uri;
728     }
729
730     const std::vector<std::string>& OCRepresentation::getResourceTypes() const
731     {
732         return m_resourceTypes;
733     }
734
735     void OCRepresentation::setResourceTypes(const std::vector<std::string>& resourceTypes)
736     {
737         m_resourceTypes = resourceTypes;
738     }
739
740     void OCRepresentation::addResourceType(const std::string& str)
741     {
742         m_resourceTypes.push_back(str);
743     }
744
745     const std::vector<std::string>& OCRepresentation::getResourceInterfaces() const
746     {
747         return m_interfaces;
748     }
749
750     void OCRepresentation::addResourceInterface(const std::string& str)
751     {
752         m_interfaces.push_back(str);
753     }
754
755     void OCRepresentation::setResourceInterfaces(const std::vector<std::string>& resourceInterfaces)
756     {
757         m_interfaces = resourceInterfaces;
758     }
759
760     bool OCRepresentation::hasAttribute(const std::string& str) const
761     {
762         return m_values.find(str) != m_values.end();
763     }
764
765     bool OCRepresentation::emptyData() const
766     {
767         // This logic is meant to determine whether based on the JSON serialization rules
768         // if this object will result in empty JSON.  URI is only serialized if there is valid
769         // data, ResourceType and Interfaces are only serialized if we are a nothing, a
770         // child of a default or link item.
771         // Our values array is only printed in the if we are the child of a Batch resource,
772         // the parent in a 'default' situation, or not in a child/parent relationship.
773         if (!m_uri.empty())
774         {
775             return false;
776         }
777         else if ((m_interfaceType == InterfaceType::None
778                         || m_interfaceType==InterfaceType::DefaultChild
779                         || m_interfaceType==InterfaceType::LinkChild)
780                     && (m_resourceTypes.size()>0 || m_interfaces.size()>0))
781         {
782             return false;
783         }
784         else if ((m_interfaceType == InterfaceType::None
785                         || m_interfaceType == InterfaceType::BatchChild
786                         || m_interfaceType == InterfaceType::DefaultParent)
787                     && m_values.size()>0)
788         {
789             return false;
790         }
791
792         if (m_children.size() > 0)
793         {
794             return false;
795         }
796
797         return true;
798     }
799
800     int OCRepresentation::numberOfAttributes() const
801     {
802         return m_values.size();
803     }
804
805     bool OCRepresentation::erase(const std::string& str)
806     {
807         return m_values.erase(str);
808     }
809
810     void OCRepresentation::setNULL(const std::string& str)
811     {
812         m_values[str] = OC::NullType();
813     }
814
815     bool OCRepresentation::isNULL(const std::string& str) const
816     {
817         auto x = m_values.find(str);
818
819         if (m_values.end() != x)
820         {
821             return x->second.which() == AttributeValueNullIndex;
822         }
823         else
824         {
825             throw OCException(OC::Exception::INVALID_ATTRIBUTE+ str);
826         }
827     }
828 }
829
830 namespace OC
831 {
832     std::ostream& operator <<(std::ostream& os, const AttributeType at)
833     {
834         switch(at)
835         {
836             case AttributeType::Null:
837                 os << "Null";
838                 break;
839             case AttributeType::Integer:
840                 os << "Integer";
841                 break;
842             case AttributeType::Double:
843                 os << "Double";
844                 break;
845             case AttributeType::Boolean:
846                 os << "Boolean";
847                 break;
848             case AttributeType::String:
849                 os << "String";
850                 break;
851             case AttributeType::OCRepresentation:
852                 os << "OCRepresentation";
853                 break;
854             case AttributeType::Vector:
855                 os << "Vector";
856                 break;
857             case AttributeType::Binary:
858                 os<< "Binary";
859         }
860         return os;
861     }
862 }
863
864 // STL Container For OCRepresentation
865 namespace OC
866 {
867     OCRepresentation::AttributeItem::AttributeItem(const std::string& name,
868             std::map<std::string, AttributeValue>& vals):
869             m_attrName(name), m_values(vals){}
870
871     OCRepresentation::AttributeItem OCRepresentation::operator[](const std::string& key)
872     {
873         OCRepresentation::AttributeItem attr{key, m_values};
874         return std::move(attr);
875     }
876
877     const OCRepresentation::AttributeItem OCRepresentation::operator[](const std::string& key) const
878     {
879         OCRepresentation::AttributeItem attr{key, m_values};
880         return std::move(attr);
881     }
882
883     const std::string& OCRepresentation::AttributeItem::attrname() const
884     {
885         return m_attrName;
886     }
887
888     template<typename T, typename = void>
889     struct type_info
890     {
891         // contains the actual type
892         typedef T type;
893         // contains the inner most vector-type
894         typedef T base_type;
895         // contains the AttributeType for this item
896         BOOST_STATIC_CONSTEXPR AttributeType enum_type =
897             AttributeTypeConvert<T>::type;
898         // contains the AttributeType for this base-type
899         BOOST_STATIC_CONSTEXPR AttributeType enum_base_type =
900             AttributeTypeConvert<T>::type;
901         // depth of the vector
902         BOOST_STATIC_CONSTEXPR size_t depth = 0;
903     };
904
905     template<typename T>
906     struct type_info<
907         T,
908         typename std::enable_if<
909             is_vector<T>::value &&
910             !std::is_same<uint8_t, typename T::value_type>::value
911         >::type
912     >
913     {
914         typedef T type;
915         typedef typename type_info<typename T::value_type>::base_type base_type;
916         BOOST_STATIC_CONSTEXPR AttributeType enum_type = AttributeType::Vector;
917         BOOST_STATIC_CONSTEXPR AttributeType enum_base_type =
918             type_info<typename T::value_type>::enum_base_type;
919         BOOST_STATIC_CONSTEXPR size_t depth = 1 +
920             type_info<typename T::value_type>::depth;
921     };
922
923     // special case for binary data, which is a std::vector<uint8_t>
924     template<>
925     struct type_info<std::vector<uint8_t>, void>
926     {
927         typedef std::vector<uint8_t> type;
928         typedef std::vector<uint8_t> base_type;
929         constexpr static AttributeType enum_type = AttributeType::Binary;
930         constexpr static AttributeType enum_base_type = AttributeType::Binary;
931         constexpr static size_t depth = 0;
932     };
933
934
935     struct type_introspection_visitor : boost::static_visitor<>
936     {
937         AttributeType type;
938         AttributeType base_type;
939         size_t depth;
940
941         type_introspection_visitor() : boost::static_visitor<>(),
942             type(AttributeType::Null), base_type(AttributeType::Null), depth(0){}
943
944         template <typename T>
945         void operator()(T const& /*item*/)
946         {
947             type = type_info<T>::enum_type;
948             base_type = type_info<T>::enum_base_type;
949             depth = type_info<T>::depth;
950         }
951     };
952
953     AttributeType OCRepresentation::AttributeItem::type() const
954     {
955         type_introspection_visitor vis;
956         boost::apply_visitor(vis, m_values[m_attrName]);
957         return vis.type;
958     }
959
960     AttributeType OCRepresentation::AttributeItem::base_type() const
961     {
962         type_introspection_visitor vis;
963         boost::apply_visitor(vis, m_values[m_attrName]);
964         return vis.base_type;
965     }
966
967     size_t OCRepresentation::AttributeItem::depth() const
968     {
969         type_introspection_visitor vis;
970         boost::apply_visitor(vis, m_values[m_attrName]);
971         return vis.depth;
972     }
973
974     OCRepresentation::iterator OCRepresentation::begin()
975     {
976         return OCRepresentation::iterator(m_values.begin(), m_values);
977     }
978
979     OCRepresentation::const_iterator OCRepresentation::begin() const
980     {
981          return OCRepresentation::const_iterator(m_values.begin(), m_values);
982     }
983
984     OCRepresentation::const_iterator OCRepresentation::cbegin() const
985     {
986         return OCRepresentation::const_iterator(m_values.cbegin(), m_values);
987     }
988
989     OCRepresentation::iterator OCRepresentation::end()
990     {
991         return OCRepresentation::iterator(m_values.end(), m_values);
992     }
993
994     OCRepresentation::const_iterator OCRepresentation::end() const
995     {
996         return OCRepresentation::const_iterator(m_values.end(), m_values);
997     }
998
999     OCRepresentation::const_iterator OCRepresentation::cend() const
1000     {
1001         return OCRepresentation::const_iterator(m_values.cend(), m_values);
1002     }
1003
1004     size_t OCRepresentation::size() const
1005     {
1006         return m_values.size();
1007     }
1008
1009     bool OCRepresentation::empty() const
1010     {
1011         return m_values.empty();
1012     }
1013
1014     bool OCRepresentation::iterator::operator==(const OCRepresentation::iterator& rhs) const
1015     {
1016         return m_iterator == rhs.m_iterator;
1017     }
1018
1019     bool OCRepresentation::iterator::operator!=(const OCRepresentation::iterator& rhs) const
1020     {
1021         return m_iterator != rhs.m_iterator;
1022     }
1023
1024     bool OCRepresentation::const_iterator::operator==(
1025             const OCRepresentation::const_iterator& rhs) const
1026     {
1027         return m_iterator == rhs.m_iterator;
1028     }
1029
1030     bool OCRepresentation::const_iterator::operator!=(
1031             const OCRepresentation::const_iterator& rhs) const
1032     {
1033         return m_iterator != rhs.m_iterator;
1034     }
1035
1036     OCRepresentation::iterator::reference OCRepresentation::iterator::operator*()
1037     {
1038         return m_item;
1039     }
1040
1041     OCRepresentation::const_iterator::const_reference
1042         OCRepresentation::const_iterator::operator*() const
1043     {
1044         return m_item;
1045     }
1046
1047     OCRepresentation::iterator::pointer OCRepresentation::iterator::operator->()
1048     {
1049         return &m_item;
1050     }
1051
1052     OCRepresentation::const_iterator::const_pointer
1053         OCRepresentation::const_iterator::operator->() const
1054     {
1055         return &m_item;
1056     }
1057
1058     OCRepresentation::iterator& OCRepresentation::iterator::operator++()
1059     {
1060         m_iterator++;
1061         if (m_iterator != m_item.m_values.end())
1062         {
1063             m_item.m_attrName = m_iterator->first;
1064         }
1065         else
1066         {
1067             m_item.m_attrName = "";
1068         }
1069         return *this;
1070     }
1071
1072     OCRepresentation::const_iterator& OCRepresentation::const_iterator::operator++()
1073     {
1074         m_iterator++;
1075         if (m_iterator != m_item.m_values.end())
1076         {
1077             m_item.m_attrName = m_iterator->first;
1078         }
1079         else
1080         {
1081             m_item.m_attrName = "";
1082         }
1083         return *this;
1084     }
1085
1086     OCRepresentation::iterator OCRepresentation::iterator::operator++(int)
1087     {
1088         OCRepresentation::iterator itr(*this);
1089         ++(*this);
1090         return itr;
1091     }
1092
1093     OCRepresentation::const_iterator OCRepresentation::const_iterator::operator++(int)
1094     {
1095         OCRepresentation::const_iterator itr(*this);
1096         ++(*this);
1097         return itr;
1098     }
1099
1100     struct to_string_visitor : boost::static_visitor<>
1101     {
1102         std::string str;
1103         template <typename T>
1104         void operator()(T const& item)
1105         {
1106             str = boost::lexical_cast<std::string>(item);
1107         }
1108
1109         template <typename T>
1110         void operator()(std::vector<T> const& item)
1111         {
1112             to_string_visitor vis;
1113             std::ostringstream stream;
1114             stream << "[";
1115
1116             for(const auto& i : item)
1117             {
1118                 vis(i);
1119                 stream << vis.str  << " ";
1120             }
1121             stream << "]";
1122             str = stream.str();
1123         }
1124     };
1125
1126     template<>
1127     void to_string_visitor::operator()(bool const& item)
1128     {
1129         str = item ? "true" : "false";
1130     }
1131
1132     template<>
1133     void to_string_visitor::operator()(std::string const& item)
1134     {
1135         str = item;
1136     }
1137
1138     template<>
1139     void to_string_visitor::operator()(NullType const& /*item*/)
1140     {
1141         str = "(null)";
1142     }
1143
1144     template<>
1145     void to_string_visitor::operator()(OCRepresentation const& /*item*/)
1146     {
1147         str = "OC::OCRepresentation";
1148     }
1149
1150     std::string OCRepresentation::getValueToString(const std::string& key) const
1151     {
1152         auto x = m_values.find(key);
1153         if (x != m_values.end())
1154         {
1155             to_string_visitor vis;
1156             boost::apply_visitor(vis, x->second);
1157             return std::move(vis.str);
1158         }
1159
1160         return "";
1161     }
1162
1163     std::string OCRepresentation::AttributeItem::getValueToString() const
1164     {
1165         to_string_visitor vis;
1166         boost::apply_visitor(vis, m_values[m_attrName]);
1167         return std::move(vis.str);
1168     }
1169
1170     std::ostream& operator<<(std::ostream& os, const OCRepresentation::AttributeItem& ai)
1171     {
1172         os << ai.getValueToString();
1173         return os;
1174     }
1175 }