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"
27 #include "valuequality.h"
29 #include <boost/algorithm/string.hpp>
30 #include <boost/any.hpp>
31 #include <boost/lexical_cast.hpp>
32 #include <boost/utility.hpp>
39 #include <type_traits>
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;
71 typedef std::vector<Zone::Type> ZoneList;
75 class AbstractPropertyType
80 * \brief The Priority enum describes prority of the property type.
84 /*!< normal priority. This is default */
90 /*!< Instant. Using this priority is not thread safe. This is typically used for
91 * Properties that need to be deterministic.
96 AbstractPropertyType(std::string property)
97 : name(property), timestamp(amb::currentTime()), sequence(-1), zone(Zone::None), priority(Normal),
98 valueQuality(amb::Quality::UncertainInitialValue)
103 virtual ~AbstractPropertyType()
105 for(auto i : destroyed)
112 * \brief toJson convert this type to json representation.
113 * The json typically looks something like this:
116 * "name" : "VehicleSpeed",
118 * "source" : "daf23v32342ddsdffafaeefe",
123 * \return json value representing the type
125 virtual const picojson::value toJson();
128 * \brief fromJson instantiate this type from json
131 virtual void fromJson(const picojson::value & json);
135 * \return strigified value
137 virtual std::string toString() const = 0;
140 * \brief fromString converts from string value
142 virtual void fromString(std::string) = 0;
146 * \return GVariant representation of value. Caller must unref the returned GVariant
148 virtual GVariant* toVariant() = 0;
151 * \brief fromVariant converts GVariant value into compatible native value. Caller owns
154 virtual void fromVariant(GVariant*) = 0;
158 * \return a copy of the AbstractPropertyType
160 virtual AbstractPropertyType* copy() = 0;
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
167 virtual void quickCopy(AbstractPropertyType* other)
169 sequence = other->sequence;
170 mValue = other->anyValue();
171 timestamp = other->timestamp;
174 bool operator == (AbstractPropertyType &other)
176 std::string one = toString();
177 std::string two = other.toString();
179 && zone == other.zone
180 && sourceUuid == other.sourceUuid
181 && name == other.name;
184 bool operator != (AbstractPropertyType &other)
186 std::string one = toString();
187 std::string two = other.toString();
192 * \brief name Property name. \see VehicleProperty for built-in supported property names
197 * \brief alias for the property name
198 * \return alias or \ref name if alias has not been set
200 const std::string alias() { return mAlias.empty() ? name : mAlias; }
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
207 void setAlias(const std::string & a) { mAlias = a; }
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()
218 * \brief sequence internal counter. Useful as a unique indentifier. values is -1 if not used (default).
223 * \brief sourceUuid uuid of the source that produced this property. This is set by the routingengine
224 * if left unmodified.
226 std::string sourceUuid;
229 * \brief zone that the property is situated in.
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.
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
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.
250 * TODO: this may be able to provide a replacement for set and get error codes: \ref AsyncPropertyReply::Error
252 amb::Quality::ValueQuality valueQuality;
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")
259 virtual void setValue(boost::any val)
262 timestamp = amb::currentTime();
263 valueQuality = amb::Quality::Good;
267 * \brief value() native value. Does not use type coercion. Will throw if types do not match.
269 template <typename T>
272 return boost::any_cast<T>(mValue);
277 * \return boost::any value
279 boost::any anyValue()
286 * \return gvariant signature
288 virtual const string signature()
290 auto var = amb::make_super(toVariant());
293 const string s = g_variant_get_type_string(var.get());
298 * \brief destroyed is called if this property is destroyed.
300 std::vector<std::function<void(AbstractPropertyType*)>> destroyed;
312 struct PropertyCompare
314 bool operator()(AbstractPropertyType* const & lhs, AbstractPropertyType* & rhs) const
316 if (lhs->name == rhs->name
317 && lhs->sourceUuid == rhs->sourceUuid
318 && lhs->zone == rhs->zone)
334 static double fromJson(picojson::value v)
336 return v.get<double>();
339 static picojson::value toJson(double v)
341 return picojson::value(v);
348 static bool fromJson(picojson::value v)
350 return v.get<bool>();
353 static picojson::value toJson(bool v)
355 return picojson::value(v);
362 static std::string fromJson(picojson::value v)
364 return v.get<std::string>();
367 static picojson::value toJson(std::string v)
369 return picojson::value(v);
374 template <typename T>
384 template <typename T>
388 class GVS<int> : public BaseGVS<int>, public JsonNumber
391 static const char* signature() { return "i"; }
393 static int value(GVariant* v)
396 g_variant_get(v, signature(), &val);
400 static std::string stringize(std::string v)
407 class GVS<double> : public BaseGVS<double>, public JsonNumber
410 static const char* signature() { return "d"; }
412 static double value(GVariant* v)
414 return g_variant_get_double(v);
416 static std::string stringize(std::string v)
423 class GVS<uint16_t> : public BaseGVS<uint16_t>, public JsonNumber
426 static const char* signature() { return "q"; }
428 static uint16_t value(GVariant* v)
430 return g_variant_get_uint16(v);
432 static std::string stringize(std::string v)
439 class GVS<int16_t> : public BaseGVS<int16_t>, public JsonNumber
442 static const char* signature() { return "n"; }
444 static int16_t value(GVariant* v)
446 return g_variant_get_int16(v);
448 static std::string stringize(std::string v)
455 class GVS<char> : public BaseGVS<char>, public JsonNumber
458 static const char* signature() { return "y"; }
460 static char value(GVariant* v)
462 return g_variant_get_byte(v);
464 static std::string stringize(std::string v)
471 class GVS<uint32_t> : public BaseGVS<uint32_t>, public JsonNumber
474 static const char* signature() { return "u"; }
476 static uint32_t value(GVariant* v)
478 return g_variant_get_uint32(v);
480 static std::string stringize(std::string v)
487 class GVS<int64_t> : public BaseGVS<int64_t>, public JsonNumber
490 static const char* signature() { return "x"; }
492 static int64_t value(GVariant* v)
494 return g_variant_get_int64(v);
496 static std::string stringize(std::string v)
503 class GVS<uint64_t> : public BaseGVS<uint64_t>, public JsonNumber
506 static const char* signature() { return "t"; }
508 static uint64_t value(GVariant* v)
510 return g_variant_get_uint64(v);
512 static std::string stringize(std::string v)
519 class GVS<bool> : public BaseGVS<bool>, public JsonBoolean
522 static const char* signature() { return "b"; }
524 static bool value(GVariant *v)
526 return g_variant_get_boolean(v);
528 static std::string stringize(std::string v)
530 if(v == "0" || v == "1")
533 boost::algorithm::to_lower(v);
534 return v == "true" ? "1":"0";
539 class GVS<std::string> : public JsonString
542 static const char* signature() { return "s"; }
544 static const char* value(GVariant *v)
546 return g_variant_get_string(v, nullptr);
548 static std::string stringize(std::string v)
552 static const char* gvalue(std::string v)
559 * \brief BasicPropertyType is a typed property type. Most internal types are derived from this class
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());
565 template <typename T>
566 class BasicPropertyType: public AbstractPropertyType
569 BasicPropertyType(): AbstractPropertyType("")
574 BasicPropertyType(BasicPropertyType const & other)
575 :AbstractPropertyType(other.name)
577 setValue(other.value<T>());
578 timestamp = other.timestamp;
579 sequence = other.sequence;
580 sourceUuid = other.sourceUuid;
586 BasicPropertyType & operator = (BasicPropertyType const & other)
588 setValue(other.value<T>());
589 timestamp = other.timestamp;
590 sequence = other.sequence;
591 sourceUuid = other.sourceUuid;
598 BasicPropertyType & operator = (T const & other)
604 BasicPropertyType & operator ++ ()
606 setValue(basicValue() + 1);
609 BasicPropertyType & operator -- ()
611 setValue(basicValue() - 1);
614 bool operator < (const BasicPropertyType<T>& other) const
616 return value<T>() < other.value<T>();
619 bool operator > (const BasicPropertyType<T>& other) const
621 return value<T>() > other.value<T>();
624 BasicPropertyType( T val)
625 :AbstractPropertyType("")
630 BasicPropertyType( std::string propertyName, T val)
631 :AbstractPropertyType(propertyName)
636 BasicPropertyType( std::string propertyName, std::string val)
637 :AbstractPropertyType(propertyName)
639 if(!val.empty() && val != "")
646 BasicPropertyType(std::string propertyName)
647 :AbstractPropertyType(propertyName)
652 AbstractPropertyType* copy()
654 return new BasicPropertyType<T>(*this);
657 const picojson::value toJson()
659 picojson::value v = AbstractPropertyType::toJson();
661 picojson::object object = v.get<picojson::object>();
663 object["value"] = amb::gvariantToJson(toVariant());
665 return picojson::value(object);
668 virtual void fromJson(const picojson::value &json)
670 AbstractPropertyType::fromJson(json);
672 fromVariant(amb::jsonToGVariant(json.get("value"), signature()));
675 void fromString(std::string val)
677 if(!val.empty() && val != "")
683 std::string toString() const
685 std::stringstream stream;
686 stream.precision(10);
692 GVariant* toVariant()
694 return serializeVariant<T>(value<T>());
697 void fromVariant(GVariant *v)
699 setValue(deserializeVariant<T>(v));
704 * \return Typed version of value. Slightly more useful than \see AbstractPropertyType::value()
714 AbstractPropertyType::setValue(val);
717 void setValue(boost::any val)
719 AbstractPropertyType::setValue(val);
725 void serialize(const std::string & val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
729 std::stringstream stream(val);
732 setValue((N)someTemp);
736 void serialize(const std::string & val, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
738 std::stringstream stream(GVS<T>::stringize(val));
745 GVariant* serializeVariant(const T val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
747 return (g_variant_new("i",(int)val));
751 GVariant* serializeVariant(const T val, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
753 return g_variant_new(GVS<T>::signature(),val);
757 T deserializeVariant(GVariant* v, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
759 return (T)GVS<int>::value(v);
763 T deserializeVariant(GVariant* v, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
765 return GVS<T>::value(v);
769 class StringPropertyType: public AbstractPropertyType
775 :AbstractPropertyType("")
777 setValue(std::string());
780 StringPropertyType(std::string propertyName)
781 :AbstractPropertyType(propertyName)
783 setValue(std::string());
786 StringPropertyType(std::string propertyName, std::string val)
787 :AbstractPropertyType(propertyName)
792 StringPropertyType(StringPropertyType const & other)
793 :AbstractPropertyType(other.name)
795 setValue(other.value<std::string>());
796 timestamp = other.timestamp;
797 sequence = other.sequence;
798 sourceUuid = other.sourceUuid;
803 StringPropertyType & operator = (StringPropertyType const & other)
805 setValue(other.value<std::string>());
806 timestamp = other.timestamp;
807 sequence = other.sequence;
808 sourceUuid = other.sourceUuid;
815 StringPropertyType & operator = (std::string const & other)
817 setValue(std::string(other));
821 bool operator < (const StringPropertyType& other) const
823 return value<std::string>() < other.value<std::string>();
826 virtual const picojson::value toJson()
828 auto val = AbstractPropertyType::toJson();
830 picojson::object obj = val.get<picojson::object>();
832 obj["value"] = amb::gvariantToJson(toVariant());
835 virtual void fromJson(const picojson::value &json)
837 AbstractPropertyType::fromJson(json);
839 fromString(json.get("value").to_str());
842 void fromString(std::string val)
847 AbstractPropertyType* copy()
849 return new StringPropertyType(*this);
852 std::string toString() const
854 return value<std::string>();
857 GVariant* toVariant()
859 //mVariant = Glib::Variant<std::string>::create(toString());
861 return g_variant_new_string(toString().c_str());
865 void fromVariant(GVariant *v)
867 setValue(std::string(g_variant_get_string(v,NULL)));
872 * \brief ListPropertyType is a AbstractPropertyType for arrays of AbstractPropertyTypes
875 class ListPropertyType: public AbstractPropertyType
879 ListPropertyType(std::string propertyName)
880 : AbstractPropertyType(propertyName), initialized(false)
885 ListPropertyType(std::string propertyName, T value)
886 : AbstractPropertyType(propertyName), initialized(false)
891 ListPropertyType(ListPropertyType & other)
892 :AbstractPropertyType(other.name),initialized(false)
894 std::vector<T> l = other.list();
900 timestamp = other.timestamp;
901 sequence = other.sequence;
902 sourceUuid = other.sourceUuid;
912 /*! \brief append - appends a property to the list
913 * \arg property - property to be appended.
915 void append(T property)
923 appendPriv(property);
931 AbstractPropertyType* copy()
933 return new ListPropertyType(*this);
936 void quickCopy(AbstractPropertyType* other)
938 AbstractPropertyType::quickCopy(other);
939 ListPropertyType<T>* v = static_cast<ListPropertyType<T>*>(other);
942 DebugOut(DebugOut::Error) << "ListPropertyType Quick Copy failed" << endl;
948 std::string toString() const
950 picojson::array array;
954 array.push_back(GVS<T>::toJson(i));
957 return picojson::value(array).serialize();
961 void fromString(std::string str)
963 if(!boost::algorithm::starts_with(str, "["))
966 if(!boost::algorithm::ends_with(str, "]"))
969 picojson::value value;
970 picojson::parse(value, str);
972 DebugOut()<< "str " << str << endl;
975 picojson::array array = value.get<picojson::array>();
979 mList.push_back(GVS<T>::fromJson(i));
982 timestamp = amb::currentTime();
986 GVariant* toVariant()
988 GVariantBuilder params;
989 g_variant_builder_init(¶ms, ((const GVariantType *) "av"));
991 for(auto itr : mList)
993 GVariant *newvar = g_variant_new("v", g_variant_new(GVS<T>::signature(), GVS<T>::gvalue(itr)));
994 g_variant_builder_add_value(¶ms, newvar);
997 GVariant* var = g_variant_builder_end(¶ms);
1003 void fromVariant(GVariant* v)
1007 /// TODO: fill this in
1008 gsize dictsize = g_variant_n_children(v);
1009 for (int i=0;i<dictsize;i++)
1011 GVariant *childvariant = g_variant_get_child_value(v,i);
1012 GVariant *innervariant = g_variant_get_variant(childvariant);
1013 appendPriv(GVS<T>::value(innervariant));
1017 std::vector<T> list() { return mList; }
1026 void appendPriv(T i)
1033 std::vector<T> mList;