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