src/INIDispatchHandler.h
branchv_0
changeset 0 1bb084f84eb9
child 1 e04e5bbc147b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/INIDispatchHandler.h	Wed Dec 09 17:55:03 2020 +0100
@@ -0,0 +1,105 @@
+/**
+ * Relational pipes
+ * Copyright © 2020 František Kučera (Frantovo.cz, GlobalCode.info)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <iostream>
+#include <sstream>
+#include <locale>
+#include <codecvt>
+#include <regex>
+#include <stdexcept>
+
+#include <relpipe/common/type/typedefs.h>
+#include <relpipe/reader/TypeId.h>
+#include <relpipe/reader/handlers/RelationalReaderStringHandler.h>
+#include <relpipe/reader/handlers/AttributeMetadata.h>
+
+#include "Configuration.h"
+#include "INIWriter.h"
+#include "INIStandardHandler.h"
+#include "INILiteralHandler.h"
+
+namespace relpipe {
+namespace out {
+namespace ini {
+
+class INIDispatchHandler : public relpipe::reader::handlers::RelationalReaderStringHandler {
+private:
+	std::ostream& output;
+	INIWriter writer;
+	Configuration& configuration;
+	std::shared_ptr<relpipe::reader::handlers::RelationalReaderStringHandler> currentHandler;
+
+	relpipe::reader::handlers::RelationalReaderStringHandler* createHandlerAuto(const relpipe::common::type::StringX& name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) {
+		bool hasKey = false;
+		bool hasValue = false;
+
+		for (auto a : attributes) {
+			if (a.getAttributeName() == L"key") hasKey = true;
+			else if (a.getAttributeName() == L"value") hasValue = true;
+		}
+
+		if (hasKey && hasValue) return new INIStandardHandler(writer);
+		else return new INILiteralHandler(writer);
+	}
+
+	relpipe::reader::handlers::RelationalReaderStringHandler* createHandler(const relpipe::common::type::StringX& name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) {
+		for (auto rc : configuration.relationConfigurations) {
+			if (std::regex_match(name, std::wregex(rc.relation))) {
+				if (rc.style == Style::Standard) return new INIStandardHandler(writer);
+				else if (rc.style == Style::Literal) return new INILiteralHandler(writer);
+				else if (rc.style == Style::LiteralWithSectionAttribute) return new INILiteralHandler(writer, L"section");
+				else if (rc.style == Style::Dropped) return nullptr;
+				else if (rc.style == Style::Automatic) return createHandlerAuto(name, attributes);
+				else throw std::invalid_argument("Unsupported style: " + std::to_string((int) rc.style));
+			}
+		}
+
+		if (configuration.relationConfigurations.size()) return nullptr;
+		else return createHandlerAuto(name, attributes);
+	}
+
+public:
+
+	INIDispatchHandler(std::ostream& output, Configuration& configuration) : output(output), writer(output), configuration(configuration) {
+		for (auto o : configuration.writerOptions) writer.setOption(o.uri, o.value);
+	}
+
+	void startRelation(relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override {
+		if (currentHandler) currentHandler->endOfPipe();
+		currentHandler.reset(createHandler(name, attributes));
+		if (currentHandler) currentHandler->startRelation(name, attributes);
+	}
+
+	void attribute(const relpipe::common::type::StringX& value) override {
+		if (currentHandler) currentHandler->attribute(value);
+	}
+
+	void endOfPipe() {
+		if (currentHandler) currentHandler->endOfPipe();
+		currentHandler.reset();
+		output.flush();
+	}
+
+};
+
+}
+}
+}