source: pacpusframework/branches/2.0-beta1/src/PacpusLib/ComponentManager.cpp@ 89

Last change on this file since 89 was 89, checked in by morasjul, 11 years ago

PACPUS 2.0 Beta deployed in new branch

Major changes:
-Add communication interface between components
-Add examples for communications interface (TestComponents)
-Move to Qt5 support

  • Property svn:executable set to *
File size: 13.4 KB
Line 
1// %pacpus:license{
2// This file is part of the PACPUS framework distributed under the
3// CECILL-C License, Version 1.0.
4// %pacpus:license}
5/// @version $Id: ComponentManager.cpp 76 2013-01-10 17:05:10Z kurdejma $
6
7#include <Pacpus/kernel/ComponentManager.h>
8#include <Pacpus/kernel/ComponentBase.h>
9#include <Pacpus/kernel/Log.h>
10#include <Pacpus/kernel/ConnectionBase.h>
11#include <QObject>
12
13#include <QDomNodeList>
14
15using namespace pacpus;
16
17DECLARE_STATIC_LOGGER("pacpus.core.ComponentManager");
18
19ComponentManager * ComponentManager::mInstance = NULL;
20
21ComponentManager * ComponentManager::create()
22{
23 return getInstance();
24}
25
26ComponentManager * ComponentManager::getInstance()
27{
28 LOG_TRACE("getInstance()");
29 LOG_TRACE("before: mInstance = " << mInstance);
30
31 if (!mInstance)
32 {
33 LOG_INFO("creating new instance...");
34 mInstance = new ComponentManager();
35 LOG_DEBUG("mInstance = " << mInstance);
36 }
37
38 LOG_TRACE("after: mInstance = " << mInstance);
39 return mInstance;
40}
41
42void ComponentManager::destroy()
43{
44 LOG_TRACE("destroy");
45
46 delete mInstance;
47 mInstance = NULL;
48}
49
50ComponentManager::ComponentManager()
51{
52 LOG_TRACE("constructor");
53
54 xmlTree_ = XmlConfigFile::create();
55 LOG_DEBUG("component manager was created");
56}
57
58ComponentManager::~ComponentManager()
59{
60 LOG_TRACE("destructor");
61
62 QMutableMapIterator<ComponentMap::key_type, ComponentMap::mapped_type> it(componentMap_);
63 while (it.hasNext())
64 unRegisterComponent(it.next().key());
65
66 LOG_DEBUG("component manager was deleted");
67}
68
69bool ComponentManager::registerComponentFactory(ComponentFactoryBase* addr, const QString& type)
70{
71 LOG_TRACE("registerComponentFactory(type="<< type << ")");
72
73 if (factoryMap_.contains(type))
74 {
75 LOG_WARN("cannot register a component factory of type '" << type << "'. It already belongs to the manager");
76 return false;
77 }
78
79 factoryMap_[type] = addr;
80 LOG_INFO("registered component factory '" << type << "'");
81
82 return true;
83}
84
85bool ComponentManager::unRegisterComponentFactory(const QString& type)
86{
87 LOG_TRACE("unRegisterComponentFactory(type="<< type << ")");
88
89 if (!factoryMap_.contains(type))
90 {
91 LOG_WARN("cannot unregister component factory '" << type << "'. It was not registered");
92 return false;
93 }
94
95 factoryMap_.remove(type);
96 LOG_INFO("unregistered component factory '" << type << "'");
97
98 return true;
99}
100
101bool ComponentManager::registerComponent(ComponentBase* addr, const QString& name)
102{
103 LOG_TRACE("registerComponent(name="<< name << ")");
104
105 if (componentMap_.contains(name))
106 {
107 LOG_WARN("cannot register component '" << name << "'. A component with the same name exists already");
108 return false;
109 }
110
111 componentMap_[name] = addr;
112 LOG_INFO("registered component " << name);
113
114 return true;
115}
116
117bool ComponentManager::unRegisterComponent(const QString& name)
118{
119 LOG_TRACE("unRegisterComponent(name="<< name << ")");
120
121 if (!componentMap_.contains(name))
122 {
123 LOG_WARN("cannot unregister component '" << name << "'. It was not registered");
124 return false;
125 }
126
127 // FIXME: delete component
128 //delete componentMap_[name];
129 componentMap_.remove(name);
130 LOG_INFO("unregistered component '" << name << "'");
131
132 return true;
133}
134
135bool ComponentManager::createComponent(const QString& type, const QString& name)
136{
137 LOG_TRACE("createComponent(type=" << type << ", " << "name="<< name << ")");
138
139 FactoryMap::iterator it = factoryMap_.find(type);
140 if (it != factoryMap_.end())
141 {
142 (*it)->addComponent(name);
143 return true;
144 }
145
146 LOG_WARN("cannot create component '" << name << "'"
147 << ". Component factory for type '" << type << "'"
148 << " does not exist or was not registered"
149 );
150 return false;
151}
152
153bool ComponentManager::loadPlugin(const QString& filename)
154{
155 LOG_TRACE("loadPlugin(filename=" << filename << ")");
156
157 pluginLoader_.setFileName(filename);
158
159 if (!pluginLoader_.load()) {
160 LOG_ERROR("cannot load plugin '" << filename << "'"
161 << ". Plugin loader returned error: " << pluginLoader_.errorString()
162 );
163 return false;
164 }
165
166 QObject * plugin = pluginLoader_.instance();
167 if (NULL == plugin) {
168 LOG_WARN("cannot create an instance of the plugin '" << filename << "'"
169 << ". Plugin loader returned error: " << pluginLoader_.errorString()
170 );
171 return false;
172 }
173 pluginList_.append(plugin);
174 LOG_INFO("loaded plugin '" << qobject_cast<PacpusPluginInterface*>(plugin)->name() << "'"
175 << " from file '" << pluginLoader_.fileName() << "'"
176 );
177 return true;
178}
179
180bool ComponentManager::createConnection(const QString& outputSignature, const QString& inputSignature, const QString& type, int priority = 0)
181{
182 QStringList output = outputSignature.split(".");
183 QStringList input = inputSignature.split(".");
184
185 if(getComponent(output[0])==NULL) {
186 LOG_WARN("cannot make connection : component " << output[0] << " not found");
187 return false;}
188 if(getComponent(output[0])->getOutput(output[1]) == NULL) {
189 LOG_WARN("cannot make connection : component " << output[0] << " doesn't have output " << output[1]);
190 return false;}
191 if(getComponent(input[0])==NULL) {
192 LOG_WARN("cannot make connection : component " << input[0] << " not found");
193 return false;}
194 if(getComponent(input[0])->getInput(input[1]) == NULL) {
195 LOG_WARN("cannot make connection : component " << input[0] << " doesn't have intput " << input[1]);
196 return false;}
197
198 OutputInterfaceBase * out = getComponent(output[0])->getOutput(output[1]);
199 InputInterfaceBase * in = getComponent(input[0])->getInput(input[1]);
200
201// if(in->getDataType() == QString(typeid(QByteArray).name()) && out->getDataType() != QString(typeid(QByteArray).name()))
202
203 if(out->getDataType() == in->getDataType() || out->getDataType() == QString(typeid(QByteArray).name()) || in->getDataType() == QString(typeid(QByteArray).name())) {
204
205 // Add connection
206 out->addConnection(ConnectionBase(in,priority)); // TODO and type argument
207 LOG_INFO("connection : Output " << out->getSignature() << " => Input " << in->getSignature())
208 return true;
209 } else {
210 LOG_WARN("connecting " << out->getSignature() << ":" << out->getDataType() << " to " << in->getSignature() << ":" << in->getDataType() << " failled : DataType incompatible " << QString(typeid(QByteArray).name()));
211 return false;
212 }
213
214 /*
215 FactoryMap::iterator it = factoryMap_.find(type);
216 if (it != factoryMap_.end())
217 {
218 (*it)->addComponent(name);
219 return true;
220 }
221 return false;*/
222}
223
224std::size_t ComponentManager::loadComponents(const QString& configFilename)
225{
226 LOG_TRACE("loadComponents(filename=" << configFilename << ")");
227
228 // load the components tree in memory
229 xmlTree_->loadFile(configFilename);
230
231 {
232 // Load the plugins containing the components
233 QStringList plugins = xmlTree_->getAllPlugins();
234 Q_FOREACH (QString plugin, plugins) {
235 if (!loadPlugin(plugin)) {
236 LOG_WARN("cannot load plugin '" << plugin << "'");
237 }
238 }
239 }
240
241 QDomNodeList componentsNodeList = xmlTree_->getAllComponents();
242 XmlComponentConfig cfg;
243
244 // First, create all the components in the XML list
245 for (int i = 0; i < componentsNodeList.size(); ++i) {
246 cfg.localCopy(componentsNodeList.item(i).toElement());
247 QString componentType = cfg.getComponentType();
248 QString componentName = cfg.getComponentName();
249 //LOG_DEBUG("try to create component '" << componentName << "'");
250 // create the component and automatically add it to the component manager list
251 if (!createComponent(componentType, componentName)) {
252 LOG_ERROR("cannot create component '" << componentName << "'");
253 continue;
254 }
255 }
256
257 int componentsToConfigureCount = componentMap_.count();
258
259 // Second, try to configure the components without regarding the dependencies
260 for (int i = 0; i < componentsNodeList.size(); ++i) {
261 //LOG_DEBUG("try to configure component '" << (*it) << "'");
262 cfg.localCopy(componentsNodeList.item(i).toElement());
263 QString componentName = cfg.getComponentName();
264
265 // copy locally the config parameters of the component
266 ComponentBase * component = getComponent(componentName);
267 if (NULL == component) {
268 LOG_WARN("component '" << componentName << "' does not exist");
269 } else {
270 component->param.localCopy(cfg.qDomElement());
271 component->configuration_ = component->configureComponent(cfg);
272
273 }
274 } // for
275
276 // Third, if some components requested a delayed configuration, retry
277 for (int i = 0; i < componentsNodeList.size(); ++i) {
278 cfg.localCopy(componentsNodeList.item(i).toElement());
279 QString componentName = cfg.getComponentName();
280
281 ComponentBase * component = getComponent(componentName);
282 if (NULL == component) {
283 LOG_WARN("component '" << componentName << "' does not exist");
284 } else {
285 if (component->configuration_ == ComponentBase::CONFIGURATION_DELAYED) {
286 //LOG_DEBUG("try to configure component '" << (*it) << "'");
287
288 // copy locally the config parameters of the component
289 component->param.localCopy(cfg.qDomElement());
290 component->configuration_ = component->configureComponent(cfg);
291 }
292
293 if (component->configuration_ == ComponentBase::CONFIGURED_OK) {
294 --componentsToConfigureCount;
295 } else {
296 /*LOG_ERROR("cannot configure component '" << (*it) << "'"
297 << ". Dependencies with other components are too complex"
298 << ". It was not configured, please review your configuration and/or your component"
299 );*/
300 component->configuration_ = ComponentBase::CONFIGURED_FAILED;
301 }
302 }
303 } // for
304
305 LOG_INFO(componentMap_.count() << " component(s) were loaded");
306 if (componentsToConfigureCount > 0) {
307 LOG_WARN(componentsToConfigureCount << " component(s) were not configured");
308 }
309
310 // Fourthly, create connections find in the XML list
311 QDomNodeList connectionsNodeList = xmlTree_->getAllConnections();
312
313 for (int i = 0; i < connectionsNodeList.size(); ++i) {
314
315 cfg.localCopy(connectionsNodeList.item(i).toElement());
316 QString connectionInput = cfg.getConnectionInput();
317 QString connectionOutput = cfg.getConnectionOutput();
318 QString connectionType = cfg.getConnectionType();
319 int connectionPriority = cfg.getConnectionPriority();
320
321 if (!createConnection(connectionOutput, connectionInput, connectionType,connectionPriority)) {
322 LOG_ERROR("cannot create connection '" << connectionOutput+"=>"+connectionInput << "'");
323 continue;
324 }
325 }
326
327 return componentMap_.count();
328}
329
330bool ComponentManager::start()
331{
332 LOG_TRACE("start()");
333
334 bool result = true;
335 for (ComponentMap::iterator it = componentMap_.begin(), itend = componentMap_.end(); it != itend; ++it )
336 result &= start(it.key());
337
338 return result;
339}
340
341bool ComponentManager::start(const QString& componentName)
342{
343 LOG_TRACE("start(component=" << componentName << ")");
344
345 ComponentBase* component = getComponent(componentName);
346 if (!component)
347 {
348 LOG_WARN("cannot start component '" << componentName << "'. It does not exist!");
349 return false;
350 }
351
352 LOG_INFO("starting component '" << componentName << "'...");
353 if (!component->startComponent())
354 LOG_WARN("cannot start component '" << componentName << "'. It can already be started");
355
356 return true;
357}
358
359bool ComponentManager::stop()
360{
361 LOG_TRACE("stop()");
362
363 bool result = true;
364 for (ComponentMap::iterator it = componentMap_.begin(); it != componentMap_.end(); ++it)
365 result &= stop(it.key());
366
367 return result;
368}
369
370bool ComponentManager::stop(const QString& componentName)
371{
372 LOG_TRACE("stop(component=" << componentName << ")");
373
374 ComponentBase* component = getComponent(componentName);
375 if (!component)
376 {
377 LOG_WARN("cannot stop component '" << componentName << "'" << ". It does not exist");
378 return false;
379 }
380
381 LOG_INFO("stopping component '" << componentName << "'...");
382 if (!component->stopComponent())
383 LOG_WARN("cannot stop component '" << componentName << "'" << ". It can be already stopped");
384
385 return true;
386}
387
388ComponentBase* ComponentManager::getComponent(const QString& name)
389{
390 LOG_TRACE("getComponent(name=" << name << ")");
391
392 ComponentMap::iterator it = componentMap_.find(name);
393 if (it != componentMap_.end())
394 return *it;
395
396 LOG_WARN("cannot retrieve component '" << name << "'" << ". It does not exist");
397 return NULL;
398}
399
400QStringList ComponentManager::getAllComponentsName() const
401{
402 LOG_TRACE("getAllComponentsName()");
403 return xmlTree_->getAllComponentsNames();
404}
Note: See TracBrowser for help on using the repository browser.