Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build_cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [macos-12]
os: [macos-14]
build_type: [Debug, Release]
cxx_version: [17, 20]
steps:
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.2.0]

### Fixed

- Spelling error in CMakeLists.txt corrected.

### Changed

- REXS 1.7 added (#57)
- Changed to new schema format on REXS hp
- Preparation for semantic versioning (major.minor.patch)

## [2.1.0]

### Fixed
Expand Down
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.22)
project(rexsapi VERSION 2.1.0 LANGUAGES CXX)
project(rexsapi VERSION 2.2.0 LANGUAGES CXX)

include(FetchContent)

Expand All @@ -17,7 +17,7 @@ if(NOT DEFINED REXSAPI_MASTER_PROJECT)
endif()

option(BUILD_WITH_EXAMPLES "Build with examples" ${REXSAPI_MASTER_PROJECT})
option(BUILD_WIHT_TESTS "Build with tests" ${REXSAPI_MASTER_PROJECT})
option(BUILD_WITH_TESTS "Build with tests" ${REXSAPI_MASTER_PROJECT})
option(BUILD_WITH_TOOLS "Build with tools" ON)
option(BUILD_WITH_DOCS "Build documentation" ${REXSAPI_MASTER_PROJECT})

Expand Down Expand Up @@ -66,7 +66,7 @@ if(BUILD_WITH_EXAMPLES)
add_subdirectory(examples)
endif()

if(BUILD_WIHT_TESTS)
if(BUILD_WITH_TESTS)
enable_testing()
message(STATUS "Building with tests")
add_subdirectory(test)
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,14 +288,14 @@ The library is header only. A build is only necessary if you want to run the tes

REXSapi uses the following thirdparty open source software

