Added complete json generation for class diagrams
This commit is contained in:
@@ -20,6 +20,127 @@
|
||||
|
||||
#include "util/error.h"
|
||||
|
||||
namespace clanguml::common::model {
|
||||
using nlohmann::json;
|
||||
|
||||
void to_json(nlohmann::json &j, const source_location &sl)
|
||||
{
|
||||
j = json{{"file", sl.file()}, {"line", sl.line()}};
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const element &c)
|
||||
{
|
||||
j = json{{"id", std::to_string(c.id())}, {"name", c.name()},
|
||||
{"namespace", c.get_namespace().to_string()}, {"type", c.type_name()},
|
||||
{"display_name", c.full_name(false)}};
|
||||
|
||||
if (!c.file().empty())
|
||||
j["source_location"] =
|
||||
dynamic_cast<const common::model::source_location &>(c);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const template_parameter &c)
|
||||
{
|
||||
j["type"] = c.type();
|
||||
j["name"] = c.name();
|
||||
if (!c.default_value().empty())
|
||||
j["default_value"] = c.default_value();
|
||||
j["is_template_parameter"] = c.is_template_parameter();
|
||||
j["is_template_template_parameter"] = c.is_template_template_parameter();
|
||||
if (c.concept_constraint())
|
||||
j["concept_constraint"] = c.concept_constraint().value();
|
||||
j["is_variadic"] = c.is_variadic();
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const relationship &c)
|
||||
{
|
||||
j["type"] = to_string(c.type());
|
||||
j["destination"] = std::to_string(c.destination());
|
||||
if (!c.multiplicity_source().empty())
|
||||
j["multiplicity_source"] = c.multiplicity_source();
|
||||
if (!c.multiplicity_destination().empty())
|
||||
j["multiplicity_destination"] = c.multiplicity_destination();
|
||||
j["access"] = to_string(c.access());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace clanguml::class_diagram::model {
|
||||
using nlohmann::json;
|
||||
void to_json(nlohmann::json &j, const class_element &c)
|
||||
{
|
||||
j = {{"name", c.name()}, {"type", c.type()},
|
||||
{"access", to_string(c.access())}};
|
||||
if (!c.file().empty())
|
||||
j["source_location"] =
|
||||
dynamic_cast<const common::model::source_location &>(c);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const class_member &c)
|
||||
{
|
||||
j = dynamic_cast<const class_element &>(c);
|
||||
j["is_static"] = c.is_static();
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const method_parameter &c)
|
||||
{
|
||||
j["name"] = c.name();
|
||||
j["type"] = c.type();
|
||||
if (!c.default_value().empty())
|
||||
j["default_value"] = c.default_value();
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const class_method &c)
|
||||
{
|
||||
j["is_static"] = c.is_static();
|
||||
j["is_const"] = c.is_const();
|
||||
j["is_defaulted"] = c.is_defaulted();
|
||||
j["is_pure_virtual"] = c.is_pure_virtual();
|
||||
j["is_virtual"] = c.is_virtual();
|
||||
j["is_implicit"] = c.is_implicit();
|
||||
|
||||
j["parameters"] = c.parameters();
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const class_parent &c)
|
||||
{
|
||||
j["is_virtual"] = c.is_virtual();
|
||||
j["id"] = std::to_string(c.id());
|
||||
j["access"] = to_string(c.access());
|
||||
j["name"] = c.name();
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const class_ &c)
|
||||
{
|
||||
j = dynamic_cast<const common::model::element &>(c);
|
||||
j["is_struct"] = c.is_struct();
|
||||
j["is_abstract"] = c.is_abstract();
|
||||
j["is_union"] = c.is_union();
|
||||
j["is_nested"] = c.is_nested();
|
||||
j["is_template"] = c.is_template();
|
||||
|
||||
j["members"] = c.members();
|
||||
j["methods"] = c.methods();
|
||||
j["bases"] = c.parents();
|
||||
|
||||
j["template_parameters"] = c.templates();
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const enum_ &c)
|
||||
{
|
||||
j = dynamic_cast<const common::model::element &>(c);
|
||||
j["is_nested"] = c.is_nested();
|
||||
j["constants"] = c.constants();
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const concept_ &c)
|
||||
{
|
||||
j = dynamic_cast<const common::model::element &>(c);
|
||||
j["parameters"] = c.requires_parameters();
|
||||
j["statements"] = c.requires_statements();
|
||||
}
|
||||
}
|
||||
|
||||
namespace clanguml::class_diagram::generators::json {
|
||||
|
||||
generator::generator(diagram_config &config, diagram_model &model)
|
||||
@@ -29,32 +150,175 @@ generator::generator(diagram_config &config, diagram_model &model)
|
||||
|
||||
void generator::generate(std::ostream &ostr) const
|
||||
{
|
||||
generate_top_level_elements(ostr);
|
||||
generate_top_level_elements(json_);
|
||||
|
||||
ostr << json_;
|
||||
}
|
||||
|
||||
void generator::generate_top_level_elements(std::ostream &ostr) const
|
||||
void generator::generate_top_level_elements(nlohmann::json &parent) const
|
||||
{
|
||||
for (const auto &p : m_model) {
|
||||
if (auto *cls = dynamic_cast<class_ *>(p.get()); cls) {
|
||||
if (auto *pkg = dynamic_cast<package *>(p.get()); pkg) {
|
||||
if (!pkg->is_empty())
|
||||
generate(*pkg, parent);
|
||||
}
|
||||
else if (auto *cls = dynamic_cast<class_ *>(p.get()); cls) {
|
||||
if (m_model.should_include(*cls)) {
|
||||
generate(*cls, ostr);
|
||||
generate(*cls, parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void generator::generate(const class_ &c, std::ostream & /*ostr*/) const
|
||||
void generator::generate(const package &p, nlohmann::json &parent) const
|
||||
{
|
||||
const auto &uns = m_config.using_namespace();
|
||||
|
||||
nlohmann::json object;
|
||||
object["id"] = std::to_string(c.id());
|
||||
object["name"] = c.name();
|
||||
object["namespace"] = c.get_namespace().to_string();
|
||||
object["type"] = c.type_name();
|
||||
object["display_name"] = c.full_name(false);
|
||||
nlohmann::json package_object;
|
||||
|
||||
if (m_config.generate_packages()) {
|
||||
LOG_DBG("Generating package {}", p.name());
|
||||
|
||||
// Don't generate packages from namespaces filtered out by
|
||||
// using_namespace
|
||||
if (!uns.starts_with({p.full_name(false)})) {
|
||||
package_object["type"] = "namespace";
|
||||
package_object["name"] = p.name();
|
||||
package_object["display_name"] = p.full_name(false);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &subpackage : p) {
|
||||
if (dynamic_cast<package *>(subpackage.get()) != nullptr) {
|
||||
// TODO: add option - generate_empty_packages
|
||||
const auto &sp = dynamic_cast<package &>(*subpackage);
|
||||
if (!sp.is_empty()) {
|
||||
if (m_config.generate_packages())
|
||||
generate(sp, package_object);
|
||||
else
|
||||
generate(sp, parent);
|
||||
}
|
||||
}
|
||||
else if (auto *cls = dynamic_cast<class_ *>(subpackage.get()); cls) {
|
||||
const auto &sp = dynamic_cast<class_ &>(*subpackage);
|
||||
if (m_model.should_include(*subpackage)) {
|
||||
if (m_config.generate_packages())
|
||||
generate(sp, package_object);
|
||||
else
|
||||
generate(sp, parent);
|
||||
}
|
||||
}
|
||||
else if (auto *enm = dynamic_cast<enum_ *>(subpackage.get()); enm) {
|
||||
const auto &sp = dynamic_cast<enum_ &>(*subpackage);
|
||||
if (m_model.should_include(*subpackage)) {
|
||||
if (m_config.generate_packages())
|
||||
generate(sp, package_object);
|
||||
else
|
||||
generate(sp, parent);
|
||||
}
|
||||
}
|
||||
else if (auto *cpt = dynamic_cast<concept_ *>(subpackage.get()); cpt) {
|
||||
const auto &sp = dynamic_cast<concept_ &>(*subpackage);
|
||||
if (m_model.should_include(*subpackage)) {
|
||||
if (m_config.generate_packages())
|
||||
generate(sp, package_object);
|
||||
else
|
||||
generate(sp, parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_config.generate_packages()) {
|
||||
parent["elements"].push_back(std::move(package_object));
|
||||
}
|
||||
}
|
||||
|
||||
void generator::generate(const class_ &c, nlohmann::json &parent) const
|
||||
{
|
||||
nlohmann::json object = c;
|
||||
json_["elements"].push_back(std::move(object));
|
||||
}
|
||||
|
||||
void generator::generate(const enum_ &e, nlohmann::json &parent) const
|
||||
{
|
||||
nlohmann::json object = e;
|
||||
json_["elements"].push_back(std::move(object));
|
||||
}
|
||||
|
||||
void generator::generate(const concept_ &c, nlohmann::json &parent) const
|
||||
{
|
||||
nlohmann::json object = c;
|
||||
json_["elements"].push_back(std::move(object));
|
||||
generate_relationships(json_);
|
||||
}
|
||||
|
||||
void generator::generate_relationships(nlohmann::json &parent) const
|
||||
{
|
||||
for (const auto &p : m_model) {
|
||||
if (auto *pkg = dynamic_cast<package *>(p.get()); pkg) {
|
||||
generate_relationships(*pkg, parent);
|
||||
}
|
||||
else if (auto *cls = dynamic_cast<class_ *>(p.get()); cls) {
|
||||
if (m_model.should_include(*cls)) {
|
||||
generate_relationships(*cls, parent);
|
||||
}
|
||||
}
|
||||
else if (auto *enm = dynamic_cast<enum_ *>(p.get()); enm) {
|
||||
if (m_model.should_include(*enm)) {
|
||||
generate_relationships(*enm, parent);
|
||||
}
|
||||
}
|
||||
else if (auto *cpt = dynamic_cast<concept_ *>(p.get()); cpt) {
|
||||
if (m_model.should_include(*cpt)) {
|
||||
generate_relationships(*cpt, parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void generator::generate_relationships(
|
||||
const class_ &c, nlohmann::json &parent) const
|
||||
{
|
||||
for (const auto &r : c.relationships()) {
|
||||
nlohmann::json rel = r;
|
||||
rel["source"] = std::to_string(c.id());
|
||||
parent["relationships"].push_back(rel);
|
||||
}
|
||||
|
||||
if (m_model.should_include(relationship_t::kExtension)) {
|
||||
for (const auto &b : c.parents()) {
|
||||
common::model::relationship r(
|
||||
relationship_t::kExtension, b.id(), b.access());
|
||||
nlohmann::json rel = r;
|
||||
rel["source"] = std::to_string(c.id());
|
||||
parent["relationships"].push_back(rel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void generator::generate_relationships(
|
||||
const enum_ &c, nlohmann::json &parent) const
|
||||
{
|
||||
for (const auto &r : c.relationships()) {
|
||||
nlohmann::json rel = r;
|
||||
rel["source"] = std::to_string(c.id());
|
||||
parent["relationships"].push_back(rel);
|
||||
}
|
||||
}
|
||||
|
||||
void generator::generate_relationships(
|
||||
const concept_ &c, nlohmann::json &parent) const
|
||||
{
|
||||
for (const auto &r : c.relationships()) {
|
||||
nlohmann::json rel = r;
|
||||
rel["source"] = std::to_string(c.id());
|
||||
parent["relationships"].push_back(rel);
|
||||
}
|
||||
}
|
||||
|
||||
void generator::generate_relationships(
|
||||
const package &p, nlohmann::json &parent) const
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace clanguml::class_diagram::generators::plantuml
|
||||
|
||||
@@ -60,15 +60,30 @@ class generator : public common_generator<diagram_config, diagram_model> {
|
||||
public:
|
||||
generator(diagram_config &config, diagram_model &model);
|
||||
|
||||
void generate(const class_ &c, std::ostream &ostr) const;
|
||||
void generate(const class_ &c, nlohmann::json &parent) const;
|
||||
|
||||
void generate_top_level_elements(std::ostream &ostr) const;
|
||||
void generate(const enum_ &c, nlohmann::json &parent) const;
|
||||
|
||||
void generate(const concept_ &c, nlohmann::json &parent) const;
|
||||
|
||||
void generate(const package &p, nlohmann::json &parent) const;
|
||||
|
||||
void generate_top_level_elements(nlohmann::json &parent) const;
|
||||
|
||||
void generate(std::ostream &ostr) const override;
|
||||
|
||||
private:
|
||||
std::string render_name(std::string name) const;
|
||||
void generate_relationships(nlohmann::json &parent) const;
|
||||
|
||||
void generate_relationships(const class_ &c, nlohmann::json &parent) const;
|
||||
|
||||
void generate_relationships(const enum_ &c, nlohmann::json &parent) const;
|
||||
|
||||
void generate_relationships(
|
||||
const concept_ &c, nlohmann::json &parent) const;
|
||||
|
||||
void generate_relationships(const package &p, nlohmann::json &parent) const;
|
||||
|
||||
private:
|
||||
mutable nlohmann::json json_;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user