src/RecfileHandler.h
branchv_0
changeset 1 1b4ca23e5d04
parent 0 9005fdd81bca
child 2 db029ce62ec5
--- a/src/RecfileHandler.h	Sat Mar 30 01:12:42 2019 +0100
+++ b/src/RecfileHandler.h	Sat Mar 30 15:50:29 2019 +0100
@@ -28,107 +28,98 @@
 
 #include <relpipe/reader/typedefs.h>
 #include <relpipe/reader/TypeId.h>
-#include <relpipe/reader/handlers/RelationalReaderValueHandler.h>
+#include <relpipe/reader/RelpipeReaderException.h>
+#include <relpipe/reader/handlers/RelationalReaderStringHandler.h>
 #include <relpipe/reader/handlers/AttributeMetadata.h>
 
-#include "RecfileWriter.h"
-
 namespace relpipe {
 namespace out {
 namespace recfile {
 
 using namespace relpipe::reader;
 
-class RecfileHandler : public handlers::RelationalReaderValueHadler {
+class RecfileHandler : public handlers::RelationalReaderStringHadler {
 private:
-	shared_ptr<RecfileWriter> recfileWriter;
-	std::vector<TypeId> columnTypes;
-	std::vector<string_t> columnTypeCodes;
-	std::vector<string_t> columnNames;
+	std::ostream& output;
+	wstring_convert<codecvt_utf8<wchar_t>> convertor; // XML output will be always in UTF-8
+	std::vector<TypeId> attributeTypes;
+	std::vector<string_t> attributeTypeCodes;
+	std::vector<string_t> attributeNames;
 	integer_t valueCount = 0;
-	integer_t columnCount = 0;
+	integer_t attributeCount = 0;
 	integer_t relationCount = 0;
 
+	void writeRelationName(const string_t& name) {
+		// FIXME: escaping/filtering
+		output << "%rec: " << convertor.to_bytes(name) << std::endl;
+	}
+
+	const std::string toRecfileType(const TypeId& type) {
+		switch (type) {
+			case TypeId::BOOLEAN: return "bool";
+			case TypeId::INTEGER: return "int";
+			case TypeId::STRING: return ""; // TODO: string type?
+			default: throw RelpipeReaderException(L"Unsupported type – unable to convert to a Recfile type");
+		}
+	}
+
+	void writeAttributeMetadata(const handlers::AttributeMetadata& attribute) {
+		// FIXME: escaping/filtering
+		// FIXME: translate to recfile types
+		output << "%type: " << convertor.to_bytes(attribute.getAttributeName()) << " " << toRecfileType(attribute.getTypeId()) << std::endl;
+	}
+
+	void writeSeparator() {
+		output << std::endl;
+	}
+
+	void writeAttribute(const string_t& name, const TypeId& type, const string_t& value) {
+		// FIXME: escaping/filtering
+		output << convertor.to_bytes(name) << ": ";
+
+		for (char ch : convertor.to_bytes(value)) {
+			output << ch;
+			if (ch == '\n') output << "+ ";
+		}
+
+		output << std::endl;
+	}
+
 public:
 
-	RecfileHandler(std::ostream& output) : recfileWriter(new RecfileWriter(output)) {
+	RecfileHandler(std::ostream& output) : output(output) {
 	}
 
 	void startRelation(string_t name, std::vector<handlers::AttributeMetadata> attributes) override {
 		valueCount = 0;
-		columnCount = 0;
+		attributeCount = 0;
 
-		if (relationCount == 0) {
-			recfileWriter->writeStartSequence(); // root
-		} else {
-			recfileWriter->writeEndSequence();
-			recfileWriter->writeEndSequence();
-		}
+		if (relationCount) writeSeparator();
+
 		relationCount++;
-		recfileWriter->writeStartSequence(); // relation
-
-		recfileWriter->writeString(name);
-
+		writeRelationName(name);
 
-		recfileWriter->writeStartSequence(); // relation metadata
-		columnCount = attributes.size();
-		columnTypes.resize(columnCount);
-		columnTypeCodes.resize(columnCount);
-		columnNames.resize(columnCount);
+		attributeCount = attributes.size();
+		attributeTypes.resize(attributeCount);
+		attributeTypeCodes.resize(attributeCount);
+		attributeNames.resize(attributeCount);
 		for (int i = 0; i < attributes.size(); i++) {
-			columnNames[i] = attributes[i].getAttributeName();
-			columnTypes[i] = attributes[i].getTypeId();
-			columnTypeCodes[i] = attributes[i].getTypeName();
-			
-			recfileWriter->writeStartSequence(); // attribute-metadata
-			recfileWriter->writeString(columnNames[i]);
-			recfileWriter->writeString(columnTypeCodes[i]);
-			recfileWriter->writeEndSequence();
+			attributeNames[i] = attributes[i].getAttributeName();
+			attributeTypes[i] = attributes[i].getTypeId();
+			attributeTypeCodes[i] = attributes[i].getTypeName();
+			writeAttributeMetadata(attributes[i]);
 		}
-		recfileWriter->writeEndSequence();
-
 	}
 
-	void attribute(const void* value, const std::type_info& type) override {
-		integer_t i = valueCount % columnCount;
-
-		if (i == 0 && valueCount) recfileWriter->writeEndSequence();
-		if (i == 0) recfileWriter->writeStartSequence();
-
+	void attribute(const string_t& value) override {
+		integer_t i = valueCount % attributeCount;
+		if (i == 0) writeSeparator();
 		valueCount++;
-		
-		switch (columnTypes[i]) {
-			case TypeId::BOOLEAN:
-			{
-				assert(type == typeid (boolean_t));
-				auto* typedValue = static_cast<const boolean_t*> (value);
-				recfileWriter->writeBoolean(*typedValue);
-				break;
-			}
-			case TypeId::INTEGER:
-			{
-				assert(type == typeid (integer_t));
-				auto* typedValue = static_cast<const integer_t*> (value);
-				recfileWriter->writeInteger(*typedValue);
-				break;
-			}
-			case TypeId::STRING:
-			{
-				assert(type == typeid (string_t));
-				auto* typedValue = static_cast<const string_t*> (value);
-				recfileWriter->writeString(*typedValue);
-				break;
-			}
-			default:
-				throw cli::RelpipeCLIException(L"Unsupported type in RecfileHandler.attribute()", cli::CLI::EXIT_CODE_UNEXPECTED_ERROR);
-		}
-		
+		writeAttribute(attributeNames[i], attributeTypes[i], value);
 	}
 
 	void endOfPipe() {
-		if (valueCount) recfileWriter->writeEndSequence();
-		if (relationCount) recfileWriter->writeEndSequence();
-		recfileWriter->writeEndSequence();
+		if (valueCount) writeSeparator();
 	}
 
 };