PropertySet_impl.h
Go to the documentation of this file.
1 /*
2  * This file is protected by Copyright. Please refer to the COPYRIGHT file
3  * distributed with this source distribution.
4  *
5  * This file is part of REDHAWK core.
6  *
7  * REDHAWK core is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by the
9  * Free Software Foundation, either version 3 of the License, or (at your
10  * option) any later version.
11  *
12  * REDHAWK core is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program. If not, see http://www.gnu.org/licenses/.
19  */
20 
21 
22 #ifndef PROPERTYSET_IMPL_H
23 #define PROPERTYSET_IMPL_H
24 
25 #include <vector>
26 #include <string>
27 #include <sstream>
28 #include <map>
29 
30 #include <boost/bind.hpp>
31 
32 #include "ossie/debug.h"
33 #include "ossie/PropertyInterface.h"
34 #include "ossie/ProcessThread.h"
35 #include "ossie/Autocomplete.h"
36 #include "CF/cf.h"
37 
38 
40 #ifdef BEGIN_AUTOCOMPLETE_IGNORE
41  : public virtual POA_CF::PropertyEmitter
42 #endif
43 {
44  ENABLE_LOGGING;
45 
46 public:
47 
50 
51  /*
52  * Sets all the execparams passed in runtime
53  */
54  void setExecparamProperties(std::map<std::string, char*>&);
55 
56  void
57  initializeProperties(const CF::Properties& initialProperties)
58  throw (CF::PropertyEmitter::AlreadyInitialized, CF::PropertySet::PartialConfiguration,
59  CF::PropertySet::InvalidConfiguration, CORBA::SystemException);
60 
61  // The core framework provides an implementation for this method.
62  void
63  configure (const CF::Properties& configProperties)
64  throw (CF::PropertySet::PartialConfiguration,
65  CF::PropertySet::InvalidConfiguration, CORBA::SystemException);
66 
67  // The core framework provides an implementation for this method.
68  void
69  query (CF::Properties& configProperties)
70  throw (CF::UnknownProperties, CORBA::SystemException);
71 
72 
73  // Preferred new-style properties.
74  PropertyInterface* getPropertyFromId (const std::string&);
75  PropertyInterface* getPropertyFromName (const std::string&);
76 
77  void registerPropertyChangePort(PropertyEventSupplier* _propertyChangePort) {
78  propertyChangePort = _propertyChangePort;
79  };
80 
81  char *registerPropertyListener( CORBA::Object_ptr listener, const CF::StringSequence &prop_ids, const CORBA::Float interval)
82  throw(CF::UnknownProperties, CF::InvalidObjectReference);
83  void unregisterPropertyListener( const char *reg_id )
84  throw(CF::InvalidIdentifier);
85 
86  //
87  // calls to start and stop property change service function
88  //
89  void startPropertyChangeMonitor( const std::string &rsc_id);
91 
92 protected:
93 
94  /*CF::Properties
95  propertySet;*/
96  CF::DataType
97  getProperty (CORBA::String_var id);
98  void
99  validate (CF::Properties property, CF::Properties& validProps,
100  CF::Properties& invalidProps);
101 
102  /*
103  * Adds a property with no initial value.
104  */
105  template <typename T>
106  PropertyInterface* addProperty (T& value,
107  const std::string& id,
108  const std::string& name,
109  const std::string& mode,
110  const std::string& units,
111  const std::string& action,
112  const std::string& kinds)
113  {
114  PropertyInterface* wrapper = PropertyWrapperFactory::Create(value);
115  wrapper->configure(id, name, mode, units, action, kinds);
116  wrapper->isNil(true);
117  ownedWrappers.push_back(wrapper);
118  propTable[wrapper->id] = wrapper;
119  _propMonitors[wrapper->id] = PropertyChange::MonitorFactory::Create(value);
120  return wrapper;
121  }
122 
123  /*
124  * Adds a property with an initial value.
125  */
126  template <typename T, typename T2>
127  PropertyInterface* addProperty (T& value,
128  const T2& initial_value,
129  const std::string& id,
130  const std::string& name,
131  const std::string& mode,
132  const std::string& units,
133  const std::string& action,
134  const std::string& kinds)
135  {
136  PropertyInterface* wrapper = addProperty(value, id, name, mode, units, action, kinds);
137  value = initial_value;
138  wrapper->isNil(false);
139  return wrapper;
140  }
141 
142  template <class C, typename T>
143  void addPropertyChangeListener (const std::string& id, C* target, void (C::*func)(const T*, const T*))
144  {
145  try {
146  PropertyWrapper<T>* wrapper = getPropertyWrapperById<T>(id);
147  wrapper->addChangeListener(target, func);
148  } catch (const std::invalid_argument& error) {
149  LOG_WARN(PropertySet_impl, "Cannot add change listener: " << error.what());
150  }
151  }
152 
153  template <typename T>
154  void addPropertyChangeListener (const std::string& id, void (*func)(const T*, const T*))
155  {
156  try {
157  PropertyWrapper<T>* wrapper = getPropertyWrapperById<T>(id);
158  wrapper->addChangeListener(func);
159  } catch (const std::invalid_argument& error) {
160  LOG_WARN(PropertySet_impl, "Cannot add change listener: " << error.what());
161  }
162  }
163 
164  template <typename Func>
165  void addPropertyChangeListener (const char* id, Func func)
166  {
167  addPropertyChangeListener(std::string(id), func);
168  }
169 
170  template <typename Target, typename Func>
171  void addPropertyChangeListener (const char* id, Target target, Func func)
172  {
173  addPropertyChangeListener(std::string(id), target, func);
174  }
175 
176  /*
177  * Set a callback function to be invoked on an object other than the property owner whenever the given property changes
178  */
179  template <typename T, typename Target, typename Func>
180  void addPropertyListener (T& value, Target target, Func func)
181  {
182  try {
183  getPropertyWrapper(value)->addChangeListener(target, func);
184  } catch (const std::invalid_argument& error) {
185  LOG_WARN(PropertySet_impl, "Cannot add change listener: " << error.what());
186  }
187  }
188 
189  /*
190  * Set a callback function to be invoked whenever the given property changes
191  */
192  template <typename T, typename Func>
193  void addPropertyListener (T& value, Func func)
194  {
195  try {
196  getPropertyWrapper(value)->addChangeListener(func);
197  } catch (const std::invalid_argument& error) {
198  LOG_WARN(PropertySet_impl, "Cannot add change listener: " << error.what());
199  }
200  }
201 
202  /*
203  * Set the implementation for querying the property value to call member function 'func'
204  * on a class instance 'target'.
205  */
206  template <typename T, typename Target, typename Func>
207  void setPropertyQueryImpl (T& value, Target target, Func func)
208  {
209  try {
210  getPropertyWrapper(value)->setQuery(target, func);
211  } catch (const std::exception& error) {
212  LOG_WARN(PropertySet_impl, "Cannot set query implementation: " << error.what());
213  }
214  }
215 
216  /*
217  * Set the implementation for querying the property value to call the function 'func'.
218  */
219  template <typename T, typename Func>
220  void setPropertyQueryImpl (T& value, Func func)
221  {
222  try {
223  getPropertyWrapper(value)->setQuery(func);
224  } catch (const std::exception& error) {
225  LOG_WARN(PropertySet_impl, "Cannot set query implementation: " << error.what());
226  }
227  }
228 
229  /*
230  * Set the implementation for configuring the property value to call member function 'func'
231  * on a class instance 'target'.
232  */
233  template <typename T, typename Target, typename Func>
234  void setPropertyConfigureImpl (T& value, Target target, Func func)
235  {
236  try {
237  getPropertyWrapper(value)->setConfigure(target, func);
238  } catch (const std::exception& error) {
239  LOG_WARN(PropertySet_impl, "Cannot set configure implementation: " << error.what());
240  }
241  }
242 
243  /*
244  * Set the implementation for configuring the property value to call the function 'func'.
245  */
246  template <typename T, typename Func>
247  void setPropertyConfigureImpl (T& value, Func func)
248  {
249  try {
250  getPropertyWrapper(value)->setConfigure(func);
251  } catch (const std::exception& error) {
252  LOG_WARN(PropertySet_impl, "Cannot set configure implementation: " << error.what());
253  }
254  }
255 
256  /*
257  * Set the callback for changes to a property to a member function on a class instance.
258  * The member function must take a string argument (the identifier of the property that changed)
259  * and return void.
260  */
261  template <class T>
262  void setPropertyChangeListener (const std::string& id, T& target, void (T::*func)(const std::string&))
263  {
264  PropertyCallback cb;
265  cb = boost::bind(func, &target, _1);
266  setPropertyCallback(id, cb);
267  }
268 
269  template <class T>
270  void setPropertyChangeListener (const std::string& id, T* target, void (T::*func)(const std::string&))
271  {
272  PropertyCallback cb;
273  cb = boost::bind(func, target, _1);
274  setPropertyCallback(id, cb);
275  }
276 
277  template <class T>
278  PropertyWrapper<T>* getPropertyWrapperById (const std::string& id)
279  {
280  PropertyInterface* property = getPropertyFromId(id);
281  if (!property) {
282  throw std::invalid_argument("No property '" + id + "'");
283  }
284  return castProperty<T>(property);
285  }
286 
287  template <class T>
288  PropertyWrapper<T>* getPropertyWrapper (T& value)
289  {
290  PropertyInterface* property = getPropertyFromAddress(&value);
291  if (!property) {
292  throw std::invalid_argument("No property associated with value");
293  }
294  return castProperty<T>(property);
295  }
296 
297  PropertyInterface* getPropertyFromAddress(const void* address);
298 
299  /*
300  * Set the callback for changes to a property to a global function.
301  * The function must take a string argument (the identifier of the property that changed)
302  * and return void.
303  */
304  typedef void (*PropertyCallbackFn)(const std::string&);
305  void setPropertyChangeListener (const std::string& id, PropertyCallbackFn func);
306 
307  /*
308  * Call the property change callback for the given identifier.
309  */
310  void executePropertyCallback (const std::string& id);
311 
312  // This mutex is used to deal with configure/query concurrency
313  boost::mutex propertySetAccess;
314 
315  PropertyEventSupplier* propertyChangePort;
316 
317  std::vector<PropertyInterface*> ownedWrappers;
318 
319  // Preferred new-style properties.
320  typedef std::map<std::string, PropertyInterface*> PropertyMap;
321  PropertyMap propTable;
322 
323 private:
324  template <typename T>
325  PropertyWrapper<T>* castProperty(PropertyInterface* property)
326  {
327  PropertyWrapper<T>* wrapper = dynamic_cast<PropertyWrapper<T>*>(property);
328  if (!wrapper) {
329  std::ostringstream message;
330  message << "Property '" << property->id << "' is of type '" << property->getNativeType() << "'"
331  << " (not '" << ossie::traits<T>::name() << "')";
332  throw std::invalid_argument(message.str());
333  }
334  return wrapper;
335  }
336 
337  typedef boost::function<void (const std::string&)> PropertyCallback;
338  void setPropertyCallback (const std::string& id, PropertyCallback callback);
339 
340  typedef std::map<std::string, PropertyCallback> PropertyCallbackMap;
341  PropertyCallbackMap propCallbacks;
342 
343  //
344  // value changed callback when PropertyChangeListeners are registered
345  //
346  struct PCL_Callback {
347  bool isChanged_;
348  bool isRecorded_;
349 
350  PCL_Callback() : isChanged_(false), isRecorded_(false) {};
351  void recordChanged(void) {
352  if ( !isRecorded_ ) {
353  isChanged_ = true;
354  isRecorded_ = true;
355  }
356  };
357  void reset() { isChanged_ = false; isRecorded_=false;};
358  bool isChanged() { return isChanged_; };
359  bool isSet() { return isRecorded_; };
360  };
361 
362  // safe pointer to clean up memory
363  typedef boost::shared_ptr<PCL_Callback> PCL_CallbackPtr;
364 
365  // map of property id to callback methods
366  typedef std::map< std::string, PCL_CallbackPtr > PropertyReportTable;
367 
368  // class that perform change notifications
369  class PropertyChangeListener;
370  class EC_PropertyChangeListener;
371  class INF_PropertyChangeListener;
372  typedef boost::shared_ptr< PropertyChangeListener > PCL_ListenerPtr;
373 
374 
375  // Registration and listerner contect to handle property change notifications
376  struct PropertyChangeRec {
377  static std::string RSC_ID;
378 
379  std::string regId; // registration id
380  CORBA::Object_ptr listener; // listener to send changes to
381  boost::posix_time::time_duration reportInterval; // > 0 wait till
382  boost::posix_time::ptime expiration; // time when next notification should happen
383  std::string rscId; // identifier of source object that change happened to
384  PropertyReportTable props; // list of property ids to report on
385  PCL_ListenerPtr pcl; // listener performs the work...
386 
387  };
388 
389  class PropertyChangeListener {
390  public:
391  virtual ~PropertyChangeListener() {};
392  virtual int notify( PropertyChangeRec *rec, CF::Properties &changes ) = 0;
393  private:
394  };
395 
396 
397  // Mappings of PropertyChangeListeners to registration identifiers
398  typedef std::map< std::string, PropertyChangeRec > PropertyChangeRegistry;
399 
400  friend class PropertyChangeThread;
401 
402  typedef std::map<std::string, PropertyChange::Monitor *> PropertyMonitorTable;
403  PropertyMonitorTable _propMonitors;
404 
405  // Registry of active PropertyChangeListeners
406  PropertyChangeRegistry _propChangeRegistry;
407 
408  // monitor thread that calls our service function
409  ossie::ProcessThread _propChangeThread;
410 
411  // service function that reports on change events
412  int _propertyChangeServiceFunction();
413 
414  bool _propertiesInitialized;
415 };
416 
417 #endif /* */
void validate(CF::Properties property, CF::Properties &validProps, CF::Properties &invalidProps)
PropertyInterface * getPropertyFromId(const std::string &)
void(* PropertyCallbackFn)(const std::string &)
Definition: PropertySet_impl.h:304
void addPropertyListener(T &value, Func func)
Definition: PropertySet_impl.h:193
void registerPropertyChangePort(PropertyEventSupplier *_propertyChangePort)
Definition: PropertySet_impl.h:77
void initializeProperties(const CF::Properties &initialProperties)
void startPropertyChangeMonitor(const std::string &rsc_id)
void setPropertyChangeListener(const std::string &id, T &target, void(T::*func)(const std::string &))
Definition: PropertySet_impl.h:262
void addPropertyChangeListener(const char *id, Target target, Func func)
Definition: PropertySet_impl.h:171
void setPropertyChangeListener(const std::string &id, T *target, void(T::*func)(const std::string &))
Definition: PropertySet_impl.h:270
PropertyInterface * getPropertyFromName(const std::string &)
void addPropertyListener(T &value, Target target, Func func)
Definition: PropertySet_impl.h:180
boost::mutex propertySetAccess
Definition: PropertySet_impl.h:313
PropertyInterface * getPropertyFromAddress(const void *address)
void unregisterPropertyListener(const char *reg_id)
friend class PropertyChangeThread
Definition: PropertySet_impl.h:400
void executePropertyCallback(const std::string &id)
PropertyMap propTable
Definition: PropertySet_impl.h:321
PropertyInterface * addProperty(T &value, const T2 &initial_value, const std::string &id, const std::string &name, const std::string &mode, const std::string &units, const std::string &action, const std::string &kinds)
Definition: PropertySet_impl.h:127
PropertyInterface * addProperty(T &value, const std::string &id, const std::string &name, const std::string &mode, const std::string &units, const std::string &action, const std::string &kinds)
Definition: PropertySet_impl.h:106
PropertyWrapper< T > * getPropertyWrapperById(const std::string &id)
Definition: PropertySet_impl.h:278
CF::DataType getProperty(CORBA::String_var id)
void setExecparamProperties(std::map< std::string, char * > &)
void query(CF::Properties &configProperties)
void addPropertyChangeListener(const char *id, Func func)
Definition: PropertySet_impl.h:165
void setPropertyQueryImpl(T &value, Func func)
Definition: PropertySet_impl.h:220
float Float
Definition: bulkio_base.h:155
void setPropertyConfigureImpl(T &value, Func func)
Definition: PropertySet_impl.h:247
void configure(const CF::Properties &configProperties)
Definition: PropertySet_impl.h:39
std::vector< PropertyInterface * > ownedWrappers
Definition: PropertySet_impl.h:317
void addPropertyChangeListener(const std::string &id, C *target, void(C::*func)(const T *, const T *))
Definition: PropertySet_impl.h:143
std::map< std::string, PropertyInterface * > PropertyMap
Definition: PropertySet_impl.h:320
PropertyWrapper< T > * getPropertyWrapper(T &value)
Definition: PropertySet_impl.h:288
void setPropertyConfigureImpl(T &value, Target target, Func func)
Definition: PropertySet_impl.h:234
void setPropertyQueryImpl(T &value, Target target, Func func)
Definition: PropertySet_impl.h:207
PropertyEventSupplier * propertyChangePort
Definition: PropertySet_impl.h:315
void addPropertyChangeListener(const std::string &id, void(*func)(const T *, const T *))
Definition: PropertySet_impl.h:154
char * registerPropertyListener(CORBA::Object_ptr listener, const CF::StringSequence &prop_ids, const CORBA::Float interval)
void stopPropertyChangeMonitor()