source: pacpusframework/branches/2.0-beta1/src/PacpusLib/XmlConfigFile.cpp@ 146

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

Update: refactoring in XmlConfigFile.
Added: attributes 'prefix', 'postfix', 'extension' in <parameters>.
Example: <parameters prefix="" postfix="_d" extension="dll">

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