Commit 30448f6284ab20cc105e4e708ba44ad7440257e6

Authored by Peter M. Groen
0 parents

Replace Qt with std::c++

CMakeLists.txt 0 → 100644
  1 +++ a/CMakeLists.txt
  1 +cmake_minimum_required(VERSION 3.0)
  2 +project(config)
  3 +
  4 +LIST( APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/submodules/cmake )
  5 +
  6 +include(projectheader)
  7 +project_header(config)
  8 +
  9 +# Build the artifacts
  10 +add_subdirectory(${CMAKE_SOURCE_DIR}/submodules/logger)
  11 +add_subdirectory(${CMAKE_SOURCE_DIR}/submodules/pugixml)
  12 +
  13 +# Build the source code
  14 +add_subdirectory(src)
  15 +
  16 +include(packaging)
  17 +package_component()
scripts/setup_submodules 0 → 100755
  1 +++ a/scripts/setup_submodules
  1 +#!/bin/bash
  2 +
  3 +# ===============================================
  4 +# == Setting some environment variables
  5 +# ===============================================
  6 +GIT_URL_OPEN="http://gitlab.osdev.nl/open_source"
  7 +GIT_URL_CLOSED="git@gitlab.osdev.nl:closed_source"
  8 +
  9 +FUNC_RESULT="-1"
  10 +
  11 +# Name : print_usage_exit()
  12 +# Description : Print the way this script is intended to be used and exit.
  13 +# Parameters : None.
  14 +# Returns : err_code 1 to the Operating System
  15 +# --------------------------------------------------------------------------------------
  16 +function print_usage_exit()
  17 +{
  18 + echo "Usage $0 -i|--install|-u|--update"
  19 + echo " -i or --install Install the submodules mentioned in the submodules.list"
  20 + echo " -u or --update Update the submodules mentioned in the submodules.list"
  21 + echo " "
  22 + exit 1
  23 +}
  24 +
  25 +# Name : check_top_or_sub
  26 +# Description : Determine if we're running in a "single" lib-build or part of a
  27 +# "meta"-repository ( submodule ).
  28 +# Parameters : None
  29 +# Returns : Updates the value FUNC_RESULT.
  30 +# -1 - We're neither a git-repo or submodule.
  31 +# 0 - We're a submodule
  32 +# 1 - We're a top-repo ( Single library )
  33 +# --------------------------------------------------------------------------------------
  34 +function check_top_or_sub()
  35 +{
  36 + # This function checks if we're the top-repository.
  37 + # In that case we need the submodules.. If we're already a submodule,
  38 + # we simply exit this script with a message
  39 + if [ -e ./.git ]; then
  40 + FUNC_RESULT="1"
  41 + return
  42 + elif [ -e ../.git ]; then
  43 + if [ -e ../.submodules ]; then
  44 + echo "Seems like we're already a submodule. Nothing to do here."
  45 + FUNC_RESULT="0"
  46 + return
  47 + fi
  48 + fi
  49 + FUNC_RESULT="-1"
  50 + return
  51 +}
  52 +
  53 +# Name : check_working_dir
  54 +# Description : If we're in the top of our repo, we can run this script further.
  55 +# Parameters : None.
  56 +# Returns : Updates the value FUNC_RESULT.
  57 +# -1 - Not used.
  58 +# 0 - We're not on the top-level
  59 +# 1 - We're at the top-level. Good to go.
  60 +# --------------------------------------------------------------------------------------
  61 +function check_working_dir()
  62 +{
  63 + FUNC_RESULT="-1"
  64 + # Check if we're in the top-level directory of our repository.
  65 + if [ -f ./scripts/submodules.list ]; then
  66 + # We're good to go
  67 + FUNC_RESULT="1"
  68 + return
  69 + fi
  70 + FUNC_RESULT="0"
  71 + return
  72 +}
  73 +
  74 +# Name : read_submodules
  75 +# Description : Read the list of submodules needed for this project
  76 +# Parameters : None
  77 +# Returns : Updates the value FUNC_RESULT
  78 +# 0 - Module list was not found
  79 +# 1 - Module list was found and read.
  80 +# --------------------------------------------------------------------------------------
  81 +function read_submodules()
  82 +{
  83 + FUNC_RESULT="-1"
  84 + if [ -e ./scripts/submodules.list ]; then
  85 + source ./scripts/submodules.list
  86 + FUNC_RESULT="1"
  87 + return
  88 + fi
  89 +
  90 + echo "Submodules list not found...."
  91 + FUNC_RESULT="0"
  92 + return
  93 +}
  94 +
  95 +# Name : add_submodules
  96 +# Description : Configure the repo to add the submodules.
  97 +# Parameters : None.
  98 +# Returns : None.
  99 +# --------------------------------------------------------------------------------------
  100 +function add_submodules()
  101 +{
  102 + echo -e "Adding SubModule(s)."
  103 + for SUB_MODULE in ${SUB_MODULES_OPEN}
  104 + do
  105 + git submodule add -f ${GIT_URL_OPEN}/${SUB_MODULE}.git submodules/${SUB_MODULE}
  106 + git config submodule.${SUB_MODULE}.url ${GIT_URL_OPEN}/${SUB_MODULE}.git
  107 + done
  108 +
  109 + for SUB_MODULE in ${SUB_MODULES_CLOSED}
  110 + do
  111 + echo {GIT_URL_CLOSED}/${SUB_MODULE}.git
  112 + git submodule add -f ${GIT_URL_CLOSED}/${SUB_MODULE}.git submodules/${SUB_MODULE}
  113 + git config submodule.${SUB_MODULE}.url ${GIT_URL_CLOSED}/${SUB_MODULE}.git
  114 + done
  115 +
  116 +}
  117 +
  118 +# Name : get_submodules
  119 +# Description : Actually get the submodules from gitlab and add them.
  120 +# Parameters : None
  121 +# Returns : None
  122 +# --------------------------------------------------------------------------------------
  123 +function get_submodules()
  124 +{
  125 + git submodule update --init --recursive
  126 +}
  127 +
  128 +# Name : update_submodules
  129 +# Description : Update the submodules already added.
  130 +# Parameters : None
  131 +# Returns : None
  132 +# --------------------------------------------------------------------------------------
  133 +function update_submodules()
  134 +{
  135 + git submodule update --recursive
  136 +}
  137 +
  138 +# =============================================================================
  139 +# == T H E M A I N E N T R Y O F T H I S S C R I P T ==
  140 +# =============================================================================
  141 +check_top_or_sub
  142 +if [ "${FUNC_RESULT}" == "0" ]; then
  143 + echo "Seems like we're a submodule already or not part of a repository."
  144 + exit 0
  145 +fi
  146 +
  147 +check_working_dir
  148 +if [ "${FUNC_RESULT}" == "0" ]; then
  149 + echo "Go to the top of this repository and type : scripts/setup_submodules [-i|--install]"
  150 + exit 0
  151 +fi
  152 +
  153 +read_submodules
  154 +
  155 +case "$1" in
  156 + -i*|--install*)
  157 + echo "Installing submodules for this repository ( ${PWD} )"
  158 + add_submodules
  159 + get_submodules
  160 + ;;
  161 + -u*|--update*)
  162 + echo "Update submodules : ${SUB_MODULES}"
  163 + update_submodules
  164 + ;;
  165 + *)
  166 + echo "No parameters found..."
  167 + print_usage_exit
  168 + ;;
  169 +esac
  170 +
scripts/submodules.list 0 → 100644
  1 +++ a/scripts/submodules.list
  1 +SUB_MODULES_OPEN="cmake
  2 +logger
  3 +pugixml"
  4 +
  5 +SUB_MODULES_CLOSED=""
src/CMakeLists.txt 0 → 100644
  1 +++ a/src/CMakeLists.txt
  1 +cmake_minimum_required(VERSION 3.0)
  2 +LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/submodules/cmake)
  3 +include(projectheader)
  4 +project_header(config)
  5 +
  6 +find_package( Qt5Core REQUIRED )
  7 +include_directories( SYSTEM
  8 + ${Qt5Core_INCLUDE_DIRS}
  9 +)
  10 +
  11 +include(compiler)
  12 +
  13 +include_directories(
  14 + ${CMAKE_SOURCE_DIR}/submodules/pugixml/src
  15 + ${CMAKE_SOURCE_DIR}/submodules/logger/src
  16 +)
  17 +
  18 +set(SRC_LIST
  19 + ${CMAKE_CURRENT_SOURCE_DIR}/connection.h
  20 + ${CMAKE_CURRENT_SOURCE_DIR}/connection.cpp
  21 + ${CMAKE_CURRENT_SOURCE_DIR}/connections.h
  22 + ${CMAKE_CURRENT_SOURCE_DIR}/connections.cpp
  23 + ${CMAKE_CURRENT_SOURCE_DIR}/connectordata.h
  24 + ${CMAKE_CURRENT_SOURCE_DIR}/connectordata.cpp
  25 + ${CMAKE_CURRENT_SOURCE_DIR}/dcxmlbase.h
  26 + ${CMAKE_CURRENT_SOURCE_DIR}/dcxmlbase.cpp
  27 + ${CMAKE_CURRENT_SOURCE_DIR}/dcxmlconfig.h
  28 + ${CMAKE_CURRENT_SOURCE_DIR}/dcxmlconfig.cpp
  29 + ${CMAKE_CURRENT_SOURCE_DIR}/dcxmletlnetwork.h
  30 + ${CMAKE_CURRENT_SOURCE_DIR}/dcxmletlnetwork.cpp
  31 + ${CMAKE_CURRENT_SOURCE_DIR}/dcxmletlservices.h
  32 + ${CMAKE_CURRENT_SOURCE_DIR}/dcxmletlservices.cpp
  33 + ${CMAKE_CURRENT_SOURCE_DIR}/dcxmlmodelmapping.h
  34 + ${CMAKE_CURRENT_SOURCE_DIR}/dcxmlmodelmapping.cpp
  35 + ${CMAKE_CURRENT_SOURCE_DIR}/dcxmldal.h
  36 + ${CMAKE_CURRENT_SOURCE_DIR}/dcxmldal.cpp
  37 + ${CMAKE_CURRENT_SOURCE_DIR}/objectdata.h
  38 + ${CMAKE_CURRENT_SOURCE_DIR}/objectdata.cpp
  39 + ${CMAKE_CURRENT_SOURCE_DIR}/jobdata.h
  40 + ${CMAKE_CURRENT_SOURCE_DIR}/jobdata.cpp
  41 +)
  42 +
  43 +link_directories(
  44 + ${CMAKE_BINARY_DIR}/lib
  45 +)
  46 +
  47 +include(library)
  48 +add_libraries(
  49 + ${Qt5Core_LIBRARIES}
  50 + logger
  51 + pugixml
  52 +)
  53 +
  54 +include(installation)
  55 +install_component()
src/connection.cpp 0 → 100644
  1 +++ a/src/connection.cpp
  1 +#include "connection.h"
  2 +
  3 +using namespace osdev::components;
  4 +
  5 +Connection::Connection()
  6 + : m_source()
  7 + , m_target()
  8 + , m_input()
  9 + , m_output()
  10 +{
  11 +}
  12 +
  13 +Connection::Connection(const std::string& _source, const std::string& _target, const std::string& _output, const std::string& _input)
  14 + : m_source(_source)
  15 + , m_target(_target)
  16 + , m_input(_input)
  17 + , m_output(_output)
  18 +{
  19 +}
src/connection.h 0 → 100644
  1 +++ a/src/connection.h
  1 +#pragma once
  2 +
  3 +#include <string>
  4 +
  5 +namespace osdev {
  6 +namespace components {
  7 +
  8 +/*
  9 + * _________________________________________
  10 + * / In a hierarchy every employee tends to \
  11 + * | rise to his level of incompetence ... |
  12 + * | in time every post tends to be occupied |
  13 + * | by an employee who is incompetent to |
  14 + * | carry out its duties ... Work is |
  15 + * | accomplished by those employees who |
  16 + * | have not yet reached their level of |
  17 + * | incompetence. |
  18 + * | |
  19 + * | -- Dr. Laurence J. Peter, "The Peter |
  20 + * \ Principle" /
  21 + * -----------------------------------------
  22 + * \
  23 + * \
  24 + * .--.
  25 + * |o_o |
  26 + * |:_/ |
  27 + * // \ \
  28 + * (| | )
  29 + * /'\_ _/`\
  30 + * \___)=(___/
  31 + ***********************************************
  32 + */
  33 +/*!
  34 + * \brief The Connection class is a representation of the connection section in the Modelmapper configurator
  35 + */
  36 +class Connection
  37 +{
  38 +public:
  39 + Connection();
  40 + /*!
  41 + * \brief CTor
  42 + * \param _source - The object we want to connect from
  43 + * \param _target - The object we want to connect to
  44 + * \param _output - The endpoint on the SOURCE
  45 + * \param _input - The endpoint on the TARGET
  46 + */
  47 + Connection(const std::string& _source, const std::string& _target, const std::string& _output, const std::string& _input);
  48 +
  49 + // GETTERS
  50 + /*!
  51 + * \brief source
  52 + * \return The object-ID we want to connect from as std::string
  53 + */
  54 + const std::string& source() const { return m_source; }
  55 +
  56 + /*!
  57 + * \brief target
  58 + * \return The object-ID we want to connect to as std::string
  59 + */
  60 + const std::string& target() const { return m_target; }
  61 +
  62 + /*!
  63 + * \brief output
  64 + * \return The output endpoint on the Source object
  65 + */
  66 + const std::string& output() const { return m_output; }
  67 +
  68 + /*!
  69 + * \brief input
  70 + * \return The input endpoint on the Target object.
  71 + */
  72 + const std::string& input() const { return m_input; }
  73 +
  74 +private:
  75 + std::string m_source; ///< The object we want to connect from
  76 + std::string m_target; ///< The object we want to connect to
  77 + std::string m_input; ///< The endpoint ont the SOURCE
  78 + std::string m_output; ///< The endpoint ont the TARGET
  79 +};
  80 +
  81 +} // namespace components
  82 +} // namespace osdev
  83 +
src/connections.cpp 0 → 100644
  1 +++ a/src/connections.cpp
  1 +#include "connections.h"
  2 +
  3 +using namespace osdev::components;
  4 +
  5 +Connections::Connections()
  6 + : m_connections()
  7 +{
  8 +}
  9 +
  10 +void Connections::addConnection(const QString& _source, const QString& _target, const QString& _output, const QString& _input)
  11 +{
  12 + m_connections.append(QSharedPointer<Connection>(new Connection(_source, _target, _output, _input)));
  13 +}
  14 +
  15 +QSharedPointer<Connection> Connections::getConnection(int index)
  16 +{
  17 + if (index < m_connections.count()) {
  18 + return m_connections.at(index);
  19 + }
  20 + return QSharedPointer<Connection>();
  21 +}
src/connections.h 0 → 100644
  1 +++ a/src/connections.h
  1 +#pragma once
  2 +
  3 +#include "connection.h"
  4 +
  5 +#include <QList>
  6 +#include <QSharedPointer>
  7 +#include <string>
  8 +#include <memory>
  9 +#include <vector>
  10 +
  11 +namespace osdev {
  12 +namespace components {
  13 +
  14 +/*
  15 + * ______________________________________
  16 + * / My opinions always matter :-) \
  17 + * | |
  18 + * | - Dan Malek on the linuxppc-embedded |
  19 + * \ list /
  20 + * --------------------------------------
  21 + * \
  22 + * \
  23 + * .--.
  24 + * |o_o |
  25 + * |:_/ |
  26 + * // \ \
  27 + * (| | )
  28 + * /'\_ _/`\
  29 + * \___)=(___/
  30 + *******************************************
  31 + */
  32 +/*!
  33 + * \brief The connections class contains the source- and target
  34 + * endpoints of function-block connections. In- and outputs
  35 + * are represented by endpoint objects to be able to translate
  36 + * those to standard signals and slots.
  37 + */
  38 +
  39 +class Connections
  40 +{
  41 +public:
  42 + /*!
  43 + * \brief CTor
  44 + */
  45 + Connections();
  46 +
  47 + /*!
  48 + * \brief addConnection - Probably adds a connection...
  49 + * \param _source - The object we want to connect from by UUId
  50 + * \param _target - The object we want to connect to by UUId
  51 + * \param _output - The endpoint on the SOURCE by Name
  52 + * \param _input - The endpoint on the TARGET by Name
  53 + */
  54 + void addConnection(const std::string& _source, const std::string& _target, const std::string& _output, const std::string& _input);
  55 +
  56 + /*!
  57 + * \return The number of connections stored.
  58 + */
  59 + int count() const { return m_connections.size(); }
  60 +
  61 + /*!
  62 + * \brief Gets the Connection for the specified index.
  63 + * \param index The index for the connection.
  64 + * \return Shared pointer to the connection.
  65 + */
  66 + std::shared_ptr<Connection> getConnection(int index);
  67 +
  68 + /*!
  69 + * \brief Get the connections.
  70 + * \return A list of connection shared pointers.
  71 + */
  72 + std::vector<std::shared_ptr<Connection>> getConnections() const { return m_connections; }
  73 +
  74 +private:
  75 + std::vector<std::shared_ptr<Connection>> m_connections;
  76 +};
  77 +
  78 +} // namespace components
  79 +} // namespace osdev
src/connectordata.cpp 0 → 100644
  1 +++ a/src/connectordata.cpp
  1 +#include "connectordata.h"
  2 +
  3 +using namespace osdev::components;
  4 +
  5 +ConnectorData::ConnectorData()
  6 + : m_name()
  7 + , m_type()
  8 + , m_id()
  9 + , m_default()
  10 + , m_excludeFromIdentityCheck(false)
  11 +{
  12 +}
  13 +
  14 +ConnectorData::ConnectorData(const QString& _name, const QString& _type, const QString& _id, const QString& _default, bool _excludeFromIdentityCheck)
  15 + : m_name(_name)
  16 + , m_type(_type)
  17 + , m_id(_id)
  18 + , m_default(_default)
  19 + , m_excludeFromIdentityCheck(_excludeFromIdentityCheck)
  20 +{
  21 +}
  22 +
  23 +void ConnectorData::setName(const QString& _name) { m_name = _name; }
  24 +
  25 +void ConnectorData::setType(const QString& _type) { m_type = _type; }
  26 +
  27 +void ConnectorData::setId(const QString& _id) { m_id = _id; }
  28 +
  29 +void ConnectorData::setDefault(const QString& _default) { m_default = _default; }
  30 +
  31 +void ConnectorData::setExcludeFromIdentityCheck(bool value) { m_excludeFromIdentityCheck = value; }
