Commit 30448f6284ab20cc105e4e708ba44ad7440257e6
0 parents
Replace Qt with std::c++
Showing
26 changed files
with
3413 additions
and
0 deletions
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
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 |