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