Index: branches/2.0-beta1/src/PacpusLib/XmlConfigFile.cpp
===================================================================
--- branches/2.0-beta1/src/PacpusLib/XmlConfigFile.cpp	(revision 110)
+++ branches/2.0-beta1/src/PacpusLib/XmlConfigFile.cpp	(revision 146)
@@ -6,4 +6,5 @@
 
 #include <Pacpus/kernel/XmlConfigFile.h>
+
 #include <Pacpus/kernel/Log.h>
 
@@ -11,4 +12,6 @@
 #include <QTextStream>
 
+////////////////////////////////////////////////////////////////////////////////
+
 using namespace pacpus;
 using namespace std;
@@ -16,5 +19,5 @@
 DECLARE_STATIC_LOGGER("pacpus.core.XmlConfigFile");
 
-XmlConfigFile * XmlConfigFile::_xmlConfigFile = NULL;
+XmlConfigFile * XmlConfigFile::m_xmlConfigFile = NULL;
 
 static const string kPropertyPluginList = "list";
@@ -22,31 +25,45 @@
 static const string kXmlConfigFilename = "pacpus_config.xml";
 
-#define rootSection "pacpus"
-#define componentSection "components"
-#define componentNode "component"
-#define connectionSection "connections"
-#define connectionNode "connection"
-#define parameterSection "parameters"
-#define pluginNode "plugin"
-#define nameAttribute "name"
-#define libAttribute "lib"
-
+static const char * kRootSection = "pacpus";
+
+static const char * kComponentSection = "components";
+static const char * kConnectionSection = "connections";
+static const char * kParameterSection = "parameters";
+
+static const char * kComponentNode = "component";
+static const char * kConnectionNode = "connection";
+static const char * kPluginNode = "plugin";
+
+static const char * kNameAttribute = "name"; // <component name="MyComponent1" type="MyComponentType"/>
+static const char * kLibAttribute = "lib"; // <plugin lib="MyLibrary.dll"/>
+static const char * kExtensionAttribute = "extension"; // <parameter extension=".dll">
+static const char * kPrefixAttribute = "prefix"; // <parameter prefix="lib">
+static const char * kPostfixAttribute = "postfix"; // <parameter postfix="_d">
+
+////////////////////////////////////////////////////////////////////////////////
+// helper method
+QDomNode getNamedItemFromDomDocument(const QDomDocument & document, const char * itemName);
+
+////////////////////////////////////////////////////////////////////////////////
+
+// CTOR/DTOR
 XmlConfigFile::XmlConfigFile()
-    : _file(NULL)
-    , _numberOfComponents(0)
+    : m_numberOfComponents(0)
 {
     LOG_TRACE("constructor");
 
     // create the root of the XML tree
-    _document.appendChild(_document.createElement(rootSection));
+    m_document.appendChild(m_document.createElement(kRootSection));
     // create the sections
-    _document.documentElement().appendChild(_document.createElement(parameterSection));
-    _document.documentElement().appendChild(_document.createElement(componentSection));
-    _document.documentElement().appendChild(_document.createElement(connectionSection));
-    _file = new QFile(kXmlConfigFilename.c_str());
-    if (NULL != _file) {
-        LOG_INFO("XML document " << kXmlConfigFilename.c_str() << " was created");
+    m_document.documentElement().appendChild(m_document.createElement(kParameterSection));
+    m_document.documentElement().appendChild(m_document.createElement(kComponentSection));
+    m_document.documentElement().appendChild(m_document.createElement(kConnectionSection));
+    m_file.setFileName(kXmlConfigFilename.c_str());
+    bool isOpenedSuccessfully = m_file.open(QIODevice::ReadWrite); // FIXME: ReadOnly ?
+    if (isOpenedSuccessfully) {
+        LOG_INFO("XML document " << kXmlConfigFilename << " was created");
     } else {
-        LOG_WARN("cannot create XML document " << kXmlConfigFilename.c_str());
+        LOG_ERROR("cannot open XML document " << kXmlConfigFilename);
+        throw "cannot open XML document file";
     }
 }
@@ -57,47 +74,55 @@
 }
 
