This is an automated email from the ASF dual-hosted git repository.

martinzink pushed a commit to branch apache-rusty
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git

commit 6a4c5f7c0f2e67597cec2be30c2d4c68f360793f
Author: Martin Zink <[email protected]>
AuthorDate: Thu Feb 19 16:47:34 2026 +0100

    MINIFICPP-2712 Generate modular docs#2097
---
 minifi_main/AgentDocs.cpp | 224 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 156 insertions(+), 68 deletions(-)

diff --git a/minifi_main/AgentDocs.cpp b/minifi_main/AgentDocs.cpp
index ff37268c9..03951a2f8 100644
--- a/minifi_main/AgentDocs.cpp
+++ b/minifi_main/AgentDocs.cpp
@@ -35,6 +35,7 @@
 #include "range/v3/view/join.hpp"
 #include "range/v3/view/transform.hpp"
 #include "utils/StringUtils.h"
+#include "utils/file/FileUtils.h"
 
 namespace {
 
@@ -42,33 +43,24 @@ namespace minifi = org::apache::nifi::minifi;
 
 std::string formatName(std::string_view name_view, bool is_required) {
   std::string name{name_view};
-  if (is_required) {
-    return "**" + name + "**";
-  } else {
-    return name;
-  }
+  if (is_required) { return "**" + name + "**"; }
+  return name;
 }
 
 std::string formatAllowedValues(const minifi::core::Property& property) {
-  if (property.getValidator().getEquivalentNifiStandardValidatorName() == 
minifi::core::StandardPropertyValidators::BOOLEAN_VALIDATOR.getEquivalentNifiStandardValidatorName())
 {
+  if (property.getValidator().getEquivalentNifiStandardValidatorName() ==
+      
minifi::core::StandardPropertyValidators::BOOLEAN_VALIDATOR.getEquivalentNifiStandardValidatorName())
 {
     return "true<br/>false";
-  } else {
-    const auto allowed_values = property.getAllowedValues();
-    return allowed_values
-        | ranges::views::join(std::string_view{"<br/>"})
-        | ranges::to<std::string>();
   }
+  const auto allowed_values = property.getAllowedValues();
+  return allowed_values | ranges::views::join(std::string_view{"<br/>"}) | 
ranges::to<std::string>();
 }
 
 std::string formatDescription(std::string_view description_view, bool 
is_sensitive = false, bool supports_expression_language = false) {
   std::string description{description_view};
   minifi::utils::string::replaceAll(description, "\n", "<br/>");
-  if (is_sensitive) {
-    description += "<br/>**Sensitive Property: true**";
-  }
-  if (supports_expression_language) {
-    description += "<br/>**Supports Expression Language: true**";
-  }
+  if (is_sensitive) { description += "<br/>**Sensitive Property: true**"; }
+  if (supports_expression_language) { description += "<br/>**Supports 
Expression Language: true**"; }
   return description;
 }
 
@@ -103,7 +95,7 @@ void writeHeader(std::ostream& docs, const 
std::vector<std::pair<std::string, mi
   docs << APACHE_LICENSE;
 
   docs << "\n\n## Table of Contents\n\n";
-  for (const auto& [name, documentation] : class_descriptions) {
+  for (const auto& [name, documentation]: class_descriptions) {
     docs << "- [" << name << "](#" << name << ")\n";
   }
 }
@@ -122,13 +114,11 @@ void writeProperties(std::ostream& docs, const 
minifi::ClassDescription& documen
   docs << "\n\nIn the list below, the names of required properties appear in 
bold. Any other properties (not in bold) are considered optional. "
        << "The table also indicates any default values, and whether a property 
supports the NiFi Expression Language.";
   minifi::docs::Table properties{{"Name", "Default Value", "Allowable Values", 
"Description"}};
-  for (const auto &property : documentation.class_properties_) {
-    properties.addRow({
-        formatName(property.getName(), property.getRequired()),
+  for (const auto& property: documentation.class_properties_) {
+    properties.addRow({formatName(property.getName(), property.getRequired()),
         property.getDefaultValue().value_or(""),
         formatAllowedValues(property),
-        formatDescription(property)
-    });
+        formatDescription(property)});
   }
   docs << "\n\n" << properties.toString();
 }
@@ -138,12 +128,8 @@ void writeDynamicProperties(std::ostream& docs, const 
minifi::ClassDescription&
 
   docs << "\n### Dynamic Properties\n\n";
   minifi::docs::Table dynamic_properties{{"Name", "Value", "Description"}};
-  for (const auto &dynamic_property : documentation.dynamic_properties_) {
-    dynamic_properties.addRow({
-        formatName(dynamic_property.name, false),
-        std::string(dynamic_property.value),
-        formatDescription(dynamic_property)
-    });
+  for (const auto& dynamic_property: documentation.dynamic_properties_) {
+    dynamic_properties.addRow({formatName(dynamic_property.name, false), 
std::string(dynamic_property.value), formatDescription(dynamic_property)});
   }
   docs << dynamic_properties.toString();
 }
@@ -151,7 +137,7 @@ void writeDynamicProperties(std::ostream& docs, const 
minifi::ClassDescription&
 void writeRelationships(std::ostream& docs, const minifi::ClassDescription& 
documentation) {
   docs << "\n### Relationships\n\n";
   minifi::docs::Table relationships{{"Name", "Description"}};
-  for (const auto &rel : documentation.class_relationships_) {
+  for (const auto& rel: documentation.class_relationships_) {
     relationships.addRow({rel.getName(), 
formatDescription(rel.getDescription())});
   }
   docs << relationships.toString();
@@ -162,9 +148,8 @@ void writeOutputAttributes(std::ostream& docs, const 
minifi::ClassDescription& d
 
   docs << "\n### Output Attributes";
   minifi::docs::Table output_attributes{{"Attribute", "Relationship", 
"Description"}};
-  for (const auto &output_attribute : documentation.output_attributes_) {
-    output_attributes.addRow({
-        std::string(output_attribute.name),
+  for (const auto& output_attribute: documentation.output_attributes_) {
+    output_attributes.addRow({std::string(output_attribute.name),
         formatListOfRelationships(output_attribute.relationships),
         formatDescription(output_attribute.description)});
   }
@@ -177,58 +162,161 @@ std::string extractClassName(const std::string& 
full_class_name) {
 
 std::string lowercaseFirst(const std::pair<std::string, 
minifi::ClassDescription>& key_value) {
   return minifi::utils::string::toLower(key_value.first);
-};
+}
 
-}  // namespace
+void writeProcessor(std::ostream& os, const std::string_view name, const 
minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+  writeDynamicProperties(os, documentation);
+  writeRelationships(os, documentation);
+  writeOutputAttributes(os, documentation);
+}
 
-namespace org::apache::nifi::minifi::docs {
+void writeControllerService(std::ostream& os, const std::string_view name, 
const minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+}
 
-void AgentDocs::generate(const std::filesystem::path& docs_dir) {
-  std::vector<std::pair<std::string, minifi::ClassDescription>> 
controller_services;
-  std::vector<std::pair<std::string, minifi::ClassDescription>> processors;
-  std::vector<std::pair<std::string, minifi::ClassDescription>> 
parameter_providers;
+void writeParameterProvider(std::ostream& os, const std::string_view name, 
const minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+}
 
-  for (const auto& [bundle_id, components]: 
ClassDescriptionRegistry::getClassDescriptions()) {
-    for (const auto &controller_service_description : 
components.controller_services) {
+class MonolithDocumentation {
+ public:
+  explicit MonolithDocumentation() {
+    for (const auto& [bundle_id, component]: 
minifi::ClassDescriptionRegistry::getClassDescriptions()) {
+      addComponents(component);
+    }
+    sort();
+  }
+
+  void write(const std::filesystem::path& docs_dir) {
+    std::ofstream controllers_md(docs_dir / "CONTROLLERS.md");
+    std::ofstream processors_md(docs_dir / "PROCESSORS.md");
+    std::ofstream parameter_providers_md(docs_dir / "PARAMETER_PROVIDERS.md");
+    gsl_Assert(controllers_md && processors_md && parameter_providers_md);
+
+    writeControllers(controllers_md);
+    writeProcessors(processors_md);
+    writeParameterProviders(parameter_providers_md);
+  }
+
+ private:
+  void addComponents(const minifi::Components& components) {
+    for (const auto& controller_service_description: 
components.controller_services) {
       
controller_services.emplace_back(extractClassName(controller_service_description.full_name_),
 controller_service_description);
     }
-    for (const auto &processor_description : components.processors) {
+    for (const auto& processor_description: components.processors) {
       
processors.emplace_back(extractClassName(processor_description.full_name_), 
processor_description);
     }
-    for (const auto& parameter_provider_description : 
components.parameter_providers) {
+    for (const auto& parameter_provider_description: 
components.parameter_providers) {
       
parameter_providers.emplace_back(extractClassName(parameter_provider_description.full_name_),
 parameter_provider_description);
     }
   }
-  std::ranges::sort(controller_services, std::less(), lowercaseFirst);
-  std::ranges::sort(processors, std::less(), lowercaseFirst);
-  std::ranges::sort(parameter_providers, std::less(), lowercaseFirst);
 
-  std::ofstream controllers_md(docs_dir / "CONTROLLERS.md");
-  writeHeader(controllers_md, controller_services);
-  for (const auto& [name, documentation] : controller_services) {
-    writeName(controllers_md, name);
-    writeDescription(controllers_md, documentation);
-    writeProperties(controllers_md, documentation);
+  void sort() {
+    std::ranges::sort(controller_services, std::less(), lowercaseFirst);
+    std::ranges::sort(processors, std::less(), lowercaseFirst);
+    std::ranges::sort(parameter_providers, std::less(), lowercaseFirst);
+  }
+
+  void writeControllers(std::ostream& os) {
+    writeHeader(os, controller_services);
+    for (const auto& [name, documentation]: controller_services) {
+      writeControllerService(os, name, documentation);
+    }
+  }
+
+  void writeProcessors(std::ostream& os) {
+    writeHeader(os, processors);
+    for (const auto& [name, documentation]: processors) {
+      writeProcessor(os, name, documentation);
+    }
+  }
+
+  void writeParameterProviders(std::ostream& os) {
+    writeHeader(os, parameter_providers);
+    for (const auto& [name, documentation]: parameter_providers) {
+      writeParameterProvider(os, name, documentation);
+    }
+  }
+
+  std::vector<std::pair<std::string, minifi::ClassDescription>> 
controller_services;
+  std::vector<std::pair<std::string, minifi::ClassDescription>> processors;
+  std::vector<std::pair<std::string, minifi::ClassDescription>> 
parameter_providers;
+};
+
+class ModularDocumentation {
+ public:
+  static void write(const std::filesystem::path& docs_dir) {
+    for (auto& [bundle_id, component]: 
minifi::ClassDescriptionRegistry::getMutableClassDescriptions()) {
+      if (component.empty()) {
+        continue;
+      }
+      sortComponents(component);
+      writeModule(docs_dir, bundle_id.name, component);
+    }
+  }
+
+ private:
+  static void sortComponents(minifi::Components& components) {
+    std::ranges::sort(components.processors, {}, 
&minifi::ClassDescription::short_name_);
+    std::ranges::sort(components.controller_services, {}, 
&minifi::ClassDescription::short_name_);
+    std::ranges::sort(components.parameter_providers, {}, 
&minifi::ClassDescription::short_name_);
+  }
+
+  static void writeComponentParts(std::ostream& os, const 
std::vector<minifi::ClassDescription>& class_descriptions, const 
std::string_view h3) {
+    if (!class_descriptions.empty()) {
+      os << fmt::format("### {}\n\n", h3);
+      for (const auto& class_description: class_descriptions) {
+        const auto name = extractClassName(class_description.full_name_);
+        os << "- [" << name << "](#" << name << ")\n";
+      }
+    }
   }
 
-  std::ofstream processors_md(docs_dir / "PROCESSORS.md");
-  writeHeader(processors_md, processors);
-  for (const auto& [name, documentation] : processors) {
-    writeName(processors_md, name);
-    writeDescription(processors_md, documentation);
-    writeProperties(processors_md, documentation);
-    writeDynamicProperties(processors_md, documentation);
-    writeRelationships(processors_md, documentation);
-    writeOutputAttributes(processors_md, documentation);
+  static void writeToC(std::ostream& os, const minifi::Components& components) 
{
+    os << "\n\n## Table of Contents\n\n";
+    writeComponentParts(os, components.processors, "Processors");
+    writeComponentParts(os, components.controller_services, "Controller 
Services");
+    writeComponentParts(os, components.parameter_providers, "Parameter 
Providers");
   }
 
-  std::ofstream parameter_providers_md(docs_dir / "PARAMETER_PROVIDERS.md");
-  writeHeader(parameter_providers_md, parameter_providers);
-  for (const auto& [name, documentation] : parameter_providers) {
-    writeName(parameter_providers_md, name);
-    writeDescription(parameter_providers_md, documentation);
-    writeProperties(parameter_providers_md, documentation);
+  static void writeModule(const std::filesystem::path& docs_dir, const 
std::string_view module_name, const minifi::Components& components) {
+    const auto dir_creation_result = minifi::utils::file::create_dir(docs_dir 
/ "modules");
+    gsl_Assert(dir_creation_result == 0);
+    std::ofstream os(docs_dir / "modules" / (std::string(module_name) + 
".md"));
+    gsl_Assert(os);
+    os << APACHE_LICENSE;
+
+    writeToC(os, components);
+
+    for (const auto& processor: components.processors) {
+      writeProcessor(os, extractClassName(processor.full_name_), processor);
+    }
+
+    for (const auto& controller_service: components.controller_services) {
+      writeControllerService(os, 
extractClassName(controller_service.full_name_), controller_service);
+    }
+
+    for (const auto& parameter_provider_description: 
components.parameter_providers) {
+      writeParameterProvider(os, 
extractClassName(parameter_provider_description.full_name_), 
parameter_provider_description);
+    }
   }
+};
+}  // namespace
+
+namespace org::apache::nifi::minifi::docs {
+
+void AgentDocs::generate(const std::filesystem::path& docs_dir) {
+  MonolithDocumentation monolith_docs;
+  monolith_docs.write(docs_dir);
+
+  ModularDocumentation::write(docs_dir);
 }
 
 }  // namespace org::apache::nifi::minifi::docs

Reply via email to