src/connectordata.h 0 → 100644
  1 +++ a/src/connectordata.h
  1 +#pragma once
  2 +
  3 +#include <string>
  4 +
  5 +namespace osdev {
  6 +namespace components {
  7 +
  8 +/* ______________________________________
  9 + * / It's hard to think of you as the end \
  10 + * | result of millions of years of |
  11 + * \ evolution. /
  12 + * --------------------------------------
  13 + * \
  14 + * \
  15 + * .--.
  16 + * |o_o |
  17 + * |:_/ |
  18 + * // \ \
  19 + * (| | )
  20 + * /'\_ _/`\
  21 + * \___)=(___/
  22 + ********************************************
  23 + */
  24 +/*!
  25 + * \brief The ConnectorData class
  26 + */
  27 +
  28 +class ConnectorData
  29 +{
  30 +public:
  31 + /*!
  32 + * \brief ConnectorData
  33 + */
  34 + ConnectorData();
  35 +
  36 + /*!
  37 + * \brief ConnectorData
  38 + * \param name The name of the ConnectorData.
  39 + * \param type The type of the ConnectorData.
  40 + * \param id The id of the ConnectorData.
  41 + * \param defaultValue The default of the ConnectorData.
  42 + * \param excludeFromIdentityCheck Flag that indicates if this variable should participate in a record identity check. Default false.
  43 + */
  44 + ConnectorData(const std::string& name, const std::string& type, const std::string& id, const string& defaultValue, bool excludeFromIdentityCheck = false);
  45 +
  46 + /*!
  47 + * \brief setName
  48 + * \param name The name of the ConnectorData.
  49 + */
  50 + void setName(const std::string& name);
  51 +
  52 + /*!
  53 + * \brief setType
  54 + * \param type The type of the ConnectorData.
  55 + */
  56 + void setType(const std::string& type);
  57 +
  58 + /*!
  59 + * \brief setId
  60 + * \param id The id of the ConnectorData.
  61 + */
  62 + void setId(const std::string& id);
  63 +
  64 + /*!
  65 + * \brief setDefault
  66 + * \param defaultValue The default of the ConnectorData.
  67 + */
  68 + void setDefault(const std::string& defaultValue);
  69 +
  70 + /*!
  71 + * \brief set excludeFromIdentityCheck flag value
  72 + * \param value The excludeFromIdentityCheck flag value of the ConnectorData.
  73 + */
  74 + void setExcludeFromIdentityCheck(bool value);
  75 +
  76 + /*!
  77 + * \return The name of the ConnectorData.
  78 + */
  79 + const std::string& name() const { return m_name; }
  80 +
  81 + /*!
  82 + * \return The type of the ConnectorData.
  83 + */
  84 + const std::string& type() const { return m_type; }
  85 +
  86 + /*!
  87 + * \return The id of the ConnectorData. A null string means that there is no id.
  88 + */
  89 + const std::string& id() const { return m_id; }
  90 +
  91 + /*!
  92 + * \return default The default of the ConnectorData.
  93 + */
  94 + const std::string& Default() const { return m_default; }
  95 +
  96 + /*!
  97 + * \return the excludeFromIdentityCheck flag
  98 + */
  99 + bool excludeFromIdentityCheck() const { return m_excludeFromIdentityCheck; }
  100 +
  101 +private:
  102 + std::string m_name; ///< The name of the variable this connector represents.
  103 + std::string m_type; ///< The type of the variable this connector represents.
  104 + std::string m_id; ///< The id of the variable this connector represents.
  105 + std::string m_default; ///< The default value of the variable this connector represents.
  106 + bool m_excludeFromIdentityCheck; ///< Flag that indicates if this variable should participate in a record identity check.
  107 +};
  108 +
  109 +} // namespace components
  110 +} // namespace osdev
src/dcxmlbase.cpp 0 → 100644
  1 +++ a/src/dcxmlbase.cpp
  1 +#include "dcxmlbase.h"
  2 +#include "log.h"
  3 +
  4 +/*
  5 + * ________________________________________
  6 + * / Distance doesn't make you any smaller, \
  7 + * | but it does make you part of a larger |
  8 + * \ picture. /
  9 + * ----------------------------------------
  10 + * \
  11 + * \
  12 + * .--.
  13 + * |o_o |
  14 + * |:_/ |
  15 + * // \ \
  16 + * (| | )
  17 + * /'\_ _/`\
  18 + * \___)=(___/
  19 + *
  20 + **********************************************************/
  21 +
  22 +using namespace osdev::components;
  23 +
  24 +void xml_string_writer::write(const void* data, size_t size)
  25 +{
  26 + result += std::string(static_cast<const char*>(data), size);
  27 +}
  28 +
  29 +DcXmlBase::DcXmlBase(const QString& xmlFile)
  30 + : m_xmldoc()
  31 + , m_xPathHash()
  32 +{
  33 + if (!xmlFile.isNull() || !xmlFile.isEmpty()) {
  34 + if (parseFile(xmlFile))
  35 + {
  36 + LogDebug("[DcXmlBase::DcXmlBase]", std::string("File : " + xmlFile + "..............[OK]."));
  37 + }
  38 + else
  39 + {
  40 + LogError("[DcXmlBase::DcXmlBase]", QString("File : %1 ..............[Failed].").arg(xmlFile));
  41 + throw std::runtime_error("[DcXmlBase::DcXmlBase] parseFile failed");
  42 + }
  43 + }
  44 +}
  45 +
  46 +DcXmlBase::~DcXmlBase() = default;
  47 +
  48 +bool DcXmlBase::parseString(const QString& qsXml)
  49 +{
  50 + bool bResult = false;
  51 +
  52 + if (!qsXml.isEmpty()) {
  53 + pugi::xml_parse_status parseStatus = m_xmldoc.load_buffer(qsXml.toStdString().c_str(),
  54 + qsXml.toStdString().size())
  55 + .status;
  56 + bResult = checkError(parseStatus);
  57 + }
  58 +
  59 + return bResult;
  60 +}
  61 +
  62 +bool DcXmlBase::parseFile(const QString& qsXml)
  63 +{
  64 + bool bResult = false;
  65 +
  66 + if (!qsXml.isEmpty()) {
  67 + pugi::xml_parse_status parseStatus = m_xmldoc.load_file(qsXml.toStdString().c_str()).status;
  68 + bResult = checkError(parseStatus);
  69 + }
  70 +
  71 + return bResult;
  72 +}
  73 +
  74 +bool DcXmlBase::checkError(pugi::xml_parse_status _parseStatus)
  75 +{
  76 + bool bResult = false;
  77 + QString sLogMessage = "An unknown error occured.";
  78 +
  79 +/*
  80 +* GCC 5.3.1 insits on all enumeration cases for this switch to be specified.
  81 +* The enumeration cases that throws -Wswitch warning are not available in pugixml for FC21.
  82 +* For backward compatibility with older pugixml version "-Wswitch" warnings are temporarily supressed.
  83 +*/
  84 +#pragma GCC diagnostic push
  85 +#pragma GCC diagnostic ignored "-Wswitch"
  86 + switch (_parseStatus) {
  87 + case pugi::status_ok:
  88 + sLogMessage = "File parsed successfully.";
  89 + bResult = true;
  90 + break;
  91 + case pugi::status_file_not_found:
  92 + sLogMessage = "File not found.";
  93 + break;
  94 + case pugi::status_io_error:
  95 + sLogMessage = "Some I/O Error occured during reading the file / stream. Check the hardware for errors.";
  96 + break;
  97 + case pugi::status_out_of_memory:
  98 + sLogMessage = "Out of Memory while parsing the file.";
  99 + break;
  100 + case pugi::status_internal_error:
  101 + sLogMessage = "Oh dear... That's different. Something went horribly wrong. It is unrecoverable. We're exiting the whole shabang..";
  102 + break;
  103 + case pugi::status_unrecognized_tag:
  104 + sLogMessage = "Parsing stopping due to a tag with either an empty name or a name which starts with an incorrect character (Left a '#' somewhere?)";
  105 + break;
  106 + case pugi::status_bad_pi:
  107 + sLogMessage = "Parsing stopped due to incorrect document declaration/processing instruction. ";
  108 + break;
  109 + case pugi::status_bad_comment:
  110 + sLogMessage = "Parsing stopped due to the invalid construct of a Comment.";
  111 + break;
  112 + case pugi::status_bad_cdata:
  113 + sLogMessage = "Parsing stopped due to the invalid construct of a CDATA section.";
  114 + break;
  115 + case pugi::status_bad_doctype:
  116 + sLogMessage = "Parsing stopped due to the invalid construct of a DocType.";
  117 + break;
  118 + case pugi::status_bad_pcdata:
  119 + sLogMessage = "Parsing stopped due to the invalid construct of a PCDATA section.";
  120 + break;
  121 + case pugi::status_bad_attribute:
  122 + sLogMessage = "Parsing stopped because there was an incorrect attribute, such as an attribute without value or with value that is not quoted (note that <node attr=1> is incorrect in XML).";
  123 + break;
  124 + case pugi::status_bad_start_element:
  125 + sLogMessage = "Parsing stopped because a starting tag either had no closing > symbol or contained some incorrect symbol.";
  126 + break;
  127 + case pugi::status_bad_end_element:
  128 + sLogMessage = "Parsing stopped because ending tag had incorrect syntax (i.e. extra non-whitespace symbols between tag name and >).";
  129 + break;
  130 + case pugi::status_end_element_mismatch:
  131 + sLogMessage = "parsing stopped because the closing tag did not match the opening one (i.e. <node></nedo>) or because some tag was not closed at all.";
  132 + break;
  133 + // DISABLED ON FEDORA 21 and CentOS 7. Not present in pugixml 1.0-8.fc21
  134 + // case pugi::status_append_invalid_root:
  135 + // case pugi::status_no_document_element:
  136 + }
  137 +#pragma GCC diagnostic pop
  138 + LogDebug("[DcXmlBase::checkError]", sLogMessage);
  139 + return bResult;
  140 +}
  141 +
  142 +void DcXmlBase::addXPath(const QString& qsName, const QString& qsXPath)
  143 +{
  144 + if (m_xPathHash.contains(qsName)) {
  145 + LogWarning("[DcXmlBase::addXPath]", "XPath already registered : " + qsName);
  146 + }
  147 + m_xPathHash.insert(qsName, qsXPath);
  148 +
  149 + LogDebug("[DcXmlBase::addXPath]", QString("XPath" + qsXPath + " registered with key : " + qsName));
  150 +}
  151 +
  152 +QString DcXmlBase::getXPath(const QString& qsXPathSelect) const
  153 +{
  154 + QString qsXPath = m_xPathHash.value(qsXPathSelect);
  155 +
  156 + if (qsXPath.isEmpty()) {
  157 + LogWarning("dcxml", "XPath not registered : " + qsXPathSelect);
  158 + }
  159 +
  160 + return qsXPath;
  161 +}
  162 +
  163 +QString DcXmlBase::evaluateXPath(const QString& qsXPathSelect,
  164 + const QList<QVariant>& arguments) const
  165 +{
  166 + QString qsResult = getXPath(qsXPathSelect);
  167 +
  168 + // LogInfo( "DcXmlBase::evaluateXPath", QString( "Found XPathExpression : " + qsResult + " for selection : " + qsXPathSelect ) );
  169 +
  170 + for (auto& value : arguments) {
  171 + qsResult = qsResult.arg(value.toString());
  172 + }
  173 +
  174 + // LogInfo( "DcXmlBase::evaluateXPath", QString( "Resulting XPathExpression : " + qsResult ) );
  175 + return qsResult;
  176 +}
  177 +
  178 +void DcXmlBase::setSimpleData(const QString& qsXPathSelect,
  179 + const QList<QVariant>& arguments,
  180 + const QVariant& data)
  181 +{
  182 + QString qsXPath = evaluateXPath(qsXPathSelect, arguments);
  183 + setNodeData(qsXPath, data);
  184 +}
  185 +
  186 +void DcXmlBase::setSimpleData(const QString& qsXPathSelect, const QVariant& data)
  187 +{
  188 + QString qsXPath = getXPath(qsXPathSelect);
  189 +
  190 + setNodeData(qsXPath, data);
  191 +}
  192 +
  193 +QVariant DcXmlBase::getSimpleData(const QString& qsXPathSelect,
  194 + const QList<QVariant>& arguments) const
  195 +{
  196 + QString qsXPath = evaluateXPath(qsXPathSelect, arguments);
  197 +
  198 + QVariant qvResult = getNodeData(qsXPath);
  199 +
  200 + return qvResult;
  201 +}
  202 +
  203 +// static
  204 +bool DcXmlBase::getBoolean(const QVariant& value)
  205 +{
  206 + bool b_result = false;
  207 +
  208 + QString l_result = value.toString().toUpper();
  209 + if ( // ------------------------
  210 + ("Y" == l_result) ||
  211 + ("YES" == l_result) ||
  212 + ("TRUE" == l_result) ||
  213 + ("ON" == l_result) ||
  214 + ("1" == l_result)
  215 + // ------------------------
  216 + ) {
  217 + b_result = true;
  218 + }
  219 +
  220 + return b_result;
  221 +}
  222 +
  223 +// static
  224 +QString DcXmlBase::getAttributeValue(const pugi::xml_node& xmlNode, const char* attributeName)
  225 +{
  226 + const auto attr = xmlNode.attribute(attributeName);
  227 + if (attr.empty()) {
  228 + return {};
  229 + }
  230 + return attr.value();
  231 +}
  232 +
  233 +pugi::xpath_node DcXmlBase::selectNode(const QString& qsXPath) const
  234 +{
  235 + return m_xmldoc.select_node(qsXPath.toStdString().c_str());
  236 +}
  237 +
  238 +QList<pugi::xpath_node> DcXmlBase::selectNodes(const QString& qsXPath) const
  239 +{
  240 + QList<pugi::xpath_node> lstResult;
  241 +
  242 + pugi::xpath_node_set nodes = m_xmldoc.select_nodes(qsXPath.toStdString().c_str());
  243 + for (auto& node : nodes) {
  244 + lstResult.append(node);
  245 + }
  246 +
  247 + return lstResult;
  248 +}
  249 +
  250 +void DcXmlBase::setNodeData(const QString& qsXPath, const QVariant& qsData)
  251 +{
  252 + pugi::xml_node selectedNode;
  253 + selectedNode = selectNode(qsXPath).node();
  254 +
  255 + if (!selectedNode.empty()) {
  256 + selectedNode.set_value(qsData.toString().toStdString().c_str());
  257 + }
  258 + else {
  259 + LogError("dcxml",
  260 + QString("No node(s) found for XPath expression : '%1'")
  261 + .arg(qsXPath));
  262 + }
  263 +}
  264 +
  265 +QVariant DcXmlBase::getNodeData(const QString& qsXPath) const
  266 +{
  267 + QVariant qvResult;
  268 + pugi::xml_node selectedNode = selectNode(qsXPath).node();
  269 + if (!selectedNode.empty()) {
  270 + qvResult = QString(selectedNode.value());
  271 + }
  272 + return qvResult;
  273 +}
  274 +
  275 +QString DcXmlBase::asString() const
  276 +{
  277 + xml_string_writer writer;
  278 + m_xmldoc.save(writer);
  279 +
  280 + return QString(writer.result.c_str());
  281 +}
