source: pacpusframework/branches/0.1.x/src/PacpusLib/XmlConfigFile.cpp

Last change on this file was 230, checked in by Marek Kurdej, 11 years ago

Fixed: Qt4 compilation on Linux

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