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 |