src/dcxmlbase.h 0 → 100644
  1 +++ a/src/dcxmlbase.h
  1 +#pragma once
  2 +
  3 +#include <pugixml.hpp>
  4 +#include <string>
  5 +
  6 +#include <QtCore>
  7 +
  8 +namespace osdev {
  9 +namespace components {
  10 +
  11 +/*!
  12 + * \brief xml_string_writer
  13 + * This struct is used to write a pugiXL DOM document to a std::string
  14 + * pugiXML is not able to this on its own, but we use the possibility to dump
  15 + * an XML-document to std::cout
  16 + */
  17 +struct xml_string_writer : pugi::xml_writer
  18 +{
  19 + std::string result = std::string();
  20 + virtual void write(const void* data, size_t size) override;
  21 +};
  22 +
  23 +/*!
  24 + * \brief The dcXmlBase class describes the base class for all xml related classes
  25 + * The basic functionality is implemented here. This class is intended to
  26 + * be inherited and specialized and not to be used directly. ( Nothing bad
  27 + * will happen, just to make life easier )
  28 + */
  29 +/*
  30 + * ________________________________________
  31 + * / I'm serious about thinking through all \
  32 + * | the possibilities before we settle on |
  33 + * | anything. All things have the |
  34 + * | advantages of their disadvantages, and |
  35 + * | vice versa. |
  36 + * | |
  37 + * | -- Larry Wall in |
  38 + * \ <199709032332.QAA21669@wall.org> /
  39 + * ----------------------------------------
  40 + * \
  41 + * \
  42 + * .--.
  43 + * |o_o |
  44 + * |:_/ |
  45 + * // \ \
  46 + * (| | )
  47 + * /'\_ _/`\
  48 + * \___)=(___/
  49 + */
  50 +
  51 +class DcXmlBase
  52 +{
  53 +public:
  54 + /*! Default constructor */
  55 + explicit DcXmlBase(const std::string& xmlFile = std::string());
  56 + virtual ~DcXmlBase();
  57 +
  58 + /*!
  59 + * \brief Parses the XML contents of the string.
  60 + * \param qsXml - String containing the contents of the XML-string
  61 + * \return true if successfull, false if not...
  62 + */
  63 + bool parseString(const std::string& qsXml);
  64 +
  65 + /*!
  66 + * \brief Parses the contents of the given XML-file.
  67 + * \param qsXml - String with the filepath & -name of the XML file.
  68 + * \return true if successfull, false if not...
  69 + */
  70 + bool parseFile(const std::string& qsXml);
  71 +
  72 + /*!
  73 + * \brief Adds an XPath expression to the internal structure.
  74 + * \param qsName - Name of the XPath expression. This should be descriptive to make life easier
  75 + * \param qsXPath - The XPath expression to the specific data we're interested in.
  76 + */
  77 + void addXPath(const std::string& qsName, const std::string& qsXPath);
  78 +
  79 + /*!
  80 + * \brief Retrieves an XPath expression from the internal structure
  81 + * \param qsXPathSelect - The name of the XPath expression.
  82 + * \return The XPath expression as stored in the internal Hash
  83 + */
  84 + std::string getXPath(const std::string& qsXPathSelect) const;
  85 +
  86 + /*!
  87 + * \brief Interprets the XPath expression and adds values to the variables.
  88 + * \param qsXPathSelect - The XPath expression as given by getXPath.
  89 + * \param arguments - The list of variables to be added to the XPath expression.
  90 + * \return The interpreted XPath expression.
  91 + */
  92 + std::string evaluateXPath(const std::string& qsXPathSelect, const std::vector<QList<QVariant>>& arguments) const;
  93 +
  94 + /*!
  95 + * \brief Set a simple node in the xml-doc.
  96 + * \param qsXPathSelect - The XPath expression of the node we want to set.
  97 + * \param arguments - the list of arguments in the node
  98 + * \param data - The nodetext.
  99 + */
  100 + void setSimpleData(const std::string& qsXPathSelect, const QList<QVariant>& arguments, const QVariant& data);
  101 +
  102 + /*!
  103 + * \brief Set a simple node in the xml-doc.
  104 + * \param qsXPathSelect - The XPath expression of the node we want to set.
  105 + * \param data - The nodetext.
  106 + */
  107 + void setSimpleData(const std::string& qsXPathSelect, const QVariant& data);
  108 +
  109 + QVariant getSimpleData(const std::string& qsXPathSelect, const QList<QVariant>& arguments) const;
  110 +
  111 + /*!
  112 + * \brief Retreive a single node based on the XPath expression
  113 + * \param qsXPath - The XPath expression
  114 + * \return - a single xpath-node
  115 + */
  116 + pugi::xpath_node selectNode(const std::string& qsXPath) const;
  117 +
  118 + /*!
  119 + * \brief Retreives a list of nodes based on the given XPath expression
  120 + * \param qsXPath - The XPath expression
  121 + * \return - The list of nodes
  122 + */
  123 + std::vector<pugi::xpath_node> selectNodes(const std::string& qsXPath) const;
  124 +
  125 + /*! Added for convenience. The DOMTree is exported as std::string */
  126 + std::string asString() const;
  127 +
  128 + /*! Helper method for the setSimpleData */
  129 + void setNodeData(const std::string& qsXPath, const QVariant& qsData);
  130 +
  131 + //! Helper method for the getSimpleData. Get data from the node that
  132 + //! is selected with the XPath expression.
  133 + virtual QVariant getNodeData(const std::string& qsXPath) const;
  134 +
  135 + /**
  136 + * @brief Turns a value into a boolean.
  137 + * @param value Value to be interpreted.
  138 + * @return boolean representation of value
  139 + *
  140 + * The following (capitalised) items convert to "true" :
  141 + * - Y
  142 + * - YES
  143 + * - TRUE
  144 + * - ON
  145 + * - 1
  146 + *
  147 + * Everything else converts to false.
  148 + */
  149 + static bool getBoolean(const QVariant& value);
  150 +
  151 + /**
  152 + * @param xmlNode The node to query for an attribute value.
  153 + * @param attributeName The name of the attribute to query.
  154 + * @return an attribute value.
  155 + * @retval value as std::string
  156 + * @retval null std::string when the attribute is not found.
  157 + */
  158 + static std::string getAttributeValue(const pugi::xml_node& xmlNode, const char* attributeName);
  159 +
  160 +private:
  161 + /*!
  162 + * \brief Translates the pugiXML status into Human Readable messages
  163 + * \param parseStatus - The pugi::XML status enum from the parser.
  164 + * \return True if there was no error whatsoever. False if not.. 8-|
  165 + */
  166 + bool checkError(pugi::xml_parse_status parseStatus);
  167 +
  168 + /*!
  169 + * \brief The internal representation of the XML document.
  170 + */
  171 + pugi::xml_document m_xmldoc;
  172 +
  173 + //! Storage for the XPath expressions
  174 + QHash<std::string, std::string> m_xPathHash;
  175 +};
  176 +
  177 +} // namespace osdev
  178 +} // namespace components
src/dcxmlconfig.cpp 0 → 100644
  1 +++ a/src/dcxmlconfig.cpp
  1 +#include "dcxmlconfig.h"
  2 +#include "log.h"
  3 +
  4 +#include <QtDebug>
  5 +
  6 +using namespace osdev::components;
  7 +
  8 +static const char* selectPluginPath = "selectPluginPath";
  9 +static const char* selectConfigPath = "selectConfigPath";
  10 +static const char* selectIniFile = "selectIniFile";
  11 +static const char* selectLogPath = "selectLogPath";
  12 +static const char* selectSslPath = "selectSslPath";
  13 +static const char* selectPlugins = "selectPlugins";
  14 +static const char* selectDbCreds = "selectDbCreds";
  15 +static const char* selectDbUserName = "selectDbUserName";
  16 +static const char* selectDbPassWord = "selectDbPassWord";
  17 +static const char* selectDbName = "selectDbName";
  18 +static const char* selectDbType = "selectDbType";
  19 +static const char* selectDbIdentifier = "selectDbIdentifier";
  20 +static const char* selectDbWdEnable = "selectDbWdEnabled";
  21 +static const char* selectDbWdInterval = "selectDbWdInterval";
  22 +static const char* selectLogFile = "selectLogFile";
  23 +static const char* selectLogLevel = "selectLogLevel";
  24 +static const char* selectModelMapConfig = "selectModelMapConfig";
  25 +static const char* selectLogQueueSizeIntervalSecs = "selectLogQueueSizeIntervalSecs";
  26 +static const char* selectOrmTables = "selectOrmTables";
  27 +static const char* selectRecTrackField = "selectRecTrackField";
  28 +static const char* selectGustavJung = "selectGustavJung";
  29 +// static const char* selectPluginMaxThreads = "selectPluginMaxThreads";
  30 +static const char* selectEventLogging = "selectEventLogging";
  31 +static const char* selectTTL = "selectTTL";
  32 +static const char* selectTransLogPath = "selectTransLogPath";
  33 +static const char* selectJobs = "selectJobs";
  34 +static const char* selectJobSettings = "selectJobSettings";
  35 +static const char* selectJobParameters = "selectJobParameters";
  36 +static const char* selectLogIpAddress = "selectLogIpAddress";
  37 +static const char* selectLogPortNum = "selectLogPortNum";
  38 +static const char* selectIpAddress = "selectIpAddress";
  39 +static const char* selectPortNumber = "selectPortNumber";
  40 +static const char* selectSslCert = "selectSslCert";
  41 +static const char* selectSslKey = "selectSslKey";
  42 +static const char* selectSslCaCert = "selectSslCaCert";
  43 +static const char* selectSslProtocol = "selectSslProtocol";
  44 +
  45 +/* Sensor Settings */
  46 +static const char* selectSensorProtocol = "selectSensorProtocol";
  47 +static const char* selectSensorCache = "selectSensorCache";
  48 +static const char* selectSensorServerHost = "selectSensorServerHost";
  49 +static const char* selectSensorServerPort = "selectSensorServerPort";
  50 +static const char* selectSensorTopics = "selectSensorTopics";
  51 +
  52 +static const char* selectTranslatorConfigPath = "selectTranslatorConfigPath";
  53 +static const char* selectTranslatorConfigFile = "selectTranslatorConfigFile";
  54 +static const char* selectDatarateDirect = "selectDatarateDirect";
  55 +static const char* selectDatarateTimed = "selectDatarateTimed";
  56 +
  57 +static const char* selectDalConfig = "selectDalConfig";
  58 +
  59 +// The only instance of the singleton config parser.
  60 +std::unique_ptr<DCXmlConfig> DCXmlConfig::s_instance( nullptr );
  61 +
  62 +DCXmlConfig::DCXmlConfig()
  63 + : m_qhDbHash()
  64 +{
  65 + constructXPathHash();
  66 + constructEnumHashes();
  67 +}
  68 +
  69 +DCXmlConfig& DCXmlConfig::Instance()
  70 +{
  71 + if( nullptr == s_instance )
  72 + {
  73 + s_instance = std::unique_ptr<DCXmlConfig>( new DCXmlConfig() );
  74 + }
  75 +
  76 + return *s_instance;
  77 +}
  78 +
  79 +bool DCXmlConfig::loadConfiguration( const QString& fileName )
  80 +{
  81 + return DcXmlBase::parseFile( fileName );
  82 +}
  83 +
  84 +QStringList DCXmlConfig::getPluginPaths() const
  85 +{
  86 + QStringList pathList;
  87 + for (const auto& pathNode : DcXmlBase::selectNodes( DcXmlBase::getXPath( selectPluginPath ) ))
  88 + {
  89 + pathList.append(pathNode.node().attribute("value").value());
  90 + }
  91 + return pathList;
  92 +}
  93 +
  94 +QStringList DCXmlConfig::getPlugins() const
  95 +{
  96 + QStringList pluginList;
  97 +
  98 + QList<pugi::xpath_node> selectedNodes = DcXmlBase::selectNodes( DcXmlBase::getXPath( selectPlugins ) );
  99 + for ( auto& nodeItem : selectedNodes )
  100 + {
  101 + pluginList.append( nodeItem.node().attribute( "value" ).value() );
  102 + }
  103 +
  104 + return pluginList;
  105 +}
  106 +
  107 +QStringList DCXmlConfig::getOrmTables() const
  108 +{
  109 + QStringList tableList;
  110 +
  111 + QList<pugi::xpath_node> selectedNodes = DcXmlBase::selectNodes( DcXmlBase::getXPath( selectOrmTables ) );
  112 + for( auto& nodeItem : selectedNodes )
  113 + {
  114 + tableList.append( nodeItem.node().attribute("value").value() );
  115 + }
  116 +
  117 + return tableList;
  118 +}
  119 +
  120 +QList<JobData> DCXmlConfig::getScheduledJobs() const
  121 +{
  122 + QList<JobData> lstResult;
  123 +
  124 + QList<pugi::xpath_node> jobList = DcXmlBase::selectNodes( DcXmlBase::getXPath( selectJobs ) );
  125 + for( auto& jobItem : jobList )
  126 + {
  127 + // Create a new JobData object for each job.
  128 + JobData oJob;
  129 + oJob.setJobName(jobItem.node().attribute("jobname").value());
  130 +
  131 + // Get settings for the current Job.
  132 + QList<QVariant> varList;
  133 + varList.append( oJob.jobName() );
  134 + QList<pugi::xpath_node> jobSettings = DcXmlBase::selectNodes( DcXmlBase::evaluateXPath( selectJobSettings, varList ) );
  135 + for (auto& jobSetting : jobSettings) {
  136 + // Attribute querying not supported in 1.0.x. Only from 1.7 and up. We have to do it the "dumb"-way.
  137 + if (!QString(jobSetting.node().attribute("date").value()).isEmpty()) {
  138 + oJob.setRunDate(QDate::fromString(QString(jobSetting.node().attribute("date").value()), QString("dd-MM-yyyy")));
  139 + }
  140 +
  141 + if( QString( jobSetting.node().attribute( "name" ).value() ) == "date" )
  142 + {
  143 + oJob.setRunDate( QDate::fromString( QString( jobSetting.node().attribute( "value" ).value() ), QString( "dd-MM-yyyy" ) ) );
  144 + }
  145 +
  146 + if( QString( jobSetting.node().attribute( "name" ).value() ) == "time" )
  147 + {
  148 + oJob.setRunTime( QTime::fromString( QString( jobSetting.node().attribute( "value" ).value() ), QString( "hh:mm:ss" ) ) );
  149 + }
  150 +
  151 + if( QString( jobSetting.node().attribute( "name" ).value() ) == "interval" )
  152 + {
  153 + oJob.setRunInterval( QString( jobSetting.node().attribute( "value" ).value() ).toInt() );
  154 + }
  155 + }
  156 +
  157 + // Get all parameters of this job and add them to the jobData object
  158 + QList<pugi::xpath_node> jobParameters = DcXmlBase::selectNodes( DcXmlBase::evaluateXPath( selectJobParameters, varList ) );
  159 + for( auto& jobParameter : jobParameters )
  160 + {
  161 + oJob.addParameter( jobParameter.node().attribute( "name" ).value(), QVariant( QString( jobParameter.node().attribute( "value" ).value() ) ) );
  162 + }
  163 +
  164 + // If arrived here, we have all data from this job. Store the result.
  165 + lstResult.append( oJob );
  166 + }
  167 +
  168 + return lstResult;
  169 +}
  170 +
  171 +bool DCXmlConfig::mqttDirectEnabled() const
  172 +{
  173 + if (QString(DcXmlBase::selectNode(DcXmlBase::getXPath(selectDatarateDirect)).node().attribute("enabled").value()) == "1")
  174 + return true;
  175 +
  176 + return false;
  177 +}
  178 +
  179 +int DCXmlConfig::mqttTimedInterval() const
  180 +{
  181 + return DcXmlBase::selectNode(DcXmlBase::getXPath(selectDatarateTimed)).node().attribute("interval").as_int();
  182 +}
  183 +
  184 +QString DCXmlConfig::getRecordTrackFieldName() const
  185 +{
  186 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectRecTrackField ) ).node().attribute( "value" ).value();
  187 +}
  188 +
  189 +QHash<DCXmlConfig::eDbSettings, QString> DCXmlConfig::getDbCredentials() const
  190 +{
  191 + return this->getServiceSettings<DCXmlConfig::eDbSettings, eDbUnknown>(selectDbCreds, m_qhDbHash);
  192 +}
  193 +
  194 +bool DCXmlConfig::getEnableDbWatchDog() const
  195 +{
  196 + return getBoolean( DcXmlBase::selectNode( DcXmlBase::getXPath( selectDbWdEnable ) ).node().attribute("value").value() );
  197 +}
  198 +
  199 +int DCXmlConfig::getDbCheckInterval() const
  200 +{
  201 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectDbWdInterval ) ).node().attribute("value").as_int();
  202 +}
  203 +
  204 +QString DCXmlConfig::getLogPath() const
  205 +{
  206 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectLogPath ) ).node().attribute("value").value();
  207 +}
  208 +
  209 +QString DCXmlConfig::getLogFile() const
  210 +{
  211 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectLogFile ) ).node().attribute("value").value();
  212 +}
  213 +
  214 +QString DCXmlConfig::getIniFile() const
  215 +{
  216 + auto iniFile = DcXmlBase::selectNode( DcXmlBase::getXPath( selectIniFile ) ).node().attribute("value").value();
  217 + return getConfigPath() + "/" + iniFile;
  218 +}
  219 +
  220 +QString DCXmlConfig::getLogLevel() const
  221 +{
  222 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectLogLevel ) ).node().attribute("value").value();
  223 +}
  224 +
  225 +QString DCXmlConfig::getModelMapConfig() const
  226 +{
  227 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectModelMapConfig ) ).node().attribute("value").value();
  228 +}
  229 +
  230 +QString DCXmlConfig::getDalConfig() const
  231 +{
  232 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectDalConfig ) ).node().attribute("value").value();
  233 +}
  234 +
  235 +QString DCXmlConfig::getConfigPath() const
  236 +{
  237 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectConfigPath ) ).node().attribute("value").value();
  238 +}
  239 +
  240 +QString DCXmlConfig::getLogIpAddress() const
  241 +{
  242 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectLogIpAddress ) ).node().attribute( "value" ).value();
  243 +}
  244 +
  245 +int DCXmlConfig::getLogPortNum() const
  246 +{
  247 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectLogPortNum ) ).node().attribute( "value" ).as_int();
  248 +}
  249 +
  250 +QString DCXmlConfig::getIpAddress() const
  251 +{
  252 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectIpAddress ) ).node().attribute("value").value();
  253 +}
  254 +
  255 +int DCXmlConfig::getPortNumber() const
  256 +{
  257 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectPortNumber ) ).node().attribute("value").as_int();
  258 +}
  259 +
  260 +QString DCXmlConfig::getSslPath() const
  261 +{
  262 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectSslPath ) ).node().attribute("value").value();
  263 +}
  264 +
  265 +QString DCXmlConfig::getSslCert() const
  266 +{
  267 + return ( this->getSslPath() + DcXmlBase::selectNode( DcXmlBase::getXPath( selectSslCert ) ).node().attribute("value").value() );
  268 +}
  269 +
  270 +QString DCXmlConfig::getSslKey() const
  271 +{
  272 + return ( this->getSslPath() + DcXmlBase::selectNode( DcXmlBase::getXPath( selectSslKey ) ).node().attribute("value").value() );
  273 +}
  274 +
  275 +QString DCXmlConfig::getSslCaCert() const
  276 +{
  277 + return ( this->getSslPath() + DcXmlBase::selectNode( DcXmlBase::getXPath( selectSslCaCert ) ).node().attribute("value").value() );
  278 +}
  279 +
  280 +QString DCXmlConfig::getSslProtocol() const
  281 +{
  282 + return ( this->getSslPath() + DcXmlBase::selectNode( DcXmlBase::getXPath( selectSslProtocol ) ).node().attribute("value").value() );
  283 +}
  284 +
  285 +QString DCXmlConfig::transactionPath() const
  286 +{
  287 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectTransLogPath ) ).node().attribute("value").value();
  288 +}
  289 +
  290 +int DCXmlConfig::timeToLive() const
  291 +{
  292 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectTTL ) ).node().attribute("value").as_int();
  293 +}
  294 +// ===========================================================================================================================================
  295 +// Sensor Settings Co2Mos
  296 +// -------------------------------------------------------------------------------------------------------------------------------------------
  297 +QString DCXmlConfig::getSensorProtocol()
  298 +{
  299 + return DcXmlBase::selectNode(DcXmlBase::getXPath( selectSensorProtocol ) ).node().attribute( "value" ).value();
  300 +}
  301 +
  302 +bool DCXmlConfig::getSensorCache()
  303 +{
  304 + return getBoolean( DcXmlBase::selectNode( DcXmlBase::getXPath( selectSensorCache ) ).node().attribute("value").value() );
  305 +}
  306 +
  307 +QString DCXmlConfig::getSensorServerHost()
  308 +{
  309 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectSensorServerHost ) ).node().attribute( "value" ).value();
  310 +}
  311 +
  312 +int DCXmlConfig::getSensorServerPort()
  313 +{
  314 + return DcXmlBase::selectNode( DcXmlBase::getXPath( selectSensorServerPort ) ).node().attribute( "value" ).as_int();
  315 +}
  316 +
  317 +QStringList DCXmlConfig::getSensorTopicList()
  318 +{
  319 + QStringList l_result;
  320 +
  321 + QList<pugi::xpath_node> node_list = DcXmlBase::selectNodes( DcXmlBase::getXPath( selectSensorTopics ) );
  322 + for( const auto& topic_node : node_list )
  323 + {
  324 + l_result.append( topic_node.node().attribute( "value" ).value() );
  325 + }
  326 +
  327 + return l_result;
  328 +}
  329 +
  330 +// ===========================================================================================================================================
  331 +void DCXmlConfig::constructXPathHash()
  332 +{
  333 + // Generic Paths
  334 + DcXmlBase::addXPath( selectConfigPath , "//configuration/context[@name='global']/context[@name='paths']/setting[@name='configpath']" );
  335 + DcXmlBase::addXPath( selectIniFile , "//configuration/context[@name='global']/context[@name='paths']/setting[@name='inifile']" );
  336 + DcXmlBase::addXPath( selectLogPath , "//configuration/context[@name='global']/context[@name='paths']/setting[@name='logpath']" );
  337 + DcXmlBase::addXPath( selectSslPath , "//configuration/context[@name='global']/context[@name='paths']/setting[@name='sslpath']" );
  338 +
  339 + // Plugin SettingsePmsServiceName
  340 + DcXmlBase::addXPath( selectPluginPath , "//configuration/context[@name='global']/context[@name='paths']/setting[@name='pluginpath']" );
  341 + DcXmlBase::addXPath( selectPlugins , "//configuration/context[@name='global']/context[@name='plugins']/setting" );
  342 +
  343 + // Database Settings
  344 + DcXmlBase::addXPath( selectDbCreds , "//configuration/context[@name='global']/context[@name='database']/setting" );
  345 + DcXmlBase::addXPath( selectDbUserName , "//configuration/context[@name='global']/context[@name='database']/setting[@name='username']" );
  346 + DcXmlBase::addXPath( selectDbPassWord , "//configuration/context[@name='global']/context[@name='database']/setting[@name='password']" );
  347 + DcXmlBase::addXPath( selectDbName , "//configuration/context[@name='global']/context[@name='database']/setting[@name='dbName']" );
  348 + DcXmlBase::addXPath( selectDbType , "//configuration/context[@name='global']/context[@name='database']/setting[@name='dbtype']" );
  349 + DcXmlBase::addXPath( selectDbIdentifier , "//configuration/context[@name='global']/context[@name='database']/setting[@name='identifier']" );
  350 + DcXmlBase::addXPath( selectDbWdEnable , "//configuration/context[@name='global']/context[@name='database']/watchdog/setting[@name='enabled']" );
  351 + DcXmlBase::addXPath( selectDbWdInterval , "//configuration/context[@name='global']/context[@name='database']/watchdog/setting[@name='interval']" );
  352 +
  353 + // ORM Settings
  354 + DcXmlBase::addXPath( selectOrmTables , "//configuration/context[@name='orm']/context[@name='tables']/setting" );
  355 + DcXmlBase::addXPath( selectRecTrackField, "//configuration/context[@name='orm']/context[@name='record_tracking']/setting" );
  356 +
  357 + // Transaction Queue Settings
  358 + DcXmlBase::addXPath( selectTTL , "//configuration/context[@name='transqueue']/setting[@name='ttl']" );
  359 + DcXmlBase::addXPath( selectTransLogPath , "//configuration/context[@name='transqueue']/setting[@name='transaction_logs']" );
  360 +
  361 + // System SettingsePmsServiceName
  362 + DcXmlBase::addXPath( selectGustavJung , "//configuration/context[@name='global']/context[@name='system']/setting[@name='synchronicity']" );
  363 +// DcXmlBase::addXPath( selectPluginMaxThreads, "//configuration/context[@name='global']/context[@name='system']/setting[@name='plugin_max_threads']" );
  364 + DcXmlBase::addXPath( selectEventLogging , "//configuration/context[@name='global']/context[@name='logging']/setting[@name='event_logging']" );
  365 + DcXmlBase::addXPath( selectLogFile , "//configuration/context[@name='global']/context[@name='logging']/setting[@name='log_file']" );
  366 + DcXmlBase::addXPath( selectLogLevel , "//configuration/context[@name='global']/context[@name='logging']/setting[@name='log_level']" );
  367 + DcXmlBase::addXPath(selectLogQueueSizeIntervalSecs, "//configuration/context[@name='global']/context[@name='logging']/setting[@name='queue_size_interval_secs']");
  368 +
  369 + // Modelmapper Settings
  370 + DcXmlBase::addXPath( selectModelMapConfig, "//configuration/context[@name='modelmapper']/context[@name='modelmapping']/setting[@name='modelmapconfig']" );
  371 +
  372 + // Jobscheduler settings
  373 + DcXmlBase::addXPath( selectJobs , "//configuration/context[@name='jobscheduler']/jobs/job" );
  374 + DcXmlBase::addXPath( selectJobSettings , "//configuration/context[@name='jobscheduler']/jobs/job[@name='%1']/settings/setting" );
  375 + DcXmlBase::addXPath( selectJobParameters, "//configuration/context[@name='jobscheduler']/jobs/job[@name='%1']/parameters/parameter" );
  376 +
  377 + // EqMqtt Config settings
  378 + DcXmlBase::addXPath(selectTranslatorConfigPath, "//configuration/context[@name='eqmqtt']/context[@name='translation']/setting[@name='translate_path']");
  379 + DcXmlBase::addXPath(selectTranslatorConfigFile, "//configuration/context[@name='eqmqtt']/context[@name='translation']/setting[@name='translate_file']");
  380 + DcXmlBase::addXPath(selectDatarateDirect, "//configuration/context[@name='eqmqtt']/context[@name='datarate']/setting[@name='direct']");
  381 + DcXmlBase::addXPath(selectDatarateTimed, "//configuration/context[@name='eqmqtt']/context[@name='datarate']/setting[@name='timed']");
  382 +
  383 + // Remote Log Viewer / server
  384 + DcXmlBase::addXPath( selectLogIpAddress , "//configuration/context[@name='logprocessor']/setting[@name='ip-address']" );
  385 + DcXmlBase::addXPath( selectLogPortNum , "//configuration/context[@name='logprocessor']/setting[@name='port']" );
  386 +
  387 + // MedCow settings
  388 + DcXmlBase::addXPath( selectIpAddress , "//configuration/context[@name='network']/setting[@name='ip_address']" );
  389 + DcXmlBase::addXPath( selectPortNumber , "//configuration/context[@name='network']/setting[@name='port_no']" );
  390 + DcXmlBase::addXPath( selectSslCert , "//configuration/context[@name='network']/setting[@name='ssl_cert']" );
  391 + DcXmlBase::addXPath( selectSslKey , "//configuration/context[@name='network']/setting[@name='ssl_key']" );
  392 + DcXmlBase::addXPath( selectSslCaCert , "//configuration/context[@name='network']/setting[@name='ssl_ca']" );
  393 + DcXmlBase::addXPath( selectSslProtocol , "//configuration/context[@name='network']/setting[@name='ssl_protocol']" );
  394 +
  395 + // Dal settings
  396 + DcXmlBase::addXPath( selectDalConfig , "//configuration/context[@name='dal']/context[@name='data_access']/setting[@name='dalconfig']" );
  397 +
  398 + // Sensor Settings
  399 + DcXmlBase::addXPath( selectSensorProtocol , "//configuration/context[@name='sensors']/setting[@name='protocol']" );
  400 + DcXmlBase::addXPath( selectSensorCache , "//configuration/context[@name='sensors']/setting[@name='cached']" );
  401 + DcXmlBase::addXPath( selectSensorServerHost , "//configuration/context[@name='sensors']/setting[@name='serverhost']" );
  402 + DcXmlBase::addXPath( selectSensorServerPort , "//configuration/context[@name='sensors']/setting[@name='serverport']" );
  403 + DcXmlBase::addXPath( selectSensorTopics , "//configuration/context[@name='sensors']/topics/topic" );
  404 +
  405 + // Dal settings
  406 + DcXmlBase::addXPath( selectDalConfig , "//configuration/context[@name='dal']/context[@name='data_access']/setting[@name='dalconfig']" );
  407 +}
  408 +
  409 +void DCXmlConfig::constructEnumHashes()
  410 +{
  411 + // Build the Db Translator Hash
  412 + m_qhDbHash.insert( "username", eDbSettings::eDbUsername );
  413 + m_qhDbHash.insert( "password", eDbSettings::eDbPassword );
  414 + m_qhDbHash.insert( "dbname", eDbSettings::eDbName );
  415 + m_qhDbHash.insert( "hostname", eDbSettings::eDbHostName );
  416 + m_qhDbHash.insert( "identifier", eDbSettings::eDbIdentifier );
  417 + m_qhDbHash.insert( "dbtype", eDbSettings::eDbType );
  418 +}
  419 +
  420 +bool DCXmlConfig::getEventLogging() const
  421 +{
  422 + bool b_result = false;
  423 +
  424 + b_result = getBoolean( DcXmlBase::selectNode( DcXmlBase::getXPath( selectEventLogging ) ).node().attribute("value").value() );
  425 +
  426 + return b_result;
  427 +}
  428 +
  429 +bool DCXmlConfig::getSynchronicity() const
  430 +{
  431 + bool b_result = false;
  432 +
  433 + b_result = getBoolean( DcXmlBase::selectNode( DcXmlBase::getXPath( selectGustavJung ) ).node().attribute("value").value() );
  434 +
  435 + return b_result;
  436 +}
  437 +
  438 +int DCXmlConfig::getLogQueueSizeIntervalSecs() const
  439 +{
  440 + return DcXmlBase::selectNode(DcXmlBase::getXPath(selectLogQueueSizeIntervalSecs)).node().attribute("value").as_int();
  441 +}
  442 +
  443 +bool DCXmlConfig::getBoolean( const QVariant& value ) const
  444 +{
  445 + bool b_result = false;
  446 +
  447 + QString l_result = value.toString().toUpper();
  448 + if ( // ------------------------
  449 + ( "Y" == l_result ) ||
  450 + ( "YES" == l_result ) ||
  451 + ( "TRUE" == l_result ) ||
  452 + ( "ON" == l_result ) ||
  453 + ( "1" == l_result )
  454 + // ------------------------
  455 + )
  456 + {
  457 + b_result = true;
  458 + }
  459 +
  460 + return b_result;
  461 +}
