source: pacpusframework/trunk/src/PacpusLib/XmlConfigFile.cpp@ 210

Last change on this file since 210 was 165, checked in by Marek Kurdej, 11 years ago

Major: changed plugins section name to plugings. Parameters section will be used for something else.

  • Property svn:executable set to *
File size: 12.0 KB
RevLine 
[89]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: XmlConfigFile.cpp 76 2013-01-10 17:05:10Z kurdejma $
6
7#include <Pacpus/kernel/XmlConfigFile.h>
[146]8
[89]9#include <Pacpus/kernel/Log.h>
10
11#include <QFile>
12#include <QTextStream>
13
[146]14////////////////////////////////////////////////////////////////////////////////
15
[89]16using namespace pacpus;
17using namespace std;
18
19DECLARE_STATIC_LOGGER("pacpus.core.XmlConfigFile");
20
[146]21XmlConfigFile * XmlConfigFile::m_xmlConfigFile = NULL;
[89]22
[147]23static const char * kXmlConfigFilename = "pacpus_config.xml";
[89]24
[146]25static const char * kRootSection = "pacpus";
[89]26
[146]27static const char * kComponentSection = "components";
28static const char * kConnectionSection = "connections";
29static const char * kParameterSection = "parameters";
[165]30static const char * kPluginSection = "plugins";
[146]31
32static const char * kComponentNode = "component";
33static const char * kConnectionNode = "connection";
[165]34static const char * kParameterNode = "parameter";
[146]35static const char * kPluginNode = "plugin";
36
37static const char * kNameAttribute = "name"; // <component name="MyComponent1" type="MyComponentType"/>
38static const char * kLibAttribute = "lib"; // <plugin lib="MyLibrary.dll"/>
39static const char * kExtensionAttribute = "extension"; // <parameter extension=".dll">
40static const char * kPrefixAttribute = "prefix"; // <parameter prefix="lib">
41static const char * kPostfixAttribute = "postfix"; // <parameter postfix="_d">
42
43////////////////////////////////////////////////////////////////////////////////
44// helper method
45QDomNode getNamedItemFromDomDocument(const QDomDocument & document, const char * itemName);
46
47////////////////////////////////////////////////////////////////////////////////
48
49// CTOR/DTOR
[89]50XmlConfigFile::XmlConfigFile()
[146]51 : m_numberOfComponents(0)
[89]52{
53 LOG_TRACE("constructor");
54
55 // create the root of the XML tree
[146]56 m_document.appendChild(m_document.createElement(kRootSection));
[89]57 // create the sections
[146]58 m_document.documentElement().appendChild(m_document.createElement(kParameterSection));
[165]59 m_document.documentElement().appendChild(m_document.createElement(kPluginSection));
[146]60 m_document.documentElement().appendChild(m_document.createElement(kComponentSection));
61 m_document.documentElement().appendChild(m_document.createElement(kConnectionSection));
[147]62 m_file.setFileName(kXmlConfigFilename);
[146]63 bool isOpenedSuccessfully = m_file.open(QIODevice::ReadWrite); // FIXME: ReadOnly ?
64 if (isOpenedSuccessfully) {
65 LOG_INFO("XML document " << kXmlConfigFilename << " was created");
[89]66 } else {
[146]67 LOG_ERROR("cannot open XML document " << kXmlConfigFilename);
68 throw "cannot open XML document file";
[89]69 }
70}
71
72XmlConfigFile::~XmlConfigFile()
73{
74 LOG_TRACE("destructor");
75}
76
[146]77// CREATE/DESTROY
[89]78XmlConfigFile * XmlConfigFile::create()
79{
[146]80 if (NULL ==m_xmlConfigFile) {
81 m_xmlConfigFile = new XmlConfigFile();
[89]82 }
[146]83 return m_xmlConfigFile;
[89]84}
85
86void XmlConfigFile::destroy()
87{
[146]88 delete m_xmlConfigFile;
89 m_xmlConfigFile = NULL;
[89]90}
91
[146]92// COMPONENTS ADD/REMOVE/CREATE
[89]93void XmlConfigFile::addComponent(QDomElement component)
94{
[146]95 QMutexLocker mutexLocker(&m_mutex); // locks mutex, unlocks it in destructor
96 (void) mutexLocker; // unused
97
[165]98 // TODO: change .tagName => .attribute(kPropertyComponentName)
[146]99 QDomNode componentSectionNode = getNamedItemFromDomDocument(m_document, kComponentSection);
100 if (componentSectionNode.namedItem(component.attribute(kNameAttribute)/*.tagName()*/).isNull()) {
101 LOG_WARN("component " << component.attribute(kNameAttribute)/*tagName()*/ << " exists already in the document");
[89]102 } else {
[146]103 QDomNode node = getNamedItemFromDomDocument(m_document, kComponentSection).appendChild(component);
104 ++m_numberOfComponents;
[89]105 LOG_INFO("component " << node.nodeName() << " has been added to the section "
[146]106 << getNamedItemFromDomDocument(m_document, kComponentSection).nodeName());
[89]107 }
108}
109
110void XmlConfigFile::delComponent(QDomElement component)
111{
[146]112 removeComponent(component);
113}
[89]114
[146]115void XmlConfigFile::removeComponent(QDomElement component)
116{
117 QMutexLocker mutexLocker(&m_mutex); // locks mutex, unlocks it in destructor
118 (void) mutexLocker; // unused
119
120 QDomNode node = getNamedItemFromDomDocument(m_document, kComponentSection).removeChild(component);
[89]121 if (node.isNull()) {
[146]122 LOG_WARN("component " << component.attribute(kNameAttribute)/*tagName()*/ << " doesn't exist in the document.");
[89]123 } else {
124 LOG_INFO("component " << node.nodeName() << " has been removed from the section "
[146]125 << getNamedItemFromDomDocument(m_document, kComponentSection).nodeName());
126 --m_numberOfComponents;
[89]127 }
128}
129
130QDomElement XmlConfigFile::createComponent(QString name)
131{
132 LOG_DEBUG("creating component " << name);
133
[146]134 QMutexLocker mutexLocker(&m_mutex); // locks mutex, unlocks it in destructor
135 (void) mutexLocker; // unused
136 return m_document.createElement(name);
[89]137}
138
[146]139// FILE I/O
[89]140void XmlConfigFile::saveFile(QString fileName)
141{
[146]142 QMutexLocker mutexLocker(&m_mutex);
143 (void) mutexLocker; // unused
[89]144
[146]145 m_file.close();
146 assert(!m_file.isOpen());
147 m_file.setFileName(fileName);
[89]148 {
[146]149 // open file
150 bool isOpenedSuccessfully = m_file.open(QIODevice::WriteOnly);
151 if (!isOpenedSuccessfully) {
152 LOG_ERROR("cannot open file '" << m_file.fileName() << "' for writing");
153 return;
[89]154 }
[146]155 QTextStream ts(&m_file);
156 ts << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
157 ts << m_document.toString();
158 m_file.close();
[89]159 }
[146]160 LOG_DEBUG("file \"" << m_file.fileName() << "\" has been saved");
[89]161}
162
163int XmlConfigFile::loadFile(QString fileName)
164{
[146]165 // lock access
166 QMutexLocker mutexLocker(&m_mutex);
167 (void) mutexLocker; // unused
[89]168
[146]169 // check if there are components already
170 if (0 != m_numberOfComponents) {
171 LOG_WARN("XML document contained " << m_numberOfComponents << " components that will be lost!");
[89]172 }
173
[146]174 m_file.close();
175 assert(!m_file.isOpen());
176 m_file.setFileName(fileName);
177 {
178 // open file
179 bool isOpenedSuccessfully = m_file.open(QIODevice::ReadOnly);
180 if (!isOpenedSuccessfully) {
181 LOG_ERROR("cannot open file '" << m_file.fileName() << "' for reading");
182 return 0;
183 }
184 // read and parse input XML file
185 QString errorMsg;
186 int errorLine = 0;
187 int errorColumn = 0;
188 if (!m_document.setContent(&m_file, /*namespaceProcessing=*/true, &errorMsg, &errorLine, &errorColumn)) {
189 LOG_ERROR("cannot parse XML file " << m_file.fileName());
190 LOG_ERROR(errorMsg << " at " << errorLine << ":" << errorColumn << " (line:col)");
191 m_file.close();
192 return 0;
193 }
194 // close file
195 m_file.close();
[89]196 }
197
198 // get the number of components in the loaded tree
[146]199 m_numberOfComponents = getAllComponents().count();
[89]200
[146]201 LOG_INFO("XML file \"" << m_file.fileName() << "\" has been loaded. Number of components = " << m_numberOfComponents);
[89]202 LOG_DEBUG("XML file content:\n"
[146]203 << "BEGIN============================================================================\n"
204 << m_document.toString()
205 << "END==============================================================================\n"
206 );
[89]207
[146]208 return m_numberOfComponents;
[89]209}
210
[165]211// XML
212QDomElement XmlConfigFile::getSection(const char * name) const
[89]213{
[165]214 QDomElement sectionElement = getNamedItemFromDomDocument(m_document, name).toElement();
215 if (sectionElement.isNull()) {
216 LOG_WARN("there is no '" << name << "' section in the XML");
217 return QDomElement();
[146]218 }
[165]219 return sectionElement;
220}
[89]221
[165]222QDomNodeList XmlConfigFile::getNodesInSection(const char * sectionName, const char * nodeName) const
223{
224 QDomElement sectionElement = getSection(sectionName);
225 return sectionElement.elementsByTagName(nodeName);
[146]226}
[89]227
[165]228// COMPONENTS
229QDomNodeList XmlConfigFile::getAllComponents() const
230{
231 return getNodesInSection(kComponentSection, kComponentNode);
232}
233
[146]234QStringList XmlConfigFile::getAllComponentsNames() const
235{
236 // get component nodes
237 QDomNodeList componentNodes = getAllComponents();
238 // get component names
239 QStringList componentNameList;
240 for (int i = 0; i < componentNodes.size(); ++i) {
241 QDomElement componentElement = componentNodes.at(i).toElement();
242 componentNameList.append(componentElement.attribute(kNameAttribute));
[89]243 }
[146]244 return componentNameList;
245}
[89]246
[146]247QDomElement XmlConfigFile::getComponent(QString componentName) const
248{
249 LOG_DEBUG("getting component " << componentName);
[89]250
[146]251 QDomNodeList componentNodes = getAllComponents();
252 for (int i = 0; i < componentNodes.size(); ++i) {
253 QDomElement componentElement = componentNodes.at(i).toElement();
254 if (componentName == componentElement.attribute(kNameAttribute)) {
255 return componentElement;
256 }
257 }
258 LOG_WARN("cannot get component " << componentName << ": document does not contain a component with this name");
259
[89]260 return QDomElement();
261}
262
[146]263// CONNECTIONS
264QDomNodeList XmlConfigFile::getAllConnections() const
[89]265{
[165]266 return getNodesInSection(kConnectionSection, kConnectionNode);
[89]267}
268
[146]269QDomElement XmlConfigFile::getConnection(QString name) const
[89]270{
[146]271 LOG_DEBUG("getting connection " << name);
272
273 QDomNodeList connectionNodes = getAllConnections();
274 for (int i = 0; i < connectionNodes.size(); ++i) {
275 QDomElement connectionElement = connectionNodes.at(i).toElement();
276 // TODO: name by attribute 'name'
277 if (name == connectionElement.attribute(kNameAttribute)) {
278 return connectionElement;
279 }
280 }
281 LOG_WARN("cannot get connection " << name << ": document does not contain a connection with this name");
282
283 return QDomElement();
[89]284}
285
[165]286// PARAMETERS
287QDomNodeList XmlConfigFile::getAllParameters() const
288{
289 return getNodesInSection(kParameterSection, kParameterNode);
290}
291
[146]292// PLUGINS
293QDomNodeList XmlConfigFile::getAllPlugins()
[89]294{
[165]295 // get section
296 QDomElement pluginsElement = getSection(kPluginSection);
[89]297
[146]298 // get attributes
[165]299 m_libraryExtension = pluginsElement.attribute(kExtensionAttribute);
[146]300 if (!m_libraryExtension.isEmpty()) {
301 // prefix with a dot '.' if there is no one
302 if ('.' != m_libraryExtension.at(0)) {
303 m_libraryExtension = '.' + m_libraryExtension;
304 }
305 }
[165]306 m_libraryPrefix = pluginsElement.attribute(kPrefixAttribute);
307 m_libraryPostfix = pluginsElement.attribute(kPostfixAttribute);
[146]308
[165]309 // get nodes
310 return getNodesInSection(kPluginSection, kPluginNode);
[89]311}
312
[146]313QStringList XmlConfigFile::getAllPluginsNames()
[89]314{
[146]315 QDomNodeList pluginList = getAllPlugins();
316 if (0 == pluginList.size()) {
317 LOG_ERROR("no plugins were specified");
318 return QStringList();
319 }
[165]320 LOG_INFO("there are " << pluginList.size() << " plugins");
[146]321
322 // get plugin library paths
323 QStringList pluginLibraryNames;
324 for (int i = 0; i < pluginList.size(); ++i) {
325 QDomElement pluginElement = pluginList.at(i).toElement();
326 QString libraryFileName = libraryPrefix() + pluginElement.attribute(kLibAttribute) + libraryPostfix() + libraryExtension();
327 pluginLibraryNames.append(libraryFileName);
328 }
329 return pluginLibraryNames;
[89]330}
[146]331
332QString XmlConfigFile::libraryExtension() const
333{
334 return m_libraryExtension;
335}
336
337QString XmlConfigFile::libraryPrefix() const
338{
339 return m_libraryPrefix;
340}
341
342QString XmlConfigFile::libraryPostfix() const
343{
344 return m_libraryPostfix;
345}
346
347////////////////////////////////////////////////////////////////////////////////
348// HELPER METHODS
349QDomNode getNamedItemFromDomDocument(const QDomDocument & document, const char * itemName)
350{
351 return document.documentElement().namedItem(itemName);
352}
Note: See TracBrowser for help on using the repository browser.