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