src/dcxmlconfig.h 0 → 100644
  1 +++ a/src/dcxmlconfig.h
  1 +#ifndef OSDEV_COMPONENTS_DCXMLCONFIG_H
  2 +#define OSDEV_COMPONENTS_DCXMLCONFIG_H
  3 +
  4 +#include "dcxmlbase.h"
  5 +#include "jobdata.h"
  6 +
  7 +#include <QObject>
  8 +#include <QStringList>
  9 +#include <memory>
  10 +
  11 +namespace osdev {
  12 +namespace components {
  13 +
  14 +/*! \brief This component locates any configuration information needed
  15 + * to initialise the application and its components.
  16 + * Parses this information and make it available to other
  17 + * components that need it.
  18 + *
  19 + * This component is implemented as a singleton. XML has the "habit"
  20 + * of expand 15 times the filesize so with this in mind, it is more
  21 + * future proof to load this only once into memory.
  22 + *
  23 + *//*
  24 + * ________________________________________
  25 + * / TCP/IP Slang Glossary, #1: \
  26 + * | |
  27 + * | Gong, n: Medieval term for privy, or |
  28 + * | what pased for them in that era. Today |
  29 + * | used whimsically to describe the |
  30 + * | aftermath of a bogon attack. Think of |
  31 + * | our community as the Galapagos of the |
  32 + * | English language. |
  33 + * | |
  34 + * | "Vogons may read you bad poetry, but |
  35 + * | bogons make you study obsolete RFCs." |
  36 + * | |
  37 + * \ -- Dave Mills /
  38 + * ----------------------------------------
  39 + * \
  40 + * \
  41 + * .--.
  42 + * |o_o |
  43 + * |:_/ |
  44 + * // \ \
  45 + * (| | )
  46 + * /'\_ _/`\
  47 + * \___)=(___/
  48 + *
  49 + */
  50 +
  51 +class DCXmlConfig : public DcXmlBase
  52 +{
  53 +public:
  54 + enum eDbSettings
  55 + {
  56 + eDbUnknown = 0, ///< The default value if translation is not possible
  57 + eDbUsername, ///< The username used to connect to the DATA scheme
  58 + eDbPassword, ///< The corresponding password
  59 + eDbName, ///< The name of the database instance
  60 + eDbHostName, ///< The hostname the database resides on
  61 + eDbIdentifier, ///< Identifier. Used internally to distinguish between multiple connections / Databases
  62 + eDbType ///< The type of database we're connecting to. This can be all databases known by the Qt framework. (QPSQL, QMYSQL, QOCI etc..)
  63 + };
  64 +
  65 + /// @return The one and only instance of the config object
  66 + static DCXmlConfig& Instance();
  67 +
  68 + // ======================================================================
  69 + /// The constructor.
  70 + DCXmlConfig();
  71 +
  72 + /// Deleted copy-constructor
  73 + DCXmlConfig(const DCXmlConfig&) = delete;
  74 +
  75 + /// Deleted assignment operator
  76 + DCXmlConfig& operator=(const DCXmlConfig&) = delete;
  77 +
  78 + /// Deleted move-constructor
  79 + DCXmlConfig(DCXmlConfig&&) = delete;
  80 +
  81 + /// Deleted move-operator
  82 + DCXmlConfig& operator=(DCXmlConfig&&) = delete;
  83 + // ======================================================================
  84 + /// @brief Loads the configuration from the given filename.
  85 + /// @param fileName - The configuration file in XML format.
  86 + virtual bool loadConfiguration( const QString& fileName );
  87 +
  88 + /// @return Plugin paths that are defined in the Configuration file
  89 + QStringList getPluginPaths() const;
  90 +
  91 + /// @return Plugins to load
  92 + QStringList getPlugins() const;
  93 +
  94 + /// @return The tables, the ORM layer is a representation of.
  95 + QStringList getOrmTables() const;
  96 +
  97 + /// @return The name of the field in each table, which represents the last timestamp this record was mutated.
  98 + QString getRecordTrackFieldName() const;
  99 +
  100 + /// @return A QHash with all database credentials.
  101 + QHash<DCXmlConfig::eDbSettings, QString> getDbCredentials() const;
  102 +
  103 + /// @return Enable or not the database watchdog.
  104 + bool getEnableDbWatchDog() const;
  105 +
  106 + /// @return Get the number of seconds each connection check should run.
  107 + int getDbCheckInterval() const;
  108 +
  109 + /// @return Returns the path to the logging
  110 + QString getLogPath() const;
  111 +
  112 + /// @return Returns the logfilename
  113 + QString getLogFile() const;
  114 +
  115 + /// @return Returns the inifilename
  116 + QString getIniFile() const;
  117 +
  118 + /// @return Returns the LogLevel
  119 + QString getLogLevel() const;
  120 +
  121 + /// @return Returns the interval in seconds we want to use for logging the queue size(s).
  122 + int getLogQueueSizeIntervalSecs() const;
  123 +
  124 + /// @return Returns the ModelMapConfig filename
  125 + QString getModelMapConfig() const;
  126 +
  127 + /// @return Returns the DalConfig filename
  128 + QString getDalConfig() const;
  129 +
  130 + /// @return Returns the path to the configuration directory.
  131 + QString getConfigPath() const;
  132 +
  133 + /// @return Returns the switch for logging inside the EventManager.
  134 + /// true means log everything
  135 + /// false means log nothing
  136 + bool getEventLogging() const;
  137 +
  138 + /*! @return Returns the switch for synchronous processing.
  139 + * true means synchronous processing
  140 + * false means a-synchronous processing
  141 + */
  142 + bool getSynchronicity() const;
  143 +
  144 + /*!
  145 + * \brief getLogIpAddress
  146 + * \return
  147 + */
  148 + QString getLogIpAddress() const;
  149 +
  150 + /*!
  151 + * \brief getLogPortNum
  152 + * \return
  153 + */
  154 + int getLogPortNum() const;
  155 +
  156 + /// @return Returns the ip addresses on which connections are allowed
  157 + QString getIpAddress() const;
  158 +
  159 + /// @return Returns the port number on which connections are allowed
  160 + int getPortNumber() const;
  161 +
  162 + /// @return Returns the ssl path where the certificates are found
  163 + QString getSslPath() const;
  164 + /// @return Returns the private ssl certificate name
  165 + QString getSslCert() const;
  166 + /// @return Returns the private ssl key name
  167 + QString getSslKey() const;
  168 + /// @return Returns the ssl CA certificate name
  169 + QString getSslCaCert() const;
  170 + /// @return Returns the protocol to use
  171 + QString getSslProtocol() const;
  172 +
  173 + /// Sensor Settings, mainly the brokersettings..
  174 + QString getSensorProtocol();
  175 + bool getSensorCache();
  176 + QString getSensorServerHost();
  177 + int getSensorServerPort();
  178 + QStringList getSensorTopicList();
  179 +
  180 + /*!
  181 + * \brief getMaxPluginThreads
  182 + * \return
  183 + */
  184 +// int getMaxPluginThreads() const;
  185 +
  186 + /*!
  187 + * @return Returns the (relative path where the reject transactions will be logged.
  188 + * If empty, the default log location will be used.
  189 + */
  190 + QString transactionPath() const;
  191 +
  192 + /*!
  193 + * @return Returns the TimeToLive counter. This will determine how many times a
  194 + * transaction can pass the queue. On each pass, its TTL-counter will be
  195 + * decreased until it reaches "zero". In that case it will be dumped to disk.
  196 + */
  197 + int timeToLive() const;
  198 +
  199 + /*!
  200 + * \brief Retrieve all jobs configured in the main configuration file.
  201 + * \return A list with all scheduled jobs, empty if none were mentioned.
  202 + */
  203 + QList<JobData> getScheduledJobs() const;
  204 +
  205 + /*!
  206 + * \brief Check if the EqMqtt client is sending its data direct, or through a trimed interval.
  207 + * \return True if direct is enabled. False if direct is disabled, switching timed on. (Default)
  208 + */
  209 + bool mqttDirectEnabled() const;
  210 +
  211 + /*!
  212 + * \brief Retrieve the time interval ( in seconds ) for the EqMqtt client to send its data in.
  213 + * \return Number of seconds (Integer)
  214 + */
  215 + int mqttTimedInterval() const;
  216 +
  217 +private:
  218 + /// @brief Builds the XPath hash to access the nodes directly.
  219 + void constructXPathHash();
  220 +
  221 + /// @brief Builds the enum hashes, used to translate strings to enums.
  222 + void constructEnumHashes();
  223 +
  224 + /// @return True on success, false on failure
  225 + bool openConfig();
  226 +
  227 + /// @return True on success, false on failure
  228 + bool closeConfig();
  229 +
  230 + /// @return True if a configuration could be found, false otherwise
  231 + bool configExists();
  232 +
  233 + /**
  234 + * @brief Turns a value into a boolean.
  235 + * @param value Value to be interpreted.
  236 + * @return boolean representation of value
  237 + *
  238 + * The following (capitalised) items convert to "true" :
  239 + * - Y
  240 + * - YES
  241 + * - TRUE
  242 + * - ON
  243 + * - 1
  244 + *
  245 + * Everything else converts to false.
  246 + */
  247 + bool getBoolean( const QVariant& value ) const;
  248 +
  249 + /**
  250 + * @brief Get the service settings from the xml configuration.
  251 + * @tparam TEnumSettings The enumeration of the various service settings.
  252 + * @tparam unknownValue The value to return when the translation from config item to enumeration value cannot be made.
  253 + * @param selectSettings Key that describes which service settings to get.
  254 + * @param translatorHash The hash that holds the mapping between config item names and their respective enumeration value.
  255 + * @return Hash with the requested configuration information.
  256 + */
  257 + template <typename TEnumSettings, TEnumSettings unknownValue>
  258 + QHash<TEnumSettings, QString> getServiceSettings(const char* selectSettings, const QHash<QString, TEnumSettings>& translatorHash) const
  259 + {
  260 + QHash<TEnumSettings, QString> l_settings;
  261 +
  262 + QList<pugi::xpath_node> selectedNodes = DcXmlBase::selectNodes( DcXmlBase::getXPath( selectSettings ) );
  263 + for( auto& selectedNode : selectedNodes )
  264 + {
  265 + const QString key = QString(selectedNode.node().attribute( "name" ).value()).toLower();
  266 + l_settings.insert( translatorHash.value(key, unknownValue)
  267 + , selectedNode.node().attribute( "value" ).value() );
  268 + }
  269 + return l_settings;
  270 + }
  271 +
  272 + static std::unique_ptr<DCXmlConfig> s_instance; ///< Instantiated Config object.
  273 +
  274 +
  275 + QHash<QString, DCXmlConfig::eDbSettings> m_qhDbHash; ///< The Db Settings Translator Hash.
  276 +};
  277 +
  278 +} /* End namespace components */
  279 +} /* End namespace osdev */
  280 +
  281 +
  282 +#endif /* OSDEV_COMPONENTS_DCXMLCONFIG_H */
