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

Last change on this file since 230 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
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: XmlConfigFile.cpp 76 2013-01-10 17:05:10Z kurdejma $
6
7#include <Pacpus/kernel/XmlConfigFile.h>
8
9#include <Pacpus/kernel/Log.h>
10
11#include <QFile>
12#include <QTextStream>
13
14////////////////////////////////////////////////////////////////////////////////
15
16using namespace pacpus;
17using namespace std;
18
19DECLARE_STATIC_LOGGER("pacpus.core.XmlConfigFile");
20
21XmlConfigFile * XmlConfigFile::m_xmlConfigFile = NULL;
22
23static const char * kXmlConfigFilename = "pacpus_config.xml";
24
25static const char * kRootSection = "pacpus";
26
27static const char * kComponentSection = "components";
28static const char * kConnectionSection = "connections";
29static const char * kParameterSection = "parameters";
30static const char * kPluginSection = "plugins";
31
32static const char * kComponentNode = "component";
33static const char * kConnectionNode = "connection";
34static const char * kParameterNode = "parameter";
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
50XmlConfigFile::XmlConfigFile()
51 : m_numberOfComponents(0)
52{
53 LOG_TRACE("constructor");
54
55 // create the root of the XML tree
56 m_document.appendChild(m_document.createElement(kRootSection));
57 // create the sections
58 m_document.documentElement().appendChild(m_document.createElement(kParameterSection));
59 m_document.documentElement().appendChild(m_document.createElement(kPluginSection));
60 m_document.documentElement().appendChild(m_document.createElement(kComponentSection));
61 m_document.documentElement().appendChild(m_document.createElement(kConnectionSection));
62 m_file.setFileName(kXmlConfigFilename);
63 bool isOpenedSuccessfully = m_file.open(QIODevice::ReadWrite); // FIXME: ReadOnly ?
64 if (isOpenedSuccessfully) {
65 LOG_INFO("XML document " << kXmlConfigFilename << " was created");
66 } else {
67 LOG_ERROR("cannot open XML document " << kXmlConfigFilename);
68 throw "cannot open XML document file";
69 }
70}
71
72XmlConfigFile::~XmlConfigFile()
73{
74 LOG_TRACE("destructor");
75}
76
77// CREATE/DESTROY
78XmlConfigFile * XmlConfigFile::create()
79{
80 if (NULL ==m_xmlConfigFile) {
81 m_xmlConfigFile = new XmlConfigFile();
82 }
83 return m_xmlConfigFile;
84}
85
86void XmlConfigFile::destroy()
87{
88 delete m_xmlConfigFile;
89 m_xmlConfigFile = NULL;
90}
91
92// COMPONENTS ADD/REMOVE/CREATE
93void XmlConfigFile::addComponent(QDomElement component)
94{
95 QMutexLocker mutexLocker(&m_mutex); // locks mutex, unlocks it in destructor
96 (void) mutexLocker; // unused
97
98 // TODO: change .tagName => .attribute(kPropertyComponentName)
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");
102 } else {
103 QDomNode node = getNamedItemFromDomDocument(m_document, kComponentSection).appendChild(component);
104 ++m_numberOfComponents;
105 LOG_INFO("component " << node.nodeName() << " has been added to the section "
106 << getNamedItemFromDomDocument(m_document, kComponentSection).nodeName());
107 }
108}
109
110void XmlConfigFile::delComponent(QDomElement component)
111{
112 removeComponent(component);
113}
114
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);
121 if (node.isNull()) {
122 LOG_WARN("component " << component.attribute(kNameAttribute)/*tagName()*/ << " doesn't exist in the document.");
123 } else {
124 LOG_INFO("component " << node.nodeName() << " has been removed from the section "
125 << getNamedItemFromDomDocument(m_document, kComponentSection).nodeName());
126 --m_numberOfComponents;
127 }
128}
129
130QDomElement XmlConfigFile::createComponent(QString name)
131{
132 LOG_DEBUG("creating component " << name);
133
134 QMutexLocker mutexLocker(&m_mutex); // locks mutex, unlocks it in destructor
135 (void) mutexLocker; // unused
136 return m_document.createElement(name);
137}
138
139// FILE I/O
140void XmlConfigFile::saveFile(QString fileName)
141{
142 QMutexLocker mutexLocker(&m_mutex);
143 (void) mutexLocker; // unused
144
145 m_file.close();
146 assert(!m_file.isOpen());
147 m_file.setFileName(fileName);
148 {
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;
154 }
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();
159 }
160 LOG_DEBUG("file \"" << m_file.fileName() << "\" has been saved");
161}
162
163int XmlConfigFile::loadFile(QString fileName)
164{
165 // lock access
166 QMutexLocker mutexLocker(&m_mutex);
167 (void) mutexLocker; // unused
168
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!");
172 }
173
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();
196 }
197
198 // get the number of components in the loaded tree
199 m_numberOfComponents = getAllComponents().count();
200
201 LOG_INFO("XML file \"" << m_file.fileName() << "\" has been loaded. Number of components = " << m_numberOfComponents);
202 LOG_DEBUG("XML file content:\n"
203 << "BEGIN============================================================================\n"
204 << m_document.toString()
205 << "END==============================================================================\n"
206 );
207
208 return m_numberOfComponents;
209}
210
211// XML
212QDomElement XmlConfigFile::getSection(const char * name) const
213{
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();
218 }
219 return sectionElement;
220}
221
222QDomNodeList XmlConfigFile::getNodesInSection(const char * sectionName, const char * nodeName) const
223{
224 QDomElement sectionElement = getSection(sectionName);
225 return sectionElement.elementsByTagName(nodeName);
226}
227
228// COMPONENTS
229QDomNodeList XmlConfigFile::getAllComponents() const
230{
231 return getNodesInSection(kComponentSection, kComponentNode);
232}
233
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));
243 }
244 return componentNameList;
245}
246
247QDomElement XmlConfigFile::getComponent(QString componentName) const
248{
249 LOG_DEBUG("getting component " << componentName);
250
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
260 return QDomElement();
261}
262
263// CONNECTIONS
264QDomNodeList XmlConfigFile::getAllConnections() const
265{
266 return getNodesInSection(kConnectionSection, kConnectionNode);
267}
268
269QDomElement XmlConfigFile::getConnection(QString name) const
270{
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();
284}
285
286// PARAMETERS
287QDomNodeList XmlConfigFile::getAllParameters() const
288{
289 return getNodesInSection(kParameterSection, kParameterNode);
290}
291
292// PLUGINS
293QDomNodeList XmlConfigFile::getAllPlugins()
294{
295 // get section
296 QDomElement pluginsElement = getSection(kPluginSection);
297
298 // get attributes
299 m_libraryExtension = pluginsElement.attribute(kExtensionAttribute);
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 }
306 m_libraryPrefix = pluginsElement.attribute(kPrefixAttribute);
307 m_libraryPostfix = pluginsElement.attribute(kPostfixAttribute);
308
309 // get nodes
310 return getNodesInSection(kPluginSection, kPluginNode);
311}
312
313QStringList XmlConfigFile::getAllPluginsNames()
314{
315 QDomNodeList pluginList = getAllPlugins();
316 if (0 == pluginList.size()) {
317 LOG_ERROR("no plugins were specified");
318 return QStringList();
319 }
320 LOG_INFO("there are " << pluginList.size() << " plugins");
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;
330}
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.