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

Last change on this file since 131 was 120, checked in by morasjul, 11 years ago
  • add PacpusSerialport (QT 5.1 required)
  • add part of QT4 / QT5 cmake script
  • fix CMake (link)
  • add ComponentBase virtual function addInput() & addOutput() call before component configuration
  • Property svn:executable set to *
File size: 12.8 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/ConnectionBase.h>
10#include <Pacpus/kernel/Log.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 // NOTE Create communicationInterface if needed ??
199
200 return connectInterface(getComponent(output[0])->getOutput(output[1]), getComponent(input[0])->getInput(input[1]), priority);
201
202}
203
204std::size_t ComponentManager::loadComponents(const QString& configFilename)
205{
206 LOG_TRACE("loadComponents(filename=" << configFilename << ")");
207
208 // load the components tree in memory
209 xmlTree_->loadFile(configFilename);
210
211 {
212 // Load the plugins containing the components
213 QStringList plugins = xmlTree_->getAllPlugins();
214 Q_FOREACH (QString plugin, plugins) {
215 if (!loadPlugin(plugin)) {
216 LOG_WARN("cannot load plugin '" << plugin << "'");
217 }
218 }
219 }
220
221 QDomNodeList componentsNodeList = xmlTree_->getAllComponents();
222 XmlComponentConfig cfg;
223
224 // First, create all the components in the XML list
225 for (int i = 0; i < componentsNodeList.size(); ++i) {
226 cfg.localCopy(componentsNodeList.item(i).toElement());
227 QString componentType = cfg.getComponentType();
228 QString componentName = cfg.getComponentName();
229 LOG_DEBUG("try to create component '" << componentName << "'");
230
231 // create the component and automatically add it to the component manager list
232 if (!createComponent(componentType, componentName)) {
233 LOG_ERROR("cannot create component '" << componentName << "'");
234 continue;
235 }
236 }
237
238 int componentsToConfigureCount = componentMap_.count();
239
240 // Second, try to configure the components without regarding the dependencies
241 for (int i = 0; i < componentsNodeList.size(); ++i) {
242 cfg.localCopy(componentsNodeList.item(i).toElement());
243 QString componentName = cfg.getComponentName();
244 LOG_DEBUG("try to configure component '" << componentName << "'");
245
246 // copy locally the config parameters of the component
247 ComponentBase * component = getComponent(componentName);
248 if (NULL == component) {
249 LOG_WARN("component '" << componentName << "' does not exist");
250 } else {
251 component->param.localCopy(cfg.qDomElement());
252 component->configuration_ = component->configureComponent(cfg);
253 }
254 } // for
255
256 // Third, if some components requested a delayed configuration, retry
257 for (int i = 0; i < componentsNodeList.size(); ++i) {
258 cfg.localCopy(componentsNodeList.item(i).toElement());
259 QString componentName = cfg.getComponentName();
260
261 ComponentBase * component = getComponent(componentName);
262 if (NULL == component) {
263 LOG_WARN("component '" << componentName << "' does not exist");
264 } else {
265 // Pacpus 2.0 : add input and output
266 component->addInput();
267 component->addOutput();
268
269 if (component->configuration_ == ComponentBase::CONFIGURATION_DELAYED) {
270 LOG_DEBUG("try to configure component '" << componentName << "'");
271
272 // copy locally the config parameters of the component
273 component->param.localCopy(cfg.qDomElement());
274 component->configuration_ = component->configureComponent(cfg);
275 }
276
277 if (component->configuration_ == ComponentBase::CONFIGURED_OK) {
278 --componentsToConfigureCount;
279 } else {
280 LOG_ERROR("cannot configure component '" << componentName << "'"
281 << ". Dependencies with other components are too complex"
282 << ". It was not configured, please review your configuration and/or your component"
283 );
284 component->configuration_ = ComponentBase::CONFIGURED_FAILED;
285 }
286 }
287 } // for
288
289 LOG_INFO(componentMap_.count() << " component(s) were loaded");
290 if (componentsToConfigureCount > 0) {
291 LOG_WARN(componentsToConfigureCount << " component(s) were not configured");
292 }
293
294 // Fourthly, create connections find in the XML list
295 QDomNodeList connectionsNodeList = xmlTree_->getAllConnections();
296
297 for (int i = 0; i < connectionsNodeList.size(); ++i) {
298
299 cfg.localCopy(connectionsNodeList.item(i).toElement());
300 QString connectionInput = cfg.getConnectionInput();
301 QString connectionOutput = cfg.getConnectionOutput();
302 QString connectionType = cfg.getConnectionType();
303 int connectionPriority = cfg.getConnectionPriority();
304
305
306 //TODO set connection mode from string
307
308 //InputInterfaceBase::GetLast;
309 //InputInterfaceBase::NeverSkip;
310 //InputInterfaceBase::TimeBounded;
311
312
313 if (!createConnection(connectionOutput, connectionInput, connectionType,connectionPriority)) {
314 LOG_ERROR("cannot create connection '" << connectionOutput+"=>"+connectionInput << "'");
315 continue;
316 }
317 } // for
318
319 return componentMap_.count();
320}
321
322bool ComponentManager::start()
323{
324 LOG_TRACE("start()");
325
326 bool result = true;
327 for (ComponentMap::iterator it = componentMap_.begin(), itend = componentMap_.end(); it != itend; ++it )
328 result &= start(it.key());
329
330 return result;
331}
332
333bool ComponentManager::start(const QString& componentName)
334{
335 LOG_TRACE("start(component=" << componentName << ")");
336
337 ComponentBase* component = getComponent(componentName);
338 if (!component)
339 {
340 LOG_WARN("cannot start component '" << componentName << "'. It does not exist!");
341 return false;
342 }
343
344 LOG_INFO("starting component '" << componentName << "'...");
345 if (!component->startComponent())
346 LOG_WARN("cannot start component '" << componentName << "'. It can already be started");
347
348 return true;
349}
350
351bool ComponentManager::stop()
352{
353 LOG_TRACE("stop()");
354
355 bool result = true;
356 for (ComponentMap::iterator it = componentMap_.begin(); it != componentMap_.end(); ++it)
357 result &= stop(it.key());
358
359 return result;
360}
361
362bool ComponentManager::stop(const QString& componentName)
363{
364 LOG_TRACE("stop(component=" << componentName << ")");
365
366 ComponentBase* component = getComponent(componentName);
367 if (!component)
368 {
369 LOG_WARN("cannot stop component '" << componentName << "'" << ". It does not exist");
370 return false;
371 }
372
373 LOG_INFO("stopping component '" << componentName << "'...");
374 if (!component->stopComponent())
375 LOG_WARN("cannot stop component '" << componentName << "'" << ". It can be already stopped");
376
377 return true;
378}
379
380ComponentBase* ComponentManager::getComponent(const QString& name)
381{
382 LOG_TRACE("getComponent(name=" << name << ")");
383
384 ComponentMap::iterator it = componentMap_.find(name);
385 if (it != componentMap_.end())
386 return *it;
387
388 LOG_WARN("cannot retrieve component '" << name << "'" << ". It does not exist");
389 return NULL;
390}
391
392QStringList ComponentManager::getAllComponentsName() const
393{
394 LOG_TRACE("getAllComponentsName()");
395 return xmlTree_->getAllComponentsNames();
396}
Note: See TracBrowser for help on using the repository browser.