src/dcxmldal.cpp 0 → 100644
  1 +++ a/src/dcxmldal.cpp
  1 +#include "dcxmldal.h"
  2 +#include "dcxmlconfig.h"
  3 +
  4 +using namespace osdev::components;
  5 +
  6 +static const char* selectFunctions = "selectFunctions"; // return all functions
  7 +static const char* selectFunctionByName = "selectFunction"; // return function by command name
  8 +
  9 +// The only instance of the singleton Dal Config Parser.
  10 +std::unique_ptr<DcXmlDal> DcXmlDal::s_instance( nullptr );
  11 +
  12 +DcXmlDal& DcXmlDal::Instance()
  13 +{
  14 + if( nullptr == s_instance )
  15 + {
  16 + s_instance = std::unique_ptr<DcXmlDal>( new DcXmlDal( DCXmlConfig::Instance().getDalConfig() ) );
  17 + }
  18 +
  19 + return *s_instance;
  20 +}
  21 +
  22 +DcXmlDal::DcXmlDal( const QString &fileName )
  23 +{
  24 + if( !fileName.isEmpty() )
  25 + {
  26 + if( !loadConfiguration( fileName ) )
  27 + {
  28 + LogWarning( "[DcXmlDal::DcXmlDal]", QString( "There was an error reading file : %1" ).arg( fileName ) );
  29 + }
  30 + }
  31 + else
  32 + {
  33 + LogWarning( "[DcXmlDal::DcXmlDal]", QString( "No filename given. No configuration read." ) );
  34 + }
  35 +
  36 + constructXPathHash();
  37 +}
  38 +
  39 +DcXmlDal::~DcXmlDal()
  40 +{
  41 +}
  42 +
  43 +bool DcXmlDal::loadConfiguration( const QString &fileName )
  44 +{
  45 + return loadConfiguration( DCXmlConfig::Instance().getConfigPath(), fileName );
  46 +}
  47 +
  48 +bool DcXmlDal::loadConfiguration( const QString &configDir, const QString &fileName )
  49 +{
  50 + return DcXmlBase::parseFile( configDir + fileName );
  51 +}
  52 +
  53 +void DcXmlDal::constructXPathHash()
  54 +{
  55 + DcXmlBase::addXPath( selectFunctions , "//data_access/functions/function" );
  56 + DcXmlBase::addXPath( selectFunctionByName , "//data_access/functions/function[@name='%1']" );
  57 +}
  58 +
  59 +QStringList DcXmlDal::getQueries() const
  60 +{
  61 + QStringList lstResult;
  62 +
  63 + QList<pugi::xpath_node> functionList = DcXmlBase::selectNodes( DcXmlBase::getXPath( selectFunctions ) );
  64 + for( const auto& nodeItem : functionList )
  65 + {
  66 + lstResult.append( nodeItem.node().attribute( "name" ).value() );
  67 + }
  68 +
  69 + return lstResult;
  70 +}
  71 +
  72 +QString DcXmlDal::getQueryByName( const QString &_queryName ) const
  73 +{
  74 + QList<QVariant> varList;
  75 + varList.append( _queryName );
  76 +
  77 + return QString( DcXmlBase::selectNode( evaluateXPath( selectFunctionByName, varList ) ).node().attribute( "value" ).value() );
  78 +}
src/dcxmldal.h 0 → 100644
  1 +++ a/src/dcxmldal.h
  1 +#ifndef OSDEV_COMPONENTS_DCXMLDAL_H
  2 +#define OSDEV_COMPONENTS_DCXMLDAL_H
  3 +
  4 +#include <QHash>
  5 +#include <QString>
  6 +
  7 +#include "dcxmlbase.h"
  8 +#include "log.h"
  9 +#include "memory"
  10 +
  11 +namespace osdev {
  12 +namespace components {
  13 +
  14 +/*!
  15 + * \brief The DcXmlDal class
  16 + * Reads data from the configuration and makes it easily accessible
  17 + */
  18 +class DcXmlDal : public DcXmlBase
  19 +{
  20 +public:
  21 + /// @return the one and only instance of the config object.
  22 + static DcXmlDal& Instance();
  23 +
  24 + /// The constructor
  25 + DcXmlDal( const QString &fileName = QString() );
  26 +
  27 + /// The destructor
  28 + virtual ~DcXmlDal();
  29 +
  30 + /// Deleted copy-constructor
  31 + DcXmlDal( const DcXmlDal& ) = delete;
  32 + /// Deleted assignment constructor
  33 + DcXmlDal& operator=( const DcXmlDal& ) = delete;
  34 + /// Deleted move-constructor
  35 + DcXmlDal( DcXmlDal&& ) = delete;
  36 + /// Deleted move-operator
  37 + DcXmlDal& operator=( DcXmlDal&& ) = delete;
  38 + // ==========================================================
  39 +
  40 + /*!
  41 + * \brief loadConfiguration - This function loads the xml file into memory
  42 + * \param configDir - configuration directory
  43 + * \param fileName - configuration file name
  44 + * \return true if succeeded
  45 + */
  46 + bool loadConfiguration( const QString &configDir, const QString &fileName );
  47 + /*!
  48 + * \brief loadConfiguration - This function loads the xml file into memory
  49 + * \param fileName - configuration file name
  50 + * \return true if succeeded
  51 + */
  52 + bool loadConfiguration( const QString &fileName );
  53 +
  54 + /*!
  55 + * \brief constructXPathHash - This function initializes all XML XPaths
  56 + */
  57 + void constructXPathHash();
  58 +
  59 + /*!
  60 + * \brief getQueries - This function fetches all function names from the config
  61 + * \return a list of function names received from the config
  62 + */
  63 + QStringList getQueries() const;
  64 + /*!
  65 + * \brief getQueryByName - This function returns the value of the requested function name
  66 + * \param _queryName - function name to look up
  67 + * \return the value matching to the function name
  68 + */
  69 + QString getQueryByName( const QString &_queryName ) const;
  70 +
  71 +private:
  72 + static std::unique_ptr<DcXmlDal> s_instance; ///< Singleton pointer
  73 +};
  74 +
  75 +} /* end namespace components */
  76 +} /* end namespace osdev */
  77 +
  78 +#endif // OSDEV_COMPONENTS_DCXMLDAL_H
