Skip to content

Commit 46ac156

Browse files
committed
Added support for top level arrays, conditions, and 3 space vectors
1 parent 2a44add commit 46ac156

File tree

2 files changed

+399
-36
lines changed

2 files changed

+399
-36
lines changed

src/mtconnect/pipeline/json_mapper.cpp

+203-31
Original file line numberDiff line numberDiff line change
@@ -159,46 +159,91 @@ namespace mtconnect::pipeline {
159159
Forward m_forward;
160160
};
161161

162-
const static map<std::string_view,KeyToken> ConditionMap {
163-
{ "nativeCode", KeyToken::NATIVE_CODE },
164-
{ "conditionId", KeyToken::CONDITION_ID },
165-
{ "qualifier", KeyToken::QUALIFIER },
166-
{ "nativeSeverity", KeyToken::NATIVE_SEVERITY },
167-
{ "level", KeyToken::LEVEL },
168-
{ "value", KeyToken::VALUE },
169-
{ "message", KeyToken::VALUE },
170-
};
171-
172-
/// @brief SAX Parser handler for JSON Parsing
173-
struct FieldHandler : rj::BaseReaderHandler<rj::UTF8<>, FieldHandler>
162+
struct VectorHandler : rj::BaseReaderHandler<rj::UTF8<>, VectorHandler>
174163
{
175-
FieldHandler(ParserContext &context)
176-
: m_context(context)
164+
VectorHandler(entity::Vector &vector)
165+
: m_value(vector)
177166
{
178167
}
179168

180169
bool Null()
181170
{
182-
m_context.m_value = "UNAVAILABLE";
171+
return true;
172+
}
173+
174+
bool Int(int i) { return Double(i); }
175+
bool Uint(unsigned i) { return Double(i); }
176+
bool Int64(int64_t i) { return Double(i); }
177+
bool Uint64(uint64_t i) { return Double(i); }
178+
179+
bool Double(double d)
180+
{
181+
m_value.push_back(d);
182+
return true;
183+
}
184+
185+
bool Default()
186+
{
187+
LOG(warning) << "Invalid vector value, expected only doubles";
188+
return false;
189+
}
190+
191+
bool EndArray(rj::SizeType count)
192+
{
193+
m_done = true;
194+
if (m_value.size() != count)
195+
{
196+
LOG(warning) << "Invalid array of values, size: " << m_value.size()
197+
<< ", expected: " << count;
198+
return false;
199+
}
200+
return true;
201+
}
202+
203+
bool operator()(rj::Reader &reader, rj::StringStream &buff)
204+
{
205+
while (!reader.IterativeParseComplete() && !m_done)
206+
{
207+
if (!reader.IterativeParseNext<rj::kParseNanAndInfFlag>(buff, *this))
208+
{
209+
LOG(warning) << "Cannot parse double vector";
210+
m_value.clear();
211+
return false;
212+
}
213+
}
214+
215+
return true;
216+
}
217+
218+
entity::Vector &m_value;
219+
bool m_done { false };
220+
};
221+
222+
/// @brief SAX Parser handler for JSON Parsing
223+
struct ValueHandler : rj::BaseReaderHandler<rj::UTF8<>, ValueHandler>
224+
{
225+
bool Null()
226+
{
227+
m_value.emplace<nullptr_t>();
183228
return true;
184229
}
185230

186231
bool Bool(bool b)
187232
{
188-
m_context.m_value = b;
233+
m_value.emplace<bool>(b);
189234
return true;
190235
}
191236
bool Int(int i) { return Int64(i); }
192237
bool Uint(unsigned i) { return Int64(i); }
238+
bool Uint64(uint64_t i) { return Int64(i); }
193239
bool Int64(int64_t i)
194240
{
195-
m_context.m_value = i;
241+
m_value.emplace<int64_t>(i);
196242
return true;
197243
}
198-
bool Uint64(uint64_t i) { return Int64(i); }
199-
bool Double(double d)
244+
bool Double(double d)
200245
{
201-
m_context.m_value = d;
246+
m_value.emplace<double>(d);
202247
return true;
203248
}
204249
bool RawNumber(const Ch *str, rj::SizeType length, bool copy)
@@ -207,29 +252,127 @@ namespace mtconnect::pipeline {
207252
}
208253
bool String(const Ch *str, rj::SizeType length, bool copy)
209254
{
210-
m_context.m_value = std::string(str, length);
255+
m_value.emplace<std::string>(str, length);
211256
return true;
212257
}
213258
bool StartObject()
214259
{
260+
// We use an entity pointer to signal we have a property set.
261+
// The PropertiesHandler will map each of the properties in the object
262+
// to the properties.
263+
m_value.emplace<EntityPtr>();
215264
return true;
216265
}
217266
bool Key(const Ch *str, rj::SizeType length, bool copy)
218267
{
219268
return false;
220269
}
221270
bool EndObject(rj::SizeType memberCount) { return true; }
222-
bool StartArray() { return true; }
223-
bool EndArray(rj::SizeType elementCount) { return true; }
271+
bool StartArray()
272+
{
273+
m_value.emplace<Vector>();
274+
return true;
275+
}
276+
bool EndArray(rj::SizeType elementCount)
277+
{
278+
return false;
279+
}
224280

225-
bool operator()(rj::Reader &reader, rj::StringStream &buff)
281+
entity::Value operator()(rj::Reader &reader, rj::StringStream &buff)
226282
{
227283
auto success = (!reader.IterativeParseComplete() &&
228284
reader.IterativeParseNext<rj::kParseNanAndInfFlag>(buff, *this));
229-
return success;
285+
if (!success)
286+
{
287+
LOG(warning) << "Cannot get value for json mapper";
288+
m_value = monostate();
289+
}
290+
else if (holds_alternative<Vector>(m_value))
291+
{
292+
VectorHandler handler(get<Vector>(m_value));
293+
handler(reader, buff);
294+
}
295+
return m_value;
230296
}
231297

232-
ParserContext &m_context;
298+
entity::Value m_value { std::monostate() };
299+
bool m_done { true };
300+
};
301+
302+
const static map<std::string_view, std::string_view> PropertyMap {
303+
{ "value", "VALUE" },
304+
{ "message", "VALUE" }
305+
};
306+
307+
struct PropertiesHandler : rj::BaseReaderHandler<rj::UTF8<>, PropertiesHandler>
308+
{
309+
PropertiesHandler(entity::Properties &props)
310+
: m_props(props)
311+
{
312+
}
313+
314+
bool Default()
315+
{
316+
LOG(warning) << "Expecting an object with keys and values";
317+
return false;
318+
}
319+
320+
321+
bool Key(const Ch *str, rj::SizeType length, bool copy)
322+
{
323+
std::string_view sv(str, length);
324+
auto f = PropertyMap.find(sv);
325+
if (f != PropertyMap.end())
326+
{
327+
m_key = f->second;
328+
}
329+
else
330+
{
331+
m_key = sv;
332+
}
333+
334+
return true;
335+
}
336+
337+
bool StartObject()
338+
{
339+
LOG(warning) << "Expecting not expecting sub-objects";
340+
return false;
341+
}
342+
343+
bool EndObject(rj::SizeType memberCount)
344+
{
345+
m_done = true;
346+
return true;
347+
}
348+
349+
bool operator()(rj::Reader &reader, rj::StringStream &buff)
350+
{
351+
while (!reader.IterativeParseComplete() && !m_done)
352+
{
353+
if (!reader.IterativeParseNext<rj::kParseNanAndInfFlag>(buff, *this))
354+
return false;
355+
else if (m_done)
356+
break;
357+
358+
ValueHandler handler;
359+
auto value = handler(reader, buff);
360+
if (!std::holds_alternative<std::monostate>(value) && !m_key.empty())
361+
{
362+
m_props.insert_or_assign(m_key, value);
363+
}
364+
else
365+
{
366+
LOG(warning) << "Could not map " << m_key;
367+
}
368+
}
369+
370+
return true;
371+
}
372+
373+
entity::Properties &m_props;
374+
bool m_done { false };
375+
std::string m_key;
233376
};
234377

