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

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

Added: scripts to create new component.

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