src/dcxmletlnetwork.cpp 0 → 100644
  1 +++ a/src/dcxmletlnetwork.cpp
  1 +#include "dcxmletlnetwork.h"
  2 +#include "log.h"
  3 +
  4 +using namespace osdev::components;
  5 +
  6 +// XPath names
  7 +// Network related
  8 +static const char* selectNetworks = "selectNetworks";
  9 +static const char* selectNetwork = "selectNetwork";
  10 +
  11 +// Functional Objects
  12 +static const char* selectObjects = "selectObjects";
  13 +static const char* selectObject = "selectObject";
  14 +// Inputs
  15 +static const char* selectInputs = "selectInputs";
  16 +static const char* selectInput = "selectInput";
  17 +static const char* selectInputVarNames = "selectInputVarNames";
  18 +// Outputs
  19 +static const char* selectOutputs = "selectOutputs";
  20 +static const char* selectOutput = "selectOutput";
  21 +static const char* selectOutputVarNames = "selectOutputVarNames";
  22 +
  23 +// Connections
  24 +static const char* selectConnections = "selectConnections";
  25 +
  26 +// QThread priorities
  27 +static const char* prio_idle = "prio_idle";
  28 +static const char* prio_lowest = "prio_lowest";
  29 +static const char* prio_low = "prio_low";
  30 +static const char* prio_normal = "prio_normal";
  31 +static const char* prio_high = "prio_high";
  32 +static const char* prio_highest = "prio_highest";
  33 +static const char* prio_time_critical = "prio_time_critical";
  34 +static const char* prio_inherit = "prio_inherit";
  35 +
  36 +namespace {
  37 +
  38 +/**
  39 + * @brief Generates DataObject input data from an xml inputs node.
  40 + * The inputs node contains one or more input nodes which describe a database table column
  41 + */
  42 +class GenerateInputData
  43 +{
  44 +public:
  45 + // Non constructable
  46 + GenerateInputData() = delete;
  47 +
  48 + /**
  49 + * @brief Generate input data from an inputs node.
  50 + * @param inputsNode xml inputs node. The method does nothing when an xml node with a different name is supplied.
  51 + * @param[out] data The input data is added to this instance.
  52 + */
  53 + static void generate(const pugi::xml_node& inputsNode, ObjectData& data);
  54 +
  55 +private:
  56 + /**
  57 + * @brief Internal method that parses an xml input node and calls this method on its child nodes when appropriate.
  58 + * @param inputNode xml input node. The method does nothing when an xml node with a different name is supplied.
  59 + * @param containerPath The context for which the input is generated. This argument is supplied by copy so that
  60 + * recursive calls can expand the context.
  61 + * @param[out] data The input data is added to this instance.
  62 + * @param level The recursion level (for debugging purposes)
  63 + */
  64 + static void handleInputNode(const pugi::xml_node& inputNode, QStringList containerPath, ObjectData& data, int level);
  65 +};
  66 +
  67 +// static
  68 +void GenerateInputData::generate(const pugi::xml_node& inputsNode, ObjectData& data)
  69 +{
  70 + if (std::string(inputsNode.name()) != std::string("inputs")) {
  71 + return;
  72 + }
  73 +
  74 + for (auto inputNode = inputsNode.child("input"); inputNode; inputNode = inputNode.next_sibling("input")) {
  75 + handleInputNode(inputNode, QStringList{}, data, 1);
  76 + }
  77 +}
  78 +
  79 +// static
  80 +void GenerateInputData::handleInputNode(const pugi::xml_node& inputNode, QStringList containerPath, ObjectData& data, int level)
  81 +{
  82 + LogTrace("[DcXmlEtlNetwork GenerateInputData]", QString("%1. current container path : %2").arg(level).arg(containerPath.join("/")));
  83 + const auto containerAttribute = inputNode.attribute("container");
  84 + const auto nameAttribute = inputNode.attribute("name");
  85 + // only expand the container when the container attribute is available and the container path is either empty or the last item in the container path
  86 + // is different from the container attribute value.
  87 + if (containerAttribute && (containerPath.empty() || containerPath.back() != QString(containerAttribute.value()))) {
  88 + containerPath.append(containerAttribute.value());
  89 + LogTrace("[DcXmlEtlNetwork GenerateInputData]", QString("%1. container path becomes %2").arg(level).arg(containerPath.join("/")));
  90 + }
  91 + if (nameAttribute) {
  92 + auto excludeFlagAttr = inputNode.attribute("exclude_from_identity_check");
  93 + bool excludeFlag = false;
  94 + if (!excludeFlagAttr.empty()) {
  95 + excludeFlag = DcXmlBase::getBoolean(excludeFlagAttr.value());
  96 + }
  97 + LogTrace("[DcXmlEtlNetwork GenerateInputData]", QString("%1. Generate data for %2 and put it in %3").arg(level).arg(containerPath.join("/") + QString(".") + nameAttribute.value(), data.getObjectId()));
  98 + data.setInputData(containerPath.join("/") + QString(".") + nameAttribute.value(),
  99 + DcXmlBase::getAttributeValue(inputNode, "type"),
  100 + DcXmlBase::getAttributeValue(inputNode, "id"),
  101 + DcXmlBase::getAttributeValue(inputNode, "default"),
  102 + excludeFlag);
  103 + }
  104 + else {
  105 + for (auto childInputNode = inputNode.child("input"); childInputNode; childInputNode = childInputNode.next_sibling("input")) {
  106 + handleInputNode(childInputNode, containerPath, data, level + 1);
  107 + }
  108 + }
  109 +}
  110 +
  111 +} // namespace
  112 +
  113 +DcXmlEtlNetwork::DcXmlEtlNetwork()
  114 + : m_qhPriority()
  115 +{
  116 + constructXPathHash();
  117 + constructEnumHash();
  118 +}
  119 +
  120 +DcXmlEtlNetwork::DcXmlEtlNetwork(const QString& fileName)
  121 + : m_qhPriority()
  122 +{
  123 + if (!DcXmlBase::parseFile(fileName)) {
  124 + LogError("[DcXmlEtlNetwork]",
  125 + QString("There was an error reading configuration : %1").arg(fileName));
  126 + throw std::runtime_error("[DcXmlEtlNetwork] parseFile failed");
  127 + }
  128 +
  129 + constructXPathHash();
  130 + constructEnumHash();
  131 +}
  132 +
  133 +DcXmlEtlNetwork::~DcXmlEtlNetwork() = default;
  134 +
  135 +QStringList DcXmlEtlNetwork::getNetworkNames() const
  136 +{
  137 + QStringList qsResult;
  138 +
  139 + QList<pugi::xpath_node> nodeList = DcXmlBase::selectNodes(DcXmlBase::getXPath(selectNetworks));
  140 + for (const auto& nodeItem : nodeList) {
  141 + qsResult.append(DcXmlBase::getAttributeValue(nodeItem.node(), "name"));
  142 + }
  143 +
  144 + return qsResult;
  145 +}
  146 +
  147 +QList<QSharedPointer<ObjectData>> DcXmlEtlNetwork::getObjectsOfNetwork(const QString& networkName) const
  148 +{
  149 + QList<QSharedPointer<ObjectData>> lstResult;
  150 +
  151 + // Create the correct XPath expression. We have the service already...
  152 + QList<QVariant> varList;
  153 + varList.append(networkName);
  154 +
  155 + // First we get a list of objects
  156 + QList<pugi::xpath_node> objectList = DcXmlBase::selectNodes(DcXmlBase::evaluateXPath(selectObjects, varList));
  157 + for (const auto& objectItem : objectList) {
  158 + auto pData = QSharedPointer<ObjectData>::create();
  159 + pData->setObjectId(DcXmlBase::getAttributeValue(objectItem.node(), "id"));
  160 + pData->setObjectType(DcXmlBase::getAttributeValue(objectItem.node(), "class"));
  161 + //====================================================================================
  162 + // Get some headerinformation based on the objecttype. Some fields are re-used.
  163 + //====================================================================================
  164 + if (pData->getObjectType() == "output") {
  165 + pData->setTargetName(DcXmlBase::getAttributeValue(objectItem.node(), "target"));
  166 + pData->setTargetAction(DcXmlBase::getAttributeValue(objectItem.node(), "default_action"));
  167 + pData->setKeyField(DcXmlBase::getAttributeValue(objectItem.node(), "key_field"));
  168 + pData->setForeignKeyField(DcXmlBase::getAttributeValue(objectItem.node(), "foreignkey_field"));
  169 + auto targetFieldAttr = objectItem.node().attribute("target_field"); // Available in combination with batch/merge update. If not set then targetField is the same as foreignKeyField
  170 + if (targetFieldAttr.empty()) {
  171 + pData->setTargetField(pData->getForeignKeyField());
  172 + }
  173 + else {
  174 + pData->setTargetField(targetFieldAttr.value());
  175 + }
  176 +
  177 + // Available in combination with merge update. Default is NULL.
  178 + pData->setTargetResetValue(DcXmlBase::getAttributeValue(objectItem.node(), "target_reset_value"));
  179 +
  180 + auto nonPersistentTimestampUsageAttr = objectItem.node().attribute("use_non_persistent_timestamp");
  181 + if (!nonPersistentTimestampUsageAttr.empty()) {
  182 + pData->setNonPersistentTimestampUsage(getBoolean(nonPersistentTimestampUsageAttr.value()));
  183 + }
  184 + if (pData->getNonPersistentTimestampUsage()) {
  185 + auto nonPersistentTimestampBufferSize = objectItem.node().attribute("nr_of_timestamps");
  186 + if (!nonPersistentTimestampBufferSize.empty()) {
  187 + bool conversionOk = false;
  188 + auto nrOfTimestamps = QVariant(nonPersistentTimestampBufferSize.value()).toUInt(&conversionOk);
  189 + if (conversionOk && nrOfTimestamps > 0) {
  190 + pData->setNonPersistentTimestampBufferSize(nrOfTimestamps);
  191 + }
  192 + else {
  193 + LogWarning("[DcXmlEtlNetwork]",
  194 + QString("Invalid nr_of_timestamps value %1, using default buffersize").arg(nonPersistentTimestampBufferSize.value()));
  195 + }
  196 + }
  197 + }
  198 + }
  199 +
  200 + if (pData->getObjectType() == "datafilter") {
  201 + pData->setTargetAction(DcXmlBase::getAttributeValue(objectItem.node(), "default_action"));
  202 + pData->setKeyField(DcXmlBase::getAttributeValue(objectItem.node(), "key_field"));
  203 + pData->setKeyValue(DcXmlBase::getAttributeValue(objectItem.node(), "key_value"));
  204 + }
  205 + //====================================================================================
  206 + // Get all inputs if there are any
  207 + varList.clear();
  208 + varList.append(networkName);
  209 + varList.append(DcXmlBase::getAttributeValue(objectItem.node(), "id"));
  210 +
  211 + if (pData->getObjectType() == "output") {
  212 + auto outputVarList = varList;
  213 + outputVarList.append("output"); // add the class
  214 +
  215 + // select all inputs from an output object
  216 + QList<pugi::xpath_node> inputsList = DcXmlBase::selectNodes(DcXmlBase::evaluateXPath(selectInputs, outputVarList));
  217 +
  218 + // Only one inputs (plural!) node is expected.
  219 + // The for loop is defensive programming
  220 + for (const auto& xpathInputsNode : inputsList) {
  221 + GenerateInputData::generate(xpathInputsNode.node(), *pData);
  222 + }
  223 + }
  224 + else if (pData->getObjectType() == "datafilter") {
  225 + auto datafilterVarList = varList;
  226 + datafilterVarList.append("datafilter"); // add the class
  227 +
  228 + // select all inputs from an output object
  229 + QList<pugi::xpath_node> inputsList = DcXmlBase::selectNodes(DcXmlBase::evaluateXPath(selectInputs, datafilterVarList));
  230 +
  231 + // Only one inputs (plural!) node is expected.
  232 + // The for loop is defensive programming
  233 + for (const auto& xpathInputsNode : inputsList) {
  234 + for (auto inputNode = xpathInputsNode.node().child("input"); inputNode; inputNode = inputNode.next_sibling("input")) {
  235 + pData->setInputData(DcXmlBase::getAttributeValue(inputNode, "name"),
  236 + DcXmlBase::getAttributeValue(inputNode, "type"),
  237 + QString{}, // no id
  238 + DcXmlBase::getAttributeValue(inputNode, "default"),
  239 + false);
  240 + }
  241 + }
  242 + }
  243 +
  244 + // And finally all outputs.
  245 + varList.clear();
  246 + varList.append(networkName);
  247 + varList.append(DcXmlBase::getAttributeValue(objectItem.node(), "id"));
  248 + QList<pugi::xpath_node> outputList = DcXmlBase::selectNodes(DcXmlBase::evaluateXPath(selectOutputs, varList));
  249 + for (const auto& outputItem : outputList) {
  250 + pData->setOutputData(DcXmlBase::getAttributeValue(outputItem.node(), "name"),
  251 + DcXmlBase::getAttributeValue(outputItem.node(), "type"),
  252 + DcXmlBase::getAttributeValue(outputItem.node(), "default"));
  253 + }
  254 +
  255 + // Add the entire objectData to the list...
  256 + lstResult.append(pData);
  257 + }
  258 +
  259 + return lstResult;
  260 +}
  261 +
  262 +Connections DcXmlEtlNetwork::getConnectionsOfNetwork(const QString& networkName) const
  263 +{
  264 + Connections cResult;
  265 +
  266 + // Create the variable list and create the correct XPath expression.
  267 + QList<QVariant> varList;
  268 + varList.append(networkName);
  269 +
  270 + // Get the list of connections..
  271 + QList<pugi::xpath_node> connectList = DcXmlBase::selectNodes(DcXmlBase::evaluateXPath(selectConnections, varList));
  272 + for (const auto& connectItem : connectList) {
  273 + const auto node = connectItem.node();
  274 + cResult.addConnection(DcXmlBase::getAttributeValue(node, "source"),
  275 + DcXmlBase::getAttributeValue(node, "target"),
  276 + DcXmlBase::getAttributeValue(node, "output"),
  277 + DcXmlBase::getAttributeValue(node, "input"));
  278 + }
  279 +
  280 + return cResult;
  281 +}
  282 +
  283 +QStringList DcXmlEtlNetwork::getInputVariables(const QString& networkName) const
  284 +{
  285 + QStringList qlResult;
  286 +
  287 + // Create the variable list and return the correct XPath expression.
  288 + QList<QVariant> varList;
  289 + varList.append(networkName);
  290 +
  291 + QList<pugi::xpath_node> inputList = DcXmlBase::selectNodes(DcXmlBase::evaluateXPath(selectInputVarNames, varList));
  292 + for (const auto& inputItem : inputList) {
  293 + qlResult.append(DcXmlBase::getAttributeValue(inputItem.node(), "name"));
  294 + }
  295 +
  296 + return qlResult;
  297 +}
  298 +
  299 +QStringList DcXmlEtlNetwork::getOutputVariables(const QString& networkName) const
  300 +{
  301 + QStringList qlResult;
  302 +
  303 + // Create the variable list and return the correct XPath expression.
  304 + QList<QVariant> varList;
  305 + varList.append(networkName);
  306 +
  307 + QList<pugi::xpath_node> outputList = DcXmlBase::selectNodes(DcXmlBase::evaluateXPath(selectOutputVarNames, varList));
  308 + for (const auto& outputItem : outputList) {
  309 + qlResult.append(DcXmlBase::getAttributeValue(outputItem.node(), "name"));
  310 + }
  311 +
  312 + return qlResult;
  313 +}
  314 +
  315 +QThread::Priority DcXmlEtlNetwork::getPrioByNetworkName(const QString& networkName) const
  316 +{
  317 + QThread::Priority priority = QThread::NormalPriority;
  318 +
  319 + // Create the variable list and create the correct XPath expression.
  320 + QList<QVariant> varList;
  321 + varList.append(networkName);
  322 +
  323 + pugi::xpath_node nodeItem = DcXmlBase::selectNode(DcXmlBase::evaluateXPath(selectNetwork, varList));
  324 + if (nodeItem) {
  325 + const auto prio = DcXmlBase::getAttributeValue(nodeItem.node(), "priority");
  326 + priority = m_qhPriority.value(prio, QThread::NormalPriority);
  327 + }
  328 +
  329 + return priority;
  330 +}
  331 +
  332 +void DcXmlEtlNetwork::constructXPathHash()
  333 +{
  334 + /* Put all XPath expressions in one hash, this way they are all localized
  335 + * centrally and not scattered around the code.
  336 + */
  337 + // Networks
  338 + DcXmlBase::addXPath(selectNetworks, "//network");
  339 + DcXmlBase::addXPath(selectNetwork, "//network[@name='%1']");
  340 + // Objects
  341 + DcXmlBase::addXPath(selectObjects, "//network[@name='%1']/objects/object");
  342 + DcXmlBase::addXPath(selectObject, "//network[@name='%1']/objects/object[@id='%2']");
  343 + // Inputs
  344 + DcXmlBase::addXPath(selectInputs, "//network[@name='%1']/objects/object[@id='%2' and @class='%3']/inputs");
  345 + DcXmlBase::addXPath(selectInputVarNames, "//network[@name='%1']/objects/object[@class='input']/outputs/output");
  346 + DcXmlBase::addXPath(selectInput, "//network[@name='%1']/objects/object[@id='%2']/inputs/input[@name='%3']");
  347 + // Outputs
  348 + DcXmlBase::addXPath(selectOutputs, "//network[@name='%1']/objects/object[@id='%2']/outputs/output");
  349 + DcXmlBase::addXPath(selectOutputVarNames, "//network[@name='%1']/objects/object[@class='output']/inputs/input");
  350 + DcXmlBase::addXPath(selectOutput, "//network[@name='%1']/objects/object[@id='%2']/outputs/output[@name='%3']");
  351 + // Connections
  352 + DcXmlBase::addXPath(selectConnections, "//network[@name='%1']/connections/connection");
  353 +}
  354 +
  355 +void DcXmlEtlNetwork::constructEnumHash()
  356 +{
  357 + m_qhPriority.insert(prio_idle, QThread::IdlePriority);
  358 + m_qhPriority.insert(prio_lowest, QThread::LowestPriority);
  359 + m_qhPriority.insert(prio_low, QThread::LowPriority);
  360 + m_qhPriority.insert(prio_normal, QThread::NormalPriority);
  361 + m_qhPriority.insert(prio_high, QThread::HighPriority);
  362 + m_qhPriority.insert(prio_highest, QThread::HighestPriority);
  363 + m_qhPriority.insert(prio_time_critical, QThread::TimeCriticalPriority);
  364 + m_qhPriority.insert(prio_inherit, QThread::InheritPriority);
  365 +}
src/dcxmletlnetwork.h 0 → 100644
  1 +++ a/src/dcxmletlnetwork.h
  1 +#ifndef OSDEV_COMPONENTS_DCXMLETLNETWORK_H
  2 +#define OSDEV_COMPONENTS_DCXMLETLNETWORK_H
  3 +
  4 +#include "connection.h"
  5 +#include "connections.h"
  6 +#include "connectordata.h"
  7 +#include "dcxmlbase.h"
  8 +#include "objectdata.h"
  9 +
  10 +// Qt
  11 +#include <QHash>
  12 +#include <QList>
  13 +#include <QSharedPointer>
  14 +#include <QString>
  15 +#include <QStringList>
  16 +#include <QThread>
  17 +
  18 +namespace osdev {
  19 +namespace components {
  20 +
  21 +/*
  22 + * _________________________________________
  23 + * / An expert is one who knows more and \
  24 + * | more about less and less until he knows |
  25 + * \ absolutely everything about nothing. /
  26 + * -----------------------------------------
  27 + * \
  28 + * \
  29 + * .--.
  30 + * |o_o |
  31 + * |:_/ |
  32 + * // \ \
  33 + * (| | )
  34 + * /'\_ _/`\
  35 + * \___)=(___/
  36 + *******************************************************/
  37 +/*!
  38 + * \brief The class that actually parses the configuration file and provides
  39 + * accessors to the internal data.
  40 + */
  41 +class DcXmlEtlNetwork : public DcXmlBase
  42 +{
  43 +public:
  44 + DcXmlEtlNetwork();
  45 + explicit DcXmlEtlNetwork(const QString& fileName);
  46 + virtual ~DcXmlEtlNetwork();
  47 +
  48 + QStringList getNetworkNames() const;
  49 + QList<QSharedPointer<ObjectData>> getObjectsOfNetwork(const QString& networkName) const;
  50 + Connections getConnectionsOfNetwork(const QString& networkName) const;
  51 +
  52 + QStringList getInputVariables(const QString& serviceName) const;
  53 + QStringList getOutputVariables(const QString& networkName) const;
  54 +
  55 + QThread::Priority getPrioByNetworkName(const QString& networkName) const;
  56 +
  57 +private:
  58 + void constructXPathHash();
  59 + void constructEnumHash();
  60 +
  61 + QHash<QString, QThread::Priority> m_qhPriority; // Enum from QThread
  62 +};
  63 +
  64 +} // namespace components
  65 +} // namespace osdev
  66 +
  67 +#endif // OSDEV_COMPONENTS_DCXMLETLNETWORK_H
src/dcxmletlservices.cpp 0 → 100644
  1 +++ a/src/dcxmletlservices.cpp
  1 +#include "dcxmletlservices.h"
  2 +#include "log.h"
  3 +#include <string>
  4 +
  5 +using namespace osdev::components;
  6 +
  7 +static const char* selectServices = "selectServices";
  8 +static const char* selectServiceById = "selectServiceById";
  9 +static const char* selectServiceByName = "selectServiceByName";
  10 +
  11 +DcXmlEtlServices::DcXmlEtlServices( const QString &fileName )
  12 +{
  13 + if( !fileName.isEmpty() )
  14 + {
  15 + if( !loadConfiguration( fileName ) )
  16 + {
  17 + LogInfo( "[DcXmlEtlServices::DcXmlEtlServices]", QString( "There was an error reading file : %1" ).arg( fileName ) );
  18 + }
  19 + }
  20 + else
  21 + {
  22 + LogInfo( "[DcXmlEtlServices::DcXmlEtlServices]", QString( "No filename given. No configuration read." ) );
  23 + }
  24 +
  25 + constructXPathHash();
  26 +}
  27 +
  28 +bool DcXmlEtlServices::loadConfiguration( const QString &fileName )
  29 +{
  30 + return DcXmlBase::parseFile( fileName );
  31 +}
  32 +
  33 +QStringList DcXmlEtlServices::getServiceNames() const
  34 +{
  35 + QStringList lstResult;
  36 +
  37 + QList<pugi::xpath_node> serviceList = DcXmlBase::selectNodes( DcXmlBase::getXPath( selectServices ) );
  38 + for( const auto& nodeItem : serviceList )
  39 + {
  40 + lstResult.append( nodeItem.node().attribute( "name" ).value() );
  41 + }
  42 +
  43 + return lstResult;
  44 +}
  45 +
  46 +QStringList DcXmlEtlServices::getServiceIds() const
  47 +{
  48 + QStringList lstResult;
  49 +
  50 + QList<pugi::xpath_node> serviceList = DcXmlBase::selectNodes( DcXmlBase::getXPath( selectServices ) );
  51 + for( const auto& nodeItem : serviceList )
  52 + {
  53 + lstResult.append( nodeItem.node().attribute( "id" ).value() );
  54 + }
  55 +
  56 + return lstResult;
  57 +}
  58 +
  59 +QString DcXmlEtlServices::getServiceConfig( const QString &serviceId ) const
  60 +{
  61 + QList<QVariant> varList;
  62 + varList.append( serviceId );
  63 +
  64 + return QString( DcXmlBase::selectNode( evaluateXPath( selectServiceById, varList ) ).node().attribute( "filename" ).value() );
  65 +}
  66 +
  67 +QHash<QString, QString> DcXmlEtlServices::getServiceConfigs() const
  68 +{
  69 + QHash<QString, QString> qhResult;
  70 +
  71 + QList<pugi::xpath_node> serviceList = DcXmlBase::selectNodes( DcXmlBase::getXPath( selectServices ) );
  72 + for( const auto& nodeItem : serviceList )
  73 + {
  74 + qhResult.insert( nodeItem.node().attribute( "id" ).value(), nodeItem.node().attribute( "filename" ).value() );
  75 + }
  76 +
  77 + return qhResult;
  78 +}
  79 +
  80 +void DcXmlEtlServices::constructXPathHash()
  81 +{
  82 + DcXmlBase::addXPath( selectServices, "//modelmapping/services/service" );
  83 + DcXmlBase::addXPath( selectServiceById, "//modelmapping/services/service[@id='%1']" );
  84 + DcXmlBase::addXPath( selectServiceByName, "//modelmapping/services/service[@name='%1']" );
  85 +}
  86 +
  87 +QString DcXmlEtlServices::getServiceConfigByName( const QString &serviceName ) const
  88 +{
  89 + return this->getValueByAttribute( selectServiceByName, serviceName, "filename" );
  90 +}
  91 +
  92 +QString DcXmlEtlServices::getServiceIdByName( const QString &serviceName ) const
  93 +{
  94 + return this->getValueByAttribute( selectServiceByName, serviceName, "id" );
  95 +}
  96 +
  97 +QString DcXmlEtlServices::getServiceConfigById( const QString &serviceId ) const
  98 +{
  99 + return this->getValueByAttribute( selectServiceById, serviceId, "filename" );
  100 +}
  101 +
  102 +QString DcXmlEtlServices::getValueByAttribute( const QString &XPath,
  103 + const QString &attrValue,
  104 + const QString &returnAttribute ) const
  105 +{
  106 + QList<QVariant> varList;
  107 + varList.append( attrValue );
  108 +
  109 + return QString( DcXmlBase::selectNode( evaluateXPath( XPath.toStdString().c_str(), varList ) ).node().attribute( returnAttribute.toStdString().c_str() ).value() );
  110 +}
