Merge pull request #15 from e8johan/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 /*!
109  * \brief The AsyncPropertyReply class is used by sources to reply to Get and Set operations.  The source should
110  * set success to true if the call is successful or 'false' if the request was not successful and set 'error'
111  * to the appropriate error.
112  * \see AbstractRoutingEngine::getPropertyAsync
113  * \see AsyncPropertyReply
114  * \see AbstractSource::Operations
115  * \see AbstractSource::getPropertyAsync
116  */
117 class AsyncPropertyReply: public AsyncPropertyRequest
118 {
119 public:
120         AsyncPropertyReply(const AsyncPropertyRequest &request);
121
122         AsyncPropertyReply(const AsyncSetPropertyRequest &request);
123
124         virtual ~AsyncPropertyReply()
125         {
126                 if(timeoutSource)
127                 {
128                         g_source_destroy(timeoutSource);
129                         g_source_unref(timeoutSource);
130                 }
131         }
132
133         /*!
134          * \brief The Error enum
135          */
136         enum Error {
137                 NoError = 0,
138                 Timeout,
139                 InvalidOperation,
140                 PermissionDenied,
141                 ZoneNotSupported
142         };
143
144         /*!
145          * \brief value of the reply.  This may be null if success = false.  This is owned by the source.
146          */
147         AbstractPropertyType* value;
148
149         /*!
150          * \brief success indicates if the request was successfull or not.  True means success.  False means fail and the 'error'
151          * member should be set.
152          */
153         bool success;
154
155         /*!
156          * \brief error contains the error if the request was not successful.\
157          * \see Error
158          */
159         Error error;
160
161 private:
162         void setTimeout();
163         GSource* timeoutSource;
164 };
165
166 /*!
167  * \brief The AsyncSetPropertyRequest class is used by sinks to set a property to the 'value'.  The source will reply
168  * with a AsyncPropertyReply containing the new value or an error.
169  * \see AbstractRoutingEngine::setProperty
170  * \see AsyncPropertyReply
171  */
172 class AsyncSetPropertyRequest: public AsyncPropertyRequest
173 {
174 public:
175         AsyncSetPropertyRequest()
176                 :value(NULL)
177         {
178
179         }
180
181         AsyncSetPropertyRequest(const AsyncPropertyRequest &request)
182                 :AsyncPropertyRequest(request), value(NULL)
183         {
184
185         }
186
187         virtual ~AsyncSetPropertyRequest()
188         {
189
190         }
191
192         /*!
193          * \brief value the new value to set the property to.
194          */
195         AbstractPropertyType* value;
196 };
197
198 /*!
199  * \brief The AsyncRangePropertyRequest class is used by sinks to request values within a time or sequence range
200  * \see AbstractRoutingEngine::getRangePropertyAsync
201  */
202 class AsyncRangePropertyRequest
203 {
204 public:
205         AsyncRangePropertyRequest()
206                 :zone(Zone::None), timeBegin(0), timeEnd(0), sequenceBegin(-1), sequenceEnd(-1)
207         {
208
209         }
210
211         AsyncRangePropertyRequest(const AsyncRangePropertyRequest &request)
212         {
213                 this->properties = request.properties;
214                 this->completed = request.completed;
215                 this->timeBegin = request.timeBegin;
216                 this->timeEnd = request.timeEnd;
217                 this->sequenceBegin = request.sequenceBegin;
218                 this->sequenceEnd = request.sequenceEnd;
219                 this->sourceUuid = request.sourceUuid;
220                 this->zone = request.zone;
221         }
222
223         virtual ~AsyncRangePropertyRequest() {}
224
225         /*!
226          * \brief properties list of properties to request
227          */
228         PropertyList properties;
229
230         /*!
231          * \brief sourceUuid if the sink wishes to request a specific source, this should be set to the uuid of the source.
232          */
233         std::string sourceUuid;
234
235         /*!
236          * \brief zone if the sink wishes to request a specific zone, this should be set to the desired zone .
237          */
238         Zone::Type zone;
239
240         /*!
241          * \brief completed callback that is called when the ranged request is complete. The reply from this request is passed
242          * into the completed call.  The completed callback must free the reply before it returns or there will be a leak.
243          */
244         GetRangedPropertyCompletedSignal completed;
245
246         /*!
247          * \brief timeBegin set this to request values for the specified property beggining at this time.  Time is seconds\
248          * since the unix epoc.  Set this to '0' if you do not want values within a time range.
249          */
250         double timeBegin;
251
252         /*!
253          * \brief timeEnd set this to request values for the specified property beggining at this time.  Time is seconds\
254          * since the unix epoc.  Set this to '0' if you do not want values within a time range.
255          */
256         double timeEnd;
257
258         /*!
259          * \brief sequenceBegin set this to request values with a sequence >= to the sequenceBegin value.  Set to -1 if
260          * you don't want values within a sequence ranges.
261          */
262         int32_t sequenceBegin;
263
264         /*!
265          * \brief sequenceEnd set this to request values with a sequence <= to the sequenceEnd value.  Set to -1 if
266          * you don't want values within a sequence ranges.
267          */
268         int32_t sequenceEnd;
269 };
270
271 /*!
272  * \brief The AsyncRangePropertyReply class is used by a source to reply to an AsyncRangePropertyRequest.
273  * the source should set success to 'true' and populate the 'values' member if the request was successful.
274  * If the request is not successful, 'success' should be set to 'false' and the 'error' member should be set.
275  */
276 class AsyncRangePropertyReply: public AsyncRangePropertyRequest
277 {
278 public:
279         AsyncRangePropertyReply(AsyncRangePropertyRequest request)
280                 :AsyncRangePropertyRequest(request), success(false)
281         {
282
283         }
284
285         ~AsyncRangePropertyReply()
286         {
287                 for(auto itr = values.begin(); itr != values.end(); itr++)
288                 {
289                         delete (*itr);
290                 }
291
292                 values.clear();
293         }
294
295         /*!
296          * \brief error this is set if there was an error in the request.  "success" will also be set to false.
297          */
298         AsyncPropertyReply::Error error;
299
300         /*!
301          * \brief values if the request was successful, this will contain a list of values meeting the criteria of the request.
302          */
303         std::list<AbstractPropertyType*> values;
304
305         /*!
306          * \brief success this will be true if the request was successful.  If not, this is false and error is set.
307          */
308         bool success;
309 };
310
311 class AbstractRoutingEngine
312 {
313 public:
314         virtual ~AbstractRoutingEngine();
315
316         virtual void registerSource(AbstractSource* src) = 0;
317         virtual void updateSupported(PropertyList added, PropertyList removed, AbstractSource* source) = 0;
318
319
320         /// Deprecated:
321         void updateProperty(VehicleProperty::Property property, AbstractPropertyType* value, std::string uuid)
322         {
323                 DebugOut(DebugOut::Warning)<<"updateProperty(VehicleProperty::Property,AbstractPropertyType*,std::string) is deprecated.  use new updateProperty(AbstractPropertyType*, const std::string &)"<<endl;
324                 updateProperty(value,uuid);
325         }
326
327         virtual void updateProperty(AbstractPropertyType* value, const std::string &uuid) = 0;
328         virtual PropertyList supported() = 0;
329
330         /// sinks:
331         virtual void registerSink(AbstractSink* self) = 0;
332         virtual void  unregisterSink(AbstractSink* self) = 0;
333
334         /**
335          * /brief sourcesForProperty
336          * /param property
337          * /return list of source uuid's that support the "property"
338          */
339         virtual std::list<std::string> sourcesForProperty(VehicleProperty::Property property) = 0;
340
341         /**
342          * /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.
343          * /see AsyncPropertyRequest
344          * /see AsyncPropertyReply.
345          * /param request requested property.
346          * /return AsyncPropertyReply. The returned AsyncPropertyReply is owned by the caller of getPropertyAsync.
347          * /example AsyncPropertyRequest request;
348          * request.property = VehicleProperty::VehicleSpeed
349          * request.completed = [](AsyncPropertyReply* reply)
350          * {
351          *   //you own the reply
352          *   delete reply;
353          * };
354          * routingEngine->getPropertyAsync(request);
355          */
356         virtual AsyncPropertyReply * getPropertyAsync(AsyncPropertyRequest request) = 0;
357
358         /*!
359          * \brief getRangePropertyAsync is used for getting a range of properties that are within the specified time or sequence parameters.
360          * \param request the request containing the property and other information required by the query
361          * \return a pointer to the reply.
362          * \example AsyncRangePropertyRequest vehicleSpeedFromLastWeek;
363          *
364          *      vehicleSpeedFromLastWeek.timeBegin = amb::currentTime() - 10;
365          *      vehicleSpeedFromLastWeek.timeEnd = amb::currentTime();
366          *
367          *      PropertyList requestList;
368          *      requestList.push_back(VehicleProperty::VehicleSpeed);
369          *      requestList.push_back(VehicleProperty::EngineSpeed);
370          *
371          *      vehicleSpeedFromLastWeek.properties = requestList;
372          *      vehicleSpeedFromLastWeek.completed = [](AsyncRangePropertyReply* reply)
373          *      {
374          *              std::list<AbstractPropertyType*> values = reply->values;
375          *              for(auto itr = values.begin(); itr != values.end(); itr++)
376          *              {
377          *                      auto val = *itr;
378          *                      DebugOut(1)<<"Value from past: ("<<val->name<<"): "<<val->toString()<<" time: "<<val->timestamp<<endl;
379          *              }
380          *
381          *              delete reply;
382          *      };
383          *
384          *      routingEngine->getRangePropertyAsync(vehicleSpeedFromLastWeek);
385          *
386          */
387         virtual AsyncRangePropertyReply * getRangePropertyAsync(AsyncRangePropertyRequest request) = 0;
388
389         /*!
390          * \brief setProperty sets a property to a value.
391          * \see AsyncSetPropertyRequest
392          * \see AsyncPropertyReply
393          * \param request the request containing the property and the value to set
394          * \return a pointer to the reply which is owned by the caller of this method
395          * \example 
396          */
397         virtual AsyncPropertyReply * setProperty(AsyncSetPropertyRequest request) = 0;
398
399         /*!
400          * \brief subscribeToProperty subscribe to changes made to a property value.
401          * \param propertyName name of the property to request a subscription for.
402          * \param self pointer to the sink who is subscribing.
403          * \example
404          * //somewhere in the sink:
405          * routingEngine->subscribeToProperty(VehicleProperty::EngineSpeed, this);
406          *
407          * //... elsewhere in the sink, this will be called when a property changes:
408          * void MySink::propertyChanged(const AbstractPropertyType* property)
409          * {
410          *   if(property->name == VehicleProperty::EngineSpeed)
411          *   {
412          *      ...
413          *   }
414          * }
415          */
416         virtual bool subscribeToProperty(VehicleProperty::Property propertyName, AbstractSink* self) = 0;
417
418         /*!
419          * \brief subscribeToProperty subscribe to changes made to a property value.
420          * \param propertyName name of the property to request a subscription for.
421          * \param sourceUuidFilter source UUID to filter.  Only property updates from this source will be sent to the sink.
422          * \param self pointer to the sink who is subscribing.
423          */
424         virtual bool subscribeToProperty(VehicleProperty::Property propertyName, std::string sourceUuidFilter, AbstractSink *self) = 0;
425
426         /*!
427          * \brief subscribeToProperty subscribe to changes made to a property value.
428          * \param propertyName name of the property to request a subscription for.
429          * \param sourceUuidFilter source UUID to filter.  Only property updates from this source will be sent to the sink.
430          * \param zoneFilter zone to filter.  Only updates from this zone will be passed to the sink.
431          * \param self pointer to the sink who is subscribing.
432          */
433         virtual bool subscribeToProperty(VehicleProperty::Property propertyName, std::string sourceUuidFilter, Zone::Type zoneFilter, AbstractSink *self) = 0;
434
435         virtual bool unsubscribeToProperty(VehicleProperty::Property, AbstractSink* self) = 0;
436
437         virtual PropertyInfo getPropertyInfo(VehicleProperty::Property, std::string sourceUuid) = 0;
438 };
439
440 #endif // ABSTRACTROUTINGENGINE_H