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 internalUpdate(false), 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 internalUpdate is used to update the property value of AMB internally
243 * without calling its related callback functions. Default value is false.
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
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.
256 * TODO: this may be able to provide a replacement for set and get error codes: \ref AsyncPropertyReply::Error
258 amb::Quality::ValueQuality valueQuality;
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")
265 virtual void setValue(boost::any val)
268 timestamp = amb::currentTime();
269 valueQuality = amb::Quality::Good;
273 * \brief value() native value. Does not use type coercion. Will throw if types do not match.
275 template <typename T>
278 return boost::any_cast<T>(mValue);
283 * \return boost::any value
285 boost::any anyValue()
292 * \return gvariant signature
294 virtual const string signature()
296 auto var = amb::make_super(toVariant());
299 const string s = g_variant_get_type_string(var.get());
304 * \brief destroyed is called if this property is destroyed.
306 std::vector<std::function<void(AbstractPropertyType*)>> destroyed;
318 struct PropertyCompare
320 bool operator()(AbstractPropertyType* const & lhs, AbstractPropertyType* & rhs) const
322 if (lhs->name == rhs->name
323 && lhs->sourceUuid == rhs->sourceUuid
324 && lhs->zone == rhs->zone)
340 static double fromJson(picojson::value v)
342 return v.get<double>();
345 static picojson::value toJson(double v)
347 return picojson::value(v);
354 static bool fromJson(picojson::value v)
356 return v.get<bool>();
359 static picojson::value toJson(bool v)
361 return picojson::value(v);
368 static std::string fromJson(picojson::value v)
370 return v.get<std::string>();
373 static picojson::value toJson(std::string v)
375 return picojson::value(v);
380 template <typename T>
390 template <typename T>
394 class GVS<int> : public BaseGVS<int>, public JsonNumber
397 static const char* signature() { return "i"; }
399 static int value(GVariant* v)
402 g_variant_get(v, signature(), &val);
406 static std::string stringize(std::string v)
413 class GVS<double> : public BaseGVS<double>, public JsonNumber
416 static const char* signature() { return "d"; }
418 static double value(GVariant* v)
420 return g_variant_get_double(v);
422 static std::string stringize(std::string v)
429 class GVS<uint16_t> : public BaseGVS<uint16_t>, public JsonNumber
432 static const char* signature() { return "q"; }
434 static uint16_t value(GVariant* v)
436 return g_variant_get_uint16(v);
438 static std::string stringize(std::string v)
445 class GVS<int16_t> : public BaseGVS<int16_t>, public JsonNumber
448 static const char* signature() { return "n"; }
450 static int16_t value(GVariant* v)
452 return g_variant_get_int16(v);
454 static std::string stringize(std::string v)
461 class GVS<char> : public BaseGVS<char>, public JsonNumber
464 static const char* signature() { return "y"; }
466 static char value(GVariant* v)
468 return g_variant_get_byte(v);
470 static std::string stringize(std::string v)
477 class GVS<uint32_t> : public BaseGVS<uint32_t>, public JsonNumber
480 static const char* signature() { return "u"; }
482 static uint32_t value(GVariant* v)
484 return g_variant_get_uint32(v);
486 static std::string stringize(std::string v)
493 class GVS<int64_t> : public BaseGVS<int64_t>, public JsonNumber
496 static const char* signature() { return "x"; }
498 static int64_t value(GVariant* v)
500 return g_variant_get_int64(v);
502 static std::string stringize(std::string v)
509 class GVS<uint64_t> : public BaseGVS<uint64_t>, public JsonNumber
512 static const char* signature() { return "t"; }
514 static uint64_t value(GVariant* v)
516 return g_variant_get_uint64(v);
518 static std::string stringize(std::string v)
525 class GVS<bool> : public BaseGVS<bool>, public JsonBoolean
528 static const char* signature() { return "b"; }
530 static bool value(GVariant *v)
532 return g_variant_get_boolean(v);
534 static std::string stringize(std::string v)
536 if(v == "0" || v == "1")
539 boost::algorithm::to_lower(v);
540 return v == "true" ? "1":"0";
545 class GVS<std::string> : public JsonString
548 static const char* signature() { return "s"; }
550 static const char* value(GVariant *v)
552 return g_variant_get_string(v, nullptr);
554 static std::string stringize(std::string v)
558 static const char* gvalue(std::string v)
565 * \brief BasicPropertyType is a typed property type. Most internal types are derived from this class
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());
571 template <typename T>
572 class BasicPropertyType: public AbstractPropertyType
575 BasicPropertyType(): AbstractPropertyType("")
580 BasicPropertyType(BasicPropertyType const & other)
581 :AbstractPropertyType(other.name)
583 setValue(other.value<T>());
584 timestamp = other.timestamp;
585 sequence = other.sequence;
586 sourceUuid = other.sourceUuid;
592 BasicPropertyType & operator = (BasicPropertyType const & other)
594 setValue(other.value<T>());
595 timestamp = other.timestamp;
596 sequence = other.sequence;
597 sourceUuid = other.sourceUuid;
604 BasicPropertyType & operator = (T const & other)
610 BasicPropertyType & operator ++ ()
612 setValue(basicValue() + 1);
615 BasicPropertyType & operator -- ()
617 setValue(basicValue() - 1);
620 bool operator < (const BasicPropertyType<T>& other) const
622 return value<T>() < other.value<T>();
625 bool operator > (const BasicPropertyType<T>& other) const
627 return value<T>() > other.value<T>();
630 BasicPropertyType( T val)
631 :AbstractPropertyType("")
636 BasicPropertyType( std::string propertyName, T val)
637 :AbstractPropertyType(propertyName)
642 BasicPropertyType( std::string propertyName, std::string val)
643 :AbstractPropertyType(propertyName)
645 if(!val.empty() && val != "")
652 BasicPropertyType(std::string propertyName)
653 :AbstractPropertyType(propertyName)
658 AbstractPropertyType* copy()
660 return new BasicPropertyType<T>(*this);
663 const picojson::value toJson()
665 picojson::value v = AbstractPropertyType::toJson();
667 picojson::object object = v.get<picojson::object>();
669 object["value"] = amb::gvariantToJson(toVariant());
671 return picojson::value(object);
674 virtual void fromJson(const picojson::value &json)
676 AbstractPropertyType::fromJson(json);
678 fromVariant(amb::jsonToGVariant(json.get("value"), signature()));
681 void fromString(std::string val)
683 if(!val.empty() && val != "")
689 std::string toString() const
691 std::stringstream stream;
692 stream.precision(10);
698 GVariant* toVariant()
700 return serializeVariant<T>(value<T>());
703 void fromVariant(GVariant *v)
705 setValue(deserializeVariant<T>(v));
710 * \return Typed version of value. Slightly more useful than \see AbstractPropertyType::value()
720 AbstractPropertyType::setValue(val);
723 void setValue(boost::any val)
725 AbstractPropertyType::setValue(val);
731 void serialize(const std::string & val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
735 std::stringstream stream(val);
738 setValue((N)someTemp);
742 void serialize(const std::string & val, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
744 std::stringstream stream(GVS<T>::stringize(val));
751 GVariant* serializeVariant(const T val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
753 return (g_variant_new("i",(int)val));
757 GVariant* serializeVariant(const T val, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
759 return g_variant_new(GVS<T>::signature(),val);
763 T deserializeVariant(GVariant* v, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
765 return (T)GVS<int>::value(v);
769 T deserializeVariant(GVariant* v, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
771 return GVS<T>::value(v);
775 class StringPropertyType: public AbstractPropertyType
781 :AbstractPropertyType("")
783 setValue(std::string());
786 StringPropertyType(std::string propertyName)
787 :AbstractPropertyType(propertyName)
789 setValue(std::string());
792 StringPropertyType(std::string propertyName, std::string val)
793 :AbstractPropertyType(propertyName)
798 StringPropertyType(StringPropertyType const & other)
799 :AbstractPropertyType(other.name)
801 setValue(other.value<std::string>());
802 timestamp = other.timestamp;
803 sequence = other.sequence;
804 sourceUuid = other.sourceUuid;
809 StringPropertyType & operator = (StringPropertyType const & other)
811 setValue(other.value<std::string>());
812 timestamp = other.timestamp;
813 sequence = other.sequence;
814 sourceUuid = other.sourceUuid;
821 StringPropertyType & operator = (std::string const & other)
823 setValue(std::string(other));
827 bool operator < (const StringPropertyType& other) const
829 return value<std::string>() < other.value<std::string>();
832 virtual const picojson::value toJson()
834 auto val = AbstractPropertyType::toJson();
836 picojson::object obj = val.get<picojson::object>();
838 obj["value"] = amb::gvariantToJson(toVariant());
841 virtual void fromJson(const picojson::value &json)
843 AbstractPropertyType::fromJson(json);
845 fromString(json.get("value").to_str());
848 void fromString(std::string val)
853 AbstractPropertyType* copy()
855 return new StringPropertyType(*this);
858 std::string toString() const
860 return value<std::string>();
863 GVariant* toVariant()
865 //mVariant = Glib::Variant<std::string>::create(toString());
867 return g_variant_new_string(toString().c_str());
871 void fromVariant(GVariant *v)
873 setValue(std::string(g_variant_get_string(v,NULL)));
878 * \brief ListPropertyType is a AbstractPropertyType for arrays of AbstractPropertyTypes
881 class ListPropertyType: public AbstractPropertyType
885 ListPropertyType(std::string propertyName)
886 : AbstractPropertyType(propertyName), initialized(false)
891 ListPropertyType(std::string propertyName, T value)
892 : AbstractPropertyType(propertyName), initialized(false)
897 ListPropertyType(ListPropertyType & other)
898 :AbstractPropertyType(other.name),initialized(false)
900 std::vector<T> l = other.list();
906 timestamp = other.timestamp;
907 sequence = other.sequence;
908 sourceUuid = other.sourceUuid;
918 /*! \brief append - appends a property to the list
919 * \arg property - property to be appended.
921 void append(T property)
929 appendPriv(property);
937 AbstractPropertyType* copy()
939 return new ListPropertyType(*this);
942 void quickCopy(AbstractPropertyType* other)
944 AbstractPropertyType::quickCopy(other);
945 ListPropertyType<T>* v = static_cast<ListPropertyType<T>*>(other);
948 DebugOut(DebugOut::Error) << "ListPropertyType Quick Copy failed" << endl;
954 std::string toString() const
956 picojson::array array;
960 array.push_back(GVS<T>::toJson(i));
963 return picojson::value(array).serialize();
967 void fromString(std::string str)
969 if(!boost::algorithm::starts_with(str, "["))
972 if(!boost::algorithm::ends_with(str, "]"))
975 picojson::value value;
976 picojson::parse(value, str);
978 DebugOut()<< "str " << str << endl;
981 picojson::array array = value.get<picojson::array>();
985 mList.push_back(GVS<T>::fromJson(i));
988 timestamp = amb::currentTime();
992 GVariant* toVariant()
994 GVariantBuilder params;
995 g_variant_builder_init(¶ms, ((const GVariantType *) "av"));
997 for(auto itr : mList)
999 GVariant *newvar = g_variant_new("v", g_variant_new(GVS<T>::signature(), GVS<T>::gvalue(itr)));
1000 g_variant_builder_add_value(¶ms, newvar);
1003 GVariant* var = g_variant_builder_end(¶ms);
1009 void fromVariant(GVariant* v)
1013 /// TODO: fill this in
1014 gsize dictsize = g_variant_n_children(v);
1015 for (int i=0;i<dictsize;i++)
1017 GVariant *childvariant = g_variant_get_child_value(v,i);
1018 GVariant *innervariant = g_variant_get_variant(childvariant);
1019 appendPriv(GVS<T>::value(innervariant));
1023 std::vector<T> list() { return mList; }
1032 void appendPriv(T i)
1039 std::vector<T> mList;