///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS org.rodnansol:spring-configuration-property-documenter-core:999-SNAPSHOT
//DEPS info.picocli:picocli:4.7.0
//JAVA 17
import org.rodnansol.core.generator.DocumentGenerationException;
import org.rodnansol.core.generator.reader.MetadataReader;
import org.rodnansol.core.generator.resolver.MetadataInputResolverContext;
import org.rodnansol.core.generator.template.TemplateMode;
import org.rodnansol.core.generator.template.compiler.TemplateCompiler;
import org.rodnansol.core.generator.template.compiler.TemplateCompilerFactory;
import org.rodnansol.core.generator.template.customization.TemplateCustomization;
import org.rodnansol.core.generator.template.data.TemplateData;
import org.rodnansol.core.generator.template.TemplateType;
import org.rodnansol.core.generator.template.customization.TemplateCustomizationFactory;
import org.rodnansol.core.generator.writer.AggregationDocumenter;
import org.rodnansol.core.generator.writer.CombinedInput;
import org.rodnansol.core.generator.writer.CreateAggregationCommand;
import org.rodnansol.core.generator.writer.CreateDocumentCommand;
import org.rodnansol.core.generator.writer.CustomTemplate;
import org.rodnansol.core.generator.writer.Documenter;
import org.rodnansol.core.generator.writer.postprocess.PropertyGroupFilterService;
import org.rodnansol.core.project.Project;
import org.rodnansol.core.project.ProjectFactory;
import org.rodnansol.core.project.ProjectType;
import picocli.CommandLine;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@CommandLine.Command(
mixinStandardHelpOptions = true,
version = PropertyDocumenter.VERSION,
description = "CLI tool that reads Jar or raw files to generate documentation about the Spring properties",
subcommands = {
PropertyDocumenter.GenerateCommand.class,
PropertyDocumenter.AggregatorCommand.class
})
public class PropertyDocumenter {
protected static final String VERSION = "0.6.0";
public static void main(String... args) {
int exitCode = new CommandLine(new PropertyDocumenter()).execute(args);
System.exit(exitCode);
}
@CommandLine.Command(name = "generate",
mixinStandardHelpOptions = true,
version = "PropertyDocumenter 0.6.0",
description =
"""
Documents the incoming input into a file.
Example: jbang PropertyDocumenter.java document \\
-n "Header title" -i ~/module-a \\
-tt HTML \\
-o property-docs.html
"""
)
static class GenerateCommand implements Runnable {
/**
* Main header name in the aggregated output file.
*
* @since 0.1.0
*/
@CommandLine.Option(names = {"-n", "--name"}, description = "Main header name", arity = "1", defaultValue = "Spring Properties")
String documentName;
/**
* Custom template file.
*
* @since 0.2.1
*/
@CommandLine.Option(names = {"-t", "--template"}, description = "Custom template file", arity = "0..1")
String template;
/**
* List of the inputs, they can be proper JSON files, JAR/Zip files or only directories. The script will determine what to consume.
*
* @since 0.1.0
*/
@CommandLine.Option(names = {"-i", "--input"}, description = "Input file, directory or JAR file", arity = "1", required = true)
File input;
/**
* Name of the output file.
*
* @since 0.1.0
*/
@CommandLine.Option(names = {"-o", "--output"}, description = "Output file name", arity = "1", required = true)
File outputFile;
/**
* Desired template type, it can be MARKDOWN, ADOC or HTML
*
* @since 0.1.0
*/
@CommandLine.Option(names = {"-tt", "--template-type"},
description = """
Desired template type, supported:
${COMPLETION-CANDIDATES}
""",
arity = "1", defaultValue = "MARKDOWN")
TemplateType templateType;
/**
* Type of the project. Currently supported:
*
*
*
* @since 0.1.0
*/
@CommandLine.Option(names = {"-pt", "--project-type"},
description = """
Type of the project,
currently supported: MAVEN, GRADLE
""", arity = "1", defaultValue = "MAVEN")
ProjectType projectType;
/**
* Custom template compiler.
*
* @since 0.2.1
*/
@CommandLine.Option(names = {"-tc", "--template-compiler"}, description = "Template's compiler fully qualified name", arity = "0..1", defaultValue = "org.rodnansol.core.generator.template.HandlebarsTemplateCompiler")
String templateCompiler = TemplateCompilerFactory.getDefaultCompilerName();
/**
* Mode of the template. Currently supported:
*
*
*
* @since 0.6.0
*/
@CommandLine.Option(names = {"-tm", "--template-mode"},
description = """
Mode of the template.
Currently supported: STANDARD, COMPACT
""", arity = "1", defaultValue = "STANDARD")
TemplateMode templateMode = TemplateMode.STANDARD;
@Override
public void run() {
Project project = ProjectFactory.ofType(new File("."), documentName, projectType);
String singleTemplate = template != null && !template.isBlank() ? template : templateType.getSingleTemplate(templateMode);
CreateDocumentCommand createDocumentCommand = new CreateDocumentCommand(project, documentName, input, singleTemplate, outputFile, TemplateCustomizationFactory.getDefaultTemplateCustomizationByType(templateType));
try {
new Documenter(MetadataReader.INSTANCE, TemplateCompilerFactory.getInstanceByClassName(templateCompiler), MetadataInputResolverContext.INSTANCE, PropertyGroupFilterService.INSTANCE).readMetadataAndGenerateRenderedFile(createDocumentCommand);
} catch (IOException e) {
throw new DocumentGenerationException("Error during generating the documentation, please check the logs...", e);
}
}
}
@CommandLine.Command(name = "aggregate",
mixinStandardHelpOptions = true,
version = "PropertyDocumenter 0.6.0",
description =
"""
Aggregates the incoming inputs into one big file while.
Please specify the module names for each input with a sequence.
Example: jbang PropertyDocumenter.java aggregate \\
-n "Multi module project" \\
-mn "Module A" -i ~/module-a \\
-mn "Module B" -i ~/module-b \\
-mn "Module C" -i ~/module-c \\
-tt HTML \\
-o aggregated-property-docs.html
"""
)
static class AggregatorCommand implements Runnable {
/**
* Main header name in the aggregated output file.
*
* @since 0.1.0
*/
@CommandLine.Option(names = {"-n", "--name"}, description = "Main header name", arity = "1", defaultValue = "Spring Properties")
String mainName;
/**
* List of the module names.
*
* @since 0.1.0
*/
@CommandLine.Option(names = {"-mn", "--module-names"}, description = "List of the module names", arity = "1..*", defaultValue = "Spring Properties")
List moduleNames;
/**
* List of the inputs, they can be proper JSON files, JAR/Zip files or only directories. The script will determine what to consume.
*
* @since 0.1.0
*/
@CommandLine.Option(names = {"-i", "--inputs"}, description = "List of input files, directories or JAR files", arity = "1..*", required = true)
List inputs;
/**
* Name of the output file.
*
* @since 0.1.0
*/
@CommandLine.Option(names = {"-o", "--output"}, description = "Output file name", arity = "1", required = true)
String outputFile;
/**
* Desired template type, it can be MARKDOWN, ADOC or HTML
*
* @since 0.1.0
*/
@CommandLine.Option(names = {"-tt", "--template-type"},
description = """
Desired template type, supported:
${COMPLETION-CANDIDATES}
""",
arity = "1", defaultValue = "MARKDOWN")
TemplateType templateType;
/**
* Type of the project. Currently supported:
*
*
*
* @since 0.1.0
*/
@CommandLine.Option(names = {"-pt", "--project-type"},
description = """
Type of the project,
currently supported: MAVEN, GRADLE
""", arity = "1", defaultValue = "MAVEN")
ProjectType projectType;
/**
* Custom header template file.
*
* @since 0.2.1
*/
@CommandLine.Option(names = {"-ht", "--header-template"}, description = "Custom header template file", arity = "0..1")
String headerTemplate;
/**
* Custom header template file.
*
* @since 0.2.1
*/
@CommandLine.Option(names = {"-ct", "--content-template"}, description = "Custom content template file", arity = "0..1")
String contentTemplate;
/**
* Custom header template file.
*
* @since 0.2.1
*/
@CommandLine.Option(names = {"-ft", "--footer-template"}, description = "Custom footer template file", arity = "0..1")
String footerTemplate;
/**
* Custom template compiler.
*
* @since 0.2.1
*/
@CommandLine.Option(names = {"-tc", "--template-compiler"}, description = "Template's compiler fully qualified name", arity = "0..1", defaultValue = "org.rodnansol.core.generator.template.HandlebarsTemplateCompiler")
String templateCompiler = TemplateCompilerFactory.getDefaultCompilerName();
/**
* Mode of the template. Currently supported:
*
*
*
* @since 0.6.0
*/
@CommandLine.Option(names = {"-tm", "--template-mode"},
description = """
Mode of the template.
Currently supported: STANDARD, COMPACT
""", arity = "1", defaultValue = "STANDARD")
TemplateMode templateMode = TemplateMode.STANDARD;
@Override
public void run() {
List combinedInputs = new ArrayList<>(inputs.size());
for (int i = 0; i < inputs.size(); i++) {
String input = inputs.get(i);
combinedInputs.add(new CombinedInput(new File(input), getModuleName(i), ""));
}
Project project = ProjectFactory.ofType(new File("."), mainName, projectType);
TemplateCustomization templateCustomization = TemplateCustomizationFactory.getDefaultTemplateCustomizationByType(templateType);
templateCustomization.setTemplateMode(templateMode);
CreateAggregationCommand createAggregationCommand = new CreateAggregationCommand(project,
mainName,
combinedInputs,
templateType,
templateCustomization,
new File(outputFile));
createAggregationCommand.setCustomTemplate(new CustomTemplate(headerTemplate, contentTemplate, footerTemplate));
new AggregationDocumenter(MetadataReader.INSTANCE, TemplateCompilerFactory.getInstanceByClassName(templateCompiler), MetadataInputResolverContext.INSTANCE, PropertyGroupFilterService.INSTANCE).createDocumentsAndAggregate(createAggregationCommand);
}
private String getModuleName(int i) {
try {
return moduleNames.get(i);
} catch (IndexOutOfBoundsException e) {
return "Module " + i;
}
}
}
public static class CustomTemplateCompiler implements TemplateCompiler {
@Override
public String compileTemplate(String s, TemplateData templateData) throws DocumentGenerationException {
return "Jbang based template compiler \n";
}
}
}