Merge pull request #58 from tripzero/master
[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                   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 valueQuality is used to indicate the quality of the value
243          * Each AMB property is given a default value.  valueQuality is a way to describe whether the value
244          * is the default one and the system has not yet provided a valid value, bad if an error occured, or
245          * good.
246          *
247          * The default value for this is \ref amb::Quality::UncertainInitialValue indicating that the amb property value is the
248          * default value.  When \ref AbastractPropertyType::setValue is called, valueQuality is set to "Good" automatically.
249          *
250          * TODO: this may be able to provide a replacement for set and get error codes: \ref AsyncPropertyReply::Error
251          */
252         amb::Quality::ValueQuality valueQuality;
253
254         /*!
255          * \brief setValue
256          * \param val boost::any value.  NOTE: boost::any does not accept type coercion.  Types must match exactly
257          * with native type. (ie, don't use "int" if the native type is "uint")
258          */
259         virtual void setValue(boost::any val)
260         {
261                 mValue = val;
262                 timestamp = amb::currentTime();
263                 valueQuality = amb::Quality::Good;
264         }
265
266         /*!
267          * \brief value() native value.  Does not use type coercion.  Will throw if types do not match.
268          */
269         template <typename T>
270         T value() const
271         {
272                 return boost::any_cast<T>(mValue);
273         }
274
275         /*!
276          * \brief anyValue
277          * \return boost::any value
278          */
279         boost::any anyValue()
280         {
281                 return mValue;
282         }
283
284         /*!
285          * \brief signature
286          * \return gvariant signature
287          */
288         virtual const string signature()
289         {
290                 auto var = amb::make_super(toVariant());
291                 if(!var) return "";
292
293                 const string s = g_variant_get_type_string(var.get());
294                 return s;
295         }
296
297         /*!
298          * \brief destroyed is called if this property is destroyed.
299          */
300         std::vector<std::function<void(AbstractPropertyType*)>> destroyed;
301
302 protected:
303
304         boost::any mValue;
305
306         std::string mAlias;
307 };
308
309 namespace amb
310 {
311
312 struct PropertyCompare
313 {
314         bool operator()(AbstractPropertyType* const & lhs, AbstractPropertyType* & rhs) const
315         {
316                 if (lhs->name == rhs->name
317                                 && lhs->sourceUuid == rhs->sourceUuid
318                                 && lhs->zone == rhs->zone)
319                 {
320                         return true;
321                 }
322
323                 return false;
324         }
325
326 };
327
328 }
329
330
331 class JsonNumber
332 {
333 public:
334         static double fromJson(picojson::value v)
335         {
336                 return v.get<double>();
337         }
338
339         static picojson::value toJson(double v)
340         {
341                 return picojson::value(v);
342         }
343 };
344
345 class JsonBoolean
346 {
347 public:
348         static bool fromJson(picojson::value v)
349         {
350                 return v.get<bool>();
351         }
352
353         static picojson::value toJson(bool v)
354         {
355                 return picojson::value(v);
356         }
357 };
358
359 class JsonString
360 {
361 public:
362         static std::string fromJson(picojson::value v)
363         {
364                 return v.get<std::string>();
365         }
366
367         static picojson::value toJson(std::string v)
368         {
369                 return picojson::value(v);
370         }
371 };
372
373
374 template <typename T>
375 class BaseGVS
376 {
377 public:
378         static T gvalue(T t)
379         {
380                 return t;
381         }
382 };
383
384 template <typename T>
385 class GVS;
386
387 template <>
388 class GVS<int> : public BaseGVS<int>, public JsonNumber
389 {
390 public:
391         static const char* signature() { return "i"; }
392
393         static int value(GVariant* v)
394         {
395                 int val = 0;
396                 g_variant_get(v, signature(), &val);
397                 return val;
398         }
399
400         static std::string stringize(std::string v)
401         {
402                 return v;
403         }
404 };
405
406 template <>
407 class GVS<double> : public BaseGVS<double>, public JsonNumber
408 {
409 public:
410         static const char* signature() { return "d"; }
411
412         static double value(GVariant* v)
413         {
414                 return g_variant_get_double(v);
415         }
416         static std::string stringize(std::string v)
417         {
418                 return v;
419         }
420 };
421
422 template <>
423 class GVS<uint16_t> : public BaseGVS<uint16_t>, public JsonNumber
424 {
425 public:
426         static const char* signature() { return "q"; }
427
428         static uint16_t value(GVariant* v)
429         {
430                 return g_variant_get_uint16(v);
431         }
432         static std::string stringize(std::string v)
433         {
434                 return v;
435         }
436 };
437
438 template <>
439 class GVS<int16_t> : public BaseGVS<int16_t>, public JsonNumber
440 {
441 public:
442         static const char* signature() { return "n"; }
443
444         static int16_t value(GVariant* v)
445         {
446                 return g_variant_get_int16(v);
447         }
448         static std::string stringize(std::string v)
449         {
450                 return v;
451         }
452 };
453
454 template <>
455 class GVS<char> : public BaseGVS<char>, public JsonNumber
456 {
457 public:
458         static const char* signature() { return "y"; }
459
460         static char value(GVariant* v)
461         {
462                 return g_variant_get_byte(v);
463         }
464         static std::string stringize(std::string v)
465         {
466                 return v;
467         }
468 };
469
470 template <>
471 class GVS<uint32_t> : public BaseGVS<uint32_t>, public JsonNumber
472 {
473 public:
474         static const char* signature() { return "u"; }
475
476         static uint32_t value(GVariant* v)
477         {
478                 return g_variant_get_uint32(v);
479         }
480         static std::string stringize(std::string v)
481         {
482                 return v;
483         }
484 };
485
486 template <>
487 class GVS<int64_t> : public BaseGVS<int64_t>, public JsonNumber
488 {
489 public:
490         static const char* signature() { return "x"; }
491
492         static int64_t value(GVariant* v)
493         {
494                 return g_variant_get_int64(v);
495         }
496         static std::string stringize(std::string v)
497         {
498                 return v;
499         }
500 };
501
502 template <>
503 class GVS<uint64_t> : public BaseGVS<uint64_t>, public JsonNumber
504 {
505 public:
506         static const char* signature() { return "t"; }
507
508         static uint64_t value(GVariant* v)
509         {
510                 return g_variant_get_uint64(v);
511         }
512         static std::string stringize(std::string v)
513         {
514                 return v;
515         }
516 };
517
518 template <>
519 class GVS<bool> : public BaseGVS<bool>, public JsonBoolean
520 {
521 public:
522         static const char* signature() { return "b"; }
523
524         static bool value(GVariant *v)
525         {
526                 return g_variant_get_boolean(v);
527         }
528         static std::string stringize(std::string v)
529         {
530                 if(v == "0" || v == "1")
531                         return v;
532
533                 boost::algorithm::to_lower(v);
534                 return v == "true" ? "1":"0";
535         }
536 };
537
538 template <>
539 class GVS<std::string> : public JsonString
540 {
541 public:
542         static const char* signature() { return "s"; }
543
544         static const char* value(GVariant *v)
545         {
546                 return g_variant_get_string(v, nullptr);
547         }
548         static std::string stringize(std::string v)
549         {
550                 return v;
551         }
552         static const char* gvalue(std::string v)
553         {
554                 return v.c_str();
555         }
556 };
557
558 /*!
559  * \brief BasicPropertyType is a typed property type.  Most internal types are derived from this class
560  * \example
561  * std::unique_ptr<BasicPropertyType<int>> boostPSI = new BasicPropertyType<int>("BoostPSI",5);
562  * boostPSI->priority = AbstractPropertyType::Instant; //set instant because we clean up right after.
563  * routingEngine->updateProperty(boostPSI.get(), sourceUuid());
564  */
565 template <typename T>
566 class BasicPropertyType: public AbstractPropertyType
567 {
568 public:
569         BasicPropertyType(): AbstractPropertyType("")
570         {
571                 mValue = T();
572         }
573
574         BasicPropertyType(BasicPropertyType const & other)
575                 :AbstractPropertyType(other.name)
576         {
577                 setValue(other.value<T>());
578                 timestamp = other.timestamp;
579                 sequence = other.sequence;
580                 sourceUuid = other.sourceUuid;
581                 name = other.name;
582                 zone = other.zone;
583
584         }
585
586         BasicPropertyType & operator = (BasicPropertyType const & other)
587         {
588                 setValue(other.value<T>());
589                 timestamp = other.timestamp;
590                 sequence = other.sequence;
591                 sourceUuid = other.sourceUuid;
592                 name = other.name;
593                 zone = other.zone;
594
595                 return *this;
596         }
597
598         BasicPropertyType & operator = (T const & other)
599         {
600                 setValue(other);
601                 return *this;
602         }
603
604         BasicPropertyType & operator ++ ()
605         {
606                 setValue(basicValue() + 1);
607         }
608
609         BasicPropertyType & operator -- ()
610         {
611                 setValue(basicValue() - 1);
612         }
613
614         bool operator < (const BasicPropertyType<T>& other) const
615         {
616                 return value<T>() < other.value<T>();
617         }
618
619         bool operator > (const BasicPropertyType<T>& other) const
620         {
621                 return value<T>() > other.value<T>();
622         }
623
624         BasicPropertyType( T val)
625                 :AbstractPropertyType("")
626         {
627                 setValue(val);
628         }
629
630         BasicPropertyType( std::string propertyName, T val)
631                 :AbstractPropertyType(propertyName)
632         {
633                 setValue(val);
634         }
635
636         BasicPropertyType( std::string propertyName, std::string val)
637                 :AbstractPropertyType(propertyName)
638         {
639                 if(!val.empty() && val != "")
640                 {
641                         serialize<T>(val);
642                 }
643                 else setValue(T());
644         }
645
646         BasicPropertyType(std::string propertyName)
647                 :AbstractPropertyType(propertyName)
648         {
649                 mValue = T();
650         }
651
652         AbstractPropertyType* copy()
653         {
654                 return new BasicPropertyType<T>(*this);
655         }
656
657         const picojson::value toJson()
658         {
659                 picojson::value v = AbstractPropertyType::toJson();
660
661                 picojson::object object = v.get<picojson::object>();
662
663                 object["value"] = amb::gvariantToJson(toVariant());
664
665                 return picojson::value(object);
666         }
667
668         virtual void fromJson(const picojson::value &json)
669         {
670                 AbstractPropertyType::fromJson(json);
671
672                 fromVariant(amb::jsonToGVariant(json.get("value"), signature()));
673         }
674
675         void fromString(std::string val)
676         {
677                 if(!val.empty() && val != "")
678                 {
679                         serialize<T>(val);
680                 }
681         }
682
683         std::string toString() const
684         {
685                 std::stringstream stream;
686                 stream.precision(10);
687                 stream<<value<T>();
688
689                 return stream.str();
690         }
691
692         GVariant* toVariant()
693         {
694                 return serializeVariant<T>(value<T>());
695         }
696
697         void fromVariant(GVariant *v)
698         {
699                 setValue(deserializeVariant<T>(v));
700         }
701
702         /*!
703          * \brief basicValue
704          * \return Typed version of value.  Slightly more useful than \see AbstractPropertyType::value()
705          */
706
707         T basicValue()
708         {
709                 return value<T>();
710         }
711
712         void setValue(T val)
713         {
714                 AbstractPropertyType::setValue(val);
715         }
716
717         void setValue(boost::any val)
718         {
719                 AbstractPropertyType::setValue(val);
720         }
721
722 private:
723
724         template <class N>
725         void serialize(const std::string & val,  typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
726         {
727                 int someTemp;
728
729                 std::stringstream stream(val);
730
731                 stream>>someTemp;
732                 setValue((N)someTemp);
733         }
734
735         template <class N>
736         void serialize(const std::string & val,  typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
737         {
738                 std::stringstream stream(GVS<T>::stringize(val));
739                 N someTemp;
740                 stream>>someTemp;
741                 setValue(someTemp);
742         }
743
744         template <class N>
745         GVariant* serializeVariant(const T val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
746         {
747                 return (g_variant_new("i",(int)val));
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(GVS<T>::signature(),val);
754         }
755
756         template <class N>
757         T deserializeVariant(GVariant* v, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
758         {
759                 return (T)GVS<int>::value(v);
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 GVS<T>::value(v);
766         }
767 };
768
769 class StringPropertyType: public AbstractPropertyType
770 {
771 public:
772
773
774         StringPropertyType()
775                 :AbstractPropertyType("")
776         {
777                 setValue(std::string());
778         }
779
780         StringPropertyType(std::string propertyName)
781                 :AbstractPropertyType(propertyName)
782         {
783                 setValue(std::string());
784         }
785
786         StringPropertyType(std::string propertyName, std::string val)
787                 :AbstractPropertyType(propertyName)
788         {
789                 setValue(val);
790         }
791
792         StringPropertyType(StringPropertyType const & other)
793         :AbstractPropertyType(other.name)
794         {
795                 setValue(other.value<std::string>());
796                 timestamp = other.timestamp;
797                 sequence = other.sequence;
798                 sourceUuid = other.sourceUuid;
799                 name = other.name;
800                 zone = other.zone;
801         }
802
803         StringPropertyType & operator = (StringPropertyType const & other)
804         {
805                 setValue(other.value<std::string>());
806                 timestamp = other.timestamp;
807                 sequence = other.sequence;
808                 sourceUuid = other.sourceUuid;
809                 name = other.name;
810                 zone = other.zone;
811
812                 return *this;
813         }
814
815         StringPropertyType & operator = (std::string const & other)
816         {
817                 setValue(std::string(other));
818                 return *this;
819         }
820
821         bool operator < (const StringPropertyType& other) const
822         {
823                 return value<std::string>() < other.value<std::string>();
824         }
825
826         virtual const picojson::value toJson()
827         {
828                 auto val = AbstractPropertyType::toJson();
829
830                 picojson::object obj = val.get<picojson::object>();
831
832                 obj["value"] = amb::gvariantToJson(toVariant());
833         }
834
835         virtual void fromJson(const picojson::value &json)
836         {
837                 AbstractPropertyType::fromJson(json);
838
839                 fromString(json.get("value").to_str());
840         }
841
842         void fromString(std::string val)
843         {
844                 setValue(val);
845         }
846
847         AbstractPropertyType* copy()
848         {
849                 return new StringPropertyType(*this);
850         }
851
852         std::string toString() const
853         {
854                 return value<std::string>();
855         }
856
857         GVariant* toVariant()
858         {
859                 //mVariant = Glib::Variant<std::string>::create(toString());
860
861                 return g_variant_new_string(toString().c_str());
862
863         }
864
865         void fromVariant(GVariant *v)
866         {
867                 setValue(std::string(g_variant_get_string(v,NULL)));
868         }
869 };
870
871 /*!
872  * \brief ListPropertyType is a AbstractPropertyType for arrays of AbstractPropertyTypes
873  */
874 template <class T>
875 class ListPropertyType: public AbstractPropertyType
876 {
877 public:
878
879         ListPropertyType(std::string propertyName)
880                 : AbstractPropertyType(propertyName), initialized(false)
881         {
882
883         }
884
885         ListPropertyType(std::string propertyName, T value)
886                 : AbstractPropertyType(propertyName), initialized(false)
887         {
888                 appendPriv(value);
889         }
890
891         ListPropertyType(ListPropertyType & other)
892                 :AbstractPropertyType(other.name),initialized(false)
893         {
894                 std::vector<T> l = other.list();
895                 for(auto i : l)
896                 {
897                         append(i);
898                 }
899
900                 timestamp = other.timestamp;
901                 sequence = other.sequence;
902                 sourceUuid = other.sourceUuid;
903                 name = other.name;
904                 zone = other.zone;
905         }
906
907         ~ListPropertyType()
908         {
909                 clear();
910         }
911
912         /*! \brief append - appends a property to the list
913          * \arg property - property to be appended.
914          **/
915         void append(T property)
916         {
917                 if(!initialized)
918                 {
919                         mList.clear();
920                         initialized = true;
921                 }
922
923                 appendPriv(property);
924         }
925
926         uint count()
927         {
928                 return mList.size();
929         }
930
931         AbstractPropertyType* copy()
932         {
933                 return new ListPropertyType(*this);
934         }
935
936         void quickCopy(AbstractPropertyType* other)
937         {
938                 AbstractPropertyType::quickCopy(other);
939                 ListPropertyType<T>* v = static_cast<ListPropertyType<T>*>(other);
940                 if(!v)
941                 {
942                         DebugOut(DebugOut::Error) << "ListPropertyType Quick Copy failed" << endl;
943                         return;
944                 }
945                 mList = v->list();
946         }
947
948         std::string toString() const
949         {
950                 picojson::array array;
951
952                 for(auto i : mList)
953                 {
954                         array.push_back(GVS<T>::toJson(i));
955                 }
956
957                 return picojson::value(array).serialize();
958         }
959
960
961         void fromString(std::string str)
962         {
963                 if(!boost::algorithm::starts_with(str, "["))
964                         str = "[" + str;
965
966                 if(!boost::algorithm::ends_with(str, "]"))
967                         str+= "]";
968
969                 picojson::value value;
970                 picojson::parse(value, str);
971
972                 DebugOut()<< "str " << str << endl;
973
974
975                 picojson::array array = value.get<picojson::array>();
976
977                 for(auto i : array)
978                 {
979                         mList.push_back(GVS<T>::fromJson(i));
980                 }
981
982                 timestamp = amb::currentTime();
983         }
984
985
986         GVariant* toVariant()
987         {
988                 GVariantBuilder params;
989                 g_variant_builder_init(&params, ((const GVariantType *) "av"));
990
991                 for(auto itr : mList)
992                 {
993                         GVariant *newvar = g_variant_new("v", g_variant_new(GVS<T>::signature(), GVS<T>::gvalue(itr)));
994                         g_variant_builder_add_value(&params, newvar);
995                 }
996
997                 GVariant* var =  g_variant_builder_end(&params);
998                 g_assert(var);
999                 return var;
1000
1001         }
1002
1003         void fromVariant(GVariant* v)
1004         {
1005                 clear();
1006
1007                 /// TODO: fill this in
1008                 gsize dictsize = g_variant_n_children(v);
1009                 for (int i=0;i<dictsize;i++)
1010                 {
1011                         GVariant *childvariant = g_variant_get_child_value(v,i);
1012                         GVariant *innervariant = g_variant_get_variant(childvariant);
1013                         appendPriv(GVS<T>::value(innervariant));
1014                 }
1015         }
1016
1017         std::vector<T> list() { return mList; }
1018
1019 private:
1020
1021         void clear()
1022         {
1023                 mList.clear();
1024         }
1025
1026         void appendPriv(T i)
1027         {
1028                 mList.push_back(i);
1029         }
1030
1031         bool initialized;
1032
1033         std::vector<T> mList;
1034 };
1035
1036 #endif