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 | ... | ... |