2 Copyright (C) 2012 Intel Corporation
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.
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.
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
19 #ifndef _ABSTRACTPROPERTYTYPE_H_
20 #define _ABSTRACTPROPERTYTYPE_H_
23 #include "jsonhelper.h"
25 #include "superptr.hpp"
26 #include "timestamp.h"
28 #include <boost/algorithm/string.hpp>
29 #include <boost/any.hpp>
30 #include <boost/lexical_cast.hpp>
31 #include <boost/utility.hpp>
38 #include <type_traits>
63 static const Zone::Type FrontRight;
64 static const Zone::Type FrontLeft;
65 static const Zone::Type MiddleRight;
66 static const Zone::Type MiddleLeft;
67 static const Zone::Type RearRight;
68 static const Zone::Type RearLeft;
70 typedef std::vector<Zone::Type> ZoneList;
74 class AbstractPropertyType
79 * \brief The Priority enum describes prority of the property type.
83 /*!< normal priority. This is default */
89 /*!< Instant. Using this priority is not thread safe. This is typically used for
90 * Properties that need to be deterministic.
95 AbstractPropertyType(std::string property)
96 : name(property), timestamp(amb::currentTime()), sequence(-1), zone(Zone::None), priority(Normal)
101 virtual ~AbstractPropertyType()
103 for(auto i : destroyed)
110 * \brief toJson convert this type to json representation.
111 * The json typically looks something like this:
114 * "name" : "VehicleSpeed",
116 * "source" : "daf23v32342ddsdffafaeefe",
121 * \return json value representing the type
123 virtual const picojson::value toJson();
126 * \brief fromJson instantiate this type from json
129 virtual void fromJson(const picojson::value & json);
133 * \return strigified value
135 virtual std::string toString() const = 0;
138 * \brief fromString converts from string value
140 virtual void fromString(std::string) = 0;
144 * \return GVariant representation of value. Caller must unref the returned GVariant
146 virtual GVariant* toVariant() = 0;
149 * \brief fromVariant converts GVariant value into compatible native value. Caller owns
152 virtual void fromVariant(GVariant*) = 0;
156 * \return a copy of the AbstractPropertyType
158 virtual AbstractPropertyType* copy() = 0;
161 * \brief quickCopy is intended as a way to quickly copy the often changing bits from one abstract property to another
162 * It assumes that the properties are almost identical in name, source, and zone.
163 * \param other the property to copy from
165 virtual void quickCopy(AbstractPropertyType* other)
167 sequence = other->sequence;
168 mValue = other->anyValue();
169 timestamp = other->timestamp;
172 bool operator == (AbstractPropertyType &other)
174 std::string one = toString();
175 std::string two = other.toString();
177 && zone == other.zone
178 && sourceUuid == other.sourceUuid
179 && name == other.name;
182 bool operator != (AbstractPropertyType &other)
184 std::string one = toString();
185 std::string two = other.toString();
190 * \brief name Property name. \see VehicleProperty for built-in supported property names
195 * \brief alias alias for the property name
196 * \return alias if any of name if alias has not been set
198 const std::string alias() { return mAlias.empty() ? name : mAlias; }
200 void setAlias(const std::string & a) { mAlias = a; }
203 * \brief timestamp. Timestamp when the value was last updated by the system. This is updated automatically
204 * any time setValue() is called
205 * \see amb::currentTime()
211 * \brief sequence internal counter. Useful as a unique indentifier. values is -1 if not used (default).
216 * \brief sourceUuid uuid of the source that produced this property. This is set by the routingengine
217 * if left unmodified.
219 std::string sourceUuid;
222 * \brief zone that the property is situated in.
227 * \brief priority is used to tell the routing engine how to prioritize routing the value to plugins.
228 * setting this value to AbstractPropertyType::Instant will tell the routing engine to immedietly
229 * route the value without any reliance on the mainloop. Instant priority is NOT thread safe.
230 * Default priority is AbstractPropertyType::Normal.
236 * \param val boost::any value. NOTE: boost::any does not accept type coercion. Types must match exactly
237 * with native type. (ie, don't use "int" if the native type is "uint")
239 virtual void setValue(boost::any val)
242 timestamp = amb::currentTime();
246 * \brief value() native value. Does not use type coercion. Will throw if types do not match.
248 template <typename T>
251 return boost::any_cast<T>(mValue);
256 * \return boost::any value
258 boost::any anyValue()
265 * \return gvariant signature
267 virtual const string signature()
269 auto var = amb::make_super(toVariant());
272 const string s = g_variant_get_type_string(var.get());
277 * \brief destroyed is called if this property is destroyed.
279 std::vector<std::function<void(AbstractPropertyType*)>> destroyed;
291 struct PropertyCompare
293 bool operator()(AbstractPropertyType* const & lhs, AbstractPropertyType* & rhs) const
295 if (lhs->name == rhs->name
296 && lhs->sourceUuid == rhs->sourceUuid
297 && lhs->zone == rhs->zone)
313 static double fromJson(picojson::value v)
315 return v.get<double>();
318 static picojson::value toJson(double v)
320 return picojson::value(v);
327 static bool fromJson(picojson::value v)
329 return v.get<bool>();
332 static picojson::value toJson(bool v)
334 return picojson::value(v);
341 static std::string fromJson(picojson::value v)
343 return v.get<std::string>();
346 static picojson::value toJson(std::string v)
348 return picojson::value(v);
353 template <typename T>
363 template <typename T>
367 class GVS<int> : public BaseGVS<int>, public JsonNumber
370 static const char* signature() { return "i"; }
372 static int value(GVariant* v)
375 g_variant_get(v, signature(), &val);
379 static std::string stringize(std::string v)
386 class GVS<double> : public BaseGVS<double>, public JsonNumber
389 static const char* signature() { return "d"; }
391 static double value(GVariant* v)
393 return g_variant_get_double(v);
395 static std::string stringize(std::string v)
402 class GVS<uint16_t> : public BaseGVS<uint16_t>, public JsonNumber
405 static const char* signature() { return "q"; }
407 static uint16_t value(GVariant* v)
409 return g_variant_get_uint16(v);
411 static std::string stringize(std::string v)
418 class GVS<int16_t> : public BaseGVS<int16_t>, public JsonNumber
421 static const char* signature() { return "n"; }
423 static int16_t value(GVariant* v)
425 return g_variant_get_int16(v);
427 static std::string stringize(std::string v)
434 class GVS<char> : public BaseGVS<char>, public JsonNumber
437 static const char* signature() { return "y"; }
439 static char value(GVariant* v)
441 return g_variant_get_byte(v);
443 static std::string stringize(std::string v)
450 class GVS<uint32_t> : public BaseGVS<uint32_t>, public JsonNumber
453 static const char* signature() { return "u"; }
455 static uint32_t value(GVariant* v)
457 return g_variant_get_uint32(v);
459 static std::string stringize(std::string v)
466 class GVS<int64_t> : public BaseGVS<int64_t>, public JsonNumber
469 static const char* signature() { return "x"; }
471 static int64_t value(GVariant* v)
473 return g_variant_get_int64(v);
475 static std::string stringize(std::string v)
482 class GVS<uint64_t> : public BaseGVS<uint64_t>, public JsonNumber
485 static const char* signature() { return "t"; }
487 static uint64_t value(GVariant* v)
489 return g_variant_get_uint64(v);
491 static std::string stringize(std::string v)
498 class GVS<bool> : public BaseGVS<bool>, public JsonBoolean
501 static const char* signature() { return "b"; }
503 static bool value(GVariant *v)
505 return g_variant_get_boolean(v);
507 static std::string stringize(std::string v)
509 if(v == "0" || v == "1")
512 boost::algorithm::to_lower(v);
513 return v == "true" ? "1":"0";
518 class GVS<std::string> : public JsonString
521 static const char* signature() { return "s"; }
523 static const char* value(GVariant *v)
525 return g_variant_get_string(v, nullptr);
527 static std::string stringize(std::string v)
531 static const char* gvalue(std::string v)
538 * \brief BasicPropertyType is a typed property type. Most internal types are derived from this class
540 * std::unique_ptr<BasicPropertyType<int>> boostPSI = new BasicPropertyType<int>("BoostPSI",5);
541 * boostPSI->priority = AbstractPropertyType::Instant; //set instant because we clean up right after.
542 * routingEngine->updateProperty(boostPSI.get(), sourceUuid());
544 template <typename T>
545 class BasicPropertyType: public AbstractPropertyType
548 BasicPropertyType(): AbstractPropertyType("")
553 BasicPropertyType(BasicPropertyType const & other)
554 :AbstractPropertyType(other.name)
556 setValue(other.value<T>());
557 timestamp = other.timestamp;
558 sequence = other.sequence;
559 sourceUuid = other.sourceUuid;
565 BasicPropertyType & operator = (BasicPropertyType const & other)
567 setValue(other.value<T>());
568 timestamp = other.timestamp;
569 sequence = other.sequence;
570 sourceUuid = other.sourceUuid;
577 BasicPropertyType & operator = (T const & other)
583 BasicPropertyType & operator ++ ()
585 setValue(basicValue() + 1);
588 BasicPropertyType & operator -- ()
590 setValue(basicValue() - 1);
593 bool operator < (const BasicPropertyType<T>& other) const
595 return value<T>() < other.value<T>();
598 bool operator > (const BasicPropertyType<T>& other) const
600 return value<T>() > other.value<T>();
603 BasicPropertyType( T val)
604 :AbstractPropertyType("")
609 BasicPropertyType( std::string propertyName, T val)
610 :AbstractPropertyType(propertyName)
615 BasicPropertyType( std::string propertyName, std::string val)
616 :AbstractPropertyType(propertyName)
618 if(!val.empty() && val != "")
625 BasicPropertyType(std::string propertyName)
626 :AbstractPropertyType(propertyName)
631 AbstractPropertyType* copy()
633 return new BasicPropertyType<T>(*this);
636 const picojson::value toJson()
638 picojson::value v = AbstractPropertyType::toJson();
640 picojson::object object = v.get<picojson::object>();
642 object["value"] = amb::gvariantToJson(toVariant());
644 return picojson::value(object);
647 virtual void fromJson(const picojson::value &json)
649 AbstractPropertyType::fromJson(json);
651 fromVariant(amb::jsonToGVariant(json.get("value"), signature()));
654 void fromString(std::string val)
656 if(!val.empty() && val != "")
662 std::string toString() const
664 std::stringstream stream;
665 stream.precision(10);
671 GVariant* toVariant()
673 return serializeVariant<T>(value<T>());
676 void fromVariant(GVariant *v)
678 setValue(deserializeVariant<T>(v));
683 * \return Typed version of value. Slightly more useful than \see AbstractPropertyType::value()
693 AbstractPropertyType::setValue(val);
696 void setValue(boost::any val)
698 AbstractPropertyType::setValue(val);
704 void serialize(const std::string & val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
708 std::stringstream stream(val);
711 setValue((N)someTemp);
715 void serialize(const std::string & val, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
717 std::stringstream stream(GVS<T>::stringize(val));
724 GVariant* serializeVariant(const T val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
726 return (g_variant_new("i",(int)val));
730 GVariant* serializeVariant(const T val, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
732 return g_variant_new(GVS<T>::signature(),val);
736 T deserializeVariant(GVariant* v, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
738 return (T)GVS<int>::value(v);
742 T deserializeVariant(GVariant* v, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
744 return GVS<T>::value(v);
748 class StringPropertyType: public AbstractPropertyType
754 :AbstractPropertyType("")
756 setValue(std::string());
759 StringPropertyType(std::string propertyName)
760 :AbstractPropertyType(propertyName)
762 setValue(std::string());
765 StringPropertyType(std::string propertyName, std::string val)
766 :AbstractPropertyType(propertyName)
771 StringPropertyType(StringPropertyType const & other)
772 :AbstractPropertyType(other.name)
774 setValue(other.value<std::string>());
775 timestamp = other.timestamp;
776 sequence = other.sequence;
777 sourceUuid = other.sourceUuid;
782 StringPropertyType & operator = (StringPropertyType const & other)
784 setValue(other.value<std::string>());
785 timestamp = other.timestamp;
786 sequence = other.sequence;
787 sourceUuid = other.sourceUuid;
794 StringPropertyType & operator = (std::string const & other)
796 setValue(std::string(other));
800 bool operator < (const StringPropertyType& other) const
802 return value<std::string>() < other.value<std::string>();
805 virtual const picojson::value toJson()
807 auto val = AbstractPropertyType::toJson();
809 picojson::object obj = val.get<picojson::object>();
811 obj["value"] = amb::gvariantToJson(toVariant());
814 virtual void fromJson(const picojson::value &json)
816 AbstractPropertyType::fromJson(json);
818 fromString(json.get("value").to_str());
821 void fromString(std::string val)
826 AbstractPropertyType* copy()
828 return new StringPropertyType(*this);
831 std::string toString() const
833 return value<std::string>();
836 GVariant* toVariant()
838 //mVariant = Glib::Variant<std::string>::create(toString());
840 return g_variant_new_string(toString().c_str());
844 void fromVariant(GVariant *v)
846 setValue(std::string(g_variant_get_string(v,NULL)));
851 * \brief ListPropertyType is a AbstractPropertyType for arrays of AbstractPropertyTypes
854 class ListPropertyType: public AbstractPropertyType
858 ListPropertyType(std::string propertyName)
859 : AbstractPropertyType(propertyName), initialized(false)
864 ListPropertyType(std::string propertyName, T value)
865 : AbstractPropertyType(propertyName), initialized(false)
870 ListPropertyType(ListPropertyType & other)
871 :AbstractPropertyType(other.name),initialized(false)
873 std::vector<T> l = other.list();
879 timestamp = other.timestamp;
880 sequence = other.sequence;
881 sourceUuid = other.sourceUuid;
891 /*! \brief append - appends a property to the list
892 * \arg property - property to be appended.
894 void append(T property)
902 appendPriv(property);
910 AbstractPropertyType* copy()
912 return new ListPropertyType(*this);
915 void quickCopy(AbstractPropertyType* other)
917 AbstractPropertyType::quickCopy(other);
918 ListPropertyType<T>* v = static_cast<ListPropertyType<T>*>(other);
921 DebugOut(DebugOut::Error) << "ListPropertyType Quick Copy failed" << endl;
927 std::string toString() const
929 picojson::array array;
933 array.push_back(GVS<T>::toJson(i));
936 return picojson::value(array).serialize();
940 void fromString(std::string str)
942 picojson::value value;
943 picojson::parse(value, str);
945 picojson::array array = value.get<picojson::array>();
949 mList.push_back(GVS<T>::fromJson(i));
952 timestamp = amb::currentTime();
956 GVariant* toVariant()
958 GVariantBuilder params;
959 g_variant_builder_init(¶ms, ((const GVariantType *) "av"));
961 for(auto itr : mList)
963 DebugOut(0) << "toVariant value: " << GVS<T>::gvalue(itr) << endl;
964 GVariant *newvar = g_variant_new("v", g_variant_new(GVS<T>::signature(), GVS<T>::gvalue(itr)));
965 g_variant_builder_add_value(¶ms, newvar);
968 GVariant* var = g_variant_builder_end(¶ms);
974 void fromVariant(GVariant* v)
978 /// TODO: fill this in
979 gsize dictsize = g_variant_n_children(v);
980 for (int i=0;i<dictsize;i++)
982 GVariant *childvariant = g_variant_get_child_value(v,i);
983 GVariant *innervariant = g_variant_get_variant(childvariant);
984 appendPriv(GVS<T>::value(innervariant));
988 std::vector<T> list() { return mList; }
1004 std::vector<T> mList;