15 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
15 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 */ |
16 */ |
17 #pragma once |
17 #pragma once |
18 |
18 |
19 #include <relpipe/writer/RelationalWriter.h> |
19 #include <relpipe/writer/RelationalWriter.h> |
|
20 #include <relpipe/writer/RelpipeWriterException.h> |
20 #include "lib/ASN1ContentHandler.h" |
21 #include "lib/ASN1ContentHandler.h" |
21 #include "Configuration.h" |
22 #include "Configuration.h" |
22 |
23 |
23 namespace relpipe { |
24 namespace relpipe { |
24 namespace in { |
25 namespace in { |
27 class RelpipeASN1ContentHandler : public lib::ASN1ContentHandler { |
28 class RelpipeASN1ContentHandler : public lib::ASN1ContentHandler { |
28 private: |
29 private: |
29 wstring_convert < codecvt_utf8<wchar_t>> convertor; // ASN.1 parser works with UTF-8 |
30 wstring_convert < codecvt_utf8<wchar_t>> convertor; // ASN.1 parser works with UTF-8 |
30 std::shared_ptr<relpipe::writer::RelationalWriter> writer; |
31 std::shared_ptr<relpipe::writer::RelationalWriter> writer; |
31 Configuration configuration; |
32 Configuration configuration; |
|
33 |
|
34 relpipe::common::type::StringX currentRelationName; |
|
35 std::vector<relpipe::writer::AttributeMetadata> currentAttributes; |
|
36 |
|
37 enum class State { |
|
38 Start, |
|
39 Relation, |
|
40 RelationName, |
|
41 Header, |
|
42 HeaderItem, |
|
43 AttributeName, |
|
44 AttributeType, |
|
45 Records, |
|
46 Record, |
|
47 Attribute, |
|
48 }; |
|
49 |
|
50 State state = State::Start; |
|
51 |
|
52 void assertTag(const Header& header, uint64_t expectedTag, TagClass expectedClass = TagClass::Universal) { |
|
53 if (header.tagClass != expectedClass || header.tag != expectedTag) throw relpipe::writer::RelpipeWriterException(L"Unexpected tag."); // TODO: add actual vs. expected values |
|
54 } |
32 |
55 |
33 public: |
56 public: |
34 |
57 |
35 RelpipeASN1ContentHandler(std::shared_ptr<relpipe::writer::RelationalWriter> writer, Configuration configuration) : writer(writer), configuration(configuration) { |
58 RelpipeASN1ContentHandler(std::shared_ptr<relpipe::writer::RelationalWriter> writer, Configuration configuration) : writer(writer), configuration(configuration) { |
36 } |
59 } |
44 |
67 |
45 void writeStreamEnd() override { |
68 void writeStreamEnd() override { |
46 } |
69 } |
47 |
70 |
48 void writeCollectionStart(const Header& header) override { |
71 void writeCollectionStart(const Header& header) override { |
|
72 assertTag(header, lib::UniversalType::Sequence); |
|
73 if (state == State::Start) state = State::Relation; |
|
74 else if (state == State::Relation) state = State::RelationName; |
|
75 else if (state == State::Header) state = State::HeaderItem; |
|
76 else if (state == State::HeaderItem) state = State::AttributeName; |
|
77 else if (state == State::Records) state = State::Record; |
|
78 else std::wcerr << L"writeCollectionStart(): state=" << (int) state << std::endl; // TODO: remove |
49 } |
79 } |
50 |
80 |
51 void writeCollectionEnd() override { |
81 void writeCollectionEnd() override { |
|
82 if (state == State::Header) state = State::Records; |
|
83 else if (state == State::AttributeType) state = State::HeaderItem; |
|
84 else if (state == State::HeaderItem) state = State::Records; |
|
85 else if (state == State::Records) state = State::Relation; |
|
86 else if (state == State::Record) state = State::Record; |
|
87 else std::wcerr << L"writeCollectionEnd(): state=" << (int) state << std::endl; // TODO: remove |
|
88 |
|
89 if (state == State::Records) { |
|
90 writer->startRelation(currentRelationName, currentAttributes, true); |
|
91 currentRelationName = L""; |
|
92 currentAttributes.clear(); |
|
93 } |
52 } |
94 } |
53 |
95 |
54 void writeBitString(const Header& header, std::vector<bool> value) override { |
96 void writeBitString(const Header& header, std::vector<bool> value) override { |
55 } |
97 } |
56 |
98 |
57 void writeBoolean(const Header& header, bool value) override { |
99 void writeBoolean(const Header& header, bool value) override { |
|
100 if (state == State::Record) writer->writeAttribute(&value, typeid (value)); |
58 } |
101 } |
59 |
102 |
60 void writeDateTime(const Header& header, DateTime value) override { |
103 void writeDateTime(const Header& header, DateTime value) override { |
61 } |
104 } |
62 |
105 |
63 void writeInteger(const Header& header, Integer value) override { |
106 void writeInteger(const Header& header, Integer value) override { |
|
107 relpipe::common::type::Integer integer = value.toInt64(); |
|
108 if (state == State::Record) writer->writeAttribute(&integer, typeid (integer)); |
64 } |
109 } |
65 |
110 |
66 void writeNull(const Header& header) override { |
111 void writeNull(const Header& header) override { |
67 } |
112 } |
68 |
113 |
71 |
116 |
72 void writeOctetString(const Header& header, std::string value) override { |
117 void writeOctetString(const Header& header, std::string value) override { |
73 } |
118 } |
74 |
119 |
75 void writeTextString(const Header& header, std::string value) override { |
120 void writeTextString(const Header& header, std::string value) override { |
|
121 assertTag(header, lib::UniversalType::UTF8String); |
|
122 relpipe::common::type::StringX str = convertor.from_bytes(value); |
|
123 |
|
124 if (state == State::RelationName) { |
|
125 currentRelationName = convertor.from_bytes(value); |
|
126 state = State::Header; |
|
127 } else if (state == State::AttributeName) { |
|
128 currentAttributes.push_back({str, relpipe::writer::TypeId::STRING}); |
|
129 state = State::AttributeType; |
|
130 } else if (state == State::AttributeType) { |
|
131 currentAttributes.back().typeId = writer->toTypeId(str); |
|
132 } else if (state == State::Record) { |
|
133 writer->writeAttribute(&str, typeid (str)); |
|
134 } else std::wcerr << L"writeTextString(): state=" << (int) state << std::endl; // TODO: remove |
76 } |
135 } |
77 |
136 |
78 void writeSpecific(const Header& header, std::string value) override { |
137 void writeSpecific(const Header& header, std::string value) override { |
79 } |
138 } |
80 |
139 |