- [cli11 2.4.1](https://github.com/CLIUtils/CLI11)
- [date 3.0.1](https://github.com/HowardHinnant/date)
- [doctest 2.4.10](https://github.com/doctest/doctest)
- [cli11 2.5.0](https://github.com/CLIUtils/CLI11)
- [date 3.0.3](https://github.com/HowardHinnant/date)
- [doctest 2.4.11](https://github.com/doctest/doctest)
- [fmt 10.2.1](https://github.com/fmtlib/fmt)
- [nlohmann json 3.11.2](https://github.com/nlohmann/json)
- [nlohmann json 3.12.0](https://github.com/nlohmann/json)
- [miniz 3.0.2](https://github.com/richgel999/miniz)
- [pugixml 1.14](https://github.com/zeux/pugixml)
- [valijson 1.0.2](https://github.com/tristanpenman/valijson)
- [pugixml 1.15](https://github.com/zeux/pugixml)
- [valijson 1.0.5](https://github.com/tristanpenman/valijson)

# License

Expand Down
2 changes: 1 addition & 1 deletion cmake/fetch_cli11.cmake
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FetchContent_Declare(
cli11
URL https://github.com/CLIUtils/CLI11/archive/refs/tags/v2.4.1.tar.gz
URL https://github.com/CLIUtils/CLI11/archive/refs/tags/v2.5.0.tar.gz
)

FetchContent_MakeAvailable(cli11)
2 changes: 1 addition & 1 deletion cmake/fetch_date.cmake
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FetchContent_Declare(
date
URL https://github.com/HowardHinnant/date/archive/refs/tags/v3.0.1.tar.gz
URL https://github.com/HowardHinnant/date/archive/refs/tags/v3.0.3.tar.gz
)

FetchContent_GetProperties(date)
Expand Down
2 changes: 1 addition & 1 deletion cmake/fetch_doctest.cmake
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FetchContent_Declare(
doctest
GIT_REPOSITORY https://github.com/doctest/doctest
GIT_TAG v2.4.10
GIT_TAG v2.4.11
)

FetchContent_GetProperties(doctest)
Expand Down
2 changes: 1 addition & 1 deletion cmake/fetch_json.cmake
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FetchContent_Declare(
json
URL https://github.com/nlohmann/json/archive/refs/tags/v3.11.2.tar.gz
URL https://github.com/nlohmann/json/archive/refs/tags/v3.12.0.tar.gz
)

FetchContent_GetProperties(json)
Expand Down
2 changes: 1 addition & 1 deletion cmake/fetch_pugixml.cmake
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FetchContent_Declare(
pugixml
GIT_REPOSITORY https://github.com/zeux/pugixml
GIT_TAG v1.14
GIT_TAG v1.15
)

if(NOT pugixml_POPULATED)
Expand Down
2 changes: 1 addition & 1 deletion cmake/fetch_valijson.cmake
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FetchContent_Declare(
valijson
URL https://github.com/tristanpenman/valijson/archive/refs/tags/v1.0.2.tar.gz
URL https://github.com/tristanpenman/valijson/archive/refs/tags/v1.0.5.tar.gz
)

FetchContent_GetProperties(valijson)
Expand Down
16 changes: 8 additions & 8 deletions include/rexsapi/ModelLoader.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace rexsapi
* @brief Creates a model registry containing all models found in the given filesystem path.
*
* The filesystem path should contain REXS database model files for different versions and languages. Additionally,
* the XML database model schema file (*rexs-dbmodel.xsd*) has to be available in the path.
* the XML database model schema file (*rexs-schema.xsd*) has to be available in the path.
*
* @param path The filesystem path to load REXS database model files from.
* @return database::TModelRegistry containing all available REXS database models
Expand Down Expand Up @@ -59,9 +59,9 @@ namespace rexsapi
*
* @param databasePath filesystem path containing REXS database model files for different versions and languages and
* all relevant schema files. The necessary schema files are:
* - rexs-dbmodel.xsd
* - rexs-schema.xsd
* - rexs-schema.json
* - rexs-file.xsd
* - rexs-file.json
* @param dataSourceResolver Will be used to load external model data sources if set. Triggers an error if not set
* and model has external references.
* @throws TException if the model registry or the schema validators cannot be created
Expand All @@ -80,9 +80,9 @@ namespace rexsapi
*
* @param databasePath filesystem path containing REXS database model files for different versions and languages and
* all relevant schema files. The necessary schema files are:
* - rexs-dbmodel.xsd
* - rexs-schema.xsd
* - rexs-schema.json
* - rexs-file.xsd
* - rexs-file.json
* @param customExtensionMappings Additional custom extension mappings to respect for REXS model file type detection
* @param dataSourceResolver Will be used to load external model data sources if set. Triggers an error if not set
* and model has external references.
Expand Down Expand Up @@ -199,7 +199,7 @@ namespace rexsapi

static inline database::TModelRegistry createModelRegistry(const std::filesystem::path& path)
{
TFileXsdSchemaLoader schemaLoader{path / "rexs-dbmodel.xsd"};
TFileXsdSchemaLoader schemaLoader{path / "rexs-schema.xsd"};
database::TFileResourceLoader resourceLoader{path};
database::TXmlModelLoader modelLoader{resourceLoader, schemaLoader};
return database::TModelRegistry::createModelRegistry(modelLoader).first;
Expand Down Expand Up @@ -257,13 +257,13 @@ namespace rexsapi

inline TXSDSchemaValidator TModelLoader::createXMLSchemaValidator(const std::filesystem::path& path)
{
TFileXsdSchemaLoader schemaLoader{path / "rexs-schema.xsd"};
TFileXsdSchemaLoader schemaLoader{path / "rexs-file.xsd"};
return TXSDSchemaValidator{schemaLoader};
}

inline TJsonSchemaValidator TModelLoader::createJsonSchemaValidator(const std::filesystem::path& path)
{
TFileJsonSchemaLoader schemaLoader{path / "rexs-schema.json"};
TFileJsonSchemaLoader schemaLoader{path / "rexs-file.json"};
return TJsonSchemaValidator{schemaLoader};
}

Expand Down
29 changes: 22 additions & 7 deletions include/rexsapi/RexsVersion.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,33 @@ namespace rexsapi
explicit TRexsVersion(const std::string& version)
{
static std::regex regExpr{R"(^(\d+)\.(\d+)$)"};
static std::regex regExpr_semantic_versioning{R"(^(\d+)\.(\d+)\.(\d+)$)"};
std::smatch match;
if (std::regex_search(version, match, regExpr)) {
m_Major = static_cast<uint32_t>(std::stoul(match[1]));
m_Minor = static_cast<uint32_t>(std::stoul(match[2]));
} else {
m_Patch = 0;
}
else if (std::regex_search(version, match, regExpr_semantic_versioning)) {
m_Major = static_cast<uint32_t>(std::stoul(match[1]));
m_Minor = static_cast<uint32_t>(std::stoul(match[2]));
m_Patch = static_cast<uint32_t>(std::stoul(match[3]));
}
else {
throw TException{fmt::format("not a valid version: '{}'", version)};
}
}

TRexsVersion(uint32_t major, uint32_t minor)
TRexsVersion(uint32_t major, uint32_t minor, uint32_t patch=0)
: m_Major{major}
, m_Minor{minor}
, m_Patch{patch}
{
}

friend bool operator==(const TRexsVersion& lhs, const TRexsVersion& rhs) noexcept
{
return lhs.getMajor() == rhs.getMajor() && lhs.getMinor() == rhs.getMinor();
return lhs.getMajor() == rhs.getMajor() && lhs.getMinor() == rhs.getMinor() && lhs.getPatch() == rhs.getPatch();
}

friend bool operator!=(const TRexsVersion& lhs, const TRexsVersion& rhs) noexcept
Expand All @@ -67,12 +76,12 @@ namespace rexsapi

friend bool operator<(const TRexsVersion& lhs, const TRexsVersion& rhs) noexcept
{
return lhs.getMajor() < rhs.getMajor() || (lhs.getMajor() == rhs.getMajor() && lhs.getMinor() < rhs.getMinor());
return lhs.getMajor() < rhs.getMajor() || (lhs.getMajor() == rhs.getMajor() && lhs.getMinor() < rhs.getMinor()) || (lhs.getMajor() == rhs.getMajor() && lhs.getMinor() < rhs.getMinor() && lhs.getPatch() < rhs.getPatch());
}

friend bool operator>(const TRexsVersion& lhs, const TRexsVersion& rhs) noexcept
{
return lhs.getMajor() > rhs.getMajor() || (lhs.getMajor() == rhs.getMajor() && lhs.getMinor() > rhs.getMinor());
return lhs.getMajor() > rhs.getMajor() || (lhs.getMajor() == rhs.getMajor() && lhs.getMinor() > rhs.getMinor()) || (lhs.getMajor() == rhs.getMajor() && lhs.getMinor() > rhs.getMinor() && lhs.getPatch() > rhs.getPatch());
}

friend bool operator<=(const TRexsVersion& lhs, const TRexsVersion& rhs) noexcept
Expand All @@ -95,19 +104,25 @@ namespace rexsapi
return m_Minor;
}

uint32_t getPatch() const noexcept
{
return m_Patch;
}

/**
* @brief Returns string representation of the version.
*
* @return std::string containing a major and a minor version number separated with a dot
*/
std::string asString() const
{
return fmt::format("{}.{}", m_Major, m_Minor);
return (m_Major<=1) ? fmt::format("{}.{}", m_Major, m_Minor) : fmt::format("{}.{}.{}", m_Major, m_Minor, m_Patch);
}

private:
uint32_t m_Major;
uint32_t m_Minor;
uint32_t m_Patch;
};
}

Expand All @@ -122,7 +137,7 @@ namespace std
struct hash<rexsapi::TRexsVersion> {
std::size_t operator()(const rexsapi::TRexsVersion& version) const noexcept
{
return std::hash<uint64_t>{}(static_cast<uint64_t>(version.getMajor()) * 100 + version.getMinor());
return std::hash<uint64_t>{}(static_cast<uint64_t>(version.getMajor()) * 10000 + static_cast<uint64_t>(version.getMinor()) * 100 + version.getPatch());
}
};
}
Expand Down
9 changes: 5 additions & 4 deletions include/rexsapi/XSDSchemaValidator.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -865,10 +865,10 @@ namespace rexsapi
auto type1 = std::make_unique<detail::TPodType<detail::TStringType>>(fmt::format("{}:string", detail::xsdSchemaNS));
m_Types.try_emplace(type1->getName(), std::move(type1));
auto type2 =
std::make_unique<detail::TPodType<detail::TIntegerType>>(fmt::format("{}:integer", detail::xsdSchemaNS));
std::make_unique<detail::TPodType<detail::TIntegerType>>(fmt::format("{}:int", detail::xsdSchemaNS));
m_Types.try_emplace(type2->getName(), std::move(type2));
auto type3 =
std::make_unique<detail::TPodType<detail::TDecimalType>>(fmt::format("{}:decimal", detail::xsdSchemaNS));
std::make_unique<detail::TPodType<detail::TDecimalType>>(fmt::format("{}:double", detail::xsdSchemaNS));
m_Types.try_emplace(type3->getName(), std::move(type3));
auto type4 =
std::make_unique<detail::TPodType<detail::TBooleanType>>(fmt::format("{}:boolean", detail::xsdSchemaNS));
Expand Down Expand Up @@ -926,9 +926,10 @@ namespace rexsapi

for (const auto& element :
node.select_nodes(fmt::format("{0}:complexType/{0}:sequence/{0}:element", detail::xsdSchemaNS).c_str())) {
auto min = convertToUint64(element.node().attribute("minOccurs").as_string());
auto minString = std::string(element.node().attribute("minOccurs").as_string());
auto min = (minString=="") ? 1 : convertToUint64(minString);
auto maxString = std::string(element.node().attribute("maxOccurs").as_string());
auto max = maxString == "unbounded" ? std::numeric_limits<uint64_t>::max() : convertToUint64(maxString);
auto max = (maxString=="") ? 1 : (maxString == "unbounded" ? std::numeric_limits<uint64_t>::max() : convertToUint64(maxString));

if (const auto refName = element.node().attribute("ref"); !refName.empty()) {
const detail::TElement& ref = findOrRegisterElement(refName.as_string());
Expand Down
12 changes: 6 additions & 6 deletions include/rexsapi/database/XMLModelLoader.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -91,25 +91,25 @@ namespace rexsapi::database
return;
}

const auto rexsModel = *doc.select_nodes("/rexsModel").begin();
const auto rexsModel = *doc.select_nodes("/rexsSchema").begin();
TModel model{TRexsVersion{rexsapi::detail::getStringAttribute(rexsModel, "version")},
rexsapi::detail::getStringAttribute(rexsModel, "language"),
rexsapi::detail::getStringAttribute(rexsModel, "date"),
statusFromString(rexsapi::detail::getStringAttribute(rexsModel, "status"))};

for (const auto& node : doc.select_nodes("/rexsModel/units/unit")) {
for (const auto& node : doc.select_nodes("/rexsSchema/units/unit")) {
auto id = convertToUint64(rexsapi::detail::getStringAttribute(node, "id"));
auto name = rexsapi::detail::getStringAttribute(node, "name");
model.addUnit(TUnit{id, name});
}

for (const auto& node : doc.select_nodes("/rexsModel/valueTypes/valueType")) {
for (const auto& node : doc.select_nodes("/rexsSchema/valueTypes/valueType")) {
auto id = convertToUint64(rexsapi::detail::getStringAttribute(node, "id"));
auto name = rexsapi::detail::getStringAttribute(node, "name");
model.addType(id, typeFromString(name));
}

for (const auto& node : doc.select_nodes("/rexsModel/attributes/attribute")) {
for (const auto& node : doc.select_nodes("/rexsSchema/attributes/attribute")) {
auto attributeId = rexsapi::detail::getStringAttribute(node, "attributeId");
auto name = rexsapi::detail::getStringAttribute(node, "name");
auto valueType =
Expand Down Expand Up @@ -137,14 +137,14 @@ namespace rexsapi::database
}

std::vector<std::pair<std::string, std::string>> attributeMappings;
for (const auto& node : doc.select_nodes("/rexsModel/componentAttributeMappings/componentAttributeMapping")) {
for (const auto& node : doc.select_nodes("/rexsSchema/componentAttributeMappings/componentAttributeMapping")) {
auto componentId = rexsapi::detail::getStringAttribute(node, "componentId");
auto attributeId = rexsapi::detail::getStringAttribute(node, "attributeId");
attributeMappings.emplace_back(componentId, attributeId);
}
rexsapi::database::detail::TComponentAttributeMapper attributeMapper{model, std::move(attributeMappings)};

for (const auto& node : doc.select_nodes("/rexsModel/components/component")) {
for (const auto& node : doc.select_nodes("/rexsSchema/components/component")) {
auto id = rexsapi::detail::getStringAttribute(node, "componentId");
auto name = rexsapi::detail::getStringAttribute(node, "name");
auto attributes = attributeMapper.getAttributesForComponent(id);
Expand Down
Loading