src/YAMLCommand.h
branchv_0
changeset 5 399380ea9750
parent 4 c176766462c5
child 6 67dc7aaa5ed7
equal deleted inserted replaced
4:c176766462c5 5:399380ea9750
    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 	using string_t = relpipe::writer::string_t;
       
    36 	using RelpipeWriterException = relpipe::writer::RelpipeWriterException;
       
    37 
    35 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // YAML strings are in UTF-8
    38 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // YAML strings are in UTF-8
    36 
    39 
    37 	class YAMLEvent {
    40 	class YAMLEvent {
    38 	private:
    41 	private:
    39 		yaml_event_t event;
    42 		yaml_event_t event;
    48 
    51 
    49 		const yaml_event_type_t getType() const {
    52 		const yaml_event_type_t getType() const {
    50 			return event.type;
    53 			return event.type;
    51 		}
    54 		}
    52 
    55 
    53 		const relpipe::writer::string_t getTypeName() const {
    56 		const string_t getTypeName() const {
    54 			return findTypeName(event.type);
    57 			return findTypeName(event.type);
    55 		}
    58 		}
    56 
    59 
    57 		/** Just for debugging and error handling */
    60 		/** Just for debugging and error handling */
    58 		static const relpipe::writer::string_t findTypeName(const yaml_event_type_t eventType) {
    61 		static const string_t findTypeName(const yaml_event_type_t eventType) {
    59 			if (eventType == YAML_NO_EVENT) return L"NO";
    62 			if (eventType == YAML_NO_EVENT) return L"NO";
    60 			else if (eventType == YAML_STREAM_START_EVENT) return L"STREAM_START";
    63 			else if (eventType == YAML_STREAM_START_EVENT) return L"STREAM_START";
    61 			else if (eventType == YAML_STREAM_END_EVENT) return L"STREAM_END";
    64 			else if (eventType == YAML_STREAM_END_EVENT) return L"STREAM_END";
    62 			else if (eventType == YAML_DOCUMENT_START_EVENT) return L"DOCUMENT_START";
    65 			else if (eventType == YAML_DOCUMENT_START_EVENT) return L"DOCUMENT_START";
    63 			else if (eventType == YAML_DOCUMENT_END_EVENT) return L"DOCUMENT_END";
    66 			else if (eventType == YAML_DOCUMENT_END_EVENT) return L"DOCUMENT_END";
   117 	using YAMLEvent_p = std::shared_ptr<YAMLEvent>;
   120 	using YAMLEvent_p = std::shared_ptr<YAMLEvent>;
   118 
   121 
   119 	YAMLParser parser;
   122 	YAMLParser parser;
   120 	std::shared_ptr<relpipe::writer::RelationalWriter> writer;
   123 	std::shared_ptr<relpipe::writer::RelationalWriter> writer;
   121 
   124 
   122 	relpipe::writer::string_t relationName;
   125 	string_t relationName;
   123 	std::vector<relpipe::writer::string_t> record;
   126 	std::vector<string_t> record;
   124 	std::vector<relpipe::writer::AttributeMetadata> attributesMetadata;
   127 	std::vector<relpipe::writer::AttributeMetadata> attributesMetadata;
   125 
   128 
   126 	relpipe::writer::string_t y2s(const yaml_char_t* value) {
   129 	string_t y2s(const yaml_char_t* value) {
   127 		return value ? convertor.from_bytes((const char*) value) : L"";
   130 		return value ? convertor.from_bytes((const char*) value) : L"";
   128 	}
   131 	}
   129 
   132 
   130 	relpipe::writer::string_t fetchScalarValue(YAMLEvent_p event) {
   133 	string_t fetchScalarValue(YAMLEvent_p event) {
   131 		if (event->getType() == YAML_SCALAR_EVENT) return y2s(event->getEvent()->data.scalar.value);
   134 		if (event->getType() == YAML_SCALAR_EVENT) return y2s(event->getEvent()->data.scalar.value);
   132 		else throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: expected SCALAR but got: " + event->getTypeName());
   135 		else throw RelpipeWriterException(L"Invalid YAML structure: expected SCALAR but got: " + event->getTypeName());
   133 	}
   136 	}
   134 
   137 
   135 	void consumeEvent(const yaml_event_type_t expectedEventType, relpipe::writer::string_t expectedScalarValue = L"") {
   138 	void consumeEvent(const yaml_event_type_t expectedEventType, string_t expectedScalarValue = L"") {
   136 		YAMLEvent_p event = YAMLEvent_p(parser.next());
   139 		YAMLEvent_p event = YAMLEvent_p(parser.next());
   137 		if (!event) throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: missing event: " + YAMLEvent::findTypeName(expectedEventType));
   140 		if (!event) throw RelpipeWriterException(L"Invalid YAML structure: missing event: " + YAMLEvent::findTypeName(expectedEventType));
   138 		if (event->getType() != expectedEventType) throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: expected event: " + YAMLEvent::findTypeName(expectedEventType) + L", but got: " + event->getTypeName());
   141 		if (event->getType() != expectedEventType) throw RelpipeWriterException(L"Invalid YAML structure: expected event: " + YAMLEvent::findTypeName(expectedEventType) + L", but got: " + event->getTypeName());
   139 		if (expectedEventType == YAML_SCALAR_EVENT && expectedScalarValue.size() && expectedScalarValue != fetchScalarValue(event)) throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: expected scalar value: " + expectedScalarValue + L", but got " + fetchScalarValue(event));
   142 		if (expectedEventType == YAML_SCALAR_EVENT && expectedScalarValue.size() && expectedScalarValue != fetchScalarValue(event)) throw RelpipeWriterException(L"Invalid YAML structure: expected scalar value: " + expectedScalarValue + L", but got " + fetchScalarValue(event));
   140 	}
   143 	}
   141 
   144 
   142 	relpipe::writer::string_t consumeScalarEvent() {
   145 	string_t consumeScalarEvent() {
   143 		YAMLEvent_p event = YAMLEvent_p(parser.next());
   146 		YAMLEvent_p event = YAMLEvent_p(parser.next());
   144 		if (event && event->getType() == YAML_SCALAR_EVENT) return fetchScalarValue(event);
   147 		if (event && event->getType() == YAML_SCALAR_EVENT) return fetchScalarValue(event);
   145 		else throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: expected SCALAR, but got: " + event->getTypeName());
   148 		else throw RelpipeWriterException(L"Invalid YAML structure: expected SCALAR, but got: " + event->getTypeName());
   146 	}
   149 	}
   147 
   150 
   148 	bool until(const yaml_event_type_t until, YAMLEvent_p& event) {
   151 	bool until(const yaml_event_type_t until, YAMLEvent_p& event) {
   149 		event = YAMLEvent_p(parser.next());
   152 		event = YAMLEvent_p(parser.next());
   150 		return event && event->getType() != until;
   153 		return event && event->getType() != until;
   152 
   155 
   153 	void processRelation() {
   156 	void processRelation() {
   154 		YAMLEvent_p event = YAMLEvent_p(parser.next());
   157 		YAMLEvent_p event = YAMLEvent_p(parser.next());
   155 		if (event->getType() == YAML_MAPPING_START_EVENT) processRelationWithMetadata();
   158 		if (event->getType() == YAML_MAPPING_START_EVENT) processRelationWithMetadata();
   156 		else if (event->getType() == YAML_SEQUENCE_START_EVENT)processRelationWithoutMetadata();
   159 		else if (event->getType() == YAML_SEQUENCE_START_EVENT)processRelationWithoutMetadata();
   157 		else throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: expected MAPPING or SEQUENCE, but got: " + event->getTypeName());
   160 		else throw RelpipeWriterException(L"Invalid YAML structure: expected MAPPING or SEQUENCE, but got: " + event->getTypeName());
   158 	}
   161 	}
   159 
   162 
   160 	void processRelationWithMetadata() {
   163 	void processRelationWithMetadata() {
   161 		consumeEvent(YAML_SCALAR_EVENT, L"attribute-metadata");
   164 		consumeEvent(YAML_SCALAR_EVENT, L"attribute-metadata");
   162 		consumeEvent(YAML_SEQUENCE_START_EVENT);
   165 		consumeEvent(YAML_SEQUENCE_START_EVENT);
   163 
   166 
   164 		for (YAMLEvent_p event; until(YAML_SEQUENCE_END_EVENT, event);) {
   167 		for (YAMLEvent_p event; until(YAML_SEQUENCE_END_EVENT, event);) {
   165 			if (event->getType() != YAML_MAPPING_START_EVENT) throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: expected MAPPING (attribute-metadata), but got: " + event->getTypeName());
   168 			if (event->getType() != YAML_MAPPING_START_EVENT) throw RelpipeWriterException(L"Invalid YAML structure: expected MAPPING (attribute-metadata), but got: " + event->getTypeName());
   166 			relpipe::writer::string_t name;
   169 			string_t name;
   167 			relpipe::writer::string_t type = L"string";
   170 			string_t type = L"string";
   168 			for (YAMLEvent_p event; until(YAML_MAPPING_END_EVENT, event);) {
   171 			for (YAMLEvent_p event; until(YAML_MAPPING_END_EVENT, event);) {
   169 				auto key = fetchScalarValue(event);
   172 				auto key = fetchScalarValue(event);
   170 				auto value = consumeScalarEvent();
   173 				auto value = consumeScalarEvent();
   171 				if (key == L"name") name = value;
   174 				if (key == L"name") name = value;
   172 				else if (key == L"type") type = value;
   175 				else if (key == L"type") type = value;
   183 			processRecords();
   186 			processRecords();
   184 			consumeEvent(YAML_MAPPING_END_EVENT);
   187 			consumeEvent(YAML_MAPPING_END_EVENT);
   185 		} else if (event->getType() == YAML_MAPPING_END_EVENT) {
   188 		} else if (event->getType() == YAML_MAPPING_END_EVENT) {
   186 			// empty relation, no records
   189 			// empty relation, no records
   187 		} else {
   190 		} else {
   188 			relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: expected 'record' or MAPPING_END, but got: " + event->getTypeName());
   191 			RelpipeWriterException(L"Invalid YAML structure: expected 'record' or MAPPING_END, but got: " + event->getTypeName());
   189 		}
   192 		}
   190 	}
   193 	}
   191 
   194 
   192 	void processRelationWithoutMetadata() {
   195 	void processRelationWithoutMetadata() {
   193 		// First record:
   196 		// First record:
   206 		processRecords();
   209 		processRecords();
   207 	}
   210 	}
   208 
   211 
   209 	void processRecords() {
   212 	void processRecords() {
   210 		for (YAMLEvent_p event; until(YAML_SEQUENCE_END_EVENT, event);) {
   213 		for (YAMLEvent_p event; until(YAML_SEQUENCE_END_EVENT, event);) {
   211 			if (event->getType() != YAML_MAPPING_START_EVENT) throw relpipe::writer::RelpipeWriterException(L"Invalid YAML structure: expected MAPPING (record), but got: " + event->getTypeName());
   214 			if (event->getType() != YAML_MAPPING_START_EVENT) throw RelpipeWriterException(L"Invalid YAML structure: expected MAPPING (record), but got: " + event->getTypeName());
   212 			record.clear();
   215 			record.clear();
   213 			record.resize(attributesMetadata.size());
   216 			record.resize(attributesMetadata.size());
   214 			for (YAMLEvent_p event; until(YAML_MAPPING_END_EVENT, event);) {
   217 			for (YAMLEvent_p event; until(YAML_MAPPING_END_EVENT, event);) {
   215 				auto name = fetchScalarValue(event);
   218 				auto name = fetchScalarValue(event);
   216 				auto value = consumeScalarEvent();
   219 				auto value = consumeScalarEvent();