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