ambd: remove redundant code in core
[profile/ivi/automotive-message-broker.git] / lib / abstractpropertytype.h
1 /*
2         Copyright (C) 2012  Intel Corporation
3
4         This library is free software; you can redistribute it and/or
5         modify it under the terms of the GNU Lesser General Public
6         License as published by the Free Software Foundation; either
7         version 2.1 of the License, or (at your option) any later version.
8
9         This library is distributed in the hope that it will be useful,
10         but WITHOUT ANY WARRANTY; without even the implied warranty of
11         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12         Lesser General Public License for more details.
13
14         You should have received a copy of the GNU Lesser General Public
15         License along with this library; if not, write to the Free Software
16         Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19 #ifndef _ABSTRACTPROPERTYTYPE_H_
20 #define _ABSTRACTPROPERTYTYPE_H_
21
22 #include <string>
23 #include <sstream>
24 #include <stdexcept>
25 #include <vector>
26 #include <iostream>
27 #include <memory>
28 #include <boost/any.hpp>
29 #include <boost/lexical_cast.hpp>
30 #include <boost/utility.hpp>
31 #include <type_traits>
32 #include <glib.h>
33 #include <list>
34 #include "timestamp.h"
35 #include <debugout.h>
36 #include <boost/algorithm/string.hpp>
37 #include <superptr.hpp>
38
39 class Zone {
40
41 public:
42
43         typedef int Type;
44
45         enum {
46                 None = 0,
47                 Front = 1,
48                 Middle = 1 << 1,
49                 Right = 1 << 2,
50                 Left = 1 << 3,
51                 Rear = 1 << 4,
52                 Center = 1 << 5,
53                 LeftSide = 1 << 6,
54                 RightSide = 1 << 7,
55                 FrontSide = 1 << 8,
56                 BackSide = 1 << 9
57         };
58
59 static const Zone::Type FrontRight;
60 static const Zone::Type FrontLeft;
61 static const Zone::Type MiddleRight;
62 static const Zone::Type MiddleLeft;
63 static const Zone::Type RearRight;
64 static const Zone::Type RearLeft;
65
66 typedef std::vector<Zone::Type> ZoneList;
67
68 };
69
70 class AbstractPropertyType
71 {
72 public:
73
74         /*!
75          * \brief The Priority enum describes prority of the property type.
76          */
77         enum Priority
78         {
79                 /*!< normal priority.  This is default */
80                 Normal = 0,
81                 /*!< Low priority. */
82                 Low,
83                 /*!< High priority*/
84                 High,
85                 /*!< Instant.  Using this priority is not thread safe.  This is typically used for
86                  *    Properties that need to be deterministic.
87                  */
88                 Instant
89         };
90
91         AbstractPropertyType(std::string property)
92                 : name(property), timestamp(amb::currentTime()), sequence(-1), zone(Zone::None), priority(Normal)
93         {
94
95         }
96
97         virtual ~AbstractPropertyType()
98         {
99                 for(auto i : destroyed)
100                 {
101                         if(i) i(this);
102                 }
103         }
104
105         /**
106          * @brief toString
107          * @return strigified value
108          */
109         virtual std::string toString() const = 0;
110
111         /**
112          * @brief fromString converts from string value
113          */
114         virtual void fromString(std::string)= 0;
115
116         /**
117          * @brief toVariant
118          * @return GVariant representation of value. Caller must unref the returned GVariant
119          */
120         virtual GVariant* toVariant() = 0;
121
122         /**
123          * @brief fromVariant converts GVariant value into compatible native value.  Caller owns
124          * GVariant argument.
125          */
126         virtual void fromVariant(GVariant*) = 0;
127
128         /**
129          * @brief copy
130          * @return a copy of the AbstractPropertyType
131          */
132         virtual AbstractPropertyType* copy() = 0;
133
134         /**
135          * @brief quickCopy is intended as a way to quickly copy the often changing bits from one abstract property to another
136          * It assumes that the properties are almost identical in name, source, and zone.
137          * @param other the property to copy from
138          */
139         virtual void quickCopy(AbstractPropertyType* other)
140         {
141                 sequence = other->sequence;
142                 mValue = other->anyValue();
143                 timestamp = other->timestamp;
144         }
145
146         bool operator == (AbstractPropertyType &other)
147         {
148                 std::string one = toString();
149                 std::string two = other.toString();
150                 return one == two
151                                 && zone == other.zone
152                                 && sourceUuid == other.sourceUuid
153                                 && name == other.name;
154         }
155
156         bool operator != (AbstractPropertyType &other)
157         {
158                 std::string one = toString();
159                 std::string two = other.toString();
160                 return one != two;
161         }
162
163         /**
164          * @brief name Property name. @see VehicleProperty for built-in supported property names
165          */
166         std::string name;
167
168         /**
169          * @brief timestamp.  Timestamp when the value was last updated by the system. This is updated automatically
170          * any time setValue() is called
171          * @see amb::currentTime()
172          * @see setValue()
173          */
174         double timestamp;
175
176         /**
177          * @brief sequence internal counter.  Useful as a unique indentifier.  values is -1 if not used (default).
178          */
179         int32_t sequence;
180
181         /**
182          * @brief sourceUuid  uuid of the source that produced this property.  This is set by the routingengine
183          * if left unmodified.
184          */
185         std::string sourceUuid;
186
187         /**
188          * @brief zone that the property is situated in.
189          */
190         Zone::Type zone;
191
192         /*!
193          * \brief priority is used to tell the routing engine how to prioritize routing the value to plugins.
194          * setting this value to AbstractPropertyType::Instant will tell the routing engine to immedietly
195          * route the value without any reliance on the mainloop.  Instant priority is NOT thread safe.
196          * Default priority is AbstractPropertyType::Normal.
197          */
198         Priority priority;
199
200         /**
201          * @brief setValue
202          * @param val boost::any value.  NOTE: boost::any does not accept type coercion.  Types must match exactly
203          * with native type. (ie, don't use "int" if the native type is "uint")
204          */
205         virtual void setValue(boost::any val)
206         {
207                 mValue = val;
208                 timestamp = amb::currentTime();
209         }
210
211         /**
212          * \brief value() native value.  Does not use type coercion.  Will throw if types do not match.
213          */
214         template <typename T>
215         T value() const
216         {
217                 return boost::any_cast<T>(mValue);
218         }
219
220         /**
221          * @brief anyValue
222          * @return boost::any value
223          */
224         boost::any anyValue()
225         {
226                 return mValue;
227         }
228
229         /*!
230          * \brief signature
231          * \return gvariant signature
232          */
233         virtual const string signature()
234         {
235                 auto var = amb::make_super(toVariant());
236                 if(!var) return "";
237
238                 const string s = g_variant_get_type_string(var.get());
239
240                 DebugOut() << "returning signature: " << s << " for "<< name << endl;
241
242                 return s;
243         }
244
245         /**
246          * @brief destroyed is called if this property is destroyed.
247          */
248         std::vector<std::function<void(AbstractPropertyType*)>> destroyed;
249
250 protected:
251
252         boost::any mValue;
253
254 };
255
256 namespace amb
257 {
258
259 struct PropertyCompare
260 {
261         bool operator()(AbstractPropertyType* const & lhs, AbstractPropertyType* & rhs) const
262         {
263                 if (lhs->name == rhs->name
264                                 && lhs->sourceUuid == rhs->sourceUuid
265                                 && lhs->zone == rhs->zone)
266                 {
267                         return true;
268                 }
269
270                 return false;
271         }
272
273 };
274
275 }
276
277
278 template <typename T>
279 class GVS;
280
281 template <>
282 class GVS<int>
283 {
284 public:
285         static const char* signature() { return "i"; }
286
287         static int value(GVariant* v)
288         {
289                 int val = 0;
290                 g_variant_get(v, signature(), &val);
291                 return val;
292         }
293
294         static std::string stringize(std::string v)
295         {
296                 return v;
297         }
298 };
299
300 template <>
301 class GVS<double>
302 {
303 public:
304         static const char* signature() { return "d"; }
305
306         static double value(GVariant* v)
307         {
308                 return g_variant_get_double(v);
309         }
310         static std::string stringize(std::string v)
311         {
312                 return v;
313         }
314 };
315
316 template <>
317 class GVS<uint16_t>
318 {
319 public:
320         static const char* signature() { return "q"; }
321
322         static uint16_t value(GVariant* v)
323         {
324                 return g_variant_get_uint16(v);
325         }
326         static std::string stringize(std::string v)
327         {
328                 return v;
329         }
330 };
331
332 template <>
333 class GVS<int16_t>
334 {
335 public:
336         static const char* signature() { return "n"; }
337
338         static int16_t value(GVariant* v)
339         {
340                 return g_variant_get_int16(v);
341         }
342         static std::string stringize(std::string v)
343         {
344                 return v;
345         }
346 };
347
348 template <>
349 class GVS<char>
350 {
351 public:
352         static const char* signature() { return "y"; }
353
354         static char value(GVariant* v)
355         {
356                 return g_variant_get_byte(v);
357         }
358         static std::string stringize(std::string v)
359         {
360                 return v;
361         }
362 };
363
364 template <>
365 class GVS<uint32_t>
366 {
367 public:
368         static const char* signature() { return "u"; }
369
370         static uint32_t value(GVariant* v)
371         {
372                 return g_variant_get_uint32(v);
373         }
374         static std::string stringize(std::string v)
375         {
376                 return v;
377         }
378 };
379
380 template <>
381 class GVS<int64_t>
382 {
383 public:
384         static const char* signature() { return "x"; }
385
386         static int64_t value(GVariant* v)
387         {
388                 return g_variant_get_int64(v);
389         }
390         static std::string stringize(std::string v)
391         {
392                 return v;
393         }
394 };
395
396 template <>
397 class GVS<uint64_t>
398 {
399 public:
400         static const char* signature() { return "t"; }
401
402         static uint64_t value(GVariant* v)
403         {
404                 return g_variant_get_uint64(v);
405         }
406         static std::string stringize(std::string v)
407         {
408                 return v;
409         }
410 };
411
412 template <>
413 class GVS<bool>
414 {
415 public:
416         static const char* signature() { return "b"; }
417
418         static bool value(GVariant *v)
419         {
420                 return g_variant_get_boolean(v);
421         }
422         static std::string stringize(std::string v)
423         {
424                 if(v == "0" || v == "1")
425                         return v;
426
427                 boost::algorithm::to_lower(v);
428                 return v == "true" ? "1":"0";
429         }
430 };
431
432 /**
433  * \brief BasicPropertyType is a typed property type.  Most internal types are derived from this class
434  * \example
435  * std::unique_ptr<BasicPropertyType<int>> boostPSI = new BasicPropertyType<int>("BoostPSI",5);
436  * boostPSI->priority = AbstractPropertyType::Instant; //set instant because we clean up right after.
437  * routingEngine->updateProperty(boostPSI.get(), sourceUuid());
438  */
439 template <typename T>
440 class BasicPropertyType: public AbstractPropertyType
441 {
442 public:
443         BasicPropertyType(): AbstractPropertyType("")
444         {
445                 mValue = T();
446         }
447
448         BasicPropertyType(BasicPropertyType const & other)
449                 :AbstractPropertyType(other.name)
450         {
451                 setValue(other.value<T>());
452                 timestamp = other.timestamp;
453                 sequence = other.sequence;
454                 sourceUuid = other.sourceUuid;
455                 name = other.name;
456                 zone = other.zone;
457
458         }
459
460         BasicPropertyType & operator = (BasicPropertyType const & other)
461         {
462                 setValue(other.value<T>());
463                 timestamp = other.timestamp;
464                 sequence = other.sequence;
465                 sourceUuid = other.sourceUuid;
466                 name = other.name;
467                 zone = other.zone;
468
469                 return *this;
470         }
471
472         BasicPropertyType & operator = (T const & other)
473         {
474                 setValue(other);
475                 return *this;
476         }
477
478         BasicPropertyType & operator ++ ()
479         {
480                 setValue(basicValue() + 1);
481         }
482
483         BasicPropertyType & operator -- ()
484         {
485                 setValue(basicValue() - 1);
486         }
487
488         bool operator < (const BasicPropertyType<T>& other) const
489         {
490                 return value<T>() < other.value<T>();
491         }
492
493         bool operator > (const BasicPropertyType<T>& other) const
494         {
495                 return value<T>() > other.value<T>();
496         }
497
498         BasicPropertyType( T val)
499                 :AbstractPropertyType("")
500         {
501                 setValue(val);
502         }
503
504         BasicPropertyType( std::string propertyName, T val)
505                 :AbstractPropertyType(propertyName)
506         {
507                 setValue(val);
508         }
509
510         BasicPropertyType( std::string propertyName, std::string val)
511                 :AbstractPropertyType(propertyName)
512         {
513                 if(!val.empty() && val != "")
514                 {
515                         serialize<T>(val);
516                 }
517                 else setValue(T());
518         }
519
520         BasicPropertyType(std::string propertyName)
521                 :AbstractPropertyType(propertyName)
522         {
523                 mValue = T();
524         }
525
526         AbstractPropertyType* copy()
527         {
528                 return new BasicPropertyType<T>(*this);
529         }
530
531         void fromString(std::string val)
532         {
533                 if(!val.empty() && val != "")
534                 {
535                         serialize<T>(val);
536                 }
537         }
538
539         std::string toString() const
540         {
541                 std::stringstream stream;
542                 stream.precision(10);
543                 stream<<value<T>();
544
545                 return stream.str();
546         }
547
548         GVariant* toVariant()
549         {
550                 return serializeVariant<T>(value<T>());
551         }
552
553         void fromVariant(GVariant *v)
554         {
555                 setValue(deserializeVariant<T>(v));
556         }
557
558         /**
559          * @brief basicValue
560          * @return Typed version of value.  Slightly more useful than @see AbstractPropertyType::value()
561          */
562
563         T basicValue()
564         {
565                 return value<T>();
566         }
567
568         void setValue(T val)
569         {
570                 AbstractPropertyType::setValue(val);
571         }
572
573         void setValue(boost::any val)
574         {
575                 AbstractPropertyType::setValue(val);
576         }
577
578 private:
579
580         //GVariant* mVariant;
581
582         template <class N>
583         void serialize(std::string val,  typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
584         {
585                 int someTemp;
586
587                 std::stringstream stream(val);
588
589                 stream>>someTemp;
590                 setValue((N)someTemp);
591         }
592
593         template <class N>
594         void serialize(std::string  val,  typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
595         {
596                 std::stringstream stream(GVS<T>::stringize(val));
597                 N someTemp;
598                 stream>>someTemp;
599                 setValue(someTemp);
600         }
601
602         template <class N>
603         GVariant* serializeVariant(T val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
604         {
605                 //mVariant = Glib::VariantBase(Glib::Variant<gint16>::create((int)val).gobj());
606
607                 return (g_variant_new("i",(int)val));
608         }
609
610         template <class N>
611         GVariant* serializeVariant(T val, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
612         {
613                 //mVariant = Glib::Variant<T>::create(val);
614                 //mVariant = g_variant_ref(g_variant_new(GVS<T>::signature(),val));
615                 return g_variant_new(GVS<T>::signature(),val);
616         }
617
618         template <class N>
619         T deserializeVariant(GVariant* v, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
620         {
621 //              return (T)((Glib::Variant<int>::cast_dynamic<Glib::Variant<int> >(*v)).get());
622
623                 return (T)GVS<int>::value(v);
624         }
625
626         template <class N>
627         T deserializeVariant(GVariant* v, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
628         {
629                 //      return Glib::VariantBase::cast_dynamic<Glib::Variant<T> >(*v).get();
630                 return GVS<T>::value(v);
631         }
632 };
633
634 class StringPropertyType: public AbstractPropertyType
635 {
636 public:
637
638
639         StringPropertyType()
640                 :AbstractPropertyType("")
641         {
642                 setValue(std::string());
643         }
644
645         StringPropertyType(std::string propertyName)
646                 :AbstractPropertyType(propertyName)
647         {
648                 setValue(std::string());
649         }
650
651         StringPropertyType(std::string propertyName, std::string val)
652                 :AbstractPropertyType(propertyName)
653         {
654                 setValue(val);
655         }
656
657         StringPropertyType(StringPropertyType const & other)
658         :AbstractPropertyType(other.name)
659         {
660                 setValue(other.value<std::string>());
661                 timestamp = other.timestamp;
662                 sequence = other.sequence;
663                 sourceUuid = other.sourceUuid;
664                 name = other.name;
665                 zone = other.zone;
666         }
667
668         StringPropertyType & operator = (StringPropertyType const & other)
669         {
670                 setValue(other.value<std::string>());
671                 timestamp = other.timestamp;
672                 sequence = other.sequence;
673                 sourceUuid = other.sourceUuid;
674                 name = other.name;
675                 zone = other.zone;
676
677                 return *this;
678         }
679
680         StringPropertyType & operator = (std::string const & other)
681         {
682                 setValue(std::string(other));
683                 return *this;
684         }
685
686         bool operator < (const StringPropertyType& other) const
687         {
688                 return value<std::string>() < other.value<std::string>();
689         }
690
691
692         void fromString(std::string val)
693         {
694                 setValue(val);
695         }
696
697         AbstractPropertyType* copy()
698         {
699                 return new StringPropertyType(*this);
700         }
701
702         std::string toString() const
703         {
704                 return value<std::string>();
705         }
706
707         GVariant* toVariant()
708         {
709                 //mVariant = Glib::Variant<std::string>::create(toString());
710
711                 return g_variant_new_string(toString().c_str());
712
713         }
714
715         void fromVariant(GVariant *v)
716         {
717                 setValue(std::string(g_variant_get_string(v,NULL)));
718         }
719 };
720
721 /*!
722  * \brief ListPropertyType is a AbstractPropertyType for arrays of AbstractPropertyTypes
723  */
724 template <class T = AbstractPropertyType>
725 class ListPropertyType: public AbstractPropertyType
726 {
727 public:
728
729         ListPropertyType(std::string propertyName)
730                 : AbstractPropertyType(propertyName), initialized(false)
731         {
732
733         }
734
735         ListPropertyType(std::string propertyName, T value)
736                 : AbstractPropertyType(propertyName), initialized(false)
737         {
738                 appendPriv(value);
739         }
740
741         ListPropertyType(ListPropertyType & other)
742                 :AbstractPropertyType(other.name),initialized(false)
743         {
744                 std::vector<T> l = other.list();
745                 for(auto i : l)
746                 {
747                         append(i);
748                 }
749
750                 timestamp = other.timestamp;
751                 sequence = other.sequence;
752                 sourceUuid = other.sourceUuid;
753                 name = other.name;
754                 zone = other.zone;
755         }
756
757         ~ListPropertyType()
758         {
759                 clear();
760         }
761
762         /** \brief append - appends a property to the list
763          * @arg property - property to be appended.
764          **/
765         void append(T property)
766         {
767                 if(!initialized)
768                 {
769                         mList.clear();
770                         initialized = true;
771                 }
772
773                 appendPriv(property);
774         }
775
776         uint count()
777         {
778                 return mList.size();
779         }
780
781         AbstractPropertyType* copy()
782         {
783                 return new ListPropertyType(*this);
784         }
785
786         void quickCopy(AbstractPropertyType* other)
787         {
788                 AbstractPropertyType::quickCopy(other);
789                 ListPropertyType<T>* v = static_cast<ListPropertyType<T>*>(other);
790                 if(!v)
791                 {
792                         DebugOut(DebugOut::Error) << "ListPropertyType Quick Copy failed" << endl;
793                         return;
794                 }
795                 mList = v->list();
796         }
797
798         std::string toString() const
799         {
800                 std::string str = "[";
801
802                 for(auto itr = mList.begin(); itr != mList.end(); itr++)
803                 {
804                         if(str != "[")
805                                 str += ",";
806
807                         T t = *itr;
808
809                         str += t.toString();
810                 }
811
812                 str += "]";
813
814                 return str;
815         }
816
817
818         void fromString(std::string str )
819         {
820                 clear();
821
822                 if(!str.length())
823                         return;
824
825                 if(str[0] == '[' && str[str.length()-1] == ']')
826                 {
827                         str = str.substr(1,str.length() - 2);
828                 }
829
830                 std::vector<std::string> elements;
831
832                 std::istringstream f(str);
833
834                 std::string element;
835                 while(std::getline(f,element,','))
836                 {
837                         T foo("", element);
838                         append (foo);
839                 }
840                 timestamp = amb::currentTime();
841         }
842
843
844         GVariant* toVariant()
845         {
846
847                 GVariantBuilder params;
848                 g_variant_builder_init(&params, ((const GVariantType *) "av"));
849
850                 for(auto itr = mList.begin(); itr != mList.end(); itr++)
851                 {
852                         T t = *itr;
853                         auto var = t.toVariant();
854                         GVariant *newvar = g_variant_new("v", var);
855                         g_variant_builder_add_value(&params, newvar);
856                 }
857
858                 GVariant* var =  g_variant_builder_end(&params);
859                 g_assert(var);
860                 return var;
861
862         }
863
864         void fromVariant(GVariant* v)
865         {
866                 clear();
867
868                 /// TODO: fill this in
869                 gsize dictsize = g_variant_n_children(v);
870                 for (int i=0;i<dictsize;i++)
871                 {
872                         GVariant *childvariant = g_variant_get_child_value(v,i);
873                         GVariant *innervariant = g_variant_get_variant(childvariant);
874                         T t;
875                         t.fromVariant(innervariant);
876                         appendPriv(t);
877                 }
878         }
879
880         std::vector<T> list() { return mList; }
881
882 private:
883
884         void clear()
885         {
886                 mList.clear();
887         }
888
889         void appendPriv(T i)
890         {
891                 mList.push_back(i);
892         }
893
894         bool initialized;
895
896         std::vector<T> mList;
897 };
898
899 #endif