src/dcxmletlservices.h 0 → 100644
  1 +++ a/src/dcxmletlservices.h
  1 +#ifndef OSDEV_COMPONENTS_DCXMLETLSERVICES_H
  2 +#define OSDEV_COMPONENTS_DCXMLETLSERVICES_H
  3 +
  4 +#include "dcxmlbase.h"
  5 +
  6 +#include <QObject>
  7 +#include <QString>
  8 +#include <QStringList>
  9 +#include <QHash>
  10 +
  11 +namespace osdev {
  12 +namespace components {
  13 +/*
  14 + * _________________________________________
  15 + * / River: "Little soul big world. Eat and \
  16 + * | sleep and eat... Many souls. Very |
  17 + * | straight, very simple" |
  18 + * | |
  19 + * | Mal: "Cattle on the ship three weeks, |
  20 + * | she don't go near 'em. Suddenly, we're |
  21 + * | on Jiangyin and she's got a driving |
  22 + * | need to commune with the beasts?" |
  23 + * | |
  24 + * | River: "They weren't cows inside. They |
  25 + * | were waiting to be, but they forgot. |
  26 + * | Now they see sky and they remember what |
  27 + * | they are." |
  28 + * | |
  29 + * | Mal: "Is it bad that what she just said |
  30 + * | makes perfect sense to me?" |
  31 + * | |
  32 + * \ --Episode #5, "Safe" /
  33 + * -----------------------------------------
  34 + * \
  35 + * \
  36 + * .--.
  37 + * |o_o |
  38 + * |:_/ |
  39 + * // \ \
  40 + * (| | )
  41 + * /'\_ _/`\
  42 + * \___)=(___/
  43 + *
  44 + **************************************************************************************/
  45 +/*! \brief This component locates all the services from the ModelMapper configuration.
  46 + * Although it can be used seperately, it is intended to be a helper class to
  47 + * XMLEtlConfig.
  48 + * While XMLEtlConfig is implemented as Singleton, this class isn't.
  49 + */
  50 +
  51 +class DcXmlEtlServices : public DcXmlBase
  52 +{
  53 +public:
  54 + DcXmlEtlServices( const QString &fileName = QString() );
  55 +
  56 + /// Deleted copy constructor
  57 + DcXmlEtlServices( const DcXmlEtlServices& ) = delete;
  58 +
  59 + /// Deleted assignment constructor
  60 + DcXmlEtlServices& operator=( const DcXmlEtlServices& ) = delete;
  61 +
  62 + /// Deleted move constructor
  63 + DcXmlEtlServices( DcXmlEtlServices&& ) = delete;
  64 +
  65 + /// Deleeted move operator
  66 + DcXmlEtlServices& operator=( DcXmlEtlServices&& ) = delete;
  67 +
  68 + /// @brief Loads the configuration from the given fileName.
  69 + /// @param fileName - The configuration file in XML format.
  70 + virtual bool loadConfiguration( const QString &fileName );
  71 +
  72 + // =========================================================================
  73 + /*!
  74 + * \brief Get the list of services mentioned in the modelmapper configuration
  75 + * If no services were mentioned, this list will be empty.
  76 + */
  77 + QStringList getServiceNames() const;
  78 +
  79 + /*!
  80 + * \brief Get the list of serviceIds mentioned in the modelmapper configuration
  81 + * If no ServiceIds were found, this list will be empty.
  82 + */
  83 + QStringList getServiceIds() const;
  84 +
  85 + /*!
  86 + * \brief Get the filename of the service-configuration file.
  87 + * This file isn't parsed here but passed on to the DcXmlNetwork class.
  88 + */
  89 + QString getServiceConfig( const QString &serviceId ) const;
  90 +
  91 + /*!
  92 + * \brief Get the list of configurations by serviceId in a Hash
  93 + * If no services are found, this Hash will be empty.
  94 + */
  95 + QHash<QString, QString> getServiceConfigs() const;
  96 +
  97 + // Convenient methods.
  98 + /*!
  99 + * @brief Added for convenience. The name is quite descriptive.
  100 + */
  101 + QString getServiceConfigByName( const QString &serviceName ) const;
  102 + QString getServiceIdByName( const QString &serviceName ) const;
  103 + QString getServiceConfigById( const QString &serviceId ) const;
  104 +
  105 +private:
  106 + void constructXPathHash();
  107 + QString getValueByAttribute( const QString &XPath,
  108 + const QString &attrValue,
  109 + const QString &returnAttribute ) const;
  110 +
  111 +};
  112 +
  113 +} /* End namespace components */
  114 +} /* End namespace osdev */
  115 +
  116 +#endif /* OSDEV_COMPONENTS_DCXMLETLSERVICES_H */
src/dcxmlmodelmapping.cpp 0 → 100644
  1 +++ a/src/dcxmlmodelmapping.cpp
  1 +#include "dcxmlmodelmapping.h"
  2 +#include "dcxmlconfig.h"
  3 +
  4 +using namespace osdev::components;
  5 +
  6 +// The only instance of the singleton Modelmapper Config Parser.
  7 +std::unique_ptr<DcXmlModelMapping> DcXmlModelMapping::s_instance(nullptr);
  8 +
  9 +DcXmlModelMapping& DcXmlModelMapping::Instance()
  10 +{
  11 + if (nullptr == s_instance) {
  12 + s_instance = std::unique_ptr<DcXmlModelMapping>(new DcXmlModelMapping());
  13 + }
  14 +
  15 + return *s_instance;
  16 +}
  17 +
  18 +DcXmlModelMapping::DcXmlModelMapping()
  19 + : m_services(nullptr)
  20 + , m_networks()
  21 +{
  22 +}
  23 +
  24 +DcXmlModelMapping::~DcXmlModelMapping()
  25 +{
  26 + this->cleanInternals();
  27 +}
  28 +
  29 +bool DcXmlModelMapping::loadConfiguration(const QString& configDir, const QString& fileName)
  30 +{
  31 + // Check if the internal service parser is instantiated. If not, do so.
  32 + // The network parsers will be parsed "on the way".
  33 + if (nullptr != m_services || !m_networks.isEmpty()) {
  34 + // clean up the internal structures.. We obviously want to (re)load the configuration.
  35 + cleanInternals();
  36 + }
  37 +
  38 + // Start the services configuration...
  39 + m_services = QSharedPointer<DcXmlEtlServices>(new DcXmlEtlServices(configDir + "/" + fileName));
  40 + for (const QString& serviceName : m_services->getServiceNames()) {
  41 + QSharedPointer<DcXmlEtlNetwork> pNetwork = QSharedPointer<DcXmlEtlNetwork>(new DcXmlEtlNetwork(configDir + "/" + m_services->getServiceConfigByName(serviceName)));
  42 +
  43 + if (nullptr != pNetwork) {
  44 + m_networks.insert(serviceName, pNetwork);
  45 + }
  46 + }
  47 +
  48 + return true;
  49 +}
  50 +
  51 +bool DcXmlModelMapping::loadConfiguration(const QString& fileName)
  52 +{
  53 + return loadConfiguration(DCXmlConfig::Instance().getConfigPath(), fileName);
  54 +}
  55 +
  56 +QStringList DcXmlModelMapping::getServices() const
  57 +{
  58 + return QStringList(m_networks.keys());
  59 +}
  60 +
  61 +QString DcXmlModelMapping::getServiceId(const QString& _serviceName) const
  62 +{
  63 + return m_services->getServiceIdByName(_serviceName);
  64 +}
  65 +
  66 +QStringList DcXmlModelMapping::getNetworksOfService(const QString& _serviceName) const
  67 +{
  68 + return m_networks.value(_serviceName)->getNetworkNames();
  69 +}
  70 +
  71 +QList<QSharedPointer<ObjectData>> DcXmlModelMapping::getObjectsOfNetwork(const QString& _networkName) const
  72 +{
  73 + // Find the network pointer containing the networkName.
  74 + QSharedPointer<DcXmlEtlNetwork> pNetwork = findNetworkByName(_networkName);
  75 + if (nullptr != pNetwork) {
  76 + return pNetwork->getObjectsOfNetwork(_networkName);
  77 + }
  78 + return QList<QSharedPointer<ObjectData>>();
  79 +}
  80 +
  81 +Connections DcXmlModelMapping::getConnectionsOfNetwork(const QString& _networkName) const
  82 +{
  83 + // Find the network pointer containing the networkName.
  84 + QSharedPointer<DcXmlEtlNetwork> pNetwork = findNetworkByName(_networkName);
  85 + if (nullptr != pNetwork) {
  86 + return pNetwork->getConnectionsOfNetwork(_networkName);
  87 + }
  88 + return Connections();
  89 +}
  90 +
  91 +QStringList DcXmlModelMapping::getInputVariables(const QString& _networkName) const
  92 +{
  93 + // Find the network pointer containing the networkName.
  94 + QSharedPointer<DcXmlEtlNetwork> pNetwork = findNetworkByName(_networkName);
  95 + if (nullptr != pNetwork) {
  96 + return pNetwork->getInputVariables(_networkName);
  97 + }
  98 + return QStringList();
  99 +}
  100 +
  101 +QStringList DcXmlModelMapping::getOutputVariables(const QString& _networkName) const
  102 +{
  103 + QSharedPointer<DcXmlEtlNetwork> pNetwork = findNetworkByName(_networkName);
  104 + if (nullptr != pNetwork) {
  105 + return pNetwork->getOutputVariables(_networkName);
  106 + }
  107 + return QStringList();
  108 +}
  109 +
  110 +QThread::Priority DcXmlModelMapping::getPrioByNetworkName(const QString& _networkName) const
  111 +{
  112 + // Find the network pointer containing the networkName.
  113 + QSharedPointer<DcXmlEtlNetwork> pNetwork = findNetworkByName(_networkName);
  114 + if (nullptr != pNetwork) {
  115 + return pNetwork->getPrioByNetworkName(_networkName);
  116 + }
  117 + return QThread::NormalPriority;
  118 +}
  119 +
  120 +void DcXmlModelMapping::cleanInternals()
  121 +{
  122 + // Retrieve every network object and destroy it...
  123 + if (!m_networks.isEmpty()) {
  124 + for (const QString& serviceName : QStringList(m_networks.keys())) {
  125 + // Clear the reference. If it was the last (only) reference
  126 + // the pointer wil be deleted.
  127 + m_networks.take(serviceName).clear();
  128 + }
  129 + }
  130 +
  131 + m_services.clear();
  132 +}
  133 +
  134 +QSharedPointer<DcXmlEtlNetwork> DcXmlModelMapping::findNetworkByName(const QString& networkName) const
  135 +{
  136 + for (QSharedPointer<DcXmlEtlNetwork> pNetwork : m_networks.values()) {
  137 + if (pNetwork->getNetworkNames().contains(networkName)) {
  138 + return pNetwork;
  139 + }
  140 + }
  141 + return QSharedPointer<DcXmlEtlNetwork>();
  142 +}
src/dcxmlmodelmapping.h 0 → 100644
  1 +++ a/src/dcxmlmodelmapping.h
  1 +#ifndef OSDEV_COMPONENTS_DCXMLMODELMAPPING_H
  2 +#define OSDEV_COMPONENTS_DCXMLMODELMAPPING_H
  3 +
  4 +#include "dcxmletlnetwork.h"
  5 +#include "dcxmletlservices.h"
  6 +
  7 +#include <QHash>
  8 +#include <QObject>
  9 +#include <QSharedPointer>
  10 +#include <QStringList>
  11 +#include <memory>
  12 +
  13 +namespace osdev {
  14 +namespace components {
  15 +
  16 +/*! \brief This component locates any configuration information needed
  17 + * to initialize the application and its components.
  18 + * Parses this information and make it available to other
  19 + * components that need it.
  20 + *
  21 + * This component is implemented as a singleton. XML has the
  22 + * "habit" of expand approx. 15 times the file size so with this
  23 + * in mind, it is more future proof to load this only once into memory.
  24 + */
  25 +/*
  26 + * ________________________________________
  27 + * / History, n.: \
  28 + * | |
  29 + * | Papa Hegel he say that all we learn |
  30 + * | from history is that we |
  31 + * | learn nothing from history. I know |
  32 + * | people who can't even learn from |
  33 + * | what happened this morning. Hegel must |
  34 + * | have been taking the long view. |
  35 + * | |
  36 + * | -- Chad C. Mulligan, "The Hipcrime |
  37 + * \ Vocab" /
  38 + * ----------------------------------------
  39 + * \
  40 + * \
  41 + * .--.
  42 + * |o_o |
  43 + * |:_/ |
  44 + * // \ \
  45 + * (| | )
  46 + * /'\_ _/`\
  47 + * \___)=(___/
  48 + */
  49 +
  50 +using network_container = QHash<QString, QSharedPointer<DcXmlEtlNetwork>>;
  51 +
  52 +class DcXmlModelMapping
  53 +{
  54 +public:
  55 + /// @return the one and only instance of the config object.
  56 + static DcXmlModelMapping& Instance();
  57 +
  58 + // =========================================================
  59 + /// The constructor
  60 + DcXmlModelMapping();
  61 +
  62 + /// The destructor
  63 + virtual ~DcXmlModelMapping();
  64 +
  65 + /// Deleted copy-constructor
  66 + DcXmlModelMapping(const DcXmlModelMapping&) = delete;
  67 + /// Deleted assignment constructor
  68 + DcXmlModelMapping& operator=(const DcXmlModelMapping&) = delete;
  69 + /// Deleted move-constructor
  70 + DcXmlModelMapping(DcXmlModelMapping&&) = delete;
  71 + /// Deleted move-operator
  72 + DcXmlModelMapping& operator=(DcXmlModelMapping&&) = delete;
  73 +
  74 + // ==========================================================
  75 + /// @brief Loads the configuration from the given filename
  76 + /// @param fileName - The configuration file in XML format.
  77 + bool loadConfiguration(const QString& configDir, const QString& fileName);
  78 +
  79 + bool loadConfiguration(const QString& fileName);
  80 +
  81 + /*! @brief Retrieve a list of services configured in the ModelMapper configuration
  82 + * @return A StringList of all serviceNames.
  83 + */
  84 + QStringList getServices() const;
  85 + QString getServiceId(const QString& _serviceName) const;
  86 +
  87 + QStringList getNetworksOfService(const QString& _serviceName) const;
  88 + QList<QSharedPointer<ObjectData>> getObjectsOfNetwork(const QString& _networkName) const;
  89 + Connections getConnectionsOfNetwork(const QString& _networkName) const;
  90 +
  91 + QStringList getInputVariables(const QString& _networkName) const;
  92 + QStringList getOutputVariables(const QString& _networkName) const;
  93 +
  94 + QThread::Priority getPrioByNetworkName(const QString& _networkName) const;
  95 +
  96 +private:
  97 + void cleanInternals(); ///< Cleanup the internal structures and destroy all objects.
  98 + QSharedPointer<DcXmlEtlNetwork> findNetworkByName(const QString& networkName) const; ///< Find the object that contains a config with this name.
  99 +
  100 + static std::unique_ptr<DcXmlModelMapping> s_instance; ///< Instantiated ModelMapper Configuration object.
  101 +
  102 + // Internal pointers......
  103 + QSharedPointer<DcXmlEtlServices> m_services; ///< Instantiated Services Configuration object.
  104 + network_container m_networks; ///< Collection of instantiated network configuration objects.
  105 +};
  106 +
  107 +} // namespace components
  108 +} // namespace osdev
  109 +
  110 +#endif // OSDEV_COMPONENTS_DCXMLMODELMAPPING_H
src/jobdata.cpp 0 → 100644
  1 +++ a/src/jobdata.cpp
  1 +#include "jobdata.h"
  2 +
  3 +using namespace osdev::components;
  4 +
  5 +JobData::JobData()
  6 + : m_jobName()
  7 + , m_runDate()
  8 + , m_runTime()
  9 + , m_interval( 0 )
  10 + , m_targetObject()
  11 + , m_parameters()
  12 +{
  13 +}
  14 +
  15 +JobData::JobData( const QString& _jobName, const QHash<QString, QVariant>& _paramList,
  16 + const QTime& _runTime, const int _interval,
  17 + const QString &_targetObject, const QDate& _runDate )
  18 + : m_jobName( _jobName )
  19 + , m_runDate( _runDate )
  20 + , m_runTime( _runTime )
  21 + , m_interval( _interval )
  22 + , m_targetObject( _targetObject )
  23 + , m_parameters( _paramList )
  24 +{
  25 +}
  26 +
  27 +JobData::JobData(const JobData& source )
  28 + : m_jobName( source.jobName() )
  29 + , m_runDate( source.runDate() )
  30 + , m_runTime( source.runTime() )
  31 + , m_interval( source.runInterval() )
  32 + , m_targetObject( source.targetObject() )
  33 + , m_parameters( source.paramList() )
  34 +{
  35 +}
  36 +
  37 +JobData& JobData::operator=( const JobData& origin )
  38 +{
  39 + if( &origin != this )
  40 + {
  41 + origin.copyImpl( this );
  42 + }
  43 + return *this;
  44 +}
  45 +
  46 +void JobData::copyImpl( JobData* dest ) const
  47 +{
  48 + dest->m_interval = m_interval;
  49 + dest->m_targetObject = m_targetObject;
  50 + dest->m_jobName = m_jobName;
  51 + dest->m_parameters = m_parameters;
  52 + dest->m_runDate = m_runDate;
  53 + dest->m_runTime = m_runTime;
  54 +}
  55 +
  56 +JobData::~JobData()
  57 +{
  58 +}
  59 +
  60 +void JobData::addParameter( const QString& _varName, const QVariant &_value )
  61 +{
  62 + m_parameters.insert( _varName, _value );
  63 +}
  64 +
  65 +void JobData::setParameters( const QHash<QString, QVariant>& _paramList )
  66 +{
  67 + // Clear the old parameter list before assigning the new parameter list. Just to be shure.
  68 + m_parameters.clear();
  69 + m_parameters = _paramList;
  70 +}
  71 +
  72 +QVariant JobData::paramValue( const QString& _varName ) const
  73 +{
  74 + if( m_parameters.contains( _varName ) )
  75 + {
  76 + return m_parameters.value( _varName );
  77 + }
  78 +
  79 + return QVariant();
  80 +}
  81 +
  82 +QStringList JobData::varNames() const
  83 +{
  84 + return QStringList( m_parameters.keys() );
  85 +}
