Skip to content

Commit 2a6f91f

Browse files
committed
MINIFICPP-2712 Generate modular docs
With this PR, ./minifi --docs <output_dir> will generate additional md files one per extension <output_dir>/modules Closes #2097 Signed-off-by: Martin Zink <martinzink@apache.org>
1 parent 1b1a774 commit 2a6f91f

File tree

1 file changed

+146
-68
lines changed

1 file changed

+146
-68
lines changed

minifi_main/AgentDocs.cpp

Lines changed: 146 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -35,40 +35,32 @@
3535
#include "range/v3/view/join.hpp"
3636
#include "range/v3/view/transform.hpp"
3737
#include "utils/StringUtils.h"
38+
#include "utils/file/FileUtils.h"
3839

3940
namespace {
4041

4142
namespace minifi = org::apache::nifi::minifi;
4243

4344
std::string formatName(std::string_view name_view, bool is_required) {
4445
std::string name{name_view};
45-
if (is_required) {
46-
return "**" + name + "**";
47-
} else {
48-
return name;
49-
}
46+
if (is_required) { return "**" + name + "**"; }
47+
return name;
5048
}
5149

5250
std::string formatAllowedValues(const minifi::core::Property& property) {
53-
if (property.getValidator().getEquivalentNifiStandardValidatorName() == minifi::core::StandardPropertyValidators::BOOLEAN_VALIDATOR.getEquivalentNifiStandardValidatorName()) {
51+
if (property.getValidator().getEquivalentNifiStandardValidatorName() ==
52+
minifi::core::StandardPropertyValidators::BOOLEAN_VALIDATOR.getEquivalentNifiStandardValidatorName()) {
5453
return "true<br/>false";
55-
} else {
56-
const auto allowed_values = property.getAllowedValues();
57-
return allowed_values
58-
| ranges::views::join(std::string_view{"<br/>"})
59-
| ranges::to<std::string>();
6054
}
55+
const auto allowed_values = property.getAllowedValues();
56+
return allowed_values | ranges::views::join(std::string_view{"<br/>"}) | ranges::to<std::string>();
6157
}
6258

6359
std::string formatDescription(std::string_view description_view, bool is_sensitive = false, bool supports_expression_language = false) {
6460
std::string description{description_view};
6561
minifi::utils::string::replaceAll(description, "\n", "<br/>");
66-
if (is_sensitive) {
67-
description += "<br/>**Sensitive Property: true**";
68-
}
69-
if (supports_expression_language) {
70-
description += "<br/>**Supports Expression Language: true**";
71-
}
62+
if (is_sensitive) { description += "<br/>**Sensitive Property: true**"; }
63+
if (supports_expression_language) { description += "<br/>**Supports Expression Language: true**"; }
7264
return description;
7365
}
7466

@@ -103,7 +95,7 @@ void writeHeader(std::ostream& docs, const std::vector<std::pair<std::string, mi
10395
docs << APACHE_LICENSE;
10496

10597
docs << "\n\n## Table of Contents\n\n";
106-
for (const auto& [name, documentation] : class_descriptions) {
98+
for (const auto& [name, documentation]: class_descriptions) {
10799
docs << "- [" << name << "](#" << name << ")\n";
108100
}
109101
}
@@ -122,13 +114,11 @@ void writeProperties(std::ostream& docs, const minifi::ClassDescription& documen
122114
docs << "\n\nIn the list below, the names of required properties appear in bold. Any other properties (not in bold) are considered optional. "
123115
<< "The table also indicates any default values, and whether a property supports the NiFi Expression Language.";
124116
minifi::docs::Table properties{{"Name", "Default Value", "Allowable Values", "Description"}};
125-
for (const auto &property : documentation.class_properties_) {
126-
properties.addRow({
127-
formatName(property.getName(), property.getRequired()),
117+
for (const auto& property: documentation.class_properties_) {
118+
properties.addRow({formatName(property.getName(), property.getRequired()),
128119
property.getDefaultValue().value_or(""),
129120
formatAllowedValues(property),
130-
formatDescription(property)
131-
});
121+
formatDescription(property)});
132122
}
133123
docs << "\n\n" << properties.toString();
134124
}
@@ -138,20 +128,16 @@ void writeDynamicProperties(std::ostream& docs, const minifi::ClassDescription&
138128

139129
docs << "\n### Dynamic Properties\n\n";
140130
minifi::docs::Table dynamic_properties{{"Name", "Value", "Description"}};
141-
for (const auto &dynamic_property : documentation.dynamic_properties_) {
142-
dynamic_properties.addRow({
143-
formatName(dynamic_property.name, false),
144-
std::string(dynamic_property.value),
145-
formatDescription(dynamic_property)
146-
});
131+
for (const auto& dynamic_property: documentation.dynamic_properties_) {
132+
dynamic_properties.addRow({formatName(dynamic_property.name, false), std::string(dynamic_property.value), formatDescription(dynamic_property)});
147133
}
148134
docs << dynamic_properties.toString();
149135
}
150136

151137
void writeRelationships(std::ostream& docs, const minifi::ClassDescription& documentation) {
152138
docs << "\n### Relationships\n\n";
153139
minifi::docs::Table relationships{{"Name", "Description"}};
154-
for (const auto &rel : documentation.class_relationships_) {
140+
for (const auto& rel: documentation.class_relationships_) {
155141
relationships.addRow({rel.getName(), formatDescription(rel.getDescription())});
156142
}
157143
docs << relationships.toString();
@@ -162,9 +148,8 @@ void writeOutputAttributes(std::ostream& docs, const minifi::ClassDescription& d
162148

163149
docs << "\n### Output Attributes";
164150
minifi::docs::Table output_attributes{{"Attribute", "Relationship", "Description"}};
165-
for (const auto &output_attribute : documentation.output_attributes_) {
166-
output_attributes.addRow({
167-
std::string(output_attribute.name),
151+
for (const auto& output_attribute: documentation.output_attributes_) {
152+
output_attributes.addRow({std::string(output_attribute.name),
168153
formatListOfRelationships(output_attribute.relationships),
169154
formatDescription(output_attribute.description)});
170155
}
@@ -177,58 +162,151 @@ std::string extractClassName(const std::string& full_class_name) {
177162

178163
std::string lowercaseFirst(const std::pair<std::string, minifi::ClassDescription>& key_value) {
179164
return minifi::utils::string::toLower(key_value.first);
180-
};
165+
}
181166

182-
} // namespace
167+
void writeProcessor(std::ostream& os, const std::string_view name, const minifi::ClassDescription& documentation) {
168+
writeName(os, name);
169+
writeDescription(os, documentation);
170+
writeProperties(os, documentation);
171+
writeDynamicProperties(os, documentation);
172+
writeRelationships(os, documentation);
173+
writeOutputAttributes(os, documentation);
174+
}
183175

184-
namespace org::apache::nifi::minifi::docs {
176+
void writeControllerService(std::ostream& os, const std::string_view name, const minifi::ClassDescription& documentation) {
177+
writeName(os, name);
178+
writeDescription(os, documentation);
179+
writeProperties(os, documentation);
180+
}
185181

186-
void AgentDocs::generate(const std::filesystem::path& docs_dir) {
187-
std::vector<std::pair<std::string, minifi::ClassDescription>> controller_services;
188-
std::vector<std::pair<std::string, minifi::ClassDescription>> processors;
189-
std::vector<std::pair<std::string, minifi::ClassDescription>> parameter_providers;
182+
void writeParameterProvider(std::ostream& os, const std::string_view name, const minifi::ClassDescription& documentation) {
183+
writeName(os, name);
184+
writeDescription(os, documentation);
185+
writeProperties(os, documentation);
186+
}
190187

191-
for (const auto& [bundle_id, components]: ClassDescriptionRegistry::getClassDescriptions()) {
192-
for (const auto &controller_service_description : components.controller_services) {
188+
class MonolithDocumentation {
189+
public:
190+
explicit MonolithDocumentation() {
191+
for (const auto& [bundle_id, component]: minifi::ClassDescriptionRegistry::getClassDescriptions()) {
192+
addComponents(component);
193+
}
194+
sort();
195+
}
196+
197+
void write(const std::filesystem::path& docs_dir) {
198+
std::ofstream controllers_md(docs_dir / "CONTROLLERS.md");
199+
std::ofstream processors_md(docs_dir / "PROCESSORS.md");
200+
std::ofstream parameter_providers_md(docs_dir / "PARAMETER_PROVIDERS.md");
201+
gsl_Assert(controllers_md && processors_md && parameter_providers_md);
202+
203+
writeControllers(controllers_md);
204+
writeProcessors(processors_md);
205+
writeParameterProviders(parameter_providers_md);
206+
}
207+
208+
private:
209+
void addComponents(const minifi::Components& components) {
210+
for (const auto& controller_service_description: components.controller_services) {
193211
controller_services.emplace_back(extractClassName(controller_service_description.full_name_), controller_service_description);
194212
}
195-
for (const auto &processor_description : components.processors) {
213+
for (const auto& processor_description: components.processors) {
196214
processors.emplace_back(extractClassName(processor_description.full_name_), processor_description);
197215
}
198-
for (const auto& parameter_provider_description : components.parameter_providers) {
216+
for (const auto& parameter_provider_description: components.parameter_providers) {
199217
parameter_providers.emplace_back(extractClassName(parameter_provider_description.full_name_), parameter_provider_description);
200218
}
201219
}
202-
std::ranges::sort(controller_services, std::less(), lowercaseFirst);
203-
std::ranges::sort(processors, std::less(), lowercaseFirst);
204-
std::ranges::sort(parameter_providers, std::less(), lowercaseFirst);
205220

206-
std::ofstream controllers_md(docs_dir / "CONTROLLERS.md");
207-
writeHeader(controllers_md, controller_services);
208-
for (const auto& [name, documentation] : controller_services) {
209-
writeName(controllers_md, name);
210-
writeDescription(controllers_md, documentation);
211-
writeProperties(controllers_md, documentation);
221+
void sort() {
222+
std::ranges::sort(controller_services, std::less(), lowercaseFirst);
223+
std::ranges::sort(processors, std::less(), lowercaseFirst);
224+
std::ranges::sort(parameter_providers, std::less(), lowercaseFirst);
225+
}
226+
227+
void writeControllers(std::ostream& os) {
228+
writeHeader(os, controller_services);
229+
for (const auto& [name, documentation]: controller_services) {
230+
writeControllerService(os, name, documentation);
231+
}
232+
}
233+
234+
void writeProcessors(std::ostream& os) {
235+
writeHeader(os, processors);
236+
for (const auto& [name, documentation]: processors) {
237+
writeProcessor(os, name, documentation);
238+
}
239+
}
240+
241+
void writeParameterProviders(std::ostream& os) {
242+
writeHeader(os, parameter_providers);
243+
for (const auto& [name, documentation]: parameter_providers) {
244+
writeParameterProvider(os, name, documentation);
245+
}
246+
}
247+
248+
std::vector<std::pair<std::string, minifi::ClassDescription>> controller_services;
249+
std::vector<std::pair<std::string, minifi::ClassDescription>> processors;
250+
std::vector<std::pair<std::string, minifi::ClassDescription>> parameter_providers;
251+
};
252+
253+
class ModularDocumentation {
254+
public:
255+
static void write(const std::filesystem::path& docs_dir) {
256+
for (const auto& [bundle_id, component]: minifi::ClassDescriptionRegistry::getClassDescriptions()) {
257+
writeModule(docs_dir, bundle_id.name, component);
258+
}
212259
}
213260

214-
std::ofstream processors_md(docs_dir / "PROCESSORS.md");
215-
writeHeader(processors_md, processors);
216-
for (const auto& [name, documentation] : processors) {
217-
writeName(processors_md, name);
218-
writeDescription(processors_md, documentation);
219-
writeProperties(processors_md, documentation);
220-
writeDynamicProperties(processors_md, documentation);
221-
writeRelationships(processors_md, documentation);
222-
writeOutputAttributes(processors_md, documentation);
261+
private:
262+
static void writeComponentParts(std::ostream& os, const std::vector<minifi::ClassDescription>& class_descriptions, const std::string_view h3) {
263+
if (!class_descriptions.empty()) {
264+
os << fmt::format("### {}\n\n", h3);
265+
for (const auto& class_description: class_descriptions) {
266+
const auto name = extractClassName(class_description.full_name_);
267+
os << "- [" << name << "](#" << name << ")\n";
268+
}
269+
}
223270
}
224271

225-
std::ofstream parameter_providers_md(docs_dir / "PARAMETER_PROVIDERS.md");
226-
writeHeader(parameter_providers_md, parameter_providers);
227-
for (const auto& [name, documentation] : parameter_providers) {
228-
writeName(parameter_providers_md, name);
229-
writeDescription(parameter_providers_md, documentation);
230-
writeProperties(parameter_providers_md, documentation);
272+
static void writeToC(std::ostream& os, const minifi::Components& components) {
273+
os << "\n\n## Table of Contents\n\n";
274+
writeComponentParts(os, components.processors, "Processors");
275+
writeComponentParts(os, components.controller_services, "Controller Services");
276+
writeComponentParts(os, components.parameter_providers, "Parameter Providers");
231277
}
278+
279+
static void writeModule(const std::filesystem::path& docs_dir, const std::string_view module_name, const minifi::Components& components) {
280+
const auto dir_creation_result = minifi::utils::file::create_dir(docs_dir / "modules");
281+
gsl_Assert(dir_creation_result == 0);
282+
std::ofstream os(docs_dir / "modules" / (std::string(module_name) + ".md"));
283+
gsl_Assert(os);
284+
os << APACHE_LICENSE;
285+
286+
writeToC(os, components);
287+
288+
for (const auto& processor: components.processors) {
289+
writeProcessor(os, extractClassName(processor.full_name_), processor);
290+
}
291+
292+
for (const auto& controller_service: components.controller_services) {
293+
writeControllerService(os, extractClassName(controller_service.full_name_), controller_service);
294+
}
295+
296+
for (const auto& parameter_provider_description: components.parameter_providers) {
297+
writeParameterProvider(os, extractClassName(parameter_provider_description.full_name_), parameter_provider_description);
298+
}
299+
}
300+
};
301+
} // namespace
302+
303+
namespace org::apache::nifi::minifi::docs {
304+
305+
void AgentDocs::generate(const std::filesystem::path& docs_dir) {
306+
MonolithDocumentation monolith_docs;
307+
monolith_docs.write(docs_dir);
308+
309+
ModularDocumentation::write(docs_dir);
232310
}
233311

234312
} // namespace org::apache::nifi::minifi::docs

0 commit comments

Comments
 (0)