Imported Upstream version 1.1.0
[platform/upstream/iotivity.git] / service / simulator / src / common / simulator_resource_model.cpp
1 /******************************************************************
2  *
3  * Copyright 2015 Samsung Electronics 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 #include "simulator_resource_model.h"
22 #include "simulator_resource_model_schema.h"
23 #include "simulator_exceptions.h"
24 #include "logger.h"
25
26 #include <boost/lexical_cast.hpp>
27 #include <cfloat>
28
29 #define TAG "SIM_RESOURCE_MODEL"
30
31 template <typename T>
32 struct TypeConverter {};
33
34 template <>
35 struct TypeConverter<int>
36 {
37     constexpr static AttributeValueType type =
38         AttributeValueType::INTEGER;
39 };
40
41 template <>
42 struct TypeConverter<double>
43 {
44     constexpr static AttributeValueType type =
45         AttributeValueType::DOUBLE;
46 };
47
48 template <>
49 struct TypeConverter<bool>
50 {
51     constexpr static AttributeValueType type =
52         AttributeValueType::BOOLEAN;
53 };
54
55 template <>
56 struct TypeConverter<std::string>
57 {
58     constexpr static AttributeValueType type =
59         AttributeValueType::STRING;
60 };
61
62 template <>
63 struct TypeConverter<SimulatorResourceModel>
64 {
65     constexpr static AttributeValueType type =
66         AttributeValueType::RESOURCE_MODEL;
67 };
68
69 template <typename T>
70 struct TypeDetails
71 {
72     constexpr static AttributeValueType type =
73         TypeConverter<T>::type;
74     constexpr static AttributeValueType baseType =
75         TypeConverter<T>::type;
76     constexpr static int depth = 0;
77 };
78
79 template <typename T>
80 struct TypeDetails<std::vector<T>>
81 {
82     constexpr static AttributeValueType type =
83         AttributeValueType::VECTOR;
84     constexpr static AttributeValueType baseType =
85         TypeDetails<T>::baseType;
86     constexpr static int depth = 1 + TypeDetails<T>::depth;
87 };
88
89 class AttributeTypeVisitor : public boost::static_visitor<>
90 {
91     public:
92         AttributeTypeVisitor() : m_type(AttributeValueType::UNKNOWN),
93             m_baseType(AttributeValueType::UNKNOWN), m_depth(0) {}
94
95         template <typename T>
96         void operator ()(const T &)
97         {
98             m_type = TypeDetails<T>::type;
99             m_baseType = TypeDetails<T>::baseType;
100             m_depth = TypeDetails<T>::depth;
101         }
102
103         AttributeValueType m_type;
104         AttributeValueType m_baseType;
105         int m_depth;
106 };
107
108 class OCRepresentationBuilder
109 {
110     public:
111         class ValueConverter : public boost::static_visitor<>
112         {
113             public:
114                 ValueConverter(OC::OCRepresentation &rep, const std::string &name)
115                     : m_rep(rep), m_name(name) {}
116
117                 template <typename T>
118                 void operator ()(const T &value)
119                 {
120                     m_rep.setValue(m_name, value);
121                 }
122
123                 void operator ()(const SimulatorResourceModel &value)
124                 {
125                     OC::OCRepresentation ocRep;
126                     for (auto &element : value.getAttributeValues())
127                     {
128                         ValueConverter visitor(ocRep, element.first);
129                         boost::apply_visitor(visitor, element.second);
130                     }
131
132                     m_rep.setValue(m_name, ocRep);
133                 }
134
135                 template <typename T>
136                 void operator ()(const std::vector<T> &values)
137                 {
138                     m_rep.setValue(m_name, values);
139                 }
140
141                 void operator ()(const std::vector<SimulatorResourceModel> &values)
142                 {
143                     std::vector<OC::OCRepresentation> ocRepArray(values.size());
144                     for (size_t i = 0; i < values.size(); i++)
145                     {
146                         for (auto &element : values[i].getAttributeValues())
147                         {
148                             ValueConverter visitor(ocRepArray[i], element.first);
149                             boost::apply_visitor(visitor, element.second);
150                         }
151                     }
152
153                     m_rep.setValue(m_name, ocRepArray);
154                 }
155
156                 template <typename T>
157                 void operator ()(const std::vector<std::vector<T>> &values)
158                 {
159                     m_rep.setValue(m_name, values);
160                 }
161
162                 void operator ()(const std::vector<std::vector<SimulatorResourceModel>> &values)
163                 {
164                     std::vector<std::vector<OC::OCRepresentation>> ocRepArray;
165                     for (size_t i = 0; i < values.size(); i++)
166                     {
167                         for (size_t j = 0; j < values[i].size(); j++)
168                         {
169                             for (auto &element : values[i][j].getAttributeValues())
170                             {
171                                 ValueConverter visitor(ocRepArray[i][j], element.first);
172                                 boost::apply_visitor(visitor, element.second);
173                             }
174                         }
175                     }
176
177                     m_rep.setValue(m_name, ocRepArray);
178                 }
179
180                 template <typename T>
181                 void operator ()(const std::vector<std::vector<std::vector<T>>> &values)
182                 {
183                     m_rep.setValue(m_name, values);
184                 }
185
186                 void operator ()(const std::vector<std::vector<std::vector<SimulatorResourceModel>>> &values)
187                 {
188                     std::vector<std::vector<std::vector<OC::OCRepresentation>>> ocRepArray;
189                     for (size_t i = 0; i < values.size(); i++)
190                     {
191                         for (size_t j = 0; j < values[i].size(); j++)
192                         {
193                             for (size_t k = 0; j < values[i][j].size(); k++)
194                             {
195                                 for (auto &element : values[i][j][k].getAttributeValues())
196                                 {
197                                     ValueConverter visitor(ocRepArray[i][j][k], element.first);
198                                     boost::apply_visitor(visitor, element.second);
199                                 }
200                             }
201                         }
202                     }
203
204                     m_rep.setValue(m_name, ocRepArray);
205                 }
206
207             private:
208                 OC::OCRepresentation &m_rep;
209                 std::string m_name;
210         };
211
212         OC::OCRepresentation build(const SimulatorResourceModel &model)
213         {
214             OC::OCRepresentation ocRep;
215             for (auto &element : model.getAttributeValues())
216             {
217                 ValueConverter visitor(ocRep, element.first);
218                 boost::apply_visitor(visitor, element.second);
219             }
220
221             return std::move(ocRep);
222         }
223 };
224
225 // TODO: Class is very heavy, revisit again to clean
226 class SimulatorResourceModelBuilder
227 {
228     public:
229         SimulatorResourceModel build(const OC::OCRepresentation &ocRep)
230         {
231             SimulatorResourceModel resModel;
232             handleRepresentationType(resModel, ocRep);
233             return std::move(resModel);
234         }
235
236     private:
237         void handleRepresentationType(SimulatorResourceModel &resModel,
238                                       const OC::OCRepresentation &ocRep)
239         {
240             for (auto &ocAttribute : ocRep)
241             {
242                 if (OC::AttributeType::Integer == ocAttribute.type())
243                 {
244                     resModel.add<int>(ocAttribute.attrname(), ocAttribute.getValue<int>());
245                 }
246                 else if (OC::AttributeType::Double == ocAttribute.type())
247                 {
248                     resModel.add<double>(ocAttribute.attrname(), ocAttribute.getValue<double>());
249                 }
250                 else if (OC::AttributeType::Boolean == ocAttribute.type())
251                 {
252                     resModel.add<bool>(ocAttribute.attrname(), ocAttribute.getValue<bool>());
253                 }
254                 else if (OC::AttributeType::String == ocAttribute.type())
255                 {
256                     resModel.add<std::string>(ocAttribute.attrname(), ocAttribute.getValue<std::string>());
257                 }
258                 else if (OC::AttributeType::OCRepresentation == ocAttribute.type())
259                 {
260                     SimulatorResourceModel subResModel;
261                     OC::OCRepresentation ocSubRep = ocAttribute.getValue<OC::OCRepresentation>();
262                     handleRepresentationType(subResModel, ocSubRep);
263                     resModel.add<SimulatorResourceModel>(ocAttribute.attrname(), subResModel);
264                 }
265                 else if (OC::AttributeType::Vector == ocAttribute.type())
266                 {
267                     handleVectorType(resModel, ocAttribute);
268                 }
269             }
270         }
271
272         void handleVectorType(SimulatorResourceModel &resModel,
273                               const OC::OCRepresentation::AttributeItem &ocAttribute)
274         {
275             if (1 == ocAttribute.depth())
276             {
277                 handleVectorTypeDepth1(resModel, ocAttribute);
278             }
279             else if (2 == ocAttribute.depth())
280             {
281                 handleVectorTypeDepth2(resModel, ocAttribute);
282             }
283             else if (3 == ocAttribute.depth())
284             {
285                 handleVectorTypeDepth3(resModel, ocAttribute);
286             }
287         }
288
289         void handleVectorTypeDepth1(SimulatorResourceModel &resModel,
290                                     const OC::OCRepresentation::AttributeItem &ocAttribute)
291         {
292             if (OC::AttributeType::Integer == ocAttribute.base_type())
293             {
294                 resModel.add(ocAttribute.attrname(), ocAttribute.getValue<std::vector<int>>());
295             }
296             else if (OC::AttributeType::Double == ocAttribute.base_type())
297             {
298                 resModel.add(ocAttribute.attrname(), ocAttribute.getValue<std::vector<double>>());
299             }
300             else if (OC::AttributeType::Boolean == ocAttribute.base_type())
301             {
302                 resModel.add(ocAttribute.attrname(), ocAttribute.getValue<std::vector<bool>>());
303             }
304             else if (OC::AttributeType::String == ocAttribute.base_type())
305             {
306                 resModel.add(ocAttribute.attrname(), ocAttribute.getValue<std::vector<std::string>>());
307             }
308             else if (OC::AttributeType::OCRepresentation == ocAttribute.base_type())
309             {
310                 std::vector<OC::OCRepresentation> ocSubRepArray =
311                     ocAttribute.getValue<std::vector<OC::OCRepresentation>>();
312
313                 std::vector<SimulatorResourceModel> subResModelArray(ocSubRepArray.size());
314                 for  (size_t i = 0; i < ocSubRepArray.size(); i++)
315                 {
316                     handleRepresentationType(subResModelArray[i], ocSubRepArray[i]);
317                 }
318
319                 resModel.add<std::vector<SimulatorResourceModel>>(ocAttribute.attrname(), subResModelArray);
320             }
321         }
322
323         void handleVectorTypeDepth2(SimulatorResourceModel &resModel,
324                                     const OC::OCRepresentation::AttributeItem &ocAttribute)
325         {
326             if (OC::AttributeType::Integer == ocAttribute.base_type())
327             {
328                 resModel.add(ocAttribute.attrname(), ocAttribute.getValue<std::vector<std::vector<int>>>());
329             }
330             else if (OC::AttributeType::Double == ocAttribute.base_type())
331             {
332                 resModel.add(ocAttribute.attrname(), ocAttribute.getValue<std::vector<std::vector<double>>>());
333             }
334             else if (OC::AttributeType::Boolean == ocAttribute.base_type())
335             {
336                 resModel.add(ocAttribute.attrname(), ocAttribute.getValue<std::vector<std::vector<bool>>>());
337             }
338             else if (OC::AttributeType::String == ocAttribute.base_type())
339             {
340                 resModel.add(ocAttribute.attrname(), ocAttribute.getValue<std::vector<std::vector<std::string>>>());
341             }
342             else if (OC::AttributeType::OCRepresentation == ocAttribute.base_type())
343             {
344                 std::vector<std::vector<OC::OCRepresentation>> ocSubRepArray =
345                             ocAttribute.getValue<std::vector<std::vector<OC::OCRepresentation>>>();
346
347                 std::vector<std::vector<SimulatorResourceModel>> subResModelArray(ocSubRepArray.size());
348                 for  (size_t i = 0; i < ocSubRepArray.size(); i++)
349                 {
350                     std::vector<SimulatorResourceModel> innerArray1(ocSubRepArray[i].size());
351                     for  (size_t j = 0; j < ocSubRepArray[i].size(); j++)
352                         handleRepresentationType(innerArray1[j], ocSubRepArray[i][j]);
353                     subResModelArray[i] = innerArray1;
354                 }
355
356                 resModel.add<std::vector<std::vector<SimulatorResourceModel>>>(
357                     ocAttribute.attrname(), subResModelArray);
358             }
359         }
360
361         void handleVectorTypeDepth3(SimulatorResourceModel &resModel,
362                                     const OC::OCRepresentation::AttributeItem &ocAttribute)
363         {
364             if (OC::AttributeType::Integer == ocAttribute.base_type())
365             {
366                 resModel.add(ocAttribute.attrname(),
367                              ocAttribute.getValue<std::vector<std::vector<std::vector<int>>>>());
368             }
369             else if (OC::AttributeType::Double == ocAttribute.base_type())
370             {
371                 resModel.add(ocAttribute.attrname(),
372                              ocAttribute.getValue<std::vector<std::vector<std::vector<double>>>>());
373             }
374             else if (OC::AttributeType::Boolean == ocAttribute.base_type())
375             {
376                 resModel.add(ocAttribute.attrname(),
377                              ocAttribute.getValue<std::vector<std::vector<std::vector<bool>>>>());
378             }
379             else if (OC::AttributeType::String == ocAttribute.base_type())
380             {
381                 resModel.add(ocAttribute.attrname(),
382                              ocAttribute.getValue<std::vector<std::vector<std::vector<std::string>>>>());
383             }
384             else if (OC::AttributeType::OCRepresentation == ocAttribute.base_type())
385             {
386                 std::vector<std::vector<std::vector<OC::OCRepresentation>>> ocSubRepArray =
387                     ocAttribute.getValue<std::vector<std::vector<std::vector<OC::OCRepresentation>>>>();
388
389                 std::vector<std::vector<std::vector<SimulatorResourceModel>>> subResModelArray(
390                     ocSubRepArray.size());
391                 for  (size_t i = 0; i < ocSubRepArray.size(); i++)
392                 {
393                     std::vector<std::vector<SimulatorResourceModel>> innerArray1(ocSubRepArray[i].size());
394                     for  (size_t j = 0; j < ocSubRepArray[i].size(); j++)
395                     {
396                         std::vector<SimulatorResourceModel> innerArray2(ocSubRepArray[i][j].size());
397                         for  (size_t k = 0; k < ocSubRepArray[i][j].size(); k++)
398                         {
399                             handleRepresentationType(innerArray2[k], ocSubRepArray[i][j][k]);
400                         }
401                         innerArray1[j] = innerArray2;
402                     }
403                     subResModelArray[i] = innerArray1;
404                 }
405
406                 resModel.add<std::vector<std::vector<std::vector<SimulatorResourceModel>>>>(
407                     ocAttribute.attrname(), subResModelArray);
408             }
409         }
410 };
411
412 class ToStringConverter
413 {
414     public:
415         class ValueVisitor : public boost::static_visitor<std::string>
416         {
417             public:
418
419                 template <typename T>
420                 std::string operator ()(const T &value)
421                 {
422                     try
423                     {
424                         return boost::lexical_cast<std::string>(value);
425                     }
426                     catch (const boost::bad_lexical_cast &e)
427                     {
428                         return "CONVERSION_FAILED!";
429                     }
430                 }
431
432                 std::string operator ()(const SimulatorResourceModel &value)
433                 {
434                     std::ostringstream out;
435                     out << "{ ";
436                     for (auto &element : value.getAttributeValues())
437                     {
438                         out << "\"" << element.first << "\" : ";
439
440                         ValueVisitor visitor;
441                         out << boost::apply_visitor(visitor, element.second);
442
443                         out << ", ";
444                     }
445                     out << "}";
446                     return out.str();
447                 }
448
449                 template <typename T>
450                 std::string operator ()(const std::vector<T> &values)
451                 {
452                     std::ostringstream out;
453                     out << "[ ";
454
455                     for (size_t i = 0; i < values.size(); i++)
456                     {
457                         out << operator ()(values[i]);
458                         out << " ";
459                     }
460
461                     out << "]";
462                     return out.str();
463                 }
464
465                 template <typename T>
466                 std::string operator ()(const std::vector<std::vector<T>> &values)
467                 {
468                     std::ostringstream out;
469                     out << "[ ";
470
471                     for (size_t i = 0; i < values.size(); i++)
472                     {
473                         out << operator ()(values[i]);
474                         out << " ";
475                     }
476
477                     out << "]";
478                     return out.str();
479                 }
480
481                 template <typename T>
482                 std::string operator ()(const std::vector<std::vector<std::vector<T>>> &values)
483                 {
484                     std::ostringstream out;
485                     out << "[ ";
486
487                     for (size_t i = 0; i < values.size(); i++)
488                     {
489                         out << operator ()(values[i]);
490                         out << " ";
491                     }
492
493                     out << "]";
494                     return out.str();
495                 }
496         };
497
498         std::string getStringRepresentation(const SimulatorResourceModel &resModel)
499         {
500             ValueVisitor visitor;
501             AttributeValueVariant value = resModel;
502             return boost::apply_visitor(visitor, value);
503         }
504
505         std::string getStringRepresentation(const AttributeValueVariant &value)
506         {
507             ValueVisitor visitor;
508             return boost::apply_visitor(visitor, value);
509         }
510 };
511
512 SimulatorResourceModel::TypeInfo::TypeInfo(
513     AttributeValueType type, AttributeValueType baseType, int depth)
514     :   m_type (type), m_baseType(baseType), m_depth(depth) {}
515
516 AttributeValueType SimulatorResourceModel::TypeInfo::type() const
517 {
518     return m_type;
519 }
520
521 AttributeValueType SimulatorResourceModel::TypeInfo::baseType() const
522 {
523     return m_baseType;
524 }
525
526 int SimulatorResourceModel::TypeInfo::depth() const
527 {
528     return m_depth;
529 }
530
531 bool SimulatorResourceModel::TypeInfo::operator==(
532     const SimulatorResourceModel::TypeInfo &rhs) const
533 {
534     if (m_type == rhs.m_type && m_baseType == rhs.m_baseType
535         && m_depth == rhs.m_depth)
536         return true;
537     return false;
538 }
539
540 SimulatorResourceAttribute::SimulatorResourceAttribute(const std::string &name)
541     : m_name(name) {}
542
543 SimulatorResourceAttribute::SimulatorResourceAttribute(const std::string &name,
544         const AttributeValueVariant &value) : m_name(name)
545 {
546     m_value = std::make_shared<AttributeValueVariant>(value);
547 }
548
549 void SimulatorResourceAttribute::setName(const std::string &name)
550 {
551     m_name = name;
552 }
553
554 std::string SimulatorResourceAttribute::getName() const
555 {
556     return m_name;
557 }
558
559 const SimulatorResourceModel::TypeInfo SimulatorResourceAttribute::getType() const
560 {
561     if (m_value)
562     {
563         AttributeTypeVisitor typeVisitor;
564         boost::apply_visitor(typeVisitor, *(m_value.get()));
565         return SimulatorResourceModel::TypeInfo(typeVisitor.m_type, typeVisitor.m_baseType,
566                                                 typeVisitor.m_depth);
567     }
568
569     return SimulatorResourceModel::TypeInfo();
570 }
571
572 void SimulatorResourceAttribute::setProperty(const std::shared_ptr<AttributeProperty> &property)
573 {
574     m_property = property;
575 }
576
577 std::shared_ptr<AttributeProperty> SimulatorResourceAttribute::getProperty() const
578 {
579     return m_property;
580 }
581
582 AttributeValueVariant SimulatorResourceAttribute::getValue() const
583 {
584     return *m_value;
585 }
586
587 std::string SimulatorResourceAttribute::asString() const
588 {
589     return ToStringConverter().getStringRepresentation(*m_value);
590 }
591
592 bool SimulatorResourceModel::remove(const std::string &name)
593 {
594     if (m_attributes.end() == m_attributes.find(name))
595     {
596         return false;
597     }
598
599     m_attributes.erase(m_attributes.find(name));
600     return true;
601 }
602
603 bool SimulatorResourceModel::contains(const std::string &name) const
604 {
605     if (m_attributes.end() != m_attributes.find(name))
606     {
607         return true;
608     }
609
610     return false;
611 }
612
613 size_t SimulatorResourceModel::size() const
614 {
615     return m_attributes.size();
616 }
617
618 SimulatorResourceModel::TypeInfo SimulatorResourceModel::getType(const std::string &name) const
619 {
620     if (m_attributes.end() != m_attributes.find(name))
621     {
622         return getTypeInfo(m_attributes.find(name)->second);
623     }
624
625     return SimulatorResourceModel::TypeInfo();
626 }
627
628 std::map<std::string, AttributeValueVariant> SimulatorResourceModel::getAttributeValues() const
629 {
630     return m_attributes;
631 }
632
633 AttributeValueVariant SimulatorResourceModel::getAttributeValue(const std::string &name) const
634 {
635     auto ite = m_attributes.find(name);
636     if (m_attributes.end() != ite)
637     {
638         return (*ite).second;
639     }
640
641     return AttributeValueVariant();
642 }
643
644 std::set<std::string> SimulatorResourceModel::getAttributeNameSet() const
645 {
646     std::set<std::string> nameSet;
647     for (auto &attributeEntry : m_attributes)
648     {
649         nameSet.insert(attributeEntry.first);
650     }
651
652     return nameSet;
653 }
654
655 SimulatorResourceModel::TypeInfo SimulatorResourceModel::getTypeInfo(const AttributeValueVariant
656         &value) const
657 {
658     AttributeTypeVisitor typeVisitor;
659     boost::apply_visitor(typeVisitor, value);
660     SimulatorResourceModel::TypeInfo typeInfo(typeVisitor.m_type, typeVisitor.m_baseType,
661             typeVisitor.m_depth);
662     return typeInfo;
663 }
664
665 bool SimulatorResourceModel::updateValue(const std::string &name,
666         const AttributeValueVariant &value)
667 {
668     if (name.empty())
669     {
670         return false;
671     }
672
673     if (m_attributes.end() == m_attributes.find(name))
674     {
675         return false;
676     }
677
678     if (!(getTypeInfo(m_attributes[name]) == getTypeInfo(value)))
679     {
680         return false;
681     }
682
683     m_attributes[name] = value;
684     return true;
685 }
686
687 OC::OCRepresentation SimulatorResourceModel::asOCRepresentation() const
688 {
689     return OCRepresentationBuilder().build(*this);
690 }
691
692 std::string SimulatorResourceModel::asString() const
693 {
694     return ToStringConverter().getStringRepresentation(*this);
695 }
696
697 SimulatorResourceModel SimulatorResourceModel::build(const OC::OCRepresentation &ocRep)
698 {
699     return SimulatorResourceModelBuilder().build(ocRep);
700 }
701