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