Skip to content

Commit d95afa1

Browse files
author
Andres Sevillano
committed
Working with c++ struct
1 parent 3be9da8 commit d95afa1

File tree

7 files changed

+131
-12
lines changed

7 files changed

+131
-12
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ rectangle BackendServer {
7070
(file\nread) .> (structured\ndata)
7171
BD -- (adding\ngeneric\nformat info)
7272
(structured\ndata) .> (adding\ngeneric\nformat info)
73-
(adding\ngeneric\nformat info) .> (MARKDOWN/TEXT)
73+
(adding\ngeneric\nformat info) .> (SIMPLY HTML)
7474
}
7575
7676
cloud FileSystem {
@@ -79,7 +79,7 @@ cloud FileSystem {
7979
8080
8181
rectangle FrontendServer {
82-
(MARKDOWN/TEXT) .> (choose specific\nCSS)
82+
(SIMPLY HTML) .> (choose specific\nCSS)
8383
(user output\nHTML\CSS) .> Customer
8484
(apply chosen format) .> (user output\nHTML\CSS)
8585
(choose specific\nCSS) .> (apply chosen format)

images/diagram.png

0 Bytes
Loading

images/json.png

-763 Bytes
Loading

include/boilerplateCodeDoc.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ namespace boilerplateCodeDoc {
9494
struct JsonSchema2HTML final: public JsonSchemaFilter {
9595

9696
///@brief Default CSS id
97-
static constexpr const char* const CSS_CLASS {"boilerplate"};
97+
static constexpr const char* const CSS_CLASS {"boilerplateExample"};
9898

9999
///@brief Default HTML head+body header
100100
static constexpr const char* const HEADER {R"(
@@ -110,7 +110,7 @@ namespace boilerplateCodeDoc {
110110
padding: 5px;
111111
text-align: left;
112112
}
113-
table.boilerplate {
113+
table.boilerplateExample {
114114
width: 90%;
115115
margin-left: auto;
116116
margin-right: auto;
@@ -160,6 +160,24 @@ namespace boilerplateCodeDoc {
160160
std::string css_class {};
161161
};
162162

163+
/// @brief Specific handler to generate HTML tables.
164+
/// @remark Style will be provided by CSS if needed.
165+
struct JsonSchema2CPP final: public JsonSchemaFilter {
166+
167+
static constexpr const char* const NAMESPACE {"boilerplateExample"};
168+
static constexpr const char* const HEADER {""};
169+
static constexpr const char* const FOOTER {""};
170+
171+
///@brief simplest constructor
172+
JsonSchema2CPP(std::string header_ = HEADER, std::string footer_ = FOOTER, std::string namespace_id_ = NAMESPACE) :
173+
JsonSchemaFilter(header_, footer_), namespace_id{std::move(namespace_id_)} {}
174+
175+
///@brief filter to apply
176+
bool operator()(const JsonSchema& jsonSchema) override;
177+
178+
///@brief namespace to isolate autogenerated code
179+
std::string namespace_id {};
180+
};
163181
} // namespace
164182

165183
#endif // header

json/schema.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,23 @@
33
"title": "Complex Json Schema example",
44
"description": "version 0.0.1",
55
"type": "object",
6+
"metatype": "struct Data",
67
"properties": {
78
"test": {
89
"type": "integer",
10+
"metatype": "unsigned int",
911
"minimum": 0,
1012
"maximum": 1,
1113
"default": 0
1214
},
1315
"id": {
14-
"type": "string"
16+
"type": "string",
17+
"metatype": "std::string"
1518
},
1619
"imp": {
1720
"description": "Impressions rock",
1821
"type": "array",
1922
"metatype": "std::vector<Impression>",
20-
"metainfo": "implemented",
2123
"bookmarkSource": "#impression",
2224
"items": {
2325
"title": "Impression",

src/boilerplateCodeDoc.cpp

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,14 @@ struct Property {
142142
std::string title {};
143143
std::string parentTitle {};
144144
std::string metatype {};
145+
std::string parentMetatype {};
145146
std::string metainfo {};
146147
std::string bookmark_source {};
147148
std::string bookmark_target {};
148149
Property(bool req, std::string sco, std::string nam, std::string typ, std::string des, std::string tit,
149-
std::string par, std::string met, std::string inf, std::string bs, std::string bt)
150+
std::string par, std::string met, std::string pm, std::string inf, std::string bs, std::string bt)
150151
: required{req}, scope{std::move(sco)}, name{std::move(nam)}, type{std::move(typ)}, description{std::move(des)}, title{std::move(tit)},
151-
parentTitle{std::move(par)}, metatype{std::move(met)}, metainfo{std::move(inf)},
152+
parentTitle{std::move(par)}, metatype{std::move(met)}, parentMetatype{std::move(pm)}, metainfo{std::move(inf)},
152153
bookmark_source{std::move(bs)}, bookmark_target{std::move(bt)} {}
153154
};
154155
using Properties = std::map<std::string, Property>;
@@ -248,8 +249,10 @@ static void SetProperties(const rapidjson::Document& document, std::string eleme
248249
getString(document, element, "/properties/", name, "/title", title);
249250
std::string parentTitle {}; // optional
250251
getString(document, element, "", "", "/title", parentTitle);
251-
std::string metatype {}; // optional
252-
getString(document, element, "/properties/", name, "/metatype", metatype);
252+
std::string parentMetatype {}; // required
253+
if(not getString(document, element, "", "", "/metatype", parentMetatype)) { continue; }
254+
std::string metatype {}; // required
255+
if(not getString(document, element, "/properties/", name, "/metatype", metatype)) { continue; }
253256
std::string metainfo {}; // optional
254257
getString(document, element, "/properties/", name, "/metainfo", metainfo);
255258
std::string scope {}; // optional
@@ -259,7 +262,7 @@ static void SetProperties(const rapidjson::Document& document, std::string eleme
259262
std::string bookmark_target {}; // optional
260263
getString(document, element, "", "", "/bookmarkTarget", bookmark_target);
261264
properties.emplace(std::make_pair(name, Property{false, scope, name, type, description, title,
262-
parentTitle, metatype, metainfo, bookmark_source, bookmark_target}));
265+
parentTitle, metatype, parentMetatype, metainfo, bookmark_source, bookmark_target}));
263266
}
264267

265268
nextElement = element + "/properties/"; // recursive call
@@ -277,6 +280,8 @@ static void SetProperties(const rapidjson::Document& document, std::string eleme
277280
getString(document, element, "/items/properties/", name, "/title", title);
278281
std::string parentTitle {}; // optional
279282
getString(document, element, "/items", "", "/title", parentTitle);
283+
std::string parentMetatype {}; // optional
284+
getString(document, element, "/items", "", "/metatype", parentMetatype);
280285
std::string metatype {}; // optional
281286
getString(document, element, "/items/properties/", name, "/metatype", metatype);
282287
std::string metainfo {}; // optional
@@ -288,7 +293,7 @@ static void SetProperties(const rapidjson::Document& document, std::string eleme
288293
std::string bookmark_target {}; // optional
289294
getString(document, element, "/items", "", "/bookmarkTarget", bookmark_target);
290295
properties.emplace(std::make_pair(name, Property{false, scope, name, type, description, title,
291-
parentTitle, metatype, metainfo, bookmark_source, bookmark_target}));
296+
parentTitle, metatype, parentMetatype, metainfo, bookmark_source, bookmark_target}));
292297
}
293298

294299
nextElement = element + "/items/properties/"; // recursive call
@@ -401,3 +406,70 @@ bool boilerplateCodeDoc::JsonSchema2HTML::operator()(const boilerplateCodeDoc::J
401406
return false;
402407
}
403408
}
409+
410+
/****************************************************************************************/
411+
/****************************************************************************************/
412+
/****************************************************************************************/
413+
/*********************** ACTUAL LOGIC CODE **********************************************/
414+
/****************************************************************************************/
415+
/****************************************************************************************/
416+
/****************************************************************************************/
417+
418+
static lambda_t cpp = [](const Properties& properties, std::string& filtered, std::string& namespace_id)
419+
{
420+
if(properties.size() > 0) {
421+
422+
// supposed metatype is a must
423+
std::string parentMetatype {};
424+
if( properties.size() > 0) {
425+
parentMetatype = properties.begin()->second.parentMetatype;
426+
}
427+
if( parentMetatype.empty() ) { return; } // required
428+
429+
for(const auto& p : properties) {
430+
431+
std::string metatype {p.second.metatype};
432+
if( metatype.empty() ) { return; } // required
433+
434+
filtered += "\nparentMetatype: " + p.second.parentMetatype;
435+
filtered += "\nname: " + p.second.name;
436+
filtered += "\nmetatype: " + p.second.metatype;
437+
filtered += "\ndescription: " + p.second.description;
438+
filtered += "\n\n";
439+
}
440+
441+
}
442+
};
443+
444+
bool boilerplateCodeDoc::JsonSchema2CPP::operator()(const boilerplateCodeDoc::JsonSchema& jsonSchema)
445+
{
446+
if( not jsonSchema.document_ptr ) {
447+
error = boilerplateCodeDoc::ParseErrorCode::ERROR_PARSING_SCHEMA_JSON;
448+
message = "Empty document pointer";
449+
return false;
450+
}
451+
452+
rapidjson::Document& document {*reinterpret_cast<rapidjson::Document*>(jsonSchema.document_ptr)};
453+
try {
454+
if(document.IsNull() || not document.IsObject() ) {
455+
error = boilerplateCodeDoc::ParseErrorCode::ERROR_PARSING_SCHEMA_JSON;
456+
message = "Root element shouldn't be NULL";
457+
return false;
458+
}
459+
460+
//std::string element {"#/properties/imp/items/properties/native"};
461+
std::string element {"#"};
462+
filtered = header;
463+
SetProperties(document, element, filtered, cpp, namespace_id);
464+
filtered += footer;
465+
466+
error = boilerplateCodeDoc::ParseErrorCode::OK;
467+
message = to_string(error);
468+
return true;
469+
470+
} catch(...) {
471+
error = boilerplateCodeDoc::ParseErrorCode::ERROR_PARSING_SCHEMA_JSON;
472+
message = "Unexpected exception";
473+
return false;
474+
}
475+
}

test/main.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,30 @@ BOOST_AUTO_TEST_CASE( test002 ) {
153153
BOOST_TEST_MESSAGE( "JsonSchema2HTML: " << handler.message << "\n\n" << handler.filtered);
154154
BOOST_CHECK( result );
155155
}
156+
157+
BOOST_AUTO_TEST_CASE( test003 ) {
158+
BOOST_TEST_MESSAGE( "\ntest003: Transform external Json Schema into C++ structure");
159+
160+
// taken for granted that CMake copied default json schema file in the very directory where this test binary is generated
161+
std::string filename{"schema.json"};
162+
std::string binary{boost::unit_test::framework::master_test_suite().argv[0]};
163+
size_t found = binary.find_last_of("/\\");
164+
if( found > 0 ) {
165+
BOOST_TEST_MESSAGE( "found=" << found);
166+
filename = binary.substr(0,found+1) + filename;
167+
}
168+
169+
int argc =boost::unit_test::framework::master_test_suite().argc;
170+
if( argc > 1) {
171+
filename = std::string(boost::unit_test::framework::master_test_suite().argv[1]);
172+
}
173+
BOOST_TEST_MESSAGE( "current binary=" << binary );
174+
BOOST_TEST_MESSAGE( "schema.json=" << filename );
175+
176+
boiler::JsonSchema jsonSchema{filename};
177+
BOOST_TEST_MESSAGE( "Json Schema: " << jsonSchema.message);
178+
boiler::JsonSchema2CPP handler {};
179+
bool result = handler(jsonSchema);
180+
BOOST_TEST_MESSAGE( "JsonSchema2CPP: " << handler.message << "\n\n" << handler.filtered);
181+
BOOST_CHECK( result );
182+
}

0 commit comments

Comments
 (0)