235378
struct DataItemHandler : rj::BaseReaderHandler<rj::UTF8<>, DataItemHandler>
@@ -319,6 +462,7 @@ namespace mtconnect::pipeline {
319462
: m_context(context)
320463
{
321464
}
465+
322466

323467
bool Default()
324468
{
@@ -427,9 +571,28 @@ namespace mtconnect::pipeline {
427571

428572
default:
429573
{
430-
FieldHandler handler(m_context);
431-
if (!handler(reader, buff))
574+
ValueHandler handler;
575+
auto value = handler(reader, buff);
576+
if (std::holds_alternative<std::monostate>(value))
432577
return false;
578+
else if (std::holds_alternative<EntityPtr>(value))
579+
{
580+
PropertiesHandler props(m_context.m_props);
581+
if (!props(reader, buff))
582+
return false;
583+
auto value = m_context.m_props.find("VALUE");
584+
if (value == m_context.m_props.end() && holds_alternative<monostate>(value->second))
585+
{
586+
LOG(warning) << "value was not given for data item " << m_context.m_dataItem->getId();
587+
return false;
588+
}
589+
m_context.m_value = value->second;
590+
m_context.m_props.erase(value);
591+
}
592+
else
593+
{
594+
m_context.m_value = value;
595+
}
433596
m_context.send();
434597
break;
435598
}
@@ -461,13 +624,17 @@ namespace mtconnect::pipeline {
461624
}
462625
bool EndObject(rj::SizeType memberCount)
463626
{
464-
m_context.m_state = ParserState::NONE;
627+
return true;
628+
}
629+
bool EndArray(rj::SizeType memberCount)
630+
{
631+
m_complete = true;
465632
return true;
466633
}
467634

468635
bool operator()(rj::Reader &reader, rj::StringStream &buff)
469636
{
470-
while (!reader.IterativeParseComplete())
637+
while (!reader.IterativeParseComplete() && !m_complete)
471638
{
472639
if (!reader.IterativeParseNext<rj::kParseNanAndInfFlag>(buff, *this))
473640
return false;
@@ -480,6 +647,7 @@ namespace mtconnect::pipeline {
480647
else
481648
{
482649
LOG(warning) << "Only objects allowed as members of top level array";
650+
return false;
483651
}
484652
}
485653

@@ -508,7 +676,11 @@ namespace mtconnect::pipeline {
508676
return true;
509677
}
510678
bool EndObject(rj::SizeType memberCount) { return true; }
511-
bool StartArray() { return true; }
679+
bool StartArray()
680+
{
681+
m_state = ParserState::ARRAY;
682+
return true;
683+
}
512684
bool EndArray(rj::SizeType elementCount) { return true; }
513685

514686
bool operator()(rj::Reader &reader, rj::StringStream &buff)

0 commit comments

Comments
 (0)