+// CREATE/DESTROY
 XmlConfigFile * XmlConfigFile::create()
 {
-    if (NULL ==_xmlConfigFile) {
-        _xmlConfigFile = new XmlConfigFile();
-    }
-    return _xmlConfigFile;
+    if (NULL ==m_xmlConfigFile) {
+        m_xmlConfigFile = new XmlConfigFile();
+    }
+    return m_xmlConfigFile;
 }
 
 void XmlConfigFile::destroy()
 {
-    delete _xmlConfigFile;
-    _xmlConfigFile = NULL;
-}
-
+    delete m_xmlConfigFile;
+    m_xmlConfigFile = NULL;
+}
+
+// COMPONENTS ADD/REMOVE/CREATE
 void XmlConfigFile::addComponent(QDomElement component)
 { 
-    _mutex.lock();
-// TODO change .tagName => .attribute(kPropertyComponentName.c_str())
-    if (_document.documentElement().namedItem(componentSection).namedItem(component.attribute(nameAttribute)/*.tagName()*/).isNull()) {
-        LOG_WARN("component " << component.attribute(nameAttribute)/*tagName()*/ << " exists already in the document");
+    QMutexLocker mutexLocker(&m_mutex); // locks mutex, unlocks it in destructor
+    (void) mutexLocker; // unused
+
+    // TODO: change .tagName => .attribute(kPropertyComponentName.c_str())
+    QDomNode componentSectionNode = getNamedItemFromDomDocument(m_document, kComponentSection);
+    if (componentSectionNode.namedItem(component.attribute(kNameAttribute)/*.tagName()*/).isNull()) {
+        LOG_WARN("component " << component.attribute(kNameAttribute)/*tagName()*/ << " exists already in the document");
     } else {
-        QDomNode node = _document.documentElement().namedItem(componentSection).appendChild(component);
-        ++_numberOfComponents;
+        QDomNode node = getNamedItemFromDomDocument(m_document, kComponentSection).appendChild(component);
+        ++m_numberOfComponents;
         LOG_INFO("component " << node.nodeName() << " has been added to the section "
-                 << _document.documentElement().namedItem(componentSection).nodeName());
-    }
-    _mutex.unlock();
+            << getNamedItemFromDomDocument(m_document, kComponentSection).nodeName());
+    }
 }
 
 void XmlConfigFile::delComponent(QDomElement component)
 {
-    _mutex.lock();
-
-    QDomNode node = _document.documentElement().namedItem(componentSection).removeChild(component);
+    removeComponent(component);
+}
+
+void XmlConfigFile::removeComponent(QDomElement component)
+{
+    QMutexLocker mutexLocker(&m_mutex); // locks mutex, unlocks it in destructor
+    (void) mutexLocker; // unused
+
+    QDomNode node = getNamedItemFromDomDocument(m_document, kComponentSection).removeChild(component);
     if (node.isNull()) {
-        LOG_WARN("component " << component.attribute(nameAttribute)/*tagName()*/ << " doesn't exist in the document.");
+        LOG_WARN("component " << component.attribute(kNameAttribute)/*tagName()*/ << " doesn't exist in the document.");
     } else {
         LOG_INFO("component " << node.nodeName() << " has been removed from the section "
-                 << _document.documentElement().namedItem(componentSection).nodeName());
-        --_numberOfComponents;
-    }
-
-    _mutex.unlock();
+            << getNamedItemFromDomDocument(m_document, kComponentSection).nodeName());
+        --m_numberOfComponents;
+    }
 }
 
@@ -106,110 +131,218 @@
     LOG_DEBUG("creating component " << name);
 