src/jobdata.h 0 → 100644
  1 +++ a/src/jobdata.h
  1 +#ifndef OSDEV_COMPONENTS_JOBDATA_H
  2 +#define OSDEV_COMPONENTS_JOBDATA_H
  3 +
  4 +#include <QHash>
  5 +#include <QVariant>
  6 +#include <QString>
  7 +#include <QDate>
  8 +#include <QTime>
  9 +#include <QStringList>
  10 +
  11 +namespace osdev {
  12 +namespace components {
  13 +
  14 +/*
  15 + * _________________________________________
  16 + * / Despite the best efforts of a quantum \
  17 + * | bigfoot drive (yes I know everyone told |
  18 + * | me they suck, now I know they were |
  19 + * | right) 2.1.109ac1 is now available |
  20 + * | |
  21 + * \ -- Alan Cox announcing Linux 2.1.109ac1 /
  22 + * -----------------------------------------
  23 + * \
  24 + * \
  25 + * .--.
  26 + * |o_o |
  27 + * |:_/ |
  28 + * // \ \
  29 + * (| | )
  30 + * /'\_ _/`\
  31 + * \___)=(___/
  32 + */
  33 +/*!
  34 + * \brief A simple class to hold all info needed to schedule a job.
  35 + */
  36 +
  37 +class JobData
  38 +{
  39 +public:
  40 + /// Default constructor
  41 + JobData();
  42 +
  43 + /*!
  44 + * \brief Construct the JobData object and set all the parameters
  45 + * \param _jobName - Name of the job (Coming from the config)
  46 + * \param _paramList - The parameters as coming from the config
  47 + * \param _runTime - Time this job has to run. (Coming from the configuration.
  48 + * \param _runDate - (Local)Date this job has to run.
  49 + * \param _interval - The interval this job has to be rescheduled
  50 + * \param _targetObject - The caelus object this job is intended for.
  51 + */
  52 + JobData( const QString& _jobName, const QHash<QString, QVariant>& _paramList,
  53 + const QTime& _runTime, const int _interval, const QString& _targetObject,
  54 + const QDate& _runDate = QDate::currentDate() );
  55 +
  56 + /* Copy Constructor */
  57 + JobData( const JobData& source );
  58 +
  59 + /* Assignment operator */
  60 + JobData& operator=( const JobData& origin );
  61 +
  62 + /** D'tor */
  63 + virtual ~JobData();
  64 +
  65 + /*!
  66 + * \return The name of the job used for registration.
  67 + * It will be set by "setJobName( const QString& _jobName )"
  68 + */
  69 + const QString& jobName() const { return m_jobName; }
  70 + void setJobName( const QString& _jobName ) { m_jobName = _jobName; }
  71 +
  72 + /*!
  73 + * \return Get the targetobject this job is intended for.
  74 + */
  75 + const QString& targetObject() const { return m_targetObject; }
  76 + void setTargetObject( const QString& _targetObject ) { m_targetObject = _targetObject; }
  77 +
  78 + /*!
  79 + * \return The date this job should run. If this returns empty, it should run each and every day.
  80 + * It will be set by "setRunDate( const QDate& _runDate )".This is LocalTime....
  81 + */
  82 + const QDate& runDate() const { return m_runDate; }
  83 + void setRunDate( const QDate& _runDate ) { m_runDate = _runDate; }
  84 +
  85 + /*!
  86 + * \return The time this job should run. It cannot be empty.
  87 + * It will be set by "setRunTime( const QTime& _runTime )"
  88 + */
  89 + const QTime& runTime() const { return m_runTime; }
  90 + void setRunTime( const QTime& _runTime ) { m_runTime = _runTime; }
  91 +
  92 + /*!
  93 + * \brief The interval the job will be re-scheduled to.
  94 + * \return
  95 + */
  96 + int runInterval() const { return m_interval; }
  97 + void setRunInterval( const int _interval ) { m_interval = _interval; }
  98 +
  99 + // ========================================================================
  100 + // == Implemented in the cpp file
  101 + // == ---------------------------------------------------------------------
  102 + /*!
  103 + * \brief Adds a parameter to the parameter list this job uses.
  104 + */
  105 + void addParameter( const QString& _varName, const QVariant &_value );
  106 +
  107 + /*!
  108 + * \brief Replace the set of parameters with the new one. The old list will be erased.
  109 + */
  110 + void setParameters( const QHash < QString, QVariant > &_paramList );
  111 +
  112 + /*!
  113 + * \return Get the value, belonging to the variable name from the hash.
  114 + * Empty if the parameter name doesn't exist.
  115 + */
  116 + QVariant paramValue( const QString& _varName ) const;
  117 +
  118 + /*!
  119 + * \return Get all parameter names from the list. Empty if none exist.
  120 + */
  121 + QStringList varNames() const;
  122 +
  123 + /*!
  124 + * \return The entire parameter list
  125 + */
  126 + QHash<QString, QVariant> paramList() const { return m_parameters; }
  127 +
  128 +private:
  129 + /*!
  130 + * \brief Copies this instance into the specified destination.
  131 + * \param[in,out] dest Pointer to the destination to which the properties of this instance are copied.
  132 + */
  133 + void copyImpl( JobData* dest ) const;
  134 +
  135 + QString m_jobName; ///< The name of the job used for registration
  136 + QDate m_runDate; ///< The date this job should run. Empty if daily.
  137 + QTime m_runTime; ///< The time this job should run.
  138 + int m_interval; ///< The interval the jod should be scheduled on.
  139 + QString m_targetObject; ///< The plugin or object this job is intended for. Used as input to the pluginmanager.
  140 + QHash<QString, QVariant> m_parameters; ///< Parameters used by the job.
  141 +};
  142 +
  143 +} /* End namespace components */
  144 +} /* End namespace osdev */
  145 +
  146 +#endif /* OSDEV_COMPONENTS_JOBDATA_H */
src/objectdata.cpp 0 → 100644
  1 +++ a/src/objectdata.cpp
  1 +#include "objectdata.h"
  2 +
  3 +using namespace osdev::components;
  4 +
  5 +ObjectData::ObjectData()
  6 + : m_objectType()
  7 + , m_objectId()
  8 + , m_targetName()
  9 + , m_targetAction()
  10 + , m_keyField()
  11 + , m_keyValue()
  12 + , m_foreignKeyField()
  13 + , m_targetField()
  14 + , m_targetResetValue()
  15 + , m_useNonPersistentTimestamp(false)
  16 + , m_npTimestampBufferSize(10)
  17 + , m_qhInputs()
  18 + , m_qhOutputs()
  19 +{
  20 +}
  21 +
  22 +void ObjectData::setObjectType(const QString& _objectType) { m_objectType = _objectType; }
  23 +
  24 +void ObjectData::setObjectId(const QString& _objectId) { m_objectId = _objectId; }
  25 +
  26 +void ObjectData::setTargetName(const QString& _targetName) { m_targetName = _targetName; }
  27 +
  28 +void ObjectData::setTargetAction(const QString& _targetAction) { m_targetAction = _targetAction; }
  29 +
  30 +void ObjectData::setKeyField(const QString& _keyField) { m_keyField = _keyField; }
  31 +
  32 +void ObjectData::setKeyValue(const QString& _keyValue) { m_keyValue = _keyValue; }
  33 +
  34 +void ObjectData::setForeignKeyField(const QString& foreignKeyField) { m_foreignKeyField = foreignKeyField; }
  35 +
  36 +void ObjectData::setTargetField(const QString& targetField) { m_targetField = targetField; }
  37 +
  38 +void ObjectData::setTargetResetValue(const QString& targetResetValue) { m_targetResetValue = targetResetValue; }
  39 +
  40 +void ObjectData::setNonPersistentTimestampUsage(bool value) { m_useNonPersistentTimestamp = value; }
  41 +
  42 +void ObjectData::setNonPersistentTimestampBufferSize(unsigned int value) { m_npTimestampBufferSize = value; }
  43 +
  44 +const QStringList ObjectData::getInputNames() const { return m_qhInputs.keys(); }
  45 +
  46 +const QString& ObjectData::getInputId(const QString& _inputName) const { return m_qhInputs.value(_inputName)->id(); }
  47 +
  48 +const QString& ObjectData::getInputType(const QString& _inputName) const { return m_qhInputs.value(_inputName)->type(); }
  49 +
  50 +const QString& ObjectData::getInputDefault(const QString& _inputName) const { return m_qhInputs.value(_inputName)->Default(); }
  51 +
  52 +bool ObjectData::getInputExcludeFromIdentityCheck(const QString& _inputName) const { return m_qhInputs.value(_inputName)->excludeFromIdentityCheck(); }
  53 +
  54 +const QStringList ObjectData::getOutputNames() const { return m_qhOutputs.keys(); }
  55 +
  56 +const QString& ObjectData::getOutputType(const QString& _outputName) const { return m_qhOutputs.value(_outputName)->type(); }
  57 +
  58 +const QString& ObjectData::getOutputDefault(const QString& _outputName) const { return m_qhOutputs.value(_outputName)->Default(); }
  59 +
  60 +void ObjectData::setInputData(const QString& _name, const QString& _type, const QString& _id, const QString& _default, bool excludeFromIdentityCheck)
  61 +{
  62 + // Use multiInsert in order to detect double entries at a later stage. The getters will return the last entry and in that sense the
  63 + // behaviour is the same as when overwriting the value in the hash with an insert. The keys method used by getInputNames however will
  64 + // return a list that holds a key multiple times if it was inserted multiple times.
  65 + m_qhInputs.insertMulti(_name, (QSharedPointer<ConnectorData>(new ConnectorData(_name, _type, _id, _default, excludeFromIdentityCheck))));
  66 +}
  67 +
  68 +void ObjectData::setOutputData(const QString& _name, const QString& _type, const QString& _default)
  69 +{
  70 + // Use multiInsert in order to detect double entries at a later stage. The getters will return the last entry and in that sense the
  71 + // behaviour is the same as when overwriting the value in the hash with an insert. The keys method used by getOutputNames however will
  72 + // return a list that holds a key multiple times if it was inserted multiple times.
  73 + m_qhOutputs.insertMulti(_name, (QSharedPointer<ConnectorData>(new ConnectorData(_name, _type, QString{}, _default)))); // no id
  74 +}
src/objectdata.h 0 → 100644
  1 +++ a/src/objectdata.h
  1 +#ifndef OSDEV_COMPONENTS_OBJECTDATA_H
  2 +#define OSDEV_COMPONENTS_OBJECTDATA_H
  3 +
  4 +#include <QSharedPointer>
  5 +#include <QStringList>
  6 +
  7 +#include "connectordata.h"
  8 +
  9 +namespace osdev {
  10 +namespace components {
  11 +
  12 +/*
  13 + * _____________________________________
  14 + * < Excellent day to have a rotten day. >
  15 + * -------------------------------------
  16 + * \
  17 + * \
  18 + * .--.
  19 + * |o_o |
  20 + * |:_/ |
  21 + * // \ \
  22 + * (| | )
  23 + * /'\_ _/`\
  24 + * \___)=(___/
  25 + *
  26 + */
  27 +/*!
  28 + * \brief The ObjectData class
  29 + */
  30 +
  31 +class ObjectData
  32 +{
  33 +public:
  34 + /*!
  35 + * \brief Default constructor;
  36 + */
  37 + ObjectData();
  38 +
  39 + /*!
  40 + * \return The object type.
  41 + */
  42 + const QString& getObjectType() const { return m_objectType; }
  43 +
  44 + /*!
  45 + * \return The object id.
  46 + */
  47 + const QString& getObjectId() const { return m_objectId; }
  48 +
  49 + /*!
  50 + * \return The target name.
  51 + */
  52 + const QString& getTargetName() const { return m_targetName; }
  53 +
  54 + /*!
  55 + * \return The target action.
  56 + */
  57 + const QString& getTargetAction() const { return m_targetAction; }
  58 +
  59 + /*!
  60 + * \return The key field.
  61 + */
  62 + const QString& getKeyField() const { return m_keyField; }
  63 +
  64 + /**
  65 + * @return The key value.
  66 + */
  67 + const QString& getKeyValue() const { return m_keyValue; }
  68 +
  69 + /**
  70 + * @return The foreign key field.
  71 + */
  72 + const QString& getForeignKeyField() const { return m_foreignKeyField; }
  73 +
  74 + /**
  75 + * @return The target field.
  76 + */
  77 + const QString& getTargetField() const { return m_targetField; }
  78 +
  79 + /**
  80 + * @return The target field reset value.
  81 + */
  82 + const QString& getTargetResetValue() const { return m_targetResetValue; }
  83 +
  84 + /**
  85 + * @return Flag value that indicates whether persistent or non persistent timestamps should be used.
  86 + */
  87 + bool getNonPersistentTimestampUsage() const { return m_useNonPersistentTimestamp; }
  88 +
  89 + /**
  90 + * @return Size of the buffer that is used for storing the non persistent timestamps.
  91 + */
  92 + unsigned int getNonPersistentTimestampBufferSize() const { return m_npTimestampBufferSize; }
  93 +
  94 + /*!
  95 + * \brief Sets the ObjectType.
  96 + * \param objectType The type to set.
  97 + */
  98 + void setObjectType(const QString& objectType);
  99 +
  100 + /*!
  101 + * \brief setObjectId Sets the object id.
  102 + * \param objectId The id to set.
  103 + */
  104 + void setObjectId(const QString& objectId);
  105 +
  106 + /*!
  107 + * \brief Sets the TargetName.
  108 + * \param targetName The target name to set.
  109 + */
  110 + void setTargetName(const QString& targetName);
  111 +
  112 + /*!
  113 + * \brief Sets the TargetAction.
  114 + * \param targetAction The action to set.
  115 + */
  116 + void setTargetAction(const QString& targetAction);
  117 +
  118 + /*!
  119 + * \brief Sets the KeyField.
  120 + * \param keyField The key field to set.
  121 + */
  122 + void setKeyField(const QString& keyField);
  123 +
  124 + /**
  125 + * @brief Sets the keyvalue for a match in a DataFilter
  126 + * @param keyValue The value to set.
  127 + */
  128 + void setKeyValue(const QString& keyValue);
  129 +
  130 + /*!
  131 + * \brief Sets the foreign key field (used for batch/merge update).
  132 + * \param foreignKeyField The foreign key field to set.
  133 + */
  134 + void setForeignKeyField(const QString& foreignKeyField);
  135 +
  136 + /**
  137 + * @brief Set the field on which a merge/batch update operation operates.
  138 + * @param targetField The field to change values on in batch/merge updates.
  139 + */
  140 + void setTargetField(const QString& targetField);
  141 +
  142 + /**
  143 + * @brief Set the reset value to which the targetfield is set in the decouple step of the merge update operation.
  144 + * @param targetResetValue The reset value to use in a field reset.
  145 + */
  146 + void setTargetResetValue(const QString& targetResetValue);
  147 +
  148 + /**
  149 + * @brief Set the flag value that indicates whether persistent or non persistent timestamps should be used.
  150 + * @param value The value to set.
  151 + */
  152 + void setNonPersistentTimestampUsage(bool value);
  153 +
  154 + /**
  155 + * @brief Set the size (number of timestamps) of the buffer used to store non persistent timestamps.
  156 + * @param value The value to set.
  157 + */
  158 + void setNonPersistentTimestampBufferSize(unsigned int value);
  159 +
  160 + /*!
  161 + * \return The input names.
  162 + */
  163 + const QStringList getInputNames() const;
  164 +
  165 + /*!
  166 + * \brief Get the id of the input element identified by name.
  167 + * \param inputName The name that identifies the input element.
  168 + * \return input id or a null string when the input does not have an id.
  169 + */
  170 + const QString& getInputId(const QString& inputName) const;
  171 +
  172 + /*!
  173 + * \brief Gets the InputType for the specified input name.
  174 + * \param inputName The name for which to get the input type.
  175 + * \return The InputType for the specified input name.
  176 + */
  177 + const QString& getInputType(const QString& inputName) const;
  178 +
  179 + /*!
  180 + * \brief Gets the InputDefault for the specified input name.
  181 + * \param inputName The inout name for chich to get the default.
  182 + * \return The InputDefault for the specified input name.
  183 + */
  184 + const QString& getInputDefault(const QString& inputName) const;
  185 +
  186 + /*!
  187 + * \brief Get the excludeFromIdentityCheck flag for the specified input name.
  188 + * \param inputName The name for which to get the excludeFromIdentityCheck flag.
  189 + * \return The excludeFromIdentityCheck flag.
  190 + */
  191 + bool getInputExcludeFromIdentityCheck(const QString& inputName) const;
  192 +
  193 + /*!
  194 + * \return The output names.
  195 + */
  196 + const QStringList getOutputNames() const;
  197 +
  198 + /*!
  199 + * \brief Gets the OutputType for the specified output name.
  200 + * \param outputName The output name for which to get the type.
  201 + * \return The OutputType for the specified output name.
  202 + */
  203 + const QString& getOutputType(const QString& outputName) const;
  204 +
  205 + /*!
  206 + * \brief Gets the OutputDefault for the specified output name.
  207 + * \param outputName The name for which to get the default.
  208 + * \return The OutputDefault for the specified output name.
  209 + */
  210 + const QString& getOutputDefault(const QString& outputName) const;
  211 +
  212 + /*!
  213 + * \brief Sets the InputData.
  214 + * \param name The name of the input data.
  215 + * \param type The type of the input data.
  216 + * \param id The id of the input data. If there is no id a null string must be used.
  217 + * \param defaultValue The defaultValue of the input data.
  218 + * \param excludeFromIdentityCheck Flag that indicates whether this data should participate in the record identity check.
  219 + */
  220 + void setInputData(const QString& name, const QString& type, const QString& id, const QString& defaultValue, bool excludeFromIdentityCheck);
  221 +
  222 + /*!
  223 + * \brief setOutputData
  224 + * \param name The name of the output data.
  225 + * \param type The type of the output data.
  226 + * \param defaultValue The defaultValue of the output data.
  227 + */
  228 + void setOutputData(const QString& name, const QString& type, const QString& defaultValue);
  229 +
  230 +private:
  231 + QString m_objectType; ///< Type of Object
  232 + QString m_objectId; ///< UUID of the object
  233 + QString m_targetName; ///< TargetTable this object represent
  234 + QString m_targetAction; ///< What action should taken on the target
  235 + QString m_keyField; ///< What TargetField is used for Querying
  236 + QString m_keyValue; ///< The value we're querying for.
  237 + QString m_foreignKeyField; ///< Contains reference to a foreign table.
  238 + QString m_targetField; ///< The field on which batch/merge operations operate.
  239 + QString m_targetResetValue; ///< The value to which fields are reset when they are not part of the merge set.
  240 + bool m_useNonPersistentTimestamp; ///< Use persistent or non persistent timestamp. Default is false.
  241 + unsigned int m_npTimestampBufferSize; ///< Number of timestamps that can be stored (circular buffer). Default is 10.
  242 +
  243 + QHash<QString, QSharedPointer<ConnectorData>> m_qhInputs; ///< Hash of all InputConnectors by Name
  244 + QHash<QString, QSharedPointer<ConnectorData>> m_qhOutputs; ///< Hash of all OutputConnectors by Name
  245 +};
  246 +
  247 +} // namespace components
  248 +} // namespace osdev
  249 +
  250 +#endif // OSDEV_COMPONENTS_OBJECTDATA_H