Fix for SVACE and Klocwork issues.
[platform/upstream/iotivity.git] / service / simulator / src / common / simulator_resource_model_schema.cpp
1 /******************************************************************
2  *
3  * Copyright 2016 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_schema.h"
22 #include "simulator_exceptions.h"
23
24 template <typename TYPE>
25 static AttributeValueVariant buildArrayValue(int depth, AttributeValueVariant &childValue)
26 {
27     if (1 == depth)
28     {
29         std::vector<TYPE> arrayValue {boost::get<TYPE>(childValue)};
30         return arrayValue;
31     }
32     else if (2 == depth)
33     {
34         std::vector<std::vector<TYPE>> arrayValue {{boost::get<TYPE>(childValue)}};
35         return arrayValue;
36     }
37
38     // This for handling array values of depth 3
39     // NOTE: Caller of this method should validate and pass the depth information.
40     // on invalid depth information this method might throw boost exception.
41     std::vector<std::vector<std::vector<TYPE>>> arrayValue {{{boost::get<TYPE>(childValue)}}};
42     return arrayValue;
43 }
44
45 template <typename T, typename=void>
46 struct UniquenessChecker
47 {
48     static bool get(const std::vector<T> &/*value*/)
49     {
50         return true;
51     }
52 };
53
54 template <typename T>
55 struct UniquenessChecker<T, typename std::enable_if<
56     std::is_same<T, int>::value
57     || std::is_same<T, double>::value
58     || std::is_same<T, bool>::value
59     || std::is_same<T, std::string>::value
60     >::type >
61 {
62     static bool get(const std::vector<T> &value)
63     {
64         std::vector<T> valueCopy = value;
65         std::sort(valueCopy.begin(), valueCopy.end());
66         if(valueCopy.end() != std::unique(valueCopy.begin(), valueCopy.end()))
67             return false;
68         return true;
69     }
70 };
71
72 class IntegerValidator : public boost::static_visitor<bool>
73 {
74     public:
75         IntegerValidator(const std::shared_ptr<IntegerProperty> &property) :
76             m_property(property) {}
77
78         template <typename T>
79         bool operator ()(const T &)
80         {
81             return false;
82         }
83
84         bool operator ()(const int &value)
85         {
86             return m_property->validate(value);
87         }
88
89     private:
90         std::shared_ptr<IntegerProperty> m_property;
91 };
92
93 class DoubleValidator : public boost::static_visitor<bool>
94 {
95     public:
96         DoubleValidator(const std::shared_ptr<DoubleProperty> &property) :
97             m_property(property) {}
98
99         template <typename T>
100         bool operator ()(const T &)
101         {
102             return false;
103         }
104
105         bool operator ()(const double &value)
106         {
107             return m_property->validate(value);
108         }
109
110     private:
111         std::shared_ptr<DoubleProperty> m_property;
112 };
113
114 class StringValidator : public boost::static_visitor<bool>
115 {
116     public:
117         StringValidator(const std::shared_ptr<StringProperty> &property) :
118             m_property(property) {}
119
120         template <typename T>
121         bool operator ()(const T &)
122         {
123             return false;
124         }
125
126         bool operator ()(const std::string &value)
127         {
128             return m_property->validate(value);
129         }
130
131     private:
132         std::shared_ptr<StringProperty> m_property;
133 };
134
135 class ArrayValidator : public boost::static_visitor<bool>
136 {
137     public:
138         ArrayValidator(const std::shared_ptr<ArrayProperty> &property) :
139             m_property(property) {}
140
141         template <typename T>
142         bool operator ()(const T &)
143         {
144             return false;
145         }
146
147         template <typename T>
148         bool operator ()(const std::vector<T> &value)
149         {
150             // Validating length of array
151             if (!checkLength(value))
152             {
153                 return false;
154             }
155
156             // Validate the uniqueness of elements of array
157             if (!checkUniqueness(value))
158             {
159                 return false;
160             }
161
162             // Validating elements of array
163             std::shared_ptr<AttributeProperty> elementProperty =
164                 m_property->getElementProperty();
165             if (elementProperty)
166             {
167                 for (size_t index = 0; index < value.size(); index++)
168                 {
169                     AttributeValueVariant element = value[index];
170                     if (!elementProperty->validate(element))
171                         return false;
172                 }
173             }
174
175             return true;
176         }
177
178     private:
179         template <typename T>
180         bool checkLength(const std::vector<T> &value)
181         {
182             if (m_property->hasRange())
183             {
184                 if (value.size() < m_property->getMinItems()
185                     || (value.size() > m_property->getMaxItems() && !m_property->isVariable()))
186                 {
187                     return false;
188                 }
189             }
190
191             return true;
192         }
193
194         template <typename T>
195         bool checkUniqueness(const std::vector<T> &value)
196         {
197             if (m_property->isUnique())
198             {
199                 return UniquenessChecker<T>::get(value);
200             }
201
202             return true;
203         }
204
205         std::shared_ptr<ArrayProperty> m_property;
206 };
207
208 class ModelValidator : public boost::static_visitor<bool>
209 {
210     public:
211         ModelValidator(const std::shared_ptr<ModelProperty> &property) :
212             m_property(property) {}
213
214         template <typename T>
215         bool operator ()(const T &)
216         {
217             return false;
218         }
219
220         bool operator ()(const SimulatorResourceModel &value)
221         {
222             return m_property->validate(value);
223         }
224
225     private:
226         std::shared_ptr<ModelProperty> m_property;
227 };
228
229 AttributeProperty::AttributeProperty(Type type) : m_type(type) {}
230
231 AttributeProperty::Type AttributeProperty::getType() const
232 {
233     return m_type;
234 }
235
236 IntegerProperty::IntegerProperty(int defaultValue)
237     : AttributeProperty(AttributeProperty::Type::INTEGER),
238       m_defaultValue(defaultValue),
239       m_min(0),
240       m_max(0),
241       m_hasRange(false) {}
242
243 std::shared_ptr<IntegerProperty> IntegerProperty::build(int defaultValue)
244 {
245     return std::shared_ptr<IntegerProperty>(new IntegerProperty(defaultValue));
246 }
247
248 bool IntegerProperty::isInteger() const
249 {
250     return true;
251 }
252
253 std::shared_ptr<IntegerProperty> IntegerProperty::asInteger()
254 {
255     return shared_from_this();
256 }
257
258 bool IntegerProperty::hasRange() const
259 {
260     return m_hasRange;
261 }
262
263 bool IntegerProperty::hasValues() const
264 {
265     return m_values.size() > 0;
266 }
267
268 int IntegerProperty::getDefaultValue() const
269 {
270     return m_defaultValue;
271 }
272
273 bool IntegerProperty::getRange(int &min, int &max) const
274 {
275     if (!m_hasRange)
276         return false;
277
278     min = m_min;
279     max = m_max;
280     return true;
281 }
282
283 bool IntegerProperty::getValues(std::vector<int> &values) const
284 {
285     if (!m_values.size())
286         return false;
287
288     values  = m_values;
289     return true;
290 }
291
292 void IntegerProperty::setDefaultValue(int value)
293 {
294     if(m_hasRange && !(value >= m_min && value <= m_max))
295     {
296         m_defaultValue = m_min;
297     }
298     else if(m_values.size() > 0
299         && m_values.end() == std::find(m_values.begin(), m_values.end(), value))
300     {
301         m_defaultValue = m_values[0];
302     }
303     else
304         m_defaultValue = value;
305 }
306
307 void IntegerProperty::setRange(int min, int max)
308 {
309     m_min = min;
310     m_max = max;
311     m_hasRange = true;
312     setDefaultValue(m_defaultValue);
313 }
314
315 void IntegerProperty::setValues(const std::vector<int> &values)
316 {
317     m_values = values;
318     setDefaultValue(m_defaultValue);
319 }
320
321 bool IntegerProperty::validate(const AttributeValueVariant &value)
322 {
323     IntegerValidator integerValidator(shared_from_this());
324     return boost::apply_visitor(integerValidator, value);
325 }
326
327 bool IntegerProperty::validate(const int &value)
328 {
329     if (m_hasRange && (value < m_min || value > m_max))
330     {
331         return false;
332     }
333     else if (m_values.size() > 0)
334     {
335         if (m_values.end() == std::find(m_values.begin(), m_values.end(), value))
336             return false;
337     }
338
339     return true;
340 }
341
342 AttributeValueVariant IntegerProperty::buildValue()
343 {
344     return m_defaultValue;
345 }
346
347 DoubleProperty::DoubleProperty(double defaultValue)
348     : AttributeProperty(AttributeProperty::Type::DOUBLE),
349       m_defaultValue(defaultValue),
350       m_min(0),
351       m_max(0),
352       m_hasRange(false) {}
353
354 std::shared_ptr<DoubleProperty> DoubleProperty::build(double defaultValue)
355 {
356     return std::shared_ptr<DoubleProperty>(new DoubleProperty(defaultValue));
357 }
358
359 bool DoubleProperty::isDouble() const
360 {
361     return true;
362 }
363
364 std::shared_ptr<DoubleProperty> DoubleProperty::asDouble()
365 {
366     return shared_from_this();
367 }
368
369 bool DoubleProperty::hasRange() const
370 {
371     return m_hasRange;
372 }
373
374 bool DoubleProperty::hasValues() const
375 {
376     return m_values.size() > 0;
377 }
378
379 double DoubleProperty::getDefaultValue() const
380 {
381     return m_defaultValue;
382 }
383
384 bool DoubleProperty::getRange(double &min, double &max) const
385 {
386     if (!m_hasRange)
387         return false;
388
389     min = m_min;
390     max = m_max;
391     return true;
392 }
393
394 bool DoubleProperty::getValues(std::vector<double> &values) const
395 {
396     if (!m_values.size())
397         return false;
398
399     values  = m_values;
400     return true;
401 }
402
403 void DoubleProperty::setDefaultValue(double value)
404 {
405     if(m_hasRange && !(value >= m_min && value <= m_max))
406     {
407         m_defaultValue = m_min;
408     }
409     else if(m_values.size() > 0
410         && m_values.end() == std::find(m_values.begin(), m_values.end(), value))
411     {
412         m_defaultValue = m_values[0];
413     }
414     else
415         m_defaultValue = value;
416 }
417
418 void DoubleProperty::setRange(double min, double max)
419 {
420     m_min = min;
421     m_max = max;
422     m_hasRange = true;
423     setDefaultValue(m_defaultValue);
424 }
425
426 void DoubleProperty::setValues(const std::vector<double> &values)
427 {
428     m_values = values;
429     setDefaultValue(m_defaultValue);
430 }
431
432 bool DoubleProperty::validate(const AttributeValueVariant &value)
433 {
434     DoubleValidator doubleValidator(shared_from_this());
435     return boost::apply_visitor(doubleValidator, value);
436 }
437
438 bool DoubleProperty::validate(const double &value)
439 {
440     if (m_hasRange && (value < m_min || value > m_max))
441     {
442         return false;
443     }
444     else if (m_values.size() > 0)
445     {
446         if (m_values.end() == std::find(m_values.begin(), m_values.end(), value))
447             return false;
448     }
449
450     return true;
451 }
452
453 AttributeValueVariant DoubleProperty::buildValue()
454 {
455     return m_defaultValue;
456 }
457
458 BooleanProperty::BooleanProperty(bool defaultValue)
459     : AttributeProperty(AttributeProperty::Type::BOOLEAN),
460       m_defaultValue(defaultValue) {}
461
462 std::shared_ptr<BooleanProperty> BooleanProperty::build(bool defaultValue)
463 {
464     return std::shared_ptr<BooleanProperty>(new BooleanProperty(defaultValue));
465 }
466
467 bool BooleanProperty::isBoolean() const
468 {
469     return true;
470 }
471
472 std::shared_ptr<BooleanProperty> BooleanProperty::asBoolean()
473 {
474     return shared_from_this();
475 }
476
477 void BooleanProperty::setDefaultValue(bool value)
478 {
479     m_defaultValue = value;
480 }
481
482 bool BooleanProperty::getDefaultValue() const
483 {
484     return m_defaultValue;
485 }
486
487 bool BooleanProperty::validate(const AttributeValueVariant &)
488 {
489     return true;
490 }
491
492 AttributeValueVariant BooleanProperty::buildValue()
493 {
494     return m_defaultValue;
495 }
496
497 StringProperty::StringProperty(const std::string &defaultValue)
498     : AttributeProperty(AttributeProperty::Type::STRING),
499       m_defaultValue(defaultValue),
500       m_min(0),
501       m_max(0),
502       m_hasRange(false) {}
503
504 std::shared_ptr<StringProperty> StringProperty::build(const std::string &defaultValue)
505 {
506     return std::shared_ptr<StringProperty>(new StringProperty(defaultValue));
507 }
508
509 bool StringProperty::isString() const
510 {
511     return true;
512 }
513
514 std::shared_ptr<StringProperty> StringProperty::asString()
515 {
516     return shared_from_this();
517 }
518
519 bool StringProperty::hasRange() const
520 {
521     return m_hasRange;
522 }
523
524 bool StringProperty::hasValues() const
525 {
526     return m_values.size() > 0;
527 }
528
529 std::string StringProperty::getDefaultValue() const
530 {
531     return m_defaultValue;
532 }
533
534 bool StringProperty::getRange(size_t &min, size_t &max) const
535 {
536     if (!m_hasRange)
537         return false;
538
539     min = m_min;
540     max = m_max;
541     return true;
542 }
543
544 bool StringProperty::getValues(std::vector<std::string> &values) const
545 {
546     if (!m_values.size())
547         return false;
548
549     values  = m_values;
550     return true;
551 }
552
553 void StringProperty::setDefaultValue(const std::string &value)
554 {
555     if(m_values.size() > 0
556         && m_values.end() == std::find(m_values.begin(), m_values.end(), value))
557     {
558         m_defaultValue = m_values[0];
559     }
560     else if(m_hasRange)
561     {
562         if(value.length() >= m_min && value.length() <= m_max)
563             m_defaultValue = value;
564         else
565             m_defaultValue.clear();
566     }
567     else
568         m_defaultValue = value;
569 }
570
571 void StringProperty::setRange(size_t min, size_t max)
572 {
573     m_min = min;
574     m_max = max;
575     m_hasRange = true;
576     setDefaultValue(m_defaultValue);
577 }
578
579 void StringProperty::setValues(const std::vector<std::string> &values)
580 {
581     m_values = values;
582     setDefaultValue(m_defaultValue);
583 }
584
585 bool StringProperty::validate(const AttributeValueVariant &value)
586 {
587     StringValidator stringValidator(shared_from_this());
588     return boost::apply_visitor(stringValidator, value);
589 }
590
591 bool StringProperty::validate(const std::string &value)
592 {
593     size_t length = value.length();
594     if (m_hasRange && (length < m_min || length > m_max))
595     {
596         return false;
597     }
598     else if (m_values.size() > 0)
599     {
600         if (m_values.end() == std::find(m_values.begin(), m_values.end(), value))
601         {
602             return false;
603         }
604     }
605
606     return true;
607 }
608
609 AttributeValueVariant StringProperty::buildValue()
610 {
611     return m_defaultValue;
612 }
613
614 ArrayProperty::ArrayProperty()
615     :   AttributeProperty(AttributeProperty::Type::ARRAY),
616         m_min(0),
617         m_max(0),
618         m_isVariableSize(false),
619         m_isUnique(false),
620         m_hasRange(false) {}
621
622 std::shared_ptr<ArrayProperty> ArrayProperty::build()
623 {
624     return std::shared_ptr<ArrayProperty>(new ArrayProperty());
625 }
626
627 bool ArrayProperty::isArray() const
628 {
629     return true;
630 }
631
632 std::shared_ptr<ArrayProperty> ArrayProperty::asArray()
633 {
634     return shared_from_this();
635 }
636
637 void ArrayProperty::setRange(size_t minItems, size_t maxItems)
638 {
639     m_min = minItems;
640     m_max = maxItems;
641     m_hasRange = true;
642 }
643
644 void ArrayProperty::setVariable(bool state)
645 {
646     m_isVariableSize = state;
647 }
648
649 void ArrayProperty::setUnique(bool state)
650 {
651     m_isUnique = state;
652 }
653
654 bool ArrayProperty::setElementProperty(const std::shared_ptr<AttributeProperty> &property)
655 {
656     if (!property)
657         return false;
658
659     m_elementProperty = property;
660     return true;
661 }
662
663 bool ArrayProperty::hasRange() const
664 {
665     return  m_hasRange;
666 }
667
668 bool ArrayProperty::isVariable() const
669 {
670     return m_isVariableSize;
671 }
672
673 bool ArrayProperty::isUnique() const
674 {
675     return m_isUnique;
676 }
677
678 size_t ArrayProperty::getMinItems() const
679 {
680     return m_min;
681 }
682
683 size_t ArrayProperty::getMaxItems() const
684 {
685     return m_max;
686 }
687
688 std::shared_ptr<AttributeProperty> ArrayProperty::getElementProperty()
689 {
690     return m_elementProperty;
691 }
692
693 bool ArrayProperty::validate(const AttributeValueVariant &value)
694 {
695     ArrayValidator arrayValidator(shared_from_this());
696     return boost::apply_visitor(arrayValidator, value);
697 }
698
699 AttributeValueVariant ArrayProperty::buildValue()
700 {
701     // Find the depth and element property
702     std::shared_ptr<AttributeProperty> elementProperty;
703     int depth = findDepth(elementProperty);
704
705     if (depth < 1 || depth > 3)
706     {
707         throw SimulatorException(SIMULATOR_BAD_SCHEMA,
708                                  "No support for array of depth more than 3!");
709     }
710
711     AttributeValueVariant elementValue  = elementProperty->buildValue();
712     if (elementProperty->isInteger())
713     {
714         return buildArrayValue<int>(depth, elementValue);
715     }
716     else if (elementProperty->isDouble())
717     {
718         return buildArrayValue<double>(depth, elementValue);
719     }
720     else if (elementProperty->isBoolean())
721     {
722         return buildArrayValue<bool>(depth, elementValue);
723     }
724     else if (elementProperty->isString())
725     {
726         return buildArrayValue<std::string>(depth, elementValue);
727     }
728     else if (elementProperty->isModel())
729     {
730         return buildArrayValue<SimulatorResourceModel>(depth, elementValue);
731     }
732
733     throw SimulatorException(SIMULATOR_ERROR,
734                              "Failed to build value from property of type array!");
735 }
736
737 int ArrayProperty::findDepth(std::shared_ptr<AttributeProperty> &elementProperty)
738 {
739     if (!m_elementProperty)
740     {
741         throw SimulatorException(SIMULATOR_BAD_SCHEMA, "Invalid Array property!");
742     }
743
744     if (!m_elementProperty->isArray())
745     {
746         elementProperty = m_elementProperty;
747         return 1;
748     }
749
750     return (1 + m_elementProperty->asArray()->findDepth(elementProperty));
751 }
752
753 ModelProperty::ModelProperty()
754     : AttributeProperty(AttributeProperty::Type::MODEL) {}
755
756 std::shared_ptr<ModelProperty> ModelProperty::build()
757 {
758     return std::shared_ptr<ModelProperty>(new ModelProperty());
759 }
760
761 bool ModelProperty::isModel() const
762 {
763     return true;
764 }
765
766 std::shared_ptr<ModelProperty> ModelProperty::asModel()
767 {
768     return shared_from_this();
769 }
770
771 bool ModelProperty::add(const std::string &name,
772                         const std::shared_ptr<AttributeProperty> &property, bool required)
773 {
774     if (name.empty() || !property)
775         return false;
776
777     m_childProperties[name] = property;
778     m_requiredAttributes[name] = required;
779     return true;
780 }
781
782 std::shared_ptr<AttributeProperty> ModelProperty::get(
783     const std::string &name)
784 {
785     if (m_childProperties.end() != m_childProperties.find(name))
786         return m_childProperties[name];
787     return nullptr;
788 }
789
790 std::unordered_map<std::string, std::shared_ptr<AttributeProperty> >
791 ModelProperty::getChildProperties()
792 {
793     return m_childProperties;
794 }
795
796 bool ModelProperty::isRequired(const std::string &name)
797 {
798     if (m_requiredAttributes.end() == m_requiredAttributes.find(name))
799         return false;
800
801     return m_requiredAttributes[name];
802 }
803
804 void ModelProperty::remove(const std::string &name)
805 {
806     if (m_requiredAttributes.end() != m_requiredAttributes.find(name))
807         m_requiredAttributes.erase(m_requiredAttributes.find(name));
808
809     if (m_childProperties.end() != m_childProperties.find(name))
810         m_childProperties.erase(m_childProperties.find(name));
811 }
812
813 void ModelProperty::setRequired(const std::string &name)
814 {
815     if (m_requiredAttributes.end() != m_requiredAttributes.find(name))
816         m_requiredAttributes[name] = true;
817 }
818
819 void ModelProperty::unsetRequired(const std::string &name)
820 {
821     if (m_requiredAttributes.end() != m_requiredAttributes.find(name))
822         m_requiredAttributes[name] = false;
823 }
824
825 bool ModelProperty::validate(const AttributeValueVariant &value)
826 {
827     ModelValidator modelValidator(shared_from_this());
828     return boost::apply_visitor(modelValidator, value);
829 }
830
831 bool ModelProperty::validate(const SimulatorResourceModel &model)
832 {
833     for (auto &attributeEntry : model.getAttributeValues())
834     {
835         std::shared_ptr<AttributeProperty> childProperty = get(attributeEntry.first);
836         if (childProperty)
837         {
838             if (!childProperty->validate(attributeEntry.second))
839                 return false;
840         }
841     }
842
843     return true;
844 }
845
846 AttributeValueVariant ModelProperty::buildValue()
847 {
848     return buildResourceModel();
849 }
850
851 SimulatorResourceModel ModelProperty::buildResourceModel()
852 {
853     SimulatorResourceModel resourceModel;
854     for (auto &propertyElement : m_childProperties)
855     {
856         resourceModel.add(propertyElement.first, (propertyElement.second)->buildValue());
857     }
858
859     return resourceModel;
860 }