1 /*=============================================================================
2 
3   Library: CTK
4 
5   Copyright (c) German Cancer Research Center,
6     Division of Medical and Biological Informatics
7 
8   Licensed under the Apache License, Version 2.0 (the "License");
9   you may not use this file except in compliance with the License.
10   You may obtain a copy of the License at
11 
12     http://www.apache.org/licenses/LICENSE-2.0
13 
14   Unless required by applicable law or agreed to in writing, software
15   distributed under the License is distributed on an "AS IS" BASIS,
16   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   See the License for the specific language governing permissions and
18   limitations under the License.
19 
20 =============================================================================*/
21 
22 
23 #ifndef CTKPLUGINTRACKER_H
24 #define CTKPLUGINTRACKER_H
25 
26 #include <QScopedPointer>
27 
28 #include "ctkPluginFrameworkExport.h"
29 
30 #include "ctkPlugin.h"
31 #include "ctkPluginTrackerCustomizer.h"
32 
33 template<class T> class ctkTrackedPlugin;
34 template<class T> class ctkPluginTrackerPrivate;
35 
36 /**
37  * \ingroup PluginFramework
38  *
39  * The <code>ctkPluginTracker</code> class simplifies tracking plugins much like
40  * the <code>ctkServiceTracker</code> simplifies tracking services.
41  * <p>
42  * A <code>ctkPluginTracker</code> is constructed with state criteria and a
43  * <code>ctkPluginTrackerCustomizer</code> object. A <code>ctkPluginTracker</code> can
44  * use the <code>ctkPluginTrackerCustomizer</code> to select which plugins are
45  * tracked and to create a customized object to be tracked with the plugin. The
46  * <code>ctkPluginTracker</code> can then be opened to begin tracking all plugins
47  * whose state matches the specified state criteria.
48  * <p>
49  * The <code>getPlugins</code> method can be called to get the
50  * <code>ctkPlugin</code> objects of the plugins being tracked. The
51  * <code>getObject</code> method can be called to get the customized object for
52  * a tracked plugin.
53  * <p>
54  * The <code>ctkPluginTracker</code> class is thread-safe. It does not call a
55  * <code>ctkPluginTrackerCustomizer</code> while holding any locks.
56  * <code>ctkPluginTrackerCustomizer</code> implementations must also be
57  * thread-safe.
58  *
59  * \tparam T The type of the tracked object. The type must be an assignable
60  *         datatype, provide a boolean conversion function, and provide
61  *         a constructor and an assignment operator which can handle 0 as an argument.
62  * \remarks This class is thread safe.
63  */
64 template<class T = QSharedPointer<ctkPlugin> >
65 class ctkPluginTracker : protected ctkPluginTrackerCustomizer<T>
66 {
67 public:
68 
69   ~ctkPluginTracker();
70 
71   /**
72    * Create a <code>ctkPluginTracker</code> for plugins whose state is present in
73    * the specified state mask.
74    *
75    * <p>
76    * Plugins whose state is present on the specified state mask will be
77    * tracked by this <code>ctkPluginTracker</code>.
78    *
79    * @param context The <code>ctkPluginContext</code> against which the tracking
80    *        is done.
81    * @param stateMask The bit mask of the <code>OR</code>ing of the plugin
82    *        states to be tracked.
83    * @param customizer The customizer object to call when plugins are added,
84    *        modified, or removed in this <code>ctkPluginTracker</code>. If
85    *        customizer is <code>null</code>, then this
86    *        <code>ctkPluginTracker</code> will be used as the
87    *        <code>ctkPluginTrackerCustomizer</code> and this
88    *        <code>ctkPluginTracker</code> will call the
89    *        <code>ctkPluginTrackerCustomizer</code> methods on itself. If the
90    *        customizer is not <code>null</code>, this <code>ctkPluginTracker</code>
91    *        takes ownership of the customizer.
92    * @see ctkPlugin#getState()
93    */
94   ctkPluginTracker(ctkPluginContext* context, ctkPlugin::States stateMask,
95                    ctkPluginTrackerCustomizer<T>* customizer = 0);
96 
97   /**
98    * Open this <code>ctkPluginTracker</code> and begin tracking plugins.
99    *
100    * <p>
101    * ctkPlugin's which match the state criteria specified when this
102    * <code>ctkPluginTracker</code> was created are now tracked by this
103    * <code>ctkPluginTracker</code>.
104    *
105    * @throws ctkIllegalStateException If the <code>ctkPluginContext</code>
106    *         with which this <code>ctkPluginTracker</code> was created is no
107    *         longer valid.
108    */
109   virtual void open();
110 
111   /**
112    * Close this <code>ctkPluginTracker</code>.
113    *
114    * <p>
115    * This method should be called when this <code>ctkPluginTracker</code> should
116    * end the tracking of plugins.
117    *
118    * <p>
119    * This implementation calls getPlugins() to get the list of
120    * tracked plugins to remove.
121    */
122   virtual void close();
123 
124   /**
125    * Return a list of <code>ctkPlugin</code>s for all plugins being tracked by
126    * this <code>ctkPluginTracker</code>.
127    *
128    * @return A list of <code>ctkPlugin</code>s.
129    */
130   virtual QList<QSharedPointer<ctkPlugin> > getPlugins() const;
131 
132   /**
133    * Returns the customized object for the specified <code>ctkPlugin</code> if
134    * the specified plugin is being tracked by this <code>ctkPluginTracker</code>.
135    *
136    * @param plugin The <code>ctkPlugin</code> being tracked.
137    * @return The customized object for the specified <code>ctkPlugin</code> or
138    *         <code>null</code> if the specified <code>ctkPlugin</code> is not
139    *         being tracked.
140    */
141   virtual T getObject(QSharedPointer<ctkPlugin> plugin) const;
142 
143   /**
144    * Remove a plugin from this <code>ctkPluginTracker</code>.
145    *
146    * The specified plugin will be removed from this <code>ctkPluginTracker</code>.
147    * If the specified plugin was being tracked then the
148    * <code>ctkPluginTrackerCustomizer::removedPlugin</code> method will be called
149    * for that plugin.
150    *
151    * @param plugin The <code>ctkPlugin</code> to be removed.
152    */
153   virtual void remove(QSharedPointer<ctkPlugin> plugin);
154 
155   /**
156    * Return the number of plugins being tracked by this
157    * <code>ctkPluginTracker</code>.
158    *
159    * @return The number of plugins being tracked.
160    */
161   virtual int size() const;
162 
163   /**
164    * Returns the tracking count for this <code>ctkPluginTracker</code>.
165    *
166    * The tracking count is initialized to 0 when this
167    * <code>ctkPluginTracker</code> is opened. Every time a plugin is added,
168    * modified or removed from this <code>ctkPluginTracker</code> the tracking
169    * count is incremented.
170    *
171    * <p>
172    * The tracking count can be used to determine if this
173    * <code>ctkPluginTracker</code> has added, modified or removed a plugin by
174    * comparing a tracking count value previously collected with the current
175    * tracking count value. If the value has not changed, then no plugin has
176    * been added, modified or removed from this <code>ctkPluginTracker</code>
177    * since the previous tracking count was collected.
178    *
179    * @return The tracking count for this <code>ctkPluginTracker</code> or -1 if
180    *         this <code>ctkPluginTracker</code> is not open.
181    */
182   virtual int getTrackingCount() const;
183 
184   /**
185    * Return a <code>QMap</code> with the <code>ctkPlugin</code>s and customized
186    * objects for all plugins being tracked by this <code>ctkPluginTracker</code>.
187    *
188    * @return A <code>QMap</code> with the <code>ctkPlugin</code>s and customized
189    *         objects for all services being tracked by this
190    *         <code>ctkPluginTracker</code>. If no plugins are being tracked, then
191    *         the returned map is empty.
192    */
193   virtual QMap<QSharedPointer<ctkPlugin>, T> getTracked() const;
194 
195   /**
196    * Return if this <code>ctkPluginTracker</code> is empty.
197    *
198    * @return <code>true</code> if this <code>ctkPluginTracker</code> is not tracking any
199    *         plugins.
200    */
201   virtual bool isEmpty() const;
202 
203 protected:
204 
205   /**
206    * Default implementation of the
207    * <code>ctkPluginTrackerCustomizer::addingPlugin</code> method.
208    *
209    * <p>
210    * This method is only called when this <code>ctkPluginTracker</code> has been
211    * constructed with a <code>null</code> ctkPluginTrackerCustomizer argument.
212    *
213    * <p>
214    * This implementation simply returns the specified <code>ctkPlugin*</code> in
215    * a QVariant.
216    *
217    * <p>
218    * This method can be overridden in a subclass to customize the object to be
219    * tracked for the plugin being added.
220    *
221    * @param plugin The <code>ctkPlugin</code> being added to this
222    *        <code>ctkPluginTracker</code> object.
223    * @param event The plugin event which caused this customizer method to be
224    *        called or an invalid event if there is no plugin event associated
225    *        with the call to this method.
226    * @return The specified plugin.
227    * @see ctkPluginTrackerCustomizer::addingPlugin(ctkPlugin*, const ctkPluginEvent&)
228    */
229   T addingPlugin(QSharedPointer<ctkPlugin> plugin, const ctkPluginEvent& event);
230 
231   /**
232    * Default implementation of the
233    * <code>ctkPluginTrackerCustomizer::modifiedPlugin</code> method.
234    *
235    * <p>
236    * This method is only called when this <code>ctkPluginTracker</code> has been
237    * constructed with a <code>null</code> ctkPluginTrackerCustomizer argument.
238    *
239    * <p>
240    * This implementation does nothing.
241    *
242    * @param plugin The <code>ctkPlugin</code> whose state has been modified.
243    * @param event The plugin event which caused this customizer method to be
244    *        called or an invalid event if there is no plugin event associated
245    *        with the call to this method.
246    * @param object The customized object for the specified ctkPlugin.
247    * @see ctkPluginTrackerCustomizer::modifiedPlugin(ctkPlugin*, const ctkPluginEvent&, QVariant)
248    */
249   void modifiedPlugin(QSharedPointer<ctkPlugin> plugin, const ctkPluginEvent& event, T object);
250 
251   /**
252    * Default implementation of the
253    * <code>ctkPluginTrackerCustomizer::removedPlugin</code> method.
254    *
255    * <p>
256    * This method is only called when this <code>ctkPluginTracker</code> has been
257    * constructed with a <code>null</code> ctkPluginTrackerCustomizer argument.
258    *
259    * <p>
260    * This implementation does nothing.
261    *
262    * @param plugin The <code>ctkPlugin</code> being removed.
263    * @param event The plugin event which caused this customizer method to be
264    *        called or an invalid event if there is no plugin event associated
265    *        with the call to this method.
266    * @param object The customized object for the specified plugin.
267    * @see ctkPluginTrackerCustomizer::removedPlugin(ctkPlugin*, const ctkPluginEvent&, QVariant)
268    */
269   void removedPlugin(QSharedPointer<ctkPlugin> plugin, const ctkPluginEvent& event, T object);
270 
271 private:
272 
273   typedef ctkPluginTracker<T> PluginTracker;
274   typedef ctkTrackedPlugin<T> TrackedPlugin;
275   typedef ctkPluginTrackerPrivate<T> PluginTrackerPrivate;
276   typedef ctkPluginTrackerCustomizer<T> PluginTrackerCustomizer;
277 
278   friend class ctkTrackedPlugin<T>;
279   friend class ctkPluginTrackerPrivate<T>;
280 
d_func()281   inline PluginTrackerPrivate* d_func()
282   {
283     return reinterpret_cast<PluginTrackerPrivate*>(qGetPtrHelper(d_ptr));
284   }
285 
d_func()286   inline const PluginTrackerPrivate* d_func() const
287   {
288     return reinterpret_cast<const PluginTrackerPrivate*>(qGetPtrHelper(d_ptr));
289   }
290 
291   const QScopedPointer<PluginTrackerPrivate> d_ptr;
292 };
293 
294 
295 #include "ctkPluginTracker.tpp"
296 
297 #endif // CTKPLUGINTRACKER_H
298