--- a/src/YAMLCommand.h Thu Dec 03 17:16:09 2020 +0100
+++ b/src/YAMLCommand.h Thu Dec 03 22:31:03 2020 +0100
@@ -32,7 +32,7 @@
class YAMLCommand {
private:
- std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
+ std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // YAML strings are in UTF-8
class YAMLEvent {
private:
@@ -98,20 +98,25 @@
using YAMLEvent_p = std::shared_ptr<YAMLEvent>;
- enum class Mode {
- ROOT,
- RELATIONS_SEQUENCE,
- MAPPING,
- MAP_KEY
+ enum class State {
+ START,
+ RELATIONS,
+ ATTRIBUTE,
+ RECORDS
};
- std::vector<Mode> mode;
+ State state;
+
+ relpipe::writer::string_t y2s(yaml_char_t* value) {
+ return value ? convertor.from_bytes((const char*) value) : L"";
+ }
- /**
- * Both YAML and XML strings are in UTF-8.
- */
- const char* y2x(yaml_char_t* value) {
- return value ? (const char*) value : "";
+ relpipe::writer::string_t findValue(std::vector<relpipe::writer::string_t> record, relpipe::writer::string_t key) {
+ if (record.size() % 2) relpipe::writer::RelpipeWriterException(L"Invalid count of values in the record vector");
+ for (size_t i = 0; i < record.size(); i += 2) {
+ if (record[i] == key) return record[i + 1];
+ }
+ return L"";
}
public:
@@ -125,32 +130,60 @@
void process(std::istream& input, std::shared_ptr<relpipe::writer::RelationalWriter> writer) {
parser.setInput(&input);
+ relpipe::writer::string_t relationName;
+ std::vector<relpipe::writer::string_t> record;
std::vector<relpipe::writer::AttributeMetadata> attributesMetadata;
- attributesMetadata.push_back(relpipe::writer::AttributeMetadata{L"todo", relpipe::writer::TypeId::STRING});
- writer->startRelation(L"YAML", attributesMetadata, true);
- mode.push_back(Mode::ROOT);
- std::string itemName;
-
- writer->writeAttribute(L"before cycle");
- for (YAMLEvent_p event = YAMLEvent_p(parser.next()); event; event = YAMLEvent_p(parser.next())) {
+ state = State::START;
- if (event->getType() == YAML_NO_EVENT) { writer->writeAttribute(L"YAML_NO_EVENT");
- } else if (event->getType() == YAML_STREAM_START_EVENT) { writer->writeAttribute(L"YAML_STREAM_START_EVENT");
- } else if (event->getType() == YAML_STREAM_END_EVENT) { writer->writeAttribute(L"YAML_STREAM_END_EVENT");
- } else if (event->getType() == YAML_DOCUMENT_START_EVENT) { writer->writeAttribute(L"YAML_DOCUMENT_START_EVENT");
- } else if (event->getType() == YAML_DOCUMENT_END_EVENT) { writer->writeAttribute(L"YAML_DOCUMENT_END_EVENT");
- } else if (event->getType() == YAML_ALIAS_EVENT) { writer->writeAttribute(L"YAML_ALIAS_EVENT");
- } else if (event->getType() == YAML_SCALAR_EVENT) { writer->writeAttribute(L"YAML_SCALAR_EVENT");
- } else if (event->getType() == YAML_SEQUENCE_START_EVENT) { writer->writeAttribute(L"YAML_SEQUENCE_START_EVENT");
- } else if (event->getType() == YAML_SEQUENCE_END_EVENT) { writer->writeAttribute(L"YAML_SEQUENCE_END_EVENT");
- } else if (event->getType() == YAML_MAPPING_START_EVENT) { writer->writeAttribute(L"YAML_MAPPING_START_EVENT");
- } else if (event->getType() == YAML_MAPPING_END_EVENT) { writer->writeAttribute(L"YAML_MAPPING_END_EVENT");
- } else { writer->writeAttribute(L"else???");
- // TODO: unsupported type?
+ for (YAMLEvent_p event = YAMLEvent_p(parser.next()); event; event = YAMLEvent_p(parser.next())) {
+ if (event->getType() == YAML_NO_EVENT) {
+ throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: YAML_NO_EVENT");
+ } else if (event->getType() == YAML_STREAM_START_EVENT) {
+ } else if (event->getType() == YAML_STREAM_END_EVENT) {
+ } else if (event->getType() == YAML_DOCUMENT_START_EVENT) {
+ } else if (event->getType() == YAML_DOCUMENT_END_EVENT) {
+ } else if (event->getType() == YAML_ALIAS_EVENT) {
+ } else if (event->getType() == YAML_SCALAR_EVENT) {
+ relpipe::writer::string_t scalarValue = y2s(event->getEvent()->data.scalar.value);
+ if (state == State::RELATIONS) relationName = scalarValue;
+ else if (state == State::ATTRIBUTE) record.push_back(scalarValue);
+ else throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: unexpected YAML_SCALAR_EVENT");
+ } else if (event->getType() == YAML_SEQUENCE_START_EVENT) {
+ if (state == State::RELATIONS) state = State::RECORDS;
+ else throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: unexpected YAML_SEQUENCE_START_EVENT");
+ } else if (event->getType() == YAML_SEQUENCE_END_EVENT) {
+ if (state == State::RECORDS) {
+ state = State::RELATIONS;
+ relationName.clear();
+ attributesMetadata.clear();
+ } else {
+ throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: unexpected YAML_SEQUENCE_END_EVENT");
+ }
+ } else if (event->getType() == YAML_MAPPING_START_EVENT) {
+ if (state == State::START) state = State::RELATIONS;
+ else if (state == State::RECORDS) state = State::ATTRIBUTE;
+ 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)
+ else throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: unexpected YAML_MAPPING_START_EVENT");
+ } else if (event->getType() == YAML_MAPPING_END_EVENT) {
+ if (state == State::ATTRIBUTE) {
+ if (attributesMetadata.size() == 0) {
+ if (record.size() % 2) relpipe::writer::RelpipeWriterException(L"Invalid count of values in the record vector");
+ for (size_t i = 0; i < record.size(); i += 2) attributesMetadata.push_back(relpipe::writer::AttributeMetadata{record[i], relpipe::writer::TypeId::STRING});
+ writer->startRelation(relationName, attributesMetadata, true);
+ }
+ for (auto m : attributesMetadata) writer->writeAttribute(findValue(record, m.attributeName));
+ record.clear();
+ state = State::RECORDS;
+ } else if (state == State::RELATIONS) {
+ break; // map of the relations ends (root)
+ } else {
+ throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: unexpected YAML_MAPPING_END_EVENT");
+ }
+ } else {
+ throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: unknown event: " + std::to_wstring(event->getType()));
}
}
- writer->writeAttribute(L"after cycle");
}
};