bugfix about AirDistribution
[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 "debugout.h"
23 #include "jsonhelper.h"
24 #include "picojson.h"
25 #include "superptr.hpp"
26 #include "timestamp.h"
27 #include "valuequality.h"
28
29 #include <boost/algorithm/string.hpp>
30 #include <boost/any.hpp>
31 #include <boost/lexical_cast.hpp>
32 #include <boost/utility.hpp>
33 #include <iostream>
34 #include <list>
35 #include <memory>
36 #include <string>
37 #include <sstream>
38 #include <stdexcept>
39 #include <type_traits>
40 #include <vector>
41
42 #include <glib.h>
43
44 class Zone {
45
46 public:
47
48         typedef int Type;
49
50         enum {
51                 None = 0,
52                 Front = 1,
53                 Middle = 1 << 1,
54                 Right = 1 << 2,
55                 Left = 1 << 3,
56                 Rear = 1 << 4,
57                 Center = 1 << 5,
58                 LeftSide = 1 << 6,
59                 RightSide = 1 << 7,
60                 FrontSide = 1 << 8,
61                 BackSide = 1 << 9
62         };
63
64 static const Zone::Type FrontRight;
65 static const Zone::Type FrontLeft;
66 static const Zone::Type MiddleRight;
67 static const Zone::Type MiddleLeft;
68 static const Zone::Type RearRight;
69 static const Zone::Type RearLeft;
70
71 typedef std::vector<Zone::Type> ZoneList;
72
73 };
74
75 class AbstractPropertyType
76 {
77 public:
78
79         /*!
80          * \brief The Priority enum describes prority of the property type.
81          */
82         enum Priority
83         {
84                 /*!< normal priority.  This is default */
85                 Normal = 0,
86                 /*!< Low priority. */
87                 Low,
88                 /*!< High priority*/
89                 High,
90                 /*!< Instant.  Using this priority is not thread safe.  This is typically used for
91                  *    Properties that need to be deterministic.
92                  */
93                 Instant
94         };
95
96         AbstractPropertyType(std::string property)
97                 : name(property), timestamp(amb::currentTime()), sequence(-1), zone(Zone::None), priority(Normal),
98                   internalUpdate(false), valueQuality(amb::Quality::UncertainInitialValue)
99         {
100
101         }
102
103         virtual ~AbstractPropertyType()
104         {
105                 for(auto i : destroyed)
106                 {
107                         if(i) i(this);
108                 }
109         }
110
111         /*!
112          * \brief toJson convert this type to json representation.
113          * The json typically looks something like this:
114          * \code
115          * {
116          *  "name" : "VehicleSpeed",
117          *  "type" : "UInt16",
118          *  "source" : "daf23v32342ddsdffafaeefe",
119          *  "zone" : 0,
120          *  "value" : 25
121          * }
122          * \endcode
123          * \return json value representing the type
124          */
125         virtual const picojson::value toJson();
126
127         /*!
128          * \brief fromJson instantiate this type from json
129          * \param json
130          */
131         virtual void fromJson(const picojson::value & json);
132
133         /*!
134          * \brief toString
135          * \return strigified value
136          */
137         virtual std::string toString() const = 0;
138
139         /*!
140          * \brief fromString converts from string value
141          */
142         virtual void fromString(std::string) = 0;
143
144         /*!
145          * \brief toVariant
146          * \return GVariant representation of value. Caller must unref the returned GVariant
147          */
148         virtual GVariant* toVariant() = 0;
149
150         /*!
151          * \brief fromVariant converts GVariant value into compatible native value.  Caller owns
152          * GVariant argument.
153          */
154         virtual void fromVariant(GVariant*) = 0;
155
156         /*!
157          * \brief copy
158          * \return a copy of the AbstractPropertyType
159          */
160         virtual AbstractPropertyType* copy() = 0;
161
162         /*!
163          * \brief quickCopy is intended as a way to quickly copy the often changing bits from one abstract property to another
164          * It assumes that the properties are almost identical in name, source, and zone.
165          * \param other the property to copy from
166          */
167         virtual void quickCopy(AbstractPropertyType* other)
168         {
169                 sequence = other->sequence;
170                 mValue = other->anyValue();
171                 timestamp = other->timestamp;
172         }
173
174         bool operator == (AbstractPropertyType &other)
175         {
176                 std::string one = toString();
177                 std::string two = other.toString();
178                 return one == two
179                                 && zone == other.zone
180                                 && sourceUuid == other.sourceUuid
181                                 && name == other.name;
182         }
183
184         bool operator != (AbstractPropertyType &other)
185         {
186                 std::string one = toString();
187                 std::string two = other.toString();
188                 return one != two;
189         }
190
191         /*!
192          * \brief name Property name. \see VehicleProperty for built-in supported property names
193          */
194         std::string name;
195
196         /*!
197          * \brief alias for the property name
198          * \return alias or \ref name if alias has not been set
199          */
200         const std::string alias() { return mAlias.empty() ? name : mAlias; }
201
202         /*!
203          * \brief setAlias sets the alias name for a property
204          * This may be useful for implementing standards where the standard name differs from the internal AMB \ref name
205          * \param a name of alias
206          */
207         void setAlias(const std::string & a) { mAlias = a; }
208
209         /*!
210          * \brief timestamp.  Timestamp when the value was last updated by the system. This is updated automatically
211          * any time setValue() is called
212          * \see amb::currentTime()
213          * \see setValue()
214          */
215         double timestamp;
216
217         /*!
218          * \brief sequence internal counter.  Useful as a unique indentifier.  values is -1 if not used (default).
219          */
220         int32_t sequence;
221
222         /*!
223          * \brief sourceUuid  uuid of the source that produced this property.  This is set by the routingengine
224          * if left unmodified.
225          */
226         std::string sourceUuid;
227
228         /*!
229          * \brief zone that the property is situated in.
230          */
231         Zone::Type zone;
232
233         /*!
234          * \brief priority is used to tell the routing engine how to prioritize routing the value to plugins.
235          * setting this value to AbstractPropertyType::Instant will tell the routing engine to immedietly
236          * route the value without any reliance on the mainloop.  Instant priority is NOT thread safe.
237          * Default priority is AbstractPropertyType::Normal.
238          */
239         Priority priority;
240
241     /*!
242      * \brief internalUpdate is used to update the property value of AMB internally
243      * without calling its related callback functions.  Default value is false.
244      */
245         bool internalUpdate;
246
247         /*!
248          * \brief valueQuality is used to indicate the quality of the value
249          * Each AMB property is given a default value.  valueQuality is a way to describe whether the value
250          * is the default one and the system has not yet provided a valid value, bad if an error occured, or
251          * good.
252          *
253          * The default value for this is \ref amb::Quality::UncertainInitialValue indicating that the amb property value is the
254          * default value.  When \ref AbastractPropertyType::setValue is called, valueQuality is set to "Good" automatically.
255          *
256          * TODO: this may be able to provide a replacement for set and get error codes: \ref AsyncPropertyReply::Error
257          */
258         amb::Quality::ValueQuality valueQuality;
259
260         /*!
261          * \brief setValue
262          * \param val boost::any value.  NOTE: boost::any does not accept type coercion.  Types must match exactly
263          * with native type. (ie, don't use "int" if the native type is "uint")
264          */
265         virtual void setValue(boost::any val)
266         {
267                 mValue = val;
268                 timestamp = amb::currentTime();
269                 valueQuality = amb::Quality::Good;
270         }
271
272         /*!
273          * \brief value() native value.  Does not use type coercion.  Will throw if types do not match.
274          */
275         template <typename T>
276         T value() const
277         {
278                 return boost::any_cast<T>(mValue);
279         }
280
281         /*!
282          * \brief anyValue
283          * \return boost::any value
284          */
285         boost::any anyValue()
286         {
287                 return mValue;
288         }
289
290         /*!
291          * \brief signature
292          * \return gvariant signature
293          */
294         virtual const string signature()
295         {
296                 auto var = amb::make_super(toVariant());
297                 if(!var) return "";
298
299                 const string s = g_variant_get_type_string(var.get());
300                 return s;
301         }
302
303         /*!
304          * \brief destroyed is called if this property is destroyed.
305          */
306         std::vector<std::function<void(AbstractPropertyType*)>> destroyed;
307
308 protected:
309
310         boost::any mValue;
311
312         std::string mAlias;
313 };
314
315 namespace amb
316 {
317
318 struct PropertyCompare
319 {
320         bool operator()(AbstractPropertyType* const & lhs, AbstractPropertyType* & rhs) const
321         {
322                 if (lhs->name == rhs->name
323                                 && lhs->sourceUuid == rhs->sourceUuid
324                                 && lhs->zone == rhs->zone)
325                 {
326                         return true;
327                 }
328
329                 return false;
330         }
331
332 };
333
334 }
335
336
337 class JsonNumber
338 {
339 public:
340         static double fromJson(picojson::value v)
341         {
342                 return v.get<double>();
343         }
344
345         static picojson::value toJson(double v)
346         {
347                 return picojson::value(v);
348         }
349 };
350
351 class JsonBoolean
352 {
353 public:
354         static bool fromJson(picojson::value v)
355         {
356                 return v.get<bool>();
357         }
358
359         static picojson::value toJson(bool v)
360         {
361                 return picojson::value(v);
362         }
363 };
364
365 class JsonString
366 {
367 public:
368         static std::string fromJson(picojson::value v)
369         {
370                 return v.get<std::string>();
371         }
372
373         static picojson::value toJson(std::string v)
374         {
375                 return picojson::value(v);
376         }
377 };
378
379
380 template <typename T>
381 class BaseGVS
382 {
383 public:
384         static T gvalue(T t)
385         {
386                 return t;
387         }
388 };
389
390 template <typename T>
391 class GVS;
392
393 template <>
394 class GVS<int> : public BaseGVS<int>, public JsonNumber
395 {
396 public:
397         static const char* signature() { return "i"; }
398
399         static int value(GVariant* v)
400         {
401                 int val = 0;
402                 g_variant_get(v, signature(), &val);
403                 return val;
404         }
405
406         static std::string stringize(std::string v)
407         {
408                 return v;
409         }
410 };
411
412 template <>
413 class GVS<double> : public BaseGVS<double>, public JsonNumber
414 {
415 public:
416         static const char* signature() { return "d"; }
417
418         static double value(GVariant* v)
419         {
420                 return g_variant_get_double(v);
421         }
422         static std::string stringize(std::string v)
423         {
424                 return v;
425         }
426 };
427
428 template <>
429 class GVS<uint16_t> : public BaseGVS<uint16_t>, public JsonNumber
430 {
431 public:
432         static const char* signature() { return "q"; }
433
434         static uint16_t value(GVariant* v)
435         {
436                 return g_variant_get_uint16(v);
437         }
438         static std::string stringize(std::string v)
439         {
440                 return v;
441         }
442 };
443
444 template <>
445 class GVS<int16_t> : public BaseGVS<int16_t>, public JsonNumber
446 {
447 public:
448         static const char* signature() { return "n"; }
449
450         static int16_t value(GVariant* v)
451         {
452                 return g_variant_get_int16(v);
453         }
454         static std::string stringize(std::string v)
455         {
456                 return v;
457         }
458 };
459
460 template <>
461 class GVS<char> : public BaseGVS<char>, public JsonNumber
462 {
463 public:
464         static const char* signature() { return "y"; }
465
466         static char value(GVariant* v)
467         {
468                 return g_variant_get_byte(v);
469         }
470         static std::string stringize(std::string v)
471         {
472                 return v;
473         }
474 };
475
476 template <>
477 class GVS<uint32_t> : public BaseGVS<uint32_t>, public JsonNumber
478 {
479 public:
480         static const char* signature() { return "u"; }
481
482         static uint32_t value(GVariant* v)
483         {
484                 return g_variant_get_uint32(v);
485         }
486         static std::string stringize(std::string v)
487         {
488                 return v;
489         }
490 };
491
492 template <>
493 class GVS<int64_t> : public BaseGVS<int64_t>, public JsonNumber
494 {
495 public:
496         static const char* signature() { return "x"; }
497
498         static int64_t value(GVariant* v)
499         {
500                 return g_variant_get_int64(v);
501         }
502         static std::string stringize(std::string v)
503         {
504                 return v;
505         }
506 };
507
508 template <>
509 class GVS<uint64_t> : public BaseGVS<uint64_t>, public JsonNumber
510 {
511 public:
512         static const char* signature() { return "t"; }
513
514         static uint64_t value(GVariant* v)
515         {
516                 return g_variant_get_uint64(v);
517         }
518         static std::string stringize(std::string v)
519         {
520                 return v;
521         }
522 };
523
524 template <>
525 class GVS<bool> : public BaseGVS<bool>, public JsonBoolean
526 {
527 public:
528         static const char* signature() { return "b"; }
529
530         static bool value(GVariant *v)
531         {
532                 return g_variant_get_boolean(v);
533         }
534         static std::string stringize(std::string v)
535         {
536                 if(v == "0" || v == "1")
537                         return v;
538
539                 boost::algorithm::to_lower(v);
540                 return v == "true" ? "1":"0";
541         }
542 };
543
544 template <>
545 class GVS<std::string> : public JsonString
546 {
547 public:
548         static const char* signature() { return "s"; }
549
550         static const char* value(GVariant *v)
551         {
552                 return g_variant_get_string(v, nullptr);
553         }
554         static std::string stringize(std::string v)
555         {
556                 return v;
557         }
558         static const char* gvalue(std::string v)
559         {
560                 return v.c_str();
561         }
562 };
563
564 /*!
565  * \brief BasicPropertyType is a typed property type.  Most internal types are derived from this class
566  * \example
567  * std::unique_ptr<BasicPropertyType<int>> boostPSI = new BasicPropertyType<int>("BoostPSI",5);
568  * boostPSI->priority = AbstractPropertyType::Instant; //set instant because we clean up right after.
569  * routingEngine->updateProperty(boostPSI.get(), sourceUuid());
570  */
571 template <typename T>
572 class BasicPropertyType: public AbstractPropertyType
573 {
574 public:
575         BasicPropertyType(): AbstractPropertyType("")
576         {
577                 mValue = T();
578         }
579
580         BasicPropertyType(BasicPropertyType const & other)
581                 :AbstractPropertyType(other.name)
582         {
583                 setValue(other.value<T>());
584                 timestamp = other.timestamp;
585                 sequence = other.sequence;
586                 sourceUuid = other.sourceUuid;
587                 name = other.name;
588                 zone = other.zone;
589
590         }
591
592         BasicPropertyType & operator = (BasicPropertyType const & other)
593         {
594                 setValue(other.value<T>());
595                 timestamp = other.timestamp;
596                 sequence = other.sequence;
597                 sourceUuid = other.sourceUuid;
598                 name = other.name;
599                 zone = other.zone;
600
601                 return *this;
602         }
603
604         BasicPropertyType & operator = (T const & other)
605         {
606                 setValue(other);
607                 return *this;
608         }
609
610         BasicPropertyType & operator ++ ()
611         {
612                 setValue(basicValue() + 1);
613         }
614
615         BasicPropertyType & operator -- ()
616         {
617                 setValue(basicValue() - 1);
618         }
619
620         bool operator < (const BasicPropertyType<T>& other) const
621         {
622                 return value<T>() < other.value<T>();
623         }
624
625         bool operator > (const BasicPropertyType<T>& other) const
626         {
627                 return value<T>() > other.value<T>();
628         }
629
630         BasicPropertyType( T val)
631                 :AbstractPropertyType("")
632         {
633                 setValue(val);
634         }
635
636         BasicPropertyType( std::string propertyName, T val)
637                 :AbstractPropertyType(propertyName)
638         {
639                 setValue(val);
640         }
641
642         BasicPropertyType( std::string propertyName, std::string val)
643                 :AbstractPropertyType(propertyName)
644         {
645                 if(!val.empty() && val != "")
646                 {
647                         serialize<T>(val);
648                 }
649                 else setValue(T());
650         }
651
652         BasicPropertyType(std::string propertyName)
653                 :AbstractPropertyType(propertyName)
654         {
655                 mValue = T();
656         }
657
658         AbstractPropertyType* copy()
659         {
660                 return new BasicPropertyType<T>(*this);
661         }
662
663         const picojson::value toJson()
664         {
665                 picojson::value v = AbstractPropertyType::toJson();
666
667                 picojson::object object = v.get<picojson::object>();
668
669                 object["value"] = amb::gvariantToJson(toVariant());
670
671                 return picojson::value(object);
672         }
673
674         virtual void fromJson(const picojson::value &json)
675         {
676                 AbstractPropertyType::fromJson(json);
677
678                 fromVariant(amb::jsonToGVariant(json.get("value"), signature()));
679         }
680
681         void fromString(std::string val)
682         {
683                 if(!val.empty() && val != "")
684                 {
685                         serialize<T>(val);
686                 }
687         }
688
689         std::string toString() const
690         {
691                 std::stringstream stream;
692                 stream.precision(10);
693                 stream<<value<T>();
694
695                 return stream.str();
696         }
697
698         GVariant* toVariant()
699         {
700                 return serializeVariant<T>(value<T>());
701         }
702
703         void fromVariant(GVariant *v)
704         {
705                 setValue(deserializeVariant<T>(v));
706         }
707
708         /*!
709          * \brief basicValue
710          * \return Typed version of value.  Slightly more useful than \see AbstractPropertyType::value()
711          */
712
713         T basicValue()
714         {
715                 return value<T>();
716         }
717
718         void setValue(T val)
719         {
720                 AbstractPropertyType::setValue(val);
721         }
722
723         void setValue(boost::any val)
724         {
725                 AbstractPropertyType::setValue(val);
726         }
727
728 private:
729
730         template <class N>
731         void serialize(const std::string & val,  typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
732         {
733                 int someTemp;
734
735                 std::stringstream stream(val);
736
737                 stream>>someTemp;
738                 setValue((N)someTemp);
739         }
740
741         template <class N>
742         void serialize(const std::string & val,  typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
743         {
744                 std::stringstream stream(GVS<T>::stringize(val));
745                 N someTemp;
746                 stream>>someTemp;
747                 setValue(someTemp);
748         }
749
750         template <class N>
751         GVariant* serializeVariant(const T val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
752         {
753                 return (g_variant_new("i",(int)val));
754         }
755
756         template <class N>
757         GVariant* serializeVariant(const T val, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
758         {
759                 return g_variant_new(GVS<T>::signature(),val);
760         }
761
762         template <class N>
763         T deserializeVariant(GVariant* v, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
764         {
765                 return (T)GVS<int>::value(v);
766         }
767
768         template <class N>
769         T deserializeVariant(GVariant* v, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
770         {
771                 return GVS<T>::value(v);
772         }
773 };
774
775 class StringPropertyType: public AbstractPropertyType
776 {
777 public:
778
779
780         StringPropertyType()
781                 :AbstractPropertyType("")
782         {
783                 setValue(std::string());
784         }
785
786         StringPropertyType(std::string propertyName)
787                 :AbstractPropertyType(propertyName)
788         {
789                 setValue(std::string());
790         }
791
792         StringPropertyType(std::string propertyName, std::string val)
793                 :AbstractPropertyType(propertyName)
794         {
795                 setValue(val);
796         }
797
798         StringPropertyType(StringPropertyType const & other)
799         :AbstractPropertyType(other.name)
800         {
801                 setValue(other.value<std::string>());
802                 timestamp = other.timestamp;
803                 sequence = other.sequence;
804                 sourceUuid = other.sourceUuid;
805                 name = other.name;
806                 zone = other.zone;
807         }
808
809         StringPropertyType & operator = (StringPropertyType const & other)
810         {
811                 setValue(other.value<std::string>());
812                 timestamp = other.timestamp;
813                 sequence = other.sequence;
814                 sourceUuid = other.sourceUuid;
815                 name = other.name;
816                 zone = other.zone;
817
818                 return *this;
819         }
820
821         StringPropertyType & operator = (std::string const & other)
822         {
823                 setValue(std::string(other));
824                 return *this;
825         }
826
827         bool operator < (const StringPropertyType& other) const
828         {
829                 return value<std::string>() < other.value<std::string>();
830         }
831
832         virtual const picojson::value toJson()
833         {
834                 auto val = AbstractPropertyType::toJson();
835
836                 picojson::object obj = val.get<picojson::object>();
837
838                 obj["value"] = amb::gvariantToJson(toVariant());
839         }
840
841         virtual void fromJson(const picojson::value &json)
842         {
843                 AbstractPropertyType::fromJson(json);
844
845                 fromString(json.get("value").to_str());
846         }
847
848         void fromString(std::string val)
849         {
850                 setValue(val);
851         }
852
853         AbstractPropertyType* copy()
854         {
855                 return new StringPropertyType(*this);
856         }
857
858         std::string toString() const
859         {
860                 return value<std::string>();
861         }
862
863         GVariant* toVariant()
864         {
865                 //mVariant = Glib::Variant<std::string>::create(toString());
866
867                 return g_variant_new_string(toString().c_str());
868
869         }
870
871         void fromVariant(GVariant *v)
872         {
873                 setValue(std::string(g_variant_get_string(v,NULL)));
874         }
875 };
876
877 /*!
878  * \brief ListPropertyType is a AbstractPropertyType for arrays of AbstractPropertyTypes
879  */
880 template <class T>
881 class ListPropertyType: public AbstractPropertyType
882 {
883 public:
884
885         ListPropertyType(std::string propertyName)
886                 : AbstractPropertyType(propertyName), initialized(false)
887         {
888
889         }
890
891         ListPropertyType(std::string propertyName, T value)
892                 : AbstractPropertyType(propertyName), initialized(false)
893         {
894                 appendPriv(value);
895         }
896
897         ListPropertyType(ListPropertyType & other)
898                 :AbstractPropertyType(other.name),initialized(false)
899         {
900                 std::vector<T> l = other.list();
901                 for(auto i : l)
902                 {
903                         append(i);
904                 }
905
906                 timestamp = other.timestamp;
907                 sequence = other.sequence;
908                 sourceUuid = other.sourceUuid;
909                 name = other.name;
910                 zone = other.zone;
911         }
912
913         ~ListPropertyType()
914         {
915                 clear();
916         }
917
918         /*! \brief append - appends a property to the list
919          * \arg property - property to be appended.
920          **/
921         void append(T property)
922         {
923                 if(!initialized)
924                 {
925                         mList.clear();
926                         initialized = true;
927                 }
928
929                 appendPriv(property);
930         }
931
932         uint count()
933         {
934                 return mList.size();
935         }
936
937         AbstractPropertyType* copy()
938         {
939                 return new ListPropertyType(*this);
940         }
941
942         void quickCopy(AbstractPropertyType* other)
943         {
944                 AbstractPropertyType::quickCopy(other);
945                 ListPropertyType<T>* v = static_cast<ListPropertyType<T>*>(other);
946                 if(!v)
947                 {
948                         DebugOut(DebugOut::Error) << "ListPropertyType Quick Copy failed" << endl;
949                         return;
950                 }
951                 mList = v->list();
952         }
953
954         std::string toString() const
955         {
956                 picojson::array array;
957
958                 for(auto i : mList)
959                 {
960                         array.push_back(GVS<T>::toJson(i));
961                 }
962
963                 return picojson::value(array).serialize();
964         }
965
966
967         void fromString(std::string str)
968         {
969                 if(!boost::algorithm::starts_with(str, "["))
970                         str = "[" + str;
971
972                 if(!boost::algorithm::ends_with(str, "]"))
973                         str+= "]";
974
975                 picojson::value value;
976                 picojson::parse(value, str);
977
978                 DebugOut()<< "str " << str << endl;
979
980
981                 picojson::array array = value.get<picojson::array>();
982
983                 for(auto i : array)
984                 {
985                         mList.push_back(GVS<T>::fromJson(i));
986                 }
987
988                 timestamp = amb::currentTime();
989         }
990
991
992         GVariant* toVariant()
993         {
994                 GVariantBuilder params;
995                 g_variant_builder_init(&params, ((const GVariantType *) "av"));
996
997                 for(auto itr : mList)
998                 {
999                         GVariant *newvar = g_variant_new("v", g_variant_new(GVS<T>::signature(), GVS<T>::gvalue(itr)));
1000                         g_variant_builder_add_value(&params, newvar);
1001                 }
1002
1003                 GVariant* var =  g_variant_builder_end(&params);
1004                 g_assert(var);
1005                 return var;
1006
1007         }
1008
1009         void fromVariant(GVariant* v)
1010         {
1011                 clear();
1012
1013                 /// TODO: fill this in
1014                 gsize dictsize = g_variant_n_children(v);
1015                 for (int i=0;i<dictsize;i++)
1016                 {
1017                         GVariant *childvariant = g_variant_get_child_value(v,i);
1018                         GVariant *innervariant = g_variant_get_variant(childvariant);
1019                         appendPriv(GVS<T>::value(innervariant));
1020                 }
1021         }
1022
1023         std::vector<T> list() { return mList; }
1024
1025 private:
1026
1027         void clear()
1028         {
1029                 mList.clear();
1030         }
1031
1032         void appendPriv(T i)
1033         {
1034                 mList.push_back(i);
1035         }
1036
1037         bool initialized;
1038
1039         std::vector<T> mList;
1040 };
1041
1042 #endif