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