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