Merge pull request #19 from tripzero/master
[profile/ivi/automotive-message-broker.git] / lib / abstractroutingengine.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
20 #ifndef ABSTRACTROUTINGENGINE_H
21 #define ABSTRACTROUTINGENGINE_H
22
23 #include <sys/types.h>
24 #include <stdlib.h>
25 #include <boost/any.hpp>
26 #include <functional>
27 #include <string>
28 #include <time.h>
29
30 #include "vehicleproperty.h"
31 #include "abstractpropertytype.h"
32 #include "propertyinfo.hpp"
33
34 class AbstractSink;
35 class AbstractSource;
36 class AsyncPropertyReply;
37 class AsyncRangePropertyReply;
38 class AsyncSetPropertyRequest;
39
40
41 typedef std::function<void (AsyncPropertyReply*)> GetPropertyCompletedSignal;
42 typedef std::function<void (AsyncRangePropertyReply*)> GetRangedPropertyCompletedSignal;
43
44 /*!
45  * \brief The AsyncPropertyRequest class is used by sinks to request property values.
46  * \see AbstractRoutingEngine::getPropertyAsync
47  * \see AsyncPropertyReply
48  */
49 class AsyncPropertyRequest
50 {
51 public:
52         AsyncPropertyRequest()
53                 :property(VehicleProperty::NoValue),zoneFilter(Zone::None), timeout(10000)
54         {
55
56         }
57
58         AsyncPropertyRequest(const AsyncPropertyRequest &request)
59         {
60                 this->property = request.property;
61                 this->completed = request.completed;
62                 this->sourceUuidFilter = request.sourceUuidFilter;
63                 this->zoneFilter = request.zoneFilter;
64                 this->timeout = request.timeout;
65         }
66
67         AsyncPropertyRequest & operator = (const AsyncPropertyRequest & other)
68         {
69                 this->property = other.property;
70                 this->completed = other.completed;
71                 this->sourceUuidFilter = other.sourceUuidFilter;
72                 this->zoneFilter = other.zoneFilter;
73                 this->timeout = other.timeout;
74
75                 return *this;
76         }
77
78         virtual ~AsyncPropertyRequest() { }
79
80         /*!
81          * \brief property property to request.
82          */
83         VehicleProperty::Property property;
84
85         /*!
86          * \brief sourceUuidFilter the requesting sink should use this to filter on a specific source or leave blank to use any source
87          */
88         std::string sourceUuidFilter;
89
90         /*!
91          * \brief zoneFilter the requesting sink should use this if he wants to filter on a specific zone
92          */
93         Zone::Type zoneFilter;
94
95         /*!
96          * \brief completed the callback when the request has been completed.
97          */
98         GetPropertyCompletedSignal completed;
99
100         /*!
101          * \brief use to specify a timeout in ms for the request.  When a timeout occurs, the 'completed' callback
102          * will be called with an error.  @see AsyncPropertyReply
103          * default value is: 10000 ms
104          */
105         uint timeout;
106
107         /*!
108          * \brief pid requesting process id
109          */
110         std::string pid;
111 };
112
113 /*!
114  * \brief The AsyncPropertyReply class is used by sources to reply to Get and Set operations.  The source should
115  * set success to true if the call is successful or 'false' if the request was not successful and set 'error'
116  * to the appropriate error.
117  * \see AbstractRoutingEngine::getPropertyAsync
118  * \see AsyncPropertyReply
119  * \see AbstractSource::Operations
120  * \see AbstractSource::getPropertyAsync
121  */
122 class AsyncPropertyReply: public AsyncPropertyRequest
123 {
124 public:
125         AsyncPropertyReply();
126
127         AsyncPropertyReply(const AsyncPropertyRequest &request);
128
129         AsyncPropertyReply(const AsyncSetPropertyRequest &request);
130
131         virtual ~AsyncPropertyReply()
132         {
133                 if(timeoutSource)
134                 {
135                         g_source_destroy(timeoutSource);
136                         g_source_unref(timeoutSource);
137                 }
138         }
139
140         /*!
141          * \brief The Error enum
142          */
143         enum Error {
144                 NoError = 0,
145                 Timeout,
146                 InvalidOperation,
147                 PermissionDenied,
148                 ZoneNotSupported
149         };
150
151         /*!
152          * \brief value of the reply.  This may be null if success = false.  This is owned by the source.
153          */
154         AbstractPropertyType* value;
155
156         /*!
157          * \brief success indicates if the request was successfull or not.  True means success.  False means fail and the 'error'
158          * member should be set.
159          */
160         bool success;
161
162         /*!
163          * \brief error contains the error if the request was not successful.\
164          * \see Error
165          */
166         Error error;
167
168 private:
169         void setTimeout();
170         GSource* timeoutSource;
171 };
172
173 /*!
174  * \brief The AsyncSetPropertyRequest class is used by sinks to set a property to the 'value'.  The source will reply
175  * with a AsyncPropertyReply containing the new value or an error.
176  * \see AbstractRoutingEngine::setProperty
177  * \see AsyncPropertyReply
178  */
179 class AsyncSetPropertyRequest: public AsyncPropertyRequest
180 {
181 public:
182         AsyncSetPropertyRequest()
183                 :value(NULL)
184         {
185
186         }
187
188         AsyncSetPropertyRequest(const AsyncPropertyRequest &request)
189                 :AsyncPropertyRequest(request), value(NULL)
190         {
191
192         }
193
194         virtual ~AsyncSetPropertyRequest()
195         {
196
197         }
198
199         /*!
200          * \brief value the new value to set the property to.
201          */
202         AbstractPropertyType* value;
203 };
204
205 /*!
206  * \brief The AsyncRangePropertyRequest class is used by sinks to request values within a time or sequence range
207  * \see AbstractRoutingEngine::getRangePropertyAsync
208  */
209 class AsyncRangePropertyRequest
210 {
211 public:
212         AsyncRangePropertyRequest()
213                 :zone(Zone::None), timeBegin(0), timeEnd(0), sequenceBegin(-1), sequenceEnd(-1)
214         {
215
216         }
217
218         AsyncRangePropertyRequest(const AsyncRangePropertyRequest &request)
219         {
220                 this->properties = request.properties;
221                 this->completed = request.completed;
222                 this->timeBegin = request.timeBegin;
223                 this->timeEnd = request.timeEnd;
224                 this->sequenceBegin = request.sequenceBegin;
225                 this->sequenceEnd = request.sequenceEnd;
226                 this->sourceUuid = request.sourceUuid;
227                 this->zone = request.zone;
228         }
229
230         virtual ~AsyncRangePropertyRequest() {}
231
232         /*!
233          * \brief properties list of properties to request
234          */
235         PropertyList properties;
236
237         /*!
238          * \brief sourceUuid if the sink wishes to request a specific source, this should be set to the uuid of the source.
239          */
240         std::string sourceUuid;
241
242         /*!
243          * \brief zone if the sink wishes to request a specific zone, this should be set to the desired zone .
244          */
245         Zone::Type zone;
246
247         /*!
248          * \brief completed callback that is called when the ranged request is complete. The reply from this request is passed
249          * into the completed call.  The completed callback must free the reply before it returns or there will be a leak.
250          */
251         GetRangedPropertyCompletedSignal completed;
252
253         /*!
254          * \brief timeBegin set this to request values for the specified property beggining at this time.  Time is seconds\
255          * since the unix epoc.  Set this to '0' if you do not want values within a time range.
256          */
257         double timeBegin;
258
259         /*!
260          * \brief timeEnd set this to request values for the specified property beggining at this time.  Time is seconds\
261          * since the unix epoc.  Set this to '0' if you do not want values within a time range.
262          */
263         double timeEnd;
264
265         /*!
266          * \brief sequenceBegin set this to request values with a sequence >= to the sequenceBegin value.  Set to -1 if
267          * you don't want values within a sequence ranges.
268          */
269         int32_t sequenceBegin;
270
271         /*!
272          * \brief sequenceEnd set this to request values with a sequence <= to the sequenceEnd value.  Set to -1 if
273          * you don't want values within a sequence ranges.
274          */
275         int32_t sequenceEnd;
276
277         /*!
278          * \brief pid requesting process id
279          */
280         std::string pid;
281 };
282
283 /*!
284  * \brief The AsyncRangePropertyReply class is used by a source to reply to an AsyncRangePropertyRequest.
285  * the source should set success to 'true' and populate the 'values' member if the request was successful.
286  * If the request is not successful, 'success' should be set to 'false' and the 'error' member should be set.
287  */
288 class AsyncRangePropertyReply: public AsyncRangePropertyRequest
289 {
290 public:
291         AsyncRangePropertyReply(AsyncRangePropertyRequest request)
292                 :AsyncRangePropertyRequest(request), success(false)
293         {
294
295         }
296
297         ~AsyncRangePropertyReply()
298         {
299                 for(auto itr = values.begin(); itr != values.end(); itr++)
300                 {
301                         delete (*itr);
302                 }
303
304                 values.clear();
305         }
306
307         /*!
308          * \brief error this is set if there was an error in the request.  "success" will also be set to false.
309          */
310         AsyncPropertyReply::Error error;
311
312         /*!
313          * \brief values if the request was successful, this will contain a list of values meeting the criteria of the request.
314          */
315         std::list<AbstractPropertyType*> values;
316
317         /*!
318          * \brief success this will be true if the request was successful.  If not, this is false and error is set.
319          */
320         bool success;
321 };
322
323 class AbstractRoutingEngine
324 {
325 public:
326         typedef std::function<void (AbstractPropertyType* value)> PropertyChangedType;
327
328         AbstractRoutingEngine(std::map<std::string, std::string> configuration):mConfig(configuration) {}
329         virtual ~AbstractRoutingEngine();
330
331         virtual void registerSource(AbstractSource* src) = 0;
332         virtual void updateSupported(PropertyList added, PropertyList removed, AbstractSource* source) = 0;
333
334
335         /// Deprecated:
336         void updateProperty(VehicleProperty::Property property, AbstractPropertyType* value, std::string uuid)
337         {
338                 DebugOut(DebugOut::Warning)<<"updateProperty(VehicleProperty::Property,AbstractPropertyType*,std::string) is deprecated.  use new updateProperty(AbstractPropertyType*, const std::string &)"<<endl;
339                 updateProperty(value,uuid);
340         }
341
342         virtual void updateProperty(AbstractPropertyType* value, const std::string &uuid) = 0;
343         virtual PropertyList supported() = 0;
344
345         /// sinks:
346         virtual void registerSink(AbstractSink* self) = 0;
347         virtual void  unregisterSink(AbstractSink* self) = 0;
348
349         /**
350          * /brief sourcesForProperty
351          * /param property
352          * /return list of source uuid's that support the "property"
353          */
354         virtual std::list<std::string> sourcesForProperty(VehicleProperty::Property property) = 0;
355
356         /**
357          * /brief getPropertyAsync requests a property value from a source.  This call has a timeout and the callback specified in the request will always be called.
358          * /see AsyncPropertyRequest
359          * /see AsyncPropertyReply.
360          * /param request requested property.
361          * /return AsyncPropertyReply. The returned AsyncPropertyReply is owned by the caller of getPropertyAsync.
362          * /example AsyncPropertyRequest request;
363          * request.property = VehicleProperty::VehicleSpeed
364          * request.completed = [](AsyncPropertyReply* reply)
365          * {
366          *   //you own the reply
367          *   delete reply;
368          * };
369          * routingEngine->getPropertyAsync(request);
370          */
371         virtual AsyncPropertyReply * getPropertyAsync(AsyncPropertyRequest request) = 0;
372
373         /*!
374          * \brief getRangePropertyAsync is used for getting a range of properties that are within the specified time or sequence parameters.
375          * \param request the request containing the property and other information required by the query
376          * \return a pointer to the reply.
377          * \example AsyncRangePropertyRequest vehicleSpeedFromLastWeek;
378          *
379          *      vehicleSpeedFromLastWeek.timeBegin = amb::currentTime() - 10;
380          *      vehicleSpeedFromLastWeek.timeEnd = amb::currentTime();
381          *
382          *      PropertyList requestList;
383          *      requestList.push_back(VehicleProperty::VehicleSpeed);
384          *      requestList.push_back(VehicleProperty::EngineSpeed);
385          *
386          *      vehicleSpeedFromLastWeek.properties = requestList;
387          *      vehicleSpeedFromLastWeek.completed = [](AsyncRangePropertyReply* reply)
388          *      {
389          *              std::list<AbstractPropertyType*> values = reply->values;
390          *              for(auto itr = values.begin(); itr != values.end(); itr++)
391          *              {
392          *                      auto val = *itr;
393          *                      DebugOut(1)<<"Value from past: ("<<val->name<<"): "<<val->toString()<<" time: "<<val->timestamp<<endl;
394          *              }
395          *
396          *              delete reply;
397          *      };
398          *
399          *      routingEngine->getRangePropertyAsync(vehicleSpeedFromLastWeek);
400          *
401          */
402         virtual AsyncRangePropertyReply * getRangePropertyAsync(AsyncRangePropertyRequest request) = 0;
403
404         /*!
405          * \brief setProperty sets a property to a value.
406          * \see AsyncSetPropertyRequest
407          * \see AsyncPropertyReply
408          * \param request the request containing the property and the value to set
409          * \return a pointer to the reply which is owned by the caller of this method
410          * \example 
411          */
412         virtual AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request) = 0;
413
414         /*!
415          * \brief subscribeToProperty subscribes to propertyName.  Value changes will be passed to callback.
416          * \param propertyName
417          * \param callback
418          * \param pid process id of the requesting application
419          * \return subscription handle
420          */
421         virtual uint subscribeToProperty(const VehicleProperty::Property & propertyName, PropertyChangedType callback, std::string pid="") = 0;
422
423         /*!
424          * \brief unsubscribeToProperty
425          * \param handle
426          */
427         virtual void unsubscribeToProperty(uint handle) = 0;
428
429         /*!
430          * \brief subscribeToProperty subscribe to changes made to a property value.
431          * \param propertyName name of the property to request a subscription for.
432          * \param self pointer to the sink who is subscribing.
433          * \example
434          * //somewhere in the sink:
435          * routingEngine->subscribeToProperty(VehicleProperty::EngineSpeed, this);
436          *
437          * //... elsewhere in the sink, this will be called when a property changes:
438          * void MySink::propertyChanged(const AbstractPropertyType* property)
439          * {
440          *   if(property->name == VehicleProperty::EngineSpeed)
441          *   {
442          *      ...
443          *   }
444          * }
445          */
446         virtual bool subscribeToProperty(const VehicleProperty::Property & propertyName, AbstractSink* self) = 0;
447
448         /*!
449          * \brief subscribeToProperty subscribe to changes made to a property value.
450          * \param propertyName name of the property to request a subscription for.
451          * \param sourceUuidFilter source UUID to filter.  Only property updates from this source will be sent to the sink.
452          * \param self pointer to the sink who is subscribing.
453          */
454         virtual bool subscribeToProperty(const VehicleProperty::Property & propertyName, const std::string & sourceUuidFilter, AbstractSink *self) = 0;
455
456         /*!
457          * \brief subscribeToProperty subscribe to changes made to a property value.
458          * \param propertyName name of the property to request a subscription for.
459          * \param sourceUuidFilter source UUID to filter.  Only property updates from this source will be sent to the sink.
460          * \param zoneFilter zone to filter.  Only updates from this zone will be passed to the sink.
461          * \param self pointer to the sink who is subscribing.
462          */
463         virtual bool subscribeToProperty(const VehicleProperty::Property & propertyName, const std::string & sourceUuidFilter, Zone::Type zoneFilter, AbstractSink *self) = 0;
464
465         virtual bool unsubscribeToProperty(const VehicleProperty::Property &, AbstractSink* self) = 0;
466
467         virtual PropertyInfo getPropertyInfo(const VehicleProperty::Property &, const std::string & sourceUuid) = 0;
468
469 protected:
470         std::map<std::string, std::string> mConfig;
471 };
472
473 #endif // ABSTRACTROUTINGENGINE_H