-    QMutexLocker mutexLocker(&_mutex);
-    Q_UNUSED(mutexLocker);
-    return _document.createElement(name);
-}
-
+    QMutexLocker mutexLocker(&m_mutex); // locks mutex, unlocks it in destructor
+    (void) mutexLocker; // unused
+    return m_document.createElement(name);
+}
+
+// FILE I/O
 void XmlConfigFile::saveFile(QString fileName)
 {
-    QMutexLocker mutexLocker(&_mutex);
-    Q_UNUSED(mutexLocker);
-
-    _file->setFileName(fileName);
+    QMutexLocker mutexLocker(&m_mutex);
+    (void) mutexLocker; // unused
+
+    m_file.close();
+    assert(!m_file.isOpen());
+    m_file.setFileName(fileName);
     {
-        _file->open(QIODevice::WriteOnly);
-        {
-            QTextStream ts(_file);
-            ts << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" + _document.toString();
-        }
-        _file->close();
-    }
-    LOG_DEBUG("file \"" << _file->fileName() << "\" has been saved");
+        // open file
+        bool isOpenedSuccessfully = m_file.open(QIODevice::WriteOnly);
+        if (!isOpenedSuccessfully) {
+            LOG_ERROR("cannot open file '" << m_file.fileName() << "' for writing");
+            return;
+        }
+        QTextStream ts(&m_file);
+        ts << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
+        ts << m_document.toString();
+        m_file.close();
+    }
+    LOG_DEBUG("file \"" << m_file.fileName() << "\" has been saved");
 }
 
 int XmlConfigFile::loadFile(QString fileName)
 {
-    QMutexLocker mutexLocker(&_mutex);
-    Q_UNUSED(mutexLocker);
-
-    int line = 0, col = 0;
-    QString errorMsg;
-
-    if (_numberOfComponents != 0) {
-        LOG_WARN("XML document contained " << _numberOfComponents << " components that will be lost!");
-    }
-
-    _file->setFileName(fileName);
-    if (!_file->open( QIODevice::ReadOnly )) {
-        LOG_ERROR("cannot open file " << fileName);
-        return 0;
-    }
-    if (!_document.setContent( _file, true, &errorMsg, &line, &col )) {
-        LOG_ERROR("cannot get data into the file " << fileName);
-        LOG_ERROR(errorMsg << " at position " << line << ":" << col << " (line:col)");
-        _file->close();
-        return 0;
-    }
-    _file->close();
+    // lock access
+    QMutexLocker mutexLocker(&m_mutex);
+    (void) mutexLocker; // unused
+
+    // check if there are components already
+    if (0 != m_numberOfComponents) {
+        LOG_WARN("XML document contained " << m_numberOfComponents << " components that will be lost!");
+    }
+
+    m_file.close();
+    assert(!m_file.isOpen());
+    m_file.setFileName(fileName);
+    {
+        // open file
+        bool isOpenedSuccessfully = m_file.open(QIODevice::ReadOnly);
+        if (!isOpenedSuccessfully) {
+            LOG_ERROR("cannot open file '" << m_file.fileName() << "' for reading");
+            return 0;
+        }
+        // read and parse input XML file
+        QString errorMsg;
+        int errorLine = 0;
+        int errorColumn = 0;
+        if (!m_document.setContent(&m_file, /*namespaceProcessing=*/true, &errorMsg, &errorLine, &errorColumn)) {
+            LOG_ERROR("cannot parse XML file " << m_file.fileName());
+            LOG_ERROR(errorMsg << " at " << errorLine << ":" << errorColumn << " (line:col)");
+            m_file.close();
+            return 0;
+        }
+        // close file
+        m_file.close();
+    }
 
     // get the number of components in the loaded tree
-    _numberOfComponents = _document.documentElement().namedItem(componentSection).childNodes().count();
-
-    LOG_INFO("XML file \"" << fileName << "\" has been loaded. Number of components = " << _numberOfComponents);
+    m_numberOfComponents = getAllComponents().count();
+
+    LOG_INFO("XML file \"" << m_file.fileName() << "\" has been loaded. Number of components = " << m_numberOfComponents);
     LOG_DEBUG("XML file content:\n"
-              << "BEGIN============================================================================\n"
-              << _document.toString()
-              << "END==============================================================================\n"
-              );
-
-    return _numberOfComponents;
-}
-
-QDomElement XmlConfigFile::getComponent(QString componentName)
+        << "BEGIN============================================================================\n"
+        << m_document.toString()
+        << "END==============================================================================\n"
+        );
+
+    return m_numberOfComponents;
+}
+
+// COMPONENTS
+QDomNodeList XmlConfigFile::getAllComponents() const
+{
+    // get components section
+    QDomElement componentsElement = getNamedItemFromDomDocument(m_document, kComponentSection).toElement();
+    if (componentsElement.isNull()) {
+        LOG_WARN("there is no '" << kComponentSection << "' section in the XML");
+        return QDomNodeList();
+    }
+
+    // get component nodes
+    return componentsElement.elementsByTagName(kComponentNode);
+}
+
+QStringList XmlConfigFile::getAllComponentsNames() const
+{
+    // get component nodes
+    QDomNodeList componentNodes = getAllComponents();
+    // get component names
+    QStringList componentNameList;
+    for (int i = 0; i < componentNodes.size(); ++i) {
+        QDomElement componentElement = componentNodes.at(i).toElement();
+        componentNameList.append(componentElement.attribute(kNameAttribute));
+    }
+    return componentNameList;
+}
+
+QDomElement XmlConfigFile::getComponent(QString componentName) const
 {
     LOG_DEBUG("getting component " << componentName);
 
-    QDomNodeList nodeList = _document.documentElement().namedItem(componentSection).toElement().elementsByTagName(componentNode);
-    for (int i = 0; i < _numberOfComponents; i++) {
-
-        if(nodeList.at(i).toElement().attribute(nameAttribute) == componentName)
-            return nodeList.at(i).toElement();
-    }
-
-    LOG_WARN("cannot get component " << componentName << ": document does not contain the component");
+    QDomNodeList componentNodes = getAllComponents();
+    for (int i = 0; i < componentNodes.size(); ++i) {
+        QDomElement componentElement = componentNodes.at(i).toElement();
+        if (componentName == componentElement.attribute(kNameAttribute)) {
+            return componentElement;
+        }
+    }
+    LOG_WARN("cannot get component " << componentName << ": document does not contain a component with this name");
 
     return QDomElement();
 } 
 
