src/YAMLCommand.h
branchv_0
changeset 2 d68192f0e960
parent 1 8d2d8f4077af
child 3 64f8f8792470
equal deleted inserted replaced
1:8d2d8f4077af 2:d68192f0e960
    30 namespace in {
    30 namespace in {
    31 namespace yaml {
    31 namespace yaml {
    32 
    32 
    33 class YAMLCommand {
    33 class YAMLCommand {
    34 private:
    34 private:
    35 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
    35 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // YAML strings are in UTF-8
    36 
    36 
    37 	class YAMLEvent {
    37 	class YAMLEvent {
    38 	private:
    38 	private:
    39 		yaml_event_t event;
    39 		yaml_event_t event;
    40 	public:
    40 	public:
    96 
    96 
    97 	YAMLParser parser;
    97 	YAMLParser parser;
    98 
    98 
    99 	using YAMLEvent_p = std::shared_ptr<YAMLEvent>;
    99 	using YAMLEvent_p = std::shared_ptr<YAMLEvent>;
   100 
   100 
   101 	enum class Mode {
   101 	enum class State {
   102 		ROOT,
   102 		START,
   103 		RELATIONS_SEQUENCE,
   103 		RELATIONS,
   104 		MAPPING,
   104 		ATTRIBUTE,
   105 		MAP_KEY
   105 		RECORDS
   106 	};
   106 	};
   107 
   107 
   108 	std::vector<Mode> mode;
   108 	State state;
   109 
   109 
   110 	/**
   110 	relpipe::writer::string_t y2s(yaml_char_t* value) {
   111 	 * Both YAML and XML strings are in UTF-8.
   111 		return value ? convertor.from_bytes((const char*) value) : L"";
   112 	 */
   112 	}
   113 	const char* y2x(yaml_char_t* value) {
   113 
   114 		return value ? (const char*) value : "";
   114 	relpipe::writer::string_t findValue(std::vector<relpipe::writer::string_t> record, relpipe::writer::string_t key) {
       
   115 		if (record.size() % 2) relpipe::writer::RelpipeWriterException(L"Invalid count of values in the record vector");
       
   116 		for (size_t i = 0; i < record.size(); i += 2) {
       
   117 			if (record[i] == key) return record[i + 1];
       
   118 		}
       
   119 		return L"";
   115 	}
   120 	}
   116 
   121 
   117 public:
   122 public:
   118 
   123 
   119 	YAMLCommand() {
   124 	YAMLCommand() {
   123 	}
   128 	}
   124 
   129 
   125 	void process(std::istream& input, std::shared_ptr<relpipe::writer::RelationalWriter> writer) {
   130 	void process(std::istream& input, std::shared_ptr<relpipe::writer::RelationalWriter> writer) {
   126 		parser.setInput(&input);
   131 		parser.setInput(&input);
   127 
   132 
       
   133 		relpipe::writer::string_t relationName;
       
   134 		std::vector<relpipe::writer::string_t> record;
   128 		std::vector<relpipe::writer::AttributeMetadata> attributesMetadata;
   135 		std::vector<relpipe::writer::AttributeMetadata> attributesMetadata;
   129 		attributesMetadata.push_back(relpipe::writer::AttributeMetadata{L"todo", relpipe::writer::TypeId::STRING});
       
   130 		writer->startRelation(L"YAML", attributesMetadata, true);
       
   131 
   136 
   132 		mode.push_back(Mode::ROOT);
   137 		state = State::START;
   133 		std::string itemName;
       
   134 
   138 
   135 		writer->writeAttribute(L"before cycle");
       
   136 		for (YAMLEvent_p event = YAMLEvent_p(parser.next()); event; event = YAMLEvent_p(parser.next())) {
   139 		for (YAMLEvent_p event = YAMLEvent_p(parser.next()); event; event = YAMLEvent_p(parser.next())) {
   137 
   140 			if (event->getType() == YAML_NO_EVENT) {
   138 			if (event->getType() == YAML_NO_EVENT) { writer->writeAttribute(L"YAML_NO_EVENT");
   141 				throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: YAML_NO_EVENT");
   139 			} else if (event->getType() == YAML_STREAM_START_EVENT) { writer->writeAttribute(L"YAML_STREAM_START_EVENT");
   142 			} else if (event->getType() == YAML_STREAM_START_EVENT) {
   140 			} else if (event->getType() == YAML_STREAM_END_EVENT) { writer->writeAttribute(L"YAML_STREAM_END_EVENT");
   143 			} else if (event->getType() == YAML_STREAM_END_EVENT) {
   141 			} else if (event->getType() == YAML_DOCUMENT_START_EVENT) { writer->writeAttribute(L"YAML_DOCUMENT_START_EVENT");
   144 			} else if (event->getType() == YAML_DOCUMENT_START_EVENT) {
   142 			} else if (event->getType() == YAML_DOCUMENT_END_EVENT) { writer->writeAttribute(L"YAML_DOCUMENT_END_EVENT");
   145 			} else if (event->getType() == YAML_DOCUMENT_END_EVENT) {
   143 			} else if (event->getType() == YAML_ALIAS_EVENT) { writer->writeAttribute(L"YAML_ALIAS_EVENT");
   146 			} else if (event->getType() == YAML_ALIAS_EVENT) {
   144 			} else if (event->getType() == YAML_SCALAR_EVENT) { writer->writeAttribute(L"YAML_SCALAR_EVENT");
   147 			} else if (event->getType() == YAML_SCALAR_EVENT) {
   145 			} else if (event->getType() == YAML_SEQUENCE_START_EVENT) { writer->writeAttribute(L"YAML_SEQUENCE_START_EVENT");
   148 				relpipe::writer::string_t scalarValue = y2s(event->getEvent()->data.scalar.value);
   146 			} else if (event->getType() == YAML_SEQUENCE_END_EVENT) { writer->writeAttribute(L"YAML_SEQUENCE_END_EVENT");
   149 				if (state == State::RELATIONS) relationName = scalarValue;
   147 			} else if (event->getType() == YAML_MAPPING_START_EVENT) { writer->writeAttribute(L"YAML_MAPPING_START_EVENT");
   150 				else if (state == State::ATTRIBUTE) record.push_back(scalarValue);
   148 			} else if (event->getType() == YAML_MAPPING_END_EVENT) { writer->writeAttribute(L"YAML_MAPPING_END_EVENT");
   151 				else throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: unexpected YAML_SCALAR_EVENT");
   149 			} else { writer->writeAttribute(L"else???");
   152 			} else if (event->getType() == YAML_SEQUENCE_START_EVENT) {
   150 				// TODO: unsupported type?
   153 				if (state == State::RELATIONS) state = State::RECORDS;
       
   154 				else throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: unexpected YAML_SEQUENCE_START_EVENT");
       
   155 			} else if (event->getType() == YAML_SEQUENCE_END_EVENT) {
       
   156 				if (state == State::RECORDS) {
       
   157 					state = State::RELATIONS;
       
   158 					relationName.clear();
       
   159 					attributesMetadata.clear();
       
   160 				} else {
       
   161 					throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: unexpected YAML_SEQUENCE_END_EVENT");
       
   162 				}
       
   163 			} else if (event->getType() == YAML_MAPPING_START_EVENT) {
       
   164 				if (state == State::START) state = State::RELATIONS;
       
   165 				else if (state == State::RECORDS) state = State::ATTRIBUTE;
       
   166 				else if (state == State::RELATIONS) throw relpipe::writer::RelpipeWriterException(L"Not yet implemented"); // TODO: there might be also a map in the relation value (not only a sequence) that would contain metadata (i.e. data types + support for relation containing no records)
       
   167 				else throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: unexpected YAML_MAPPING_START_EVENT");
       
   168 			} else if (event->getType() == YAML_MAPPING_END_EVENT) {
       
   169 				if (state == State::ATTRIBUTE) {
       
   170 					if (attributesMetadata.size() == 0) {
       
   171 						if (record.size() % 2) relpipe::writer::RelpipeWriterException(L"Invalid count of values in the record vector");
       
   172 						for (size_t i = 0; i < record.size(); i += 2) attributesMetadata.push_back(relpipe::writer::AttributeMetadata{record[i], relpipe::writer::TypeId::STRING});
       
   173 						writer->startRelation(relationName, attributesMetadata, true);
       
   174 					}
       
   175 					for (auto m : attributesMetadata) writer->writeAttribute(findValue(record, m.attributeName));
       
   176 					record.clear();
       
   177 					state = State::RECORDS;
       
   178 				} else if (state == State::RELATIONS) {
       
   179 					break; // map of the relations ends (root)
       
   180 				} else {
       
   181 					throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: unexpected YAML_MAPPING_END_EVENT");
       
   182 				}
       
   183 			} else {
       
   184 				throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: unknown event: " + std::to_wstring(event->getType()));
   151 			}
   185 			}
   152 		}
   186 		}
   153 		writer->writeAttribute(L"after cycle");
       
   154 	}
   187 	}
   155 };
   188 };
   156 
   189 
   157 }
   190 }
   158 }
   191 }