107 if (fileName.empty()) {
111 std::ifstream planFile(fileName);
112 if (!planFile.is_open()) {
113 throw std::runtime_error(
"Cannot open mqttstore projection file '" + fileName +
"'");
118 planJson =
nlohmann::json::parse(std::string(std::istreambuf_iterator<
char>(planFile), std::istreambuf_iterator<
char>()));
119 }
catch (
const nlohmann::json::parse_error& exception) {
120 throw std::runtime_error(
"Cannot parse mqttstore projection file '" + fileName +
"': " + exception.what());
125 }
catch (
const std::exception& exception) {
126 throw std::runtime_error(
"Cannot load mqttstore projection file '" + fileName +
"': " + exception.what());
135 const nlohmann::json& projectionsJson = json.contains(
"projections") ? json.at(
"projections") : json;
136 if (!projectionsJson.is_array()) {
137 throw std::runtime_error(
"mqttstore projection configuration must be an array or contain a projections array");
140 for (
const nlohmann::json& projectionJson : projectionsJson) {
141 Projection projection;
142 projection.name = projectionJson.value(
"name",
"");
143 projection.topic = projectionJson.at(
"topic").get<std::string>();
144 projection.table = projectionJson.at(
"table").get<std::string>();
146 const nlohmann::json& columnsJson = projectionJson.at(
"columns");
147 if (!columnsJson.is_object()) {
148 throw std::runtime_error(
"mqttstore projection columns must be an object");
151 for (
auto columnIterator = columnsJson.begin(); columnIterator != columnsJson.end(); ++columnIterator) {
152 ColumnMapping mapping;
153 mapping.column = columnIterator.key();
155 if (columnIterator.value().is_string()) {
156 mapping.jsonPointer = columnIterator.value().get<std::string>();
158 const nlohmann::json& mappingJson = columnIterator.value();
159 mapping.jsonPointer = mappingJson.value(
"json_pointer",
"");
160 mapping.required = mappingJson.value(
"required",
false);
162 if (mappingJson.contains(
"topic_level")) {
163 mapping.topicLevel = mappingJson.at(
"topic_level").get<std::size_t>();
165 if (mappingJson.contains(
"literal")) {
166 mapping.literal = mappingJson.at(
"literal").get<std::string>();
170 projection.columns.push_back(mapping);
173 plan.projections.push_back(projection);
196 const std::vector<std::string> filterLevels = splitTopic(filter);
197 const std::vector<std::string> topicLevels = splitTopic(topic);
199 for (std::size_t level = 0; level < filterLevels.size(); ++level) {
200 if (filterLevels[level] ==
"#") {
201 return level + 1 == filterLevels.size();
204 if (level >= topicLevels.size()) {
208 if (filterLevels[level] !=
"+" && filterLevels[level] != topicLevels[level]) {
213 return filterLevels.size() == topicLevels.size();