-QStringList XmlConfigFile::getAllComponentsNames()
-{
-    QStringList componentNameList;   
-    QDomNodeList nodeList = _document.documentElement().namedItem(componentSection).toElement().elementsByTagName(componentNode);
-     for (int i = 0; i < _numberOfComponents; i++) {
-         componentNameList.append(nodeList.at(i).toElement().attribute(nameAttribute));
-    }
-    return componentNameList;
-}
-
-QDomNodeList XmlConfigFile::getAllComponents()
-{
-    return _document.documentElement().namedItem(componentSection).toElement().elementsByTagName(componentNode);
-}
-
-QStringList XmlConfigFile::getAllPlugins()
-{
-    QDomNodeList nodeList = _document.documentElement().namedItem(parameterSection).toElement().elementsByTagName(pluginNode);
-    QStringList stringList;
-    if(nodeList.size() == 0) {
-        LOG_WARN("no plugins were specified");
-    } else
-        for(int i = 0; i< nodeList.size(); ++i)
-            stringList.append(nodeList.at(i).toElement().attribute(libAttribute));
-
-    return stringList;
-}
-
-QDomNodeList XmlConfigFile::getAllConnections()
-{
-   return _document.documentElement().namedItem(connectionSection).childNodes();
-}
+// CONNECTIONS
+QDomNodeList XmlConfigFile::getAllConnections() const
+{
+    // get connections section
+    QDomElement connectionsElement = getNamedItemFromDomDocument(m_document, kParameterSection).toElement();
+    if (connectionsElement.isNull()) {
+        LOG_WARN("there is no '" << kParameterSection << "' section in the XML");
+        return QDomNodeList();
+    }
+
+    // get connection nodes
+    //return connectionsElement.elementsByTagName(kConnectionNode);
+    return getNamedItemFromDomDocument(m_document, kConnectionSection).childNodes();
+}
+
+QDomElement XmlConfigFile::getConnection(QString name) const
+{
+    LOG_DEBUG("getting connection " << name);
+
+    QDomNodeList connectionNodes = getAllConnections();
+    for (int i = 0; i < connectionNodes.size(); ++i) {
+        QDomElement connectionElement = connectionNodes.at(i).toElement();
+        // TODO: name by attribute 'name'
+        if (name == connectionElement.attribute(kNameAttribute)) {
+            return connectionElement;
+        }
+    }
+    LOG_WARN("cannot get connection " << name << ": document does not contain a connection with this name");
+
+    return QDomElement();
+}
+
+// PLUGINS
+QDomNodeList XmlConfigFile::getAllPlugins()
+{
+    // get parameters section
+    QDomElement parametersElement = getNamedItemFromDomDocument(m_document, kParameterSection).toElement();
+    if (parametersElement.isNull()) {
+        LOG_WARN("there is no '" << kParameterSection << "' section in the XML");
+        return QDomNodeList();
+    }
+
+    // get attributes
+    m_libraryExtension = parametersElement.attribute(kExtensionAttribute);
+    if (!m_libraryExtension.isEmpty()) {
+        // prefix with a dot '.' if there is no one
+        if ('.' != m_libraryExtension.at(0)) {
+            m_libraryExtension = '.' + m_libraryExtension;
+        }
+    }
+    m_libraryPrefix = parametersElement.attribute(kPrefixAttribute);
+    m_libraryPostfix = parametersElement.attribute(kPostfixAttribute);
+    
+    // get plugin nodes
+    return parametersElement.elementsByTagName(kPluginNode);
+}
+
+QStringList XmlConfigFile::getAllPluginsNames()
+{
+    QDomNodeList pluginList = getAllPlugins();
+    if (0 == pluginList.size()) {
+        LOG_ERROR("no plugins were specified");
+        return QStringList();
+    }
+
+    // get plugin library paths
+    QStringList pluginLibraryNames;
+    for (int i = 0; i < pluginList.size(); ++i) {
+        QDomElement pluginElement = pluginList.at(i).toElement();
+        QString libraryFileName = libraryPrefix() + pluginElement.attribute(kLibAttribute) + libraryPostfix() + libraryExtension();
+        pluginLibraryNames.append(libraryFileName);
+    }
+    return pluginLibraryNames;
+}
+
+QString XmlConfigFile::libraryExtension() const
+{
+    return m_libraryExtension;
+}
+
+QString XmlConfigFile::libraryPrefix() const
+{
+    return m_libraryPrefix;
+}
+
+QString XmlConfigFile::libraryPostfix() const
+{
+    return m_libraryPostfix;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// HELPER METHODS
+QDomNode getNamedItemFromDomDocument(const QDomDocument & document, const char * itemName)
+{
+    return document.documentElement().namedItem(itemName);
+}
