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(); |