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