ctkServiceTracker.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. /*=============================================================================
  2. Library: CTK
  3. Copyright (c) German Cancer Research Center,
  4. Division of Medical and Biological Informatics
  5. Licensed under the Apache License, Version 2.0 (the "License");
  6. you may not use this file except in compliance with the License.
  7. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. =============================================================================*/
  15. #ifndef CTKSERVICETRACKER_H
  16. #define CTKSERVICETRACKER_H
  17. #include <QScopedPointer>
  18. #include "ctkPluginFrameworkExport.h"
  19. #include "ctkServiceReference.h"
  20. #include "ctkServiceTrackerCustomizer.h"
  21. #include "ctkLDAPSearchFilter.h"
  22. template<class S, class T> class ctkTrackedService;
  23. template<class S, class T> class ctkServiceTrackerPrivate;
  24. class ctkPluginContext;
  25. /**
  26. * \ingroup PluginFramework
  27. *
  28. * The <code>ctkServiceTracker</code> class simplifies using services from the
  29. * Framework's service registry.
  30. * <p>
  31. * A <code>ctkServiceTracker</code> object is constructed with search criteria and
  32. * a <code>ctkServiceTrackerCustomizer</code> object. A <code>ctkServiceTracker</code>
  33. * can use a <code>ctkServiceTrackerCustomizer</code> to customize the service
  34. * objects to be tracked. The <code>ctkServiceTracker</code> can then be opened to
  35. * begin tracking all services in the Framework's service registry that match
  36. * the specified search criteria. The <code>ctkServiceTracker</code> correctly
  37. * handles all of the details of listening to <code>ctkServiceEvent</code>s and
  38. * getting and ungetting services.
  39. * <p>
  40. * The <code>getServiceReferences</code> method can be called to get references
  41. * to the services being tracked. The <code>getService</code> and
  42. * <code>getServices</code> methods can be called to get the service objects for
  43. * the tracked service.
  44. * <p>
  45. * The <code>ctkServiceTracker</code> class is thread-safe. It does not call a
  46. * <code>ctkServiceTrackerCustomizer</code> while holding any locks.
  47. * <code>ctkServiceTrackerCustomizer</code> implementations must also be
  48. * thread-safe.
  49. *
  50. * \tparam S The type of the service being tracked. The type must be an
  51. * assignable datatype. Further, if the
  52. * <code>ctkServiceTracker(ctkPluginContext*, ctkServiceTrackerCustomizer<T>*)</code>
  53. * constructor is used, the type must have an associated interface id via
  54. * Q_DECLARE_INTERFACE.
  55. * \tparam T The type of the tracked object. The type must be an assignable
  56. * datatype, provide a boolean conversion function, and provide
  57. * a constructor and an assignment operator which can handle 0 as an argument.
  58. * \remarks This class is thread safe.
  59. */
  60. template<class S = QObject*, class T = S>
  61. class ctkServiceTracker : protected ctkServiceTrackerCustomizer<T>
  62. {
  63. public:
  64. ~ctkServiceTracker();
  65. /**
  66. * Create a <code>ctkServiceTracker</code> on the specified
  67. * <code>ctkServiceReference</code>.
  68. *
  69. * <p>
  70. * The service referenced by the specified <code>ctkServiceReference</code>
  71. * will be tracked by this <code>ctkServiceTracker</code>.
  72. *
  73. * @param context The <code>ctkPluginContext</code> against which the tracking
  74. * is done.
  75. * @param reference The <code>ctkServiceReference</code> for the service to be
  76. * tracked.
  77. * @param customizer The customizer object to call when services are added,
  78. * modified, or removed in this <code>ctkServiceTracker</code>. If
  79. * customizer is <code>null</code>, then this
  80. * <code>ctkServiceTracker</code> will be used as the
  81. * <code>ctkServiceTrackerCustomizer</code> and this
  82. * <code>ctkServiceTracker</code> will call the
  83. * <code>ctkServiceTrackerCustomizer</code> methods on itself.
  84. */
  85. ctkServiceTracker(ctkPluginContext* context,
  86. const ctkServiceReference& reference,
  87. ctkServiceTrackerCustomizer<T>* customizer = 0);
  88. /**
  89. * Create a <code>ctkServiceTracker</code> on the specified class name.
  90. *
  91. * <p>
  92. * Services registered under the specified class name will be tracked by
  93. * this <code>ctkServiceTracker</code>.
  94. *
  95. * @param context The <code>ctkPluginContext</code> against which the tracking
  96. * is done.
  97. * @param clazz The class name of the services to be tracked.
  98. * @param customizer The customizer object to call when services are added,
  99. * modified, or removed in this <code>ctkServiceTracker</code>. If
  100. * customizer is <code>null</code>, then this
  101. * <code>ctkServiceTracker</code> will be used as the
  102. * <code>ctkServiceTrackerCustomizer</code> and this
  103. * <code>ctkServiceTracker</code> will call the
  104. * <code>ctkServiceTrackerCustomizer</code> methods on itself.
  105. */
  106. ctkServiceTracker(ctkPluginContext* context, const QString& clazz,
  107. ctkServiceTrackerCustomizer<T>* customizer = 0);
  108. /**
  109. * Create a <code>ctkServiceTracker</code> on the specified
  110. * <code>ctkLDAPSearchFilter</code> object.
  111. *
  112. * <p>
  113. * Services which match the specified <code>ctkLDAPSearchFilter</code> object will be
  114. * tracked by this <code>ctkServiceTracker</code>.
  115. *
  116. * @param context The <code>ctkPluginContext</code> against which the tracking
  117. * is done.
  118. * @param filter The <code>ctkLDAPSearchFilter</code> to select the services to be
  119. * tracked.
  120. * @param customizer The customizer object to call when services are added,
  121. * modified, or removed in this <code>ctkServiceTracker</code>. If
  122. * customizer is null, then this <code>ctkServiceTracker</code> will be
  123. * used as the <code>ctkServiceTrackerCustomizer</code> and this
  124. * <code>ctkServiceTracker</code> will call the
  125. * <code>ctkServiceTrackerCustomizer</code> methods on itself.
  126. */
  127. ctkServiceTracker(ctkPluginContext* context, const ctkLDAPSearchFilter& filter,
  128. ctkServiceTrackerCustomizer<T>* customizer = 0);
  129. /**
  130. * Create a <code>ctkServiceTracker</code> on the class template
  131. * argument S.
  132. *
  133. * <p>
  134. * Services registered under the interface name of the class template
  135. * argument S will be tracked by this <code>ctkServiceTracker</code>.
  136. *
  137. * @param context The <code>ctkPluginContext</code> against which the tracking
  138. * is done.
  139. * @param customizer The customizer object to call when services are added,
  140. * modified, or removed in this <code>ctkServiceTracker</code>. If
  141. * customizer is null, then this <code>ctkServiceTracker</code> will be
  142. * used as the <code>ctkServiceTrackerCustomizer</code> and this
  143. * <code>ctkServiceTracker</code> will call the
  144. * <code>ctkServiceTrackerCustomizer</code> methods on itself.
  145. */
  146. ctkServiceTracker(ctkPluginContext* context, ctkServiceTrackerCustomizer<T>* customizer = 0);
  147. /**
  148. * Open this <code>ctkServiceTracker</code> and begin tracking services.
  149. *
  150. * <p>
  151. * Services which match the search criteria specified when this
  152. * <code>ctkServiceTracker</code> was created are now tracked by this
  153. * <code>ctkServiceTracker</code>.
  154. *
  155. * @throws std::logic_error If the <code>ctkPluginContext</code>
  156. * with which this <code>ctkServiceTracker</code> was created is no
  157. * longer valid.
  158. */
  159. virtual void open();
  160. /**
  161. * Close this <code>ctkServiceTracker</code>.
  162. *
  163. * <p>
  164. * This method should be called when this <code>ctkServiceTracker</code> should
  165. * end the tracking of services.
  166. *
  167. * <p>
  168. * This implementation calls getServiceReferences() to get the list
  169. * of tracked services to remove.
  170. */
  171. virtual void close();
  172. /**
  173. * Wait for at least one service to be tracked by this
  174. * <code>ctkServiceTracker</code>. This method will also return when this
  175. * <code>ctkServiceTracker</code> is closed.
  176. *
  177. * <p>
  178. * It is strongly recommended that <code>waitForService</code> is not used
  179. * during the calling of the <code>ctkPluginActivator</code> methods.
  180. * <code>ctkPluginActivator</code> methods are expected to complete in a short
  181. * period of time.
  182. *
  183. * <p>
  184. * This implementation calls getService() to determine if a service
  185. * is being tracked.
  186. *
  187. * @param timeout The time interval in milliseconds to wait. If zero, the
  188. * method will wait indefinitely.
  189. * @return Returns the result of getService().
  190. */
  191. virtual T waitForService(unsigned long timeout);
  192. /**
  193. * Return a list of <code>ctkServiceReference</code>s for all services being
  194. * tracked by this <code>ctkServiceTracker</code>.
  195. *
  196. * @return List of <code>ctkServiceReference</code>s.
  197. */
  198. virtual QList<ctkServiceReference> getServiceReferences() const;
  199. /**
  200. * Returns a <code>ctkServiceReference</code> for one of the services being
  201. * tracked by this <code>ctkServiceTracker</code>.
  202. *
  203. * <p>
  204. * If multiple services are being tracked, the service with the highest
  205. * ranking (as specified in its <code>service.ranking</code> property) is
  206. * returned. If there is a tie in ranking, the service with the lowest
  207. * service ID (as specified in its <code>service.id</code> property); that
  208. * is, the service that was registered first is returned. This is the same
  209. * algorithm used by <code>ctkPluginContext::getServiceReference()</code>.
  210. *
  211. * <p>
  212. * This implementation calls getServiceReferences() to get the list
  213. * of references for the tracked services.
  214. *
  215. * @return A <code>ctkServiceReference</code> for a tracked service.
  216. * @throws ctkServiceException if no services are being tracked.
  217. */
  218. virtual ctkServiceReference getServiceReference() const;
  219. /**
  220. * Returns the service object for the specified
  221. * <code>ctkServiceReference</code> if the specified referenced service is
  222. * being tracked by this <code>ctkServiceTracker</code>.
  223. *
  224. * @param reference The reference to the desired service.
  225. * @return A service object or <code>null</code> if the service referenced
  226. * by the specified <code>ctkServiceReference</code> is not being
  227. * tracked.
  228. */
  229. virtual T getService(const ctkServiceReference& reference) const;
  230. /**
  231. * Return a list of service objects for all services being tracked by this
  232. * <code>ctkServiceTracker</code>.
  233. *
  234. * <p>
  235. * This implementation calls getServiceReferences() to get the list
  236. * of references for the tracked services and then calls
  237. * getService(const ctkServiceReference&) for each reference to get the
  238. * tracked service object.
  239. *
  240. * @return A list of service objects or an empty list if no services
  241. * are being tracked.
  242. */
  243. virtual QList<T> getServices() const;
  244. /**
  245. * Returns a service object for one of the services being tracked by this
  246. * <code>ctkServiceTracker</code>.
  247. *
  248. * <p>
  249. * If any services are being tracked, this implementation returns the result
  250. * of calling <code>getService(getServiceReference())</code>.
  251. *
  252. * @return A service object or <code>null</code> if no services are being
  253. * tracked.
  254. */
  255. virtual T getService() const;
  256. /**
  257. * Remove a service from this <code>ctkServiceTracker</code>.
  258. *
  259. * The specified service will be removed from this
  260. * <code>ctkServiceTracker</code>. If the specified service was being tracked
  261. * then the <code>ctkServiceTrackerCustomizer::removedService</code> method will
  262. * be called for that service.
  263. *
  264. * @param reference The reference to the service to be removed.
  265. */
  266. virtual void remove(const ctkServiceReference& reference);
  267. /**
  268. * Return the number of services being tracked by this
  269. * <code>ctkServiceTracker</code>.
  270. *
  271. * @return The number of services being tracked.
  272. */
  273. virtual int size() const;
  274. /**
  275. * Returns the tracking count for this <code>ctkServiceTracker</code>.
  276. *
  277. * The tracking count is initialized to 0 when this
  278. * <code>ctkServiceTracker</code> is opened. Every time a service is added,
  279. * modified or removed from this <code>ctkServiceTracker</code>, the tracking
  280. * count is incremented.
  281. *
  282. * <p>
  283. * The tracking count can be used to determine if this
  284. * <code>ctkServiceTracker</code> has added, modified or removed a service by
  285. * comparing a tracking count value previously collected with the current
  286. * tracking count value. If the value has not changed, then no service has
  287. * been added, modified or removed from this <code>ctkServiceTracker</code>
  288. * since the previous tracking count was collected.
  289. *
  290. * @return The tracking count for this <code>ctkServiceTracker</code> or -1 if
  291. * this <code>ctkServiceTracker</code> is not open.
  292. */
  293. virtual int getTrackingCount() const;
  294. /**
  295. * Return a sorted <code>QMap</code> of the <code>ctkServiceReference</code>s and
  296. * service objects for all services being tracked by this
  297. * <code>ctkServiceTracker</code>. The map is sorted in natural order
  298. * of <code>ctkServiceReference</code>. That is, the last entry is the service
  299. * with the highest ranking and the lowest service id.
  300. *
  301. * @return A <code>QMap</code> with the <code>ctkServiceReference</code>s
  302. * and service objects for all services being tracked by this
  303. * <code>ctkServiceTracker</code>. If no services are being tracked,
  304. * then the returned map is empty.
  305. */
  306. virtual QMap<ctkServiceReference, T> getTracked() const;
  307. /**
  308. * Return if this <code>ctkServiceTracker</code> is empty.
  309. *
  310. * @return <code>true</code> if this <code>ctkServiceTracker</code> is not tracking any
  311. * services.
  312. */
  313. virtual bool isEmpty() const;
  314. protected:
  315. /**
  316. * Default implementation of the
  317. * <code>ctkServiceTrackerCustomizer::addingService</code> method.
  318. *
  319. * <p>
  320. * This method is only called when this <code>ctkServiceTracker</code> has been
  321. * constructed with a <code>null</code> ctkServiceTrackerCustomizer argument.
  322. *
  323. * <p>
  324. * This implementation returns the result of calling <code>getService</code>
  325. * on the <code>ctkPluginContext</code> with which this
  326. * <code>ctkServiceTracker</code> was created passing the specified
  327. * <code>ctkServiceReference</code>.
  328. * <p>
  329. * This method can be overridden in a subclass to customize the service
  330. * object to be tracked for the service being added. In that case, take care
  331. * not to rely on the default implementation of
  332. * \link removedService(const ctkServiceReference&, T service) removedService\endlink
  333. * to unget the service.
  334. *
  335. * @param reference The reference to the service being added to this
  336. * <code>ctkServiceTracker</code>.
  337. * @return The service object to be tracked for the service added to this
  338. * <code>ctlServiceTracker</code>.
  339. * @see ctkServiceTrackerCustomizer::addingService(const ctkServiceReference&)
  340. */
  341. T addingService(const ctkServiceReference& reference);
  342. /**
  343. * Default implementation of the
  344. * <code>ctkServiceTrackerCustomizer::modifiedService</code> method.
  345. *
  346. * <p>
  347. * This method is only called when this <code>ctkServiceTracker</code> has been
  348. * constructed with a <code>null</code> ctkServiceTrackerCustomizer argument.
  349. *
  350. * <p>
  351. * This implementation does nothing.
  352. *
  353. * @param reference The reference to modified service.
  354. * @param service The service object for the modified service.
  355. * @see ctkServiceTrackerCustomizer::modifiedService(const ctkServiceReference&, QObject*)
  356. */
  357. void modifiedService(const ctkServiceReference& reference, T service);
  358. /**
  359. * Default implementation of the
  360. * <code>ctkServiceTrackerCustomizer::removedService</code> method.
  361. *
  362. * <p>
  363. * This method is only called when this <code>ctkServiceTracker</code> has been
  364. * constructed with a <code>null</code> ctkServiceTrackerCustomizer argument.
  365. *
  366. * <p>
  367. * This implementation calls <code>ungetService</code>, on the
  368. * <code>ctkPluginContext</code> with which this <code>ctkServiceTracker</code>
  369. * was created, passing the specified <code>ctkServiceReference</code>.
  370. * <p>
  371. * This method can be overridden in a subclass. If the default
  372. * implementation of \link addingService(const ctkServiceReference&) addingService\endlink
  373. * method was used, this method must unget the service.
  374. *
  375. * @param reference The reference to removed service.
  376. * @param service The service object for the removed service.
  377. * @see ctkServiceTrackerCustomizer::removedService(const ServiceReference&, QObject*)
  378. */
  379. void removedService(const ctkServiceReference& reference, T service);
  380. private:
  381. typedef ctkServiceTracker<S,T> ServiceTracker;
  382. typedef ctkTrackedService<S,T> TrackedService;
  383. typedef ctkServiceTrackerPrivate<S,T> ServiceTrackerPrivate;
  384. typedef ctkServiceTrackerCustomizer<T> ServiceTrackerCustomizer;
  385. friend class ctkTrackedService<S,T>;
  386. friend class ctkServiceTrackerPrivate<S,T>;
  387. inline ServiceTrackerPrivate* d_func()
  388. {
  389. return reinterpret_cast<ServiceTrackerPrivate*>(qGetPtrHelper(d_ptr));
  390. }
  391. inline const ServiceTrackerPrivate* d_func() const
  392. {
  393. return reinterpret_cast<const ServiceTrackerPrivate*>(qGetPtrHelper(d_ptr));
  394. }
  395. const QScopedPointer<ServiceTrackerPrivate> d_ptr;
  396. };
  397. #include "ctkServiceTracker.tpp"
  398. #endif // CTKSERVICETRACKER_H