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 #include "ctkMTProviderTracker_p.h"
24 
25 #include "ctkMTMsg_p.h"
26 
27 #include <service/cm/ctkManagedService.h>
28 #include <service/cm/ctkManagedServiceFactory.h>
29 #include <service/log/ctkLogService.h>
30 
31 #include <QCoreApplication>
32 
33 class ctkMTProviderTracker::MetaTypeProviderWrapper
34 {
35 public:
36 
37   ctkMetaTypeProvider* provider;
38   QString pid;
39   bool factory;
40 
MetaTypeProviderWrapper(ctkMetaTypeProvider * provider,const QString & pid,bool factory)41   MetaTypeProviderWrapper(ctkMetaTypeProvider* provider, const QString& pid, bool factory)
42     : provider(provider), pid(pid), factory(factory)
43   {
44 
45   }
46 
operator ==(const MetaTypeProviderWrapper & o) const47   bool operator==(const MetaTypeProviderWrapper& o) const
48   {
49     if (this == &o)
50       return true;
51     return provider == o.provider && pid == o.pid && factory == o.factory;
52   }
53 
54 };
55 
qHash(const ctkMTProviderTracker::MetaTypeProviderWrapper wrapper)56 uint qHash(const ctkMTProviderTracker::MetaTypeProviderWrapper wrapper)
57 {
58   uint result = 17;
59   result = 31 * result + qHash(wrapper.provider);
60   result = 31 * result + qHash(wrapper.pid);
61   result = 31 * result + (wrapper.factory ? 1 : 0);
62   return result;
63 }
64 
ctkMTProviderTracker(const QSharedPointer<ctkPlugin> & plugin,ctkLogService * log,ctkServiceTracker<> * tracker)65 ctkMTProviderTracker::ctkMTProviderTracker(const QSharedPointer<ctkPlugin>& plugin, ctkLogService* log, ctkServiceTracker<>* tracker)
66   : _plugin(plugin), log(log), _tracker(tracker)
67 {
68 
69 }
70 
getPids() const71 QStringList ctkMTProviderTracker::getPids() const
72 {
73   return getPids(false);
74 }
75 
getFactoryPids() const76 QStringList ctkMTProviderTracker::getFactoryPids() const
77 {
78   return getPids(true);
79 }
80 
getPlugin() const81 QSharedPointer<ctkPlugin> ctkMTProviderTracker::getPlugin() const
82 {
83   return _plugin;
84 }
85 
getObjectClassDefinition(const QString & id,const QLocale & locale)86 ctkObjectClassDefinitionPtr ctkMTProviderTracker::getObjectClassDefinition(const QString& id, const QLocale& locale)
87 {
88   if (_plugin->getState() != ctkPlugin::ACTIVE)
89   {
90     return ctkObjectClassDefinitionPtr(); // return none if not active
91   }
92 
93   QSet<MetaTypeProviderWrapper> wrappers = getMetaTypeProviders();
94   QSet<MetaTypeProviderWrapper>::ConstIterator end = wrappers.end();
95   for (QSet<MetaTypeProviderWrapper>::ConstIterator it = wrappers.begin();
96        it != end; ++it)
97   {
98     if (id == (*it).pid)
99     {
100       // found a matching pid now call the actual provider
101       return (*it).provider->getObjectClassDefinition(id, locale);
102     }
103   }
104   return ctkObjectClassDefinitionPtr();
105 }
106 
getLocales() const107 QList<QLocale> ctkMTProviderTracker::getLocales() const
108 {
109   if (_plugin->getState() != ctkPlugin::ACTIVE)
110   {
111     return QList<QLocale>(); // return none if not active
112   }
113 
114   QSet<MetaTypeProviderWrapper> wrappers = getMetaTypeProviders();
115   QList<QLocale> locales;
116   // collect all the unique locales from all providers we found
117   QSet<MetaTypeProviderWrapper>::ConstIterator end = wrappers.end();
118   for (QSet<MetaTypeProviderWrapper>::ConstIterator it = wrappers.begin();
119        it != end; ++it)
120   {
121     QList<QLocale> wrappedLocales = (*it).provider->getLocales();
122     if (wrappedLocales.isEmpty())
123       continue;
124     for (int j = 0; j < wrappedLocales.size(); j++)
125       if (!locales.contains(wrappedLocales[j]))
126         locales.push_back(wrappedLocales[j]);
127   }
128   return locales;
129 }
130 
getPids(bool factory) const131 QStringList ctkMTProviderTracker::getPids(bool factory) const
132 {
133   if (_plugin->getState() != ctkPlugin::ACTIVE)
134   {
135     return QStringList(); // return none if not active
136   }
137 
138   QSet<MetaTypeProviderWrapper> wrappers = getMetaTypeProviders();
139   QStringList results;
140   QSet<MetaTypeProviderWrapper>::ConstIterator end = wrappers.end();
141   for (QSet<MetaTypeProviderWrapper>::ConstIterator it = wrappers.begin();
142        it != end; ++it)
143   {
144     // return only the correct type of pids (regular or factory)
145     if (factory == (*it).factory)
146       results.push_back((*it).pid);
147   }
148   return results;
149 }
150 
getMetaTypeProviders() const151 QSet<ctkMTProviderTracker::MetaTypeProviderWrapper> ctkMTProviderTracker::getMetaTypeProviders() const
152 {
153   QMap<ctkServiceReference, QObject*> services = _tracker->getTracked();
154   if (services.isEmpty())
155   {
156     return QSet<MetaTypeProviderWrapper>();
157   }
158   QList<ctkServiceReference> serviceReferences = services.keys();
159   QSet<MetaTypeProviderWrapper> result;
160   foreach (ctkServiceReference serviceReference, serviceReferences)
161   {
162     if (serviceReference.getPlugin() == _plugin)
163     {
164       QObject* service = services.value(serviceReference);
165       // If the service is not a ctkMetaTypeProvider, we're not interested in it.
166       if (ctkMetaTypeProvider* metatypeService = qobject_cast<ctkMetaTypeProvider*>(service))
167       {
168         // Include the METATYPE_PID, if present, to return as part of getPids(). Also, include the
169         // METATYPE_FACTORY_PID, if present, to return as part of getFactoryPids().
170         // The filter ensures at least one of these properties was set for a standalone ctkMetaTypeProvider.
171         addMetaTypeProviderWrappers(ctkMetaTypeProvider::METATYPE_PID, serviceReference, metatypeService, false, result);
172         addMetaTypeProviderWrappers(ctkMetaTypeProvider::METATYPE_FACTORY_PID, serviceReference, metatypeService, true, result);
173         // If the service is a ctkManagedService, include the SERVICE_PID to return as part of getPids().
174         // The filter ensures the SERVICE_PID property was set.
175         if (qobject_cast<ctkManagedService*>(service))
176         {
177           addMetaTypeProviderWrappers(ctkPluginConstants::SERVICE_PID, serviceReference, metatypeService, false, result);
178         }
179         // If the service is a ctkManagedServiceFactory, include the SERVICE_PID to return as part of getFactoryPids().
180         // The filter ensures the SERVICE_PID property was set.
181         else if (qobject_cast<ctkManagedServiceFactory*>(service))
182         {
183           addMetaTypeProviderWrappers(ctkPluginConstants::SERVICE_PID, serviceReference, metatypeService, true, result);
184         }
185       }
186     }
187   }
188   return result;
189 }
190 
addMetaTypeProviderWrappers(const QString & servicePropertyName,const ctkServiceReference & serviceReference,ctkMetaTypeProvider * service,bool factory,QSet<MetaTypeProviderWrapper> & wrappers) const191 void ctkMTProviderTracker::addMetaTypeProviderWrappers(const QString& servicePropertyName,
192                                                        const ctkServiceReference& serviceReference,
193                                                        ctkMetaTypeProvider* service, bool factory,
194                                                        QSet<MetaTypeProviderWrapper>& wrappers) const
195 {
196   QStringList pids = getStringProperty(servicePropertyName, serviceReference.getProperty(servicePropertyName));
197   foreach (QString pid, pids)
198   {
199     wrappers.insert(MetaTypeProviderWrapper(service, pid, factory));
200   }
201 }
202 
getStringProperty(const QString & name,const QVariant & value) const203 QStringList ctkMTProviderTracker::getStringProperty(const QString& name, const QVariant& value) const
204 {
205   // Don't log a warning if the value is null. The filter guarantees at least one of the necessary properties
206   // is there. If others are not, this method will get called with value equal to null.
207   if (value.isNull())
208     return QStringList();
209 
210   if (value.canConvert<QStringList>())
211   {
212     return value.toStringList();
213   }
214 
215   CTK_WARN(log) << QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::INVALID_PID_METATYPE_PROVIDER_IGNORED)
216                    .arg(_plugin->getSymbolicName()).arg(_plugin->getPluginId()).arg(name). arg(value.toString());
217   return QStringList();
218 }
219 
220