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