diff --git a/docs/modules/ROOT/pages/gradle-plugin.adoc b/docs/modules/ROOT/pages/gradle-plugin.adoc index 42b55dc..e1e3523 100644 --- a/docs/modules/ROOT/pages/gradle-plugin.adoc +++ b/docs/modules/ROOT/pages/gradle-plugin.adoc @@ -399,6 +399,12 @@ Or run them in two separate commands: |Empty list - Everything will be included |0.5.0 +|failOnMissingInput +|Defines if the build should fail if the input file is missing/not existing. +|Yes +| +|0.7.0 + |=== ==== @@ -504,6 +510,12 @@ Or run them in two separate commands: | |0.5.0 +|failOnMissingInput +|Defines if the build should fail if the input file is missing/not existing. +|Yes +| +|0.7.0 + |=== [#aggregation-input] diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index a1de22d..816d74d 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -16,7 +16,7 @@ endif::[] :toc: :toc-placement!: :toclevels: 4 -:latest-version: 0.6.1 +:latest-version: 0.7.0 [.text-center] image:https://img.shields.io/maven-central/v/org.rodnansol/spring-configuration-property-documenter.svg[Maven Central] diff --git a/docs/modules/ROOT/pages/maven-plugin.adoc b/docs/modules/ROOT/pages/maven-plugin.adoc index 5d98205..53fbfe9 100644 --- a/docs/modules/ROOT/pages/maven-plugin.adoc +++ b/docs/modules/ROOT/pages/maven-plugin.adoc @@ -374,6 +374,12 @@ As we can see in the `input` tags we can define an `input` field that can be: |Empty list - Everything will be included |0.4.0 +|failOnMissingInput +|Defines if the build should fail if the input file is missing/not existing. +|Yes +| +|0.7.0 + |=== ==== @@ -479,6 +485,12 @@ As we can see in the `input` tags we can define an `input` field that can be: | |0.2.1 +|failOnMissingInput +|Defines if the build should fail if any of the input files are missing/not existing. +|Yes +| +|0.7.0 + |=== [#aggregation-mojo-input] diff --git a/docs/modules/ROOT/pages/migrations.adoc b/docs/modules/ROOT/pages/migrations.adoc index ebbc144..d932e9e 100644 --- a/docs/modules/ROOT/pages/migrations.adoc +++ b/docs/modules/ROOT/pages/migrations.adoc @@ -1,5 +1,6 @@ [#header] = Migrations + ifndef::env-github[] :icons: font endif::[] @@ -14,7 +15,106 @@ endif::[] :toc-placement!: :toclevels: 4 +[#version-0-7-0] +== 0.6.0 -> 0.7.0 + +Before the 0.7.0 version in case any of the input files during the `generate-and-aggregate-documents` Maven goal or `generateAndAggregateDocuments` Gradle task was missing the documentation was created but the missing elements were not rendered into the document, because there was nothing to be read. + +With the release of the 0.7.0 this changes and the build will fail, but it can be parametrized for both available goals/tasks. + +Maven goals: + +* generate-property-document +* generate-and-aggregate-documents + +Gradle tasks: + +* generatePropertyDocument +* generateAndAggregateDocuments + +=== Maven + +.pom.xml +[source,xml] +---- + + + generate-adoc + process-classes + + generate-property-document + + + TYPE + + true + + + + generate-adoc + process-classes + + generate-and-aggregate-documents + + + TYPE + + true + + + +---- + +=== Gradle + +.gradle.build +[source,groovy] +---- +tasks.register('generateAdoc') { + dependsOn generatePropertyDocument { + failOnMissingInput = true // Will fail if input is missing + documentName = "Hello World" + type = "ADOC" + asciiDocCustomization { + contentCustomization { + includeEnvFormat = true + includeClass = false + includeDeprecation = false + includeDescription = false + } + unknownGroupLocalization = "Renamed unknown group" + tocLevels = 3 + } + } +} + +tasks.register('generateAdocFromMissingInputFile') { + dependsOn generatePropertyDocument { + failOnMissingInput = false // Won't fail if input is missing, and empty file will be made + metadataInput = new File("non-existing.json") + outputFile = new File("build/property-docs/non-existing-file.adoc") + documentName = "Hello World" + type = "ADOC" + asciiDocCustomization { + contentCustomization { + includeEnvFormat = true + includeClass = false + includeDeprecation = false + includeDescription = false + } + unknownGroupLocalization = "Renamed unknown group" + tocLevels = 3 + } + } +} +---- + +[#version-0-6-1] +== 0.6.0 -> 0.6.1 +No changes required. + +[#version-0-6-0] == 0.5.1 -> 0.6.0 === Including environment format @@ -24,6 +124,7 @@ Header appearance in the tables are now customizable, and to make sure the envir A new level of configuration is introduced, it can be configured with the `contentCustomization` key in Maven and in Gradle. ==== Maven + .Till 0.5.1 [source,xml] ---- @@ -92,6 +193,7 @@ A new level of configuration is introduced, it can be configured with the `conte ---- ==== Gradle + .Till 0.5.1 [source,groovy] ---- @@ -188,32 +290,52 @@ tasks.register('generateXml') { } ---- +[#version-0-5-1] == 0.5.0 -> 0.5.1 + No changes required. +[#version-0-5-0] == 0.4.0 -> 0.5.0 + No changes required. +[#version-0-4-0] == 0.3.0 -> 0.4.0 + No changes required. +[#version-0-3-0] == 0.2.4 -> 0.3.0 + No changes required. +[#version-0-2-4] == 0.2.3 -> 0.2.4 + No changes required. +[#version-0-2-3] == 0.2.2 -> 0.2.3 + No changes required. +[#version-0-2-2] == 0.2.1 -> 0.2.2 + No changes required. +[#version-0-2-1] == 0.2.0 -> 0.2.1 + No changes required. +[#version-0-2-0] == 0.1.1 -> 0.2.0 + No changes required. +[#version-0-1-1] == 0.1.0 -> 0.1.1 + No changes required. diff --git a/hooks/commit-msg b/hooks/commit-msg index a6d3254..d121e9b 100755 --- a/hooks/commit-msg +++ b/hooks/commit-msg @@ -1,5 +1,10 @@ #!/usr/bin/env bash +if git rev-parse -q --verify MERGE_HEAD; then + echo "This is a merge commit, no checks are required" + exit 0 +fi + # Create a regex for a conventional commit. convetional_commit_regex="^(release|build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\([a-z \-]+\))?!?: .+$" diff --git a/hooks/pre-commit b/hooks/pre-commit index 061b753..e6906f3 100755 --- a/hooks/pre-commit +++ b/hooks/pre-commit @@ -1,4 +1,8 @@ #!/usr/bin/env bash -echo "Verifying project before committing" -./mvnw clean verify +if git rev-parse -q --verify MERGE_HEAD; then + echo "This is a merge commit, no builds are going to be executed." +else + echo "Building project" + ./mvnw clean verify +fi diff --git a/samples/gradle/simple-gradle-project/build.gradle b/samples/gradle/simple-gradle-project/build.gradle index 5817b41..9d288be 100644 --- a/samples/gradle/simple-gradle-project/build.gradle +++ b/samples/gradle/simple-gradle-project/build.gradle @@ -42,6 +42,7 @@ tasks.named('test') { tasks.register('generateAdoc') { dependsOn generatePropertyDocument { + failOnMissingInput = true documentName = "Hello World" type = "ADOC" asciiDocCustomization { @@ -86,3 +87,23 @@ tasks.register('generateXml') { } } } + +tasks.register('generateAdocFromMissingInputFile') { + dependsOn generatePropertyDocument { + failOnMissingInput = false + metadataInput = new File("non-existing.json") + outputFile = new File("build/property-docs/non-existing-file.adoc") + documentName = "Hello World" + type = "ADOC" + asciiDocCustomization { + contentCustomization { + includeEnvFormat = true + includeClass = false + includeDeprecation = false + includeDescription = false + } + unknownGroupLocalization = "Renamed unknown group" + tocLevels = 3 + } + } +} \ No newline at end of file diff --git a/samples/multi-module/multi-module-docs/pom.xml b/samples/multi-module/multi-module-docs/pom.xml index 14c8a09..9f7e6d5 100644 --- a/samples/multi-module/multi-module-docs/pom.xml +++ b/samples/multi-module/multi-module-docs/pom.xml @@ -61,6 +61,36 @@ + + aggregate-docs-markdown-with-non-existing-sources + + generate-and-aggregate-documents + + package + + MARKDOWN + false + + + Multi Module A + Multi Module A properties with a folder input + ../multi-module-non-existing-a + + + Multi Module B + Multi Module B properties with a folder input + ../multi-module-non-existing-b + + + + false + + true + + + target/aggregated-non-existing-sources-md.md + + aggregate-docs-markdown-with-spring-related-configurations @@ -335,7 +365,7 @@ - true + COMPACT target/compact-include-and-exclude-list-based-document.adoc diff --git a/samples/pom.xml b/samples/pom.xml index feee481..33e4f8e 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -12,7 +12,7 @@ single-module multi-module quarkus-spring-boot-single-module - kotlin-example + diff --git a/samples/single-module/pom.xml b/samples/single-module/pom.xml index 38fdaac..129f724 100644 --- a/samples/single-module/pom.xml +++ b/samples/single-module/pom.xml @@ -78,7 +78,7 @@ ADOC - true + COMPACT target/compact-mode.adoc @@ -99,6 +99,18 @@ + + generate-empty-output-file-because-input-file-is-missing + process-classes + + generate-property-document + + + not-existing.json + ADOC + target/not-existing-input-file.adoc + + generate-adoc-with-include-list process-classes @@ -216,7 +228,7 @@ MARKDOWN - true + COMPACT target/compact-mode.md @@ -262,7 +274,7 @@ HTML - true + COMPACT target/compact-mode.html diff --git a/spring-configuration-property-documenter-core/src/it/java/org/rodnansol/core/generator/writer/AggregationDocumenterIT.java b/spring-configuration-property-documenter-core/src/it/java/org/rodnansol/core/generator/writer/AggregationDocumenterIT.java index be68425..fa05f3d 100644 --- a/spring-configuration-property-documenter-core/src/it/java/org/rodnansol/core/generator/writer/AggregationDocumenterIT.java +++ b/spring-configuration-property-documenter-core/src/it/java/org/rodnansol/core/generator/writer/AggregationDocumenterIT.java @@ -1,11 +1,14 @@ package org.rodnansol.core.generator.writer; +import org.assertj.core.api.ThrowableAssert; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; +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; @@ -21,11 +24,13 @@ import org.rodnansol.core.project.simple.SimpleProject; import java.io.File; +import java.io.IOException; import java.nio.file.Path; import java.util.List; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.fail; @ExtendWith(MockitoExtension.class) @@ -118,6 +123,52 @@ void readMetadataAndGenerateRenderedFile_shouldReturnDocumentInCompactMode_whenC assertThat(resolve).hasSameTextualContentAs(Path.of(testCase.expectedFile)); } + @Test + @DisplayName("Should return an empty file with basic content when the input file is missing and it is set to not fail") + void readMetadataAndGenerateRenderedFile_shouldReturnEmptyFile_whenInputFileIsMissing() throws IOException { + // Given + TemplateType templateType = TemplateType.ADOC; + Path resolve = tempDir.resolve("IT-output-non-existing-input-" + templateType.name() + templateType.getExtension()); + AbstractTemplateCustomization templateCustomization = getTemplateCustomization(templateType); + templateCustomization.setTemplateMode(TemplateMode.COMPACT); + CreateAggregationCommand createAggregationCommand = new CreateAggregationCommand(PROJECT, "IT", + List.of( + new CombinedInput(new File("non-existing-file.json"), "Document 1", "Document 1 description") + ), + templateType, templateCustomization, resolve.toFile()); + createAggregationCommand.setDescription("This is a test description"); + createAggregationCommand.setFailOnMissingInput(false); + + // When + underTest.createDocumentsAndAggregate(createAggregationCommand); + + // Then + assertThat(resolve).hasSameTextualContentAs(Path.of(MAIN_EXPECTED_FOLDER + "expected-non-existing-input-file.adoc")); + } + + @Test + @DisplayName("Should throw DocumentGenerationException exception when the input file is missing and it is meant to fail in this case") + void readMetadataAndGenerateRenderedFile_shouldFail_whenInputFileIsMissingAndItIsMeanToFail() { + // Given + TemplateType templateType = TemplateType.ADOC; + Path resolve = tempDir.resolve("IT-output-non-existing-input-" + templateType.name() + templateType.getExtension()); + AbstractTemplateCustomization templateCustomization = getTemplateCustomization(templateType); + templateCustomization.setTemplateMode(TemplateMode.COMPACT); + CreateAggregationCommand createAggregationCommand = new CreateAggregationCommand(PROJECT, "IT", + List.of( + new CombinedInput(new File("non-existing-file.json"), "Document 1", "Document 1 description") + ), + templateType, templateCustomization, resolve.toFile()); + createAggregationCommand.setDescription("This is a test description"); + createAggregationCommand.setFailOnMissingInput(true); + + // When + ThrowableAssert.ThrowingCallable callable = () -> underTest.createDocumentsAndAggregate(createAggregationCommand); + + // Then + assertThatThrownBy(callable).isInstanceOf(DocumentGenerationException.class); + } + private AbstractTemplateCustomization getTemplateCustomization(TemplateType templateType) { AbstractTemplateCustomization templateCustomization = null; switch (templateType) { diff --git a/spring-configuration-property-documenter-core/src/it/java/org/rodnansol/core/generator/writer/DocumenterIT.java b/spring-configuration-property-documenter-core/src/it/java/org/rodnansol/core/generator/writer/DocumenterIT.java index f72c66c..2361c55 100644 --- a/spring-configuration-property-documenter-core/src/it/java/org/rodnansol/core/generator/writer/DocumenterIT.java +++ b/spring-configuration-property-documenter-core/src/it/java/org/rodnansol/core/generator/writer/DocumenterIT.java @@ -1,16 +1,19 @@ package org.rodnansol.core.generator.writer; +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; +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.TemplateCompilerFactory; import org.rodnansol.core.generator.template.TemplateType; +import org.rodnansol.core.generator.template.compiler.TemplateCompilerFactory; import org.rodnansol.core.generator.template.customization.AbstractTemplateCustomization; import org.rodnansol.core.generator.template.customization.AsciiDocTemplateCustomization; import org.rodnansol.core.generator.template.customization.HtmlTemplateCustomization; @@ -26,6 +29,7 @@ import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.fail; @ExtendWith(MockitoExtension.class) @@ -33,10 +37,9 @@ class DocumenterIT { protected static final String TEST_DOCUMENT_HEADER = "IT"; protected static final SimpleProject PROJECT = ProjectFactory.ofSimpleProject(new File("."), TEST_DOCUMENT_HEADER); + protected static final String TEST_DESCRIPTION = "This is a test description"; private static final String MAIN_EXPECTED_FOLDER = "src/it/resources/it/single/"; private static final String TEST_JSON = MAIN_EXPECTED_FOLDER + "spring-configuration-metadata-empty-sourceType.json"; - protected static final String TEST_DESCRIPTION = "This is a test description"; - @TempDir Path tempDir; @@ -68,6 +71,29 @@ public static Stream compactModeCases() { ); } + private AbstractTemplateCustomization getTemplateCustomization(TemplateType templateType) { + AbstractTemplateCustomization templateCustomization = null; + switch (templateType) { + case MARKDOWN: + templateCustomization = new MarkdownTemplateCustomization(); + break; + case ADOC: + templateCustomization = new AsciiDocTemplateCustomization(); + break; + case HTML: + templateCustomization = new HtmlTemplateCustomization(); + break; + case XML: + templateCustomization = new XmlTemplateCustomization(); + break; + default: + fail("Unknown template type"); + break; + } + templateCustomization.setIncludeGenerationDate(false); + return templateCustomization; + } + @ParameterizedTest @MethodSource("noEnvFormatCases") @DisplayName("Should NOT include environment variable format when disabled") @@ -123,27 +149,40 @@ void readMetadataAndGenerateRenderedFile_shouldReturnDocumentInCompactMode_whenC assertThat(resolve).hasSameTextualContentAs(Path.of(testCase.expectedFile)); } - private static AbstractTemplateCustomization getTemplateCustomization(TemplateType templateType) { - AbstractTemplateCustomization templateCustomization = null; - switch (templateType) { - case MARKDOWN: - templateCustomization = new MarkdownTemplateCustomization(); - break; - case ADOC: - templateCustomization = new AsciiDocTemplateCustomization(); - break; - case HTML: - templateCustomization = new HtmlTemplateCustomization(); - break; - case XML: - templateCustomization = new XmlTemplateCustomization(); - break; - default: - fail("Unknown template type"); - break; - } - templateCustomization.setIncludeGenerationDate(false); - return templateCustomization; + @Test + @DisplayName("Should return an empty file with basic content when the input file is missing and it is set to not fail") + void readMetadataAndGenerateRenderedFile_shouldReturnEmptyFile_whenInputFileIsMissing() throws IOException { + // Given + TemplateType templateType = TemplateType.ADOC; + Path resolve = tempDir.resolve("IT-output-non-existing-source-" + templateType.name() + templateType.getExtension()); + AbstractTemplateCustomization templateCustomization = getTemplateCustomization(templateType); + CreateDocumentCommand command = new CreateDocumentCommand(PROJECT, TEST_DOCUMENT_HEADER, new File("non-existing-file.json"), templateType.getSingleTemplate(templateCustomization.getTemplateMode()), resolve.toFile(), templateCustomization); + command.setFailOnMissingInput(false); + command.setDescription(TEST_DESCRIPTION); + + // When + underTest.readMetadataAndGenerateRenderedFile(command); + + // Then + assertThat(resolve).hasSameTextualContentAs(Path.of(MAIN_EXPECTED_FOLDER + "expected-non-existing-input-file.adoc")); + } + + @Test + @DisplayName("Should throw DocumentGenerationException exception when the input file is missing and it is meant to fail in this case") + void readMetadataAndGenerateRenderedFile_shouldFail_whenInputFileIsMissingAndItIsMeanToFail() { + // Given + TemplateType templateType = TemplateType.ADOC; + Path resolve = tempDir.resolve("IT-output-non-existing-source-" + templateType.name() + templateType.getExtension()); + AbstractTemplateCustomization templateCustomization = getTemplateCustomization(templateType); + CreateDocumentCommand command = new CreateDocumentCommand(PROJECT, TEST_DOCUMENT_HEADER, new File("non-existing-file.json"), templateType.getSingleTemplate(templateCustomization.getTemplateMode()), resolve.toFile(), templateCustomization); + command.setFailOnMissingInput(true); + command.setDescription(TEST_DESCRIPTION); + + // When + ThrowingCallable callable = () -> underTest.readMetadataAndGenerateRenderedFile(command); + + // Then + assertThatThrownBy(callable).isInstanceOf(DocumentGenerationException.class); } static class TestCase { diff --git a/spring-configuration-property-documenter-core/src/it/resources/it/aggregated/expected-non-existing-input-file.adoc b/spring-configuration-property-documenter-core/src/it/resources/it/aggregated/expected-non-existing-input-file.adoc new file mode 100644 index 0000000..067adc3 --- /dev/null +++ b/spring-configuration-property-documenter-core/src/it/resources/it/aggregated/expected-non-existing-input-file.adoc @@ -0,0 +1,14 @@ += IT +:toc: auto +:toc-title: Table of Contents +:toclevels: 4 + +This is a test description + + + +[cols="2,1,3,1,1"] +|=== +|Key |Type |Description |Default value |Deprecation + +|=== diff --git a/spring-configuration-property-documenter-core/src/it/resources/it/single/expected-non-existing-input-file.adoc b/spring-configuration-property-documenter-core/src/it/resources/it/single/expected-non-existing-input-file.adoc new file mode 100644 index 0000000..31808b2 --- /dev/null +++ b/spring-configuration-property-documenter-core/src/it/resources/it/single/expected-non-existing-input-file.adoc @@ -0,0 +1,10 @@ += IT +:toc: auto +:toc-title: Table of Contents +:toclevels: 4 + +This is a test description + + + + diff --git a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/action/DocumentGenerationAction.java b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/action/DocumentGenerationAction.java index ed01d90..0710fa0 100644 --- a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/action/DocumentGenerationAction.java +++ b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/action/DocumentGenerationAction.java @@ -41,6 +41,7 @@ public class DocumentGenerationAction { private List includedGroups; private List excludedProperties; private List includedProperties; + private boolean failOnMissingInput; public DocumentGenerationAction(Project project, String name, TemplateCustomization templateCustomization, TemplateType templateType, File metadataInput) { this.project = Objects.requireNonNull(project, "project is NULL"); @@ -69,6 +70,7 @@ private void generateDocument() throws DocumentGenerationException { command.setIncludedGroups(includedGroups); command.setExcludedProperties(excludedProperties); command.setIncludedProperties(includedProperties); + command.setFailOnMissingInput(failOnMissingInput); documenter.readMetadataAndGenerateRenderedFile(command); } catch (IOException e) { throw new DocumentGenerationException("Unable to create final document", e); @@ -124,4 +126,11 @@ public void setIncludedProperties(List includedProperties) { this.includedProperties = includedProperties; } + public boolean isFailOnMissingInput() { + return failOnMissingInput; + } + + public void setFailOnMissingInput(boolean failOnMissingInput) { + this.failOnMissingInput = failOnMissingInput; + } } diff --git a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/reader/MetadataReader.java b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/reader/MetadataReader.java index 7118920..d513a5a 100644 --- a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/reader/MetadataReader.java +++ b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/reader/MetadataReader.java @@ -60,13 +60,16 @@ public Map> readPropertiesAsMap(InputStream metadataStrea *

* NOTE: The current implementation is a bit fuzzy, when the time comes we can come up with a more efficient solution, but right now this is the "contact" basically. * - * @param metadataStream stream containing the content of the spring-configuration-metadata.json. + * @param metadataStream stream containing the content of the spring-configuration-metadata.json or an empty list if the incoming stream is empty. * @return groups and properties converted to a List of {@link PropertyGroup}. * @since 0.1.0 */ public List readPropertiesAsPropertyGroupList(InputStream metadataStream) { Objects.requireNonNull(metadataStream, "metadataStream is NULL"); try { + if (metadataStream.available() == 0) { + return List.of(); + } ConfigurationMetadata configurationMetadata = new JsonMarshaller().read(metadataStream); Map> propertyMap = getPropertyMap(configurationMetadata); Map> propertyGroupsByType = getPropertyGroups(configurationMetadata); @@ -94,9 +97,9 @@ private Property updateProperty(PropertyGroup propertyGroup, Property property) private List flattenValues(Map> propertyGroupsByType) { return propertyGroupsByType.values() - .stream() - .flatMap(Collection::stream) - .collect(Collectors.toList()); + .stream() + .flatMap(Collection::stream) + .collect(Collectors.toList()); } private void updateGroupsWithPropertiesAndAssociations(Map> propertyMap, Map> propertyGroupsByType) { @@ -114,10 +117,10 @@ private void updateGroupsWithPropertiesAndAssociations(Map updatePropertiesAndReturnNestedGroups(Map> propertyMap, Map.Entry> propertyEntry) { return propertyEntry.getValue() - .stream() - .map(propertyGroup -> setProperties(propertyMap, propertyGroup)) - .filter(PropertyGroup::isNested) - .collect(Collectors.toList()); + .stream() + .map(propertyGroup -> setProperties(propertyMap, propertyGroup)) + .filter(PropertyGroup::isNested) + .collect(Collectors.toList()); } private PropertyGroup setProperties(Map> propertyMap, PropertyGroup propertyGroup) { @@ -127,19 +130,19 @@ private PropertyGroup setProperties(Map> propertyMap, Pro return propertyGroup; } List collectedProperties = properties.stream() - .filter(property -> property.getFqName().startsWith(propertyGroup.getGroupName()) || propertyGroup.isUnknownGroup()) - .map(property -> updateProperty(propertyGroup, property)) - .collect(Collectors.toList()); + .filter(property -> property.getFqName().startsWith(propertyGroup.getGroupName()) || propertyGroup.isUnknownGroup()) + .map(property -> updateProperty(propertyGroup, property)) + .collect(Collectors.toList()); propertyGroup.setProperties(collectedProperties); return propertyGroup; } private Map> getPropertyGroups(ConfigurationMetadata configurationMetadata) { Map> propertyGroupMap = configurationMetadata.getItems() - .stream() - .filter(itemMetadata -> itemMetadata.isOfItemType(ItemMetadata.ItemType.GROUP)) - .map(itemMetadata -> new PropertyGroup(itemMetadata.getName(), itemMetadata.getType(), getSourceTypeOrDefault(itemMetadata))) - .collect(Collectors.groupingBy(PropertyGroup::getSourceType, Collectors.toList())); + .stream() + .filter(itemMetadata -> itemMetadata.isOfItemType(ItemMetadata.ItemType.GROUP)) + .map(itemMetadata -> new PropertyGroup(itemMetadata.getName(), itemMetadata.getType(), getSourceTypeOrDefault(itemMetadata))) + .collect(Collectors.groupingBy(PropertyGroup::getSourceType, Collectors.toList())); List value = new ArrayList<>(); value.add(PropertyGroup.createUnknownGroup()); propertyGroupMap.put(PropertyGroupConstants.UNKNOWN, value); @@ -149,11 +152,11 @@ private Map> getPropertyGroups(ConfigurationMetadata private Map> getPropertyMap(ConfigurationMetadata configurationMetadata) { Function getSourceType = this::getSourceTypeOrDefault; return configurationMetadata.getItems() - .stream() - .filter(itemMetadata -> itemMetadata.isOfItemType(ItemMetadata.ItemType.PROPERTY)) - .collect(Collectors.groupingBy(getSourceType, - Collectors.mapping(this::mapToProperty, Collectors.toList())) - ); + .stream() + .filter(itemMetadata -> itemMetadata.isOfItemType(ItemMetadata.ItemType.PROPERTY)) + .collect(Collectors.groupingBy(getSourceType, + Collectors.mapping(this::mapToProperty, Collectors.toList())) + ); } private String getSourceTypeOrDefault(ItemMetadata current) { diff --git a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/resolver/InputFileResolutionStrategy.java b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/resolver/InputFileResolutionStrategy.java new file mode 100644 index 0000000..3118725 --- /dev/null +++ b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/resolver/InputFileResolutionStrategy.java @@ -0,0 +1,37 @@ +package org.rodnansol.core.generator.resolver; + +/** + * Represents the strategies for resolving input file operations. + * + * @author nandorholozsnyak + * @since 0.7.0 + */ +public enum InputFileResolutionStrategy { + + /** + * Throw an exception if the input file is not found. + * + * @since 0.7.0 + */ + THROW_EXCEPTION, + + /** + * Return an empty input stream is the file is not found. + * + * @since 0.7.0 + */ + RETURN_EMPTY; + + /** + * Creates an instance of InputFileResolutionStrategy based on the boolean value provided. + * + * @param value the boolean value to determine the resolution strategy + * @return the corresponding InputFileResolutionStrategy instance: + * - THROW_EXCEPTION if the value is true + * - RETURN_EMPTY if the value is false + */ + public static InputFileResolutionStrategy ofBooleanValue(boolean value) { + return value ? THROW_EXCEPTION : RETURN_EMPTY; + } + +} diff --git a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/resolver/MetadataInputResolverContext.java b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/resolver/MetadataInputResolverContext.java index e3c50ae..55eaa7c 100644 --- a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/resolver/MetadataInputResolverContext.java +++ b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/resolver/MetadataInputResolverContext.java @@ -17,11 +17,19 @@ public class MetadataInputResolverContext { public static final MetadataInputResolverContext INSTANCE = new MetadataInputResolverContext(); - private static final List METADATA_INPUT_RESOLVERS = List.of( - new JarFileMetadataInputResolver(), - new FileMetadataInputResolver(), - new DirectoryMetadataInputResolver() - ); + private final List metadataInputResolvers; + + public MetadataInputResolverContext() { + this(List.of( + new JarFileMetadataInputResolver(), + new FileMetadataInputResolver(), + new DirectoryMetadataInputResolver() + )); + } + + public MetadataInputResolverContext(List metadataInputResolvers) { + this.metadataInputResolvers = metadataInputResolvers; + } /** * Returns the requested file from the given input. @@ -37,11 +45,11 @@ public class MetadataInputResolverContext { * * @param project project instance. * @param input input. - * @return the file's content in an {@link InputStream} instance. - * @throws DocumentGenerationException if none of the resolvers are able to find the file. + * @return the file's content in an {@link InputStream} instance or an empty input stream if the {@link InputFileResolutionStrategy} is RETURN_EMPTY + * @throws DocumentGenerationException if none of the resolvers are able to find the file and the {@link InputFileResolutionStrategy} is THROW_EXCEPTION */ - public InputStream getInputStreamFromFile(Project project, File input) { - for (MetadataInputResolver metadataInputResolver : METADATA_INPUT_RESOLVERS) { + public InputStream getInputStreamFromFile(Project project, File input, InputFileResolutionStrategy inputFileResolutionStrategy) { + for (MetadataInputResolver metadataInputResolver : metadataInputResolvers) { if (metadataInputResolver.supports(input)) { InputStream inputStream = metadataInputResolver.resolveInputStream(project, input); if (inputStream != null) { @@ -49,7 +57,10 @@ public InputStream getInputStreamFromFile(Project project, File input) { } } } - throw new DocumentGenerationException("Unable to locate the spring-configuration-metadata.json file from the given input:[" + input + "]"); + if (inputFileResolutionStrategy == InputFileResolutionStrategy.THROW_EXCEPTION) { + throw new DocumentGenerationException("Unable to locate the spring-configuration-metadata.json file from the given input:[" + input + "]"); + } + return InputStream.nullInputStream(); } } diff --git a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/template/customization/AbstractTemplateCustomization.java b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/template/customization/AbstractTemplateCustomization.java index c45ba5c..48ba83d 100644 --- a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/template/customization/AbstractTemplateCustomization.java +++ b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/template/customization/AbstractTemplateCustomization.java @@ -1,8 +1,8 @@ package org.rodnansol.core.generator.template.customization; import edu.umd.cs.findbugs.annotations.NonNull; -import org.rodnansol.core.generator.template.data.PropertyGroupConstants; import org.rodnansol.core.generator.template.TemplateMode; +import org.rodnansol.core.generator.template.data.PropertyGroupConstants; import java.io.Serializable; import java.util.Objects; diff --git a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/AggregationDocumenter.java b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/AggregationDocumenter.java index 20e8303..5c705ad 100644 --- a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/AggregationDocumenter.java +++ b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/AggregationDocumenter.java @@ -5,14 +5,15 @@ import com.github.jknack.handlebars.internal.lang3.tuple.Pair; import org.rodnansol.core.generator.DocumentGenerationException; import org.rodnansol.core.generator.reader.MetadataReader; +import org.rodnansol.core.generator.resolver.InputFileResolutionStrategy; import org.rodnansol.core.generator.resolver.MetadataInputResolverContext; -import org.rodnansol.core.generator.template.data.MainTemplateData; -import org.rodnansol.core.generator.template.data.PropertyGroup; -import org.rodnansol.core.generator.template.data.SubTemplateData; +import org.rodnansol.core.generator.template.TemplateType; import org.rodnansol.core.generator.template.compiler.TemplateCompiler; import org.rodnansol.core.generator.template.compiler.TemplateCompilerMemoryStoreConstants; -import org.rodnansol.core.generator.template.TemplateType; import org.rodnansol.core.generator.template.customization.TemplateCustomization; +import org.rodnansol.core.generator.template.data.MainTemplateData; +import org.rodnansol.core.generator.template.data.PropertyGroup; +import org.rodnansol.core.generator.template.data.SubTemplateData; import org.rodnansol.core.generator.writer.postprocess.PostProcessPropertyGroupsCommand; import org.rodnansol.core.generator.writer.postprocess.PropertyGroupFilterService; import org.rodnansol.core.util.CoreFileUtils; @@ -72,11 +73,16 @@ private Pair, List> createSubTemplateDataAn List propertyGroups = new ArrayList<>(createAggregationCommand.getCombinedInputs().size()); for (CombinedInput entry : createAggregationCommand.getCombinedInputs()) { LOGGER.info("Processing entry:[{}]", entry); - try (InputStream inputStream = metadataInputResolverContext.getInputStreamFromFile(createAggregationCommand.getProject(), entry.getInput())) { + try (InputStream inputStream = getInputStreamFromFile(createAggregationCommand, entry)) { List groups = metadataReader.readPropertiesAsPropertyGroupList(inputStream); filterGroupsAndProperties(createAggregationCommand.getTemplateCustomization(), entry, groups); propertyGroups.addAll(groups); subTemplateDataList.add(createModuleTemplateData(createAggregationCommand.getTemplateCustomization(), entry.getSectionName(), groups, entry.getDescription())); + } catch (DocumentGenerationException e) { + // [#68] Generate an empty file if the spring-configuration-metadata.json is missing + // Because of the introduction of the "failOnMissingInput" attribute this exception must be propagated + // Other exceptions can be just logged out + throw e; } catch (Exception e) { LOGGER.warn("Error during reading an entry:[" + entry.getInput() + "]", e); } @@ -84,6 +90,12 @@ private Pair, List> createSubTemplateDataAn return new ImmutablePair<>(subTemplateDataList, propertyGroups); } + private InputStream getInputStreamFromFile(CreateAggregationCommand createAggregationCommand, CombinedInput entry) { + return metadataInputResolverContext.getInputStreamFromFile(createAggregationCommand.getProject(), + entry.getInput(), + InputFileResolutionStrategy.ofBooleanValue(createAggregationCommand.isFailOnMissingInput())); + } + void filterGroupsAndProperties(TemplateCustomization templateCustomization, CombinedInput entry, List groups) { propertyGroupFilterService.postProcessPropertyGroups(new PostProcessPropertyGroupsCommand(templateCustomization, groups, entry.getExcludedGroups(), entry.getIncludedGroups(), entry.getExcludedProperties(), entry.getIncludedProperties())); } diff --git a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/CombinedInput.java b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/CombinedInput.java index 64fd054..0b39fd0 100644 --- a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/CombinedInput.java +++ b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/CombinedInput.java @@ -3,6 +3,7 @@ import java.io.File; import java.util.List; import java.util.Objects; +import java.util.StringJoiner; /** * @author nandorholozsnyak @@ -70,14 +71,14 @@ public void setIncludedGroups(List includedGroups) { @Override public String toString() { - return "CombinedInput{" + - "input=" + input + '\n' + - ", sectionName='" + sectionName + '\'' + '\n' + - ", description='" + description + '\'' + '\n' + - ", excludedProperties=" + excludedProperties + '\n' + - ", includedProperties=" + includedProperties + '\n' + - ", excludedGroups=" + excludedGroups + '\n' + - ", includedGroups=" + includedGroups + '\n' + - '}'; + return new StringJoiner(", ", CombinedInput.class.getSimpleName() + "[", "]") + .add("input=" + input) + .add("sectionName='" + sectionName + "'") + .add("description='" + description + "'") + .add("excludedGroups=" + excludedGroups) + .add("includedGroups=" + includedGroups) + .add("excludedProperties=" + excludedProperties) + .add("includedProperties=" + includedProperties) + .toString(); } } diff --git a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/CreateAggregationCommand.java b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/CreateAggregationCommand.java index 27625b6..e5a1972 100644 --- a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/CreateAggregationCommand.java +++ b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/CreateAggregationCommand.java @@ -7,6 +7,7 @@ import java.io.File; import java.util.List; import java.util.Objects; +import java.util.StringJoiner; /** * Class representing the aggregation action command. @@ -24,6 +25,7 @@ public class CreateAggregationCommand { private final File output; private String description; private CustomTemplate customTemplate; + private boolean failOnMissingInput; public CreateAggregationCommand(Project project, String aggregatedDocumentHeader, List inputStreams, TemplateType templateType, TemplateCustomization templateCustomization, File output) { this.project = Objects.requireNonNull(project, "project is NULL"); @@ -74,17 +76,26 @@ public void setCustomTemplate(CustomTemplate customTemplate) { this.customTemplate = customTemplate; } + public boolean isFailOnMissingInput() { + return failOnMissingInput; + } + + public void setFailOnMissingInput(boolean failOnMissingInput) { + this.failOnMissingInput = failOnMissingInput; + } + @Override public String toString() { - return "CreateAggregationCommand{ \n" + - "project=" + project + '\n' + - ", aggregatedDocumentHeader='" + aggregatedDocumentHeader + '\'' + '\n' + - ", combinedInputs=" + combinedInputs + '\n' + - ", templateType=" + templateType + '\n' + - ", templateCustomization=" + templateCustomization + '\n' + - ", output=" + output + '\n' + - ", description='" + description + '\'' + '\n' + - ", customTemplate=" + customTemplate + '\n' + - '}'; + return new StringJoiner(", ", CreateAggregationCommand.class.getSimpleName() + "[", "]") + .add("project=" + project) + .add("aggregatedDocumentHeader='" + aggregatedDocumentHeader + "'") + .add("combinedInputs=" + combinedInputs) + .add("templateType=" + templateType) + .add("templateCustomization=" + templateCustomization) + .add("output=" + output) + .add("description='" + description + "'") + .add("customTemplate=" + customTemplate) + .add("failOnMissingInput=" + failOnMissingInput) + .toString(); } } diff --git a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/CreateDocumentCommand.java b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/CreateDocumentCommand.java index bfd918c..82efe42 100644 --- a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/CreateDocumentCommand.java +++ b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/CreateDocumentCommand.java @@ -26,6 +26,7 @@ public class CreateDocumentCommand { private List includedGroups; private List excludedProperties; private List includedProperties; + private boolean failOnMissingInput; public CreateDocumentCommand(Project project, String name, File metadataInput, String template, File output, TemplateCustomization templateCustomization) { this.project = Objects.requireNonNull(project, "project is NULL"); @@ -99,4 +100,13 @@ public List getIncludedGroups() { public void setIncludedGroups(List includedGroups) { this.includedGroups = includedGroups; } + + + public boolean isFailOnMissingInput() { + return failOnMissingInput; + } + + public void setFailOnMissingInput(boolean failOnMissingInput) { + this.failOnMissingInput = failOnMissingInput; + } } diff --git a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/Documenter.java b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/Documenter.java index 6585f1b..c318316 100644 --- a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/Documenter.java +++ b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/generator/writer/Documenter.java @@ -1,6 +1,7 @@ package org.rodnansol.core.generator.writer; import org.rodnansol.core.generator.reader.MetadataReader; +import org.rodnansol.core.generator.resolver.InputFileResolutionStrategy; import org.rodnansol.core.generator.resolver.MetadataInputResolverContext; import org.rodnansol.core.generator.template.data.MainTemplateData; import org.rodnansol.core.generator.template.data.PropertyGroup; @@ -67,7 +68,9 @@ private void setupMemoryStore(MainTemplateData mainTemplateData) { } private MainTemplateData createTemplateData(CreateDocumentCommand createDocumentCommand) throws IOException { - try (InputStream inputStream = metadataInputResolverContext.getInputStreamFromFile(createDocumentCommand.getProject(), createDocumentCommand.getMetadataInput())) { + try (InputStream inputStream = metadataInputResolverContext.getInputStreamFromFile(createDocumentCommand.getProject(), + createDocumentCommand.getMetadataInput(), + InputFileResolutionStrategy.ofBooleanValue(createDocumentCommand.isFailOnMissingInput()))) { List propertyGroups = metadataReader.readPropertiesAsPropertyGroupList(inputStream); TemplateCustomization templateCustomization = createDocumentCommand.getTemplateCustomization(); filterGroupsAndProperties(createDocumentCommand, propertyGroups, templateCustomization); diff --git a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/project/Project.java b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/project/Project.java index 0e4ef8d..9d6c59c 100644 --- a/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/project/Project.java +++ b/spring-configuration-property-documenter-core/src/main/java/org/rodnansol/core/project/Project.java @@ -4,6 +4,7 @@ import java.io.File; import java.util.List; +import java.util.StringJoiner; /** * Class representing a project. @@ -46,12 +47,12 @@ public ProjectType getProjectType() { @Override public String toString() { - return "Project{" + - "basedir=" + basedir + '\n' + - ", name='" + name + '\'' + '\n' + - ", modules=" + modules + '\n' + - ", projectType=" + projectType + '\n' + - '}'; + return new StringJoiner(", ", Project.class.getSimpleName() + "[", "]") + .add("basedir=" + basedir) + .add("name='" + name + "'") + .add("projectType=" + projectType) + .add("modules=" + modules) + .toString(); } /** diff --git a/spring-configuration-property-documenter-core/src/test/java/org/rodnansol/core/generator/reader/MetadataReaderTest.java b/spring-configuration-property-documenter-core/src/test/java/org/rodnansol/core/generator/reader/MetadataReaderTest.java index 4773e84..2baf51c 100644 --- a/spring-configuration-property-documenter-core/src/test/java/org/rodnansol/core/generator/reader/MetadataReaderTest.java +++ b/spring-configuration-property-documenter-core/src/test/java/org/rodnansol/core/generator/reader/MetadataReaderTest.java @@ -183,7 +183,6 @@ void readPropertiesAsPropertyGroupList_shouldReturnListOfPropertyGroup_whenInput @ParameterizedTest @ValueSource(strings = { - TEST_RESOURCES_DIRECTORY + "spring-configuration-metadata-empty.json", TEST_RESOURCES_DIRECTORY + "spring-configuration-metadata-invalid.json"}) void readPropertiesAsPropertyGroupList_shouldThrowMetadataConversionException_whenAnErrorOccursDuringConversion(String metadataFileLocation) throws FileNotFoundException { // Given @@ -195,6 +194,20 @@ void readPropertiesAsPropertyGroupList_shouldThrowMetadataConversionException_wh } + @ParameterizedTest + @ValueSource(strings = { + TEST_RESOURCES_DIRECTORY + "spring-configuration-metadata-empty.json"}) + void readPropertiesAsPropertyGroupList_shouldReturnEmptyList_whenInputIsEmpty(String metadataFileLocation) throws FileNotFoundException { + // Given + + // When + List propertyGroups = underTest.readPropertiesAsPropertyGroupList(new FileInputStream(metadataFileLocation)); + + // Then + assertThat(propertyGroups).isEmpty(); + + } + @ParameterizedTest @MethodSource("validMetadataFileTestCasesWithMaps") void readPropertiesAsMap_shouldReturnListOfPropertyGroup_whenInputFileContainsProperties(ReadPropertiesAsMapTestCase testCase) throws FileNotFoundException { diff --git a/spring-configuration-property-documenter-core/src/test/java/org/rodnansol/core/generator/resolver/MetadataInputResolverContextTest.java b/spring-configuration-property-documenter-core/src/test/java/org/rodnansol/core/generator/resolver/MetadataInputResolverContextTest.java new file mode 100644 index 0000000..9c81d08 --- /dev/null +++ b/spring-configuration-property-documenter-core/src/test/java/org/rodnansol/core/generator/resolver/MetadataInputResolverContextTest.java @@ -0,0 +1,72 @@ +package org.rodnansol.core.generator.resolver; + +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.rodnansol.core.generator.DocumentGenerationException; +import org.rodnansol.core.project.simple.SimpleProject; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MetadataInputResolverContextTest { + + @Test + void getInputStreamFromFile_shouldThrowException_whenResolverDoesNotSupportAndStrategyIsThrowException() { + // Given + File file = new File("test.json"); + MetadataInputResolver metadataInputResolver = mock(MetadataInputResolver.class); + when(metadataInputResolver.supports(file)).thenReturn(false); + // When + MetadataInputResolverContext underTest = new MetadataInputResolverContext(List.of(metadataInputResolver)); + ThrowingCallable throwable = () -> underTest.getInputStreamFromFile(new SimpleProject(new File("."), "test-folder"), + file, InputFileResolutionStrategy.THROW_EXCEPTION); + // Then + assertThatThrownBy(throwable).isInstanceOf(DocumentGenerationException.class); + } + + @Test + void getInputStreamFromFile_shouldReturnNullStream_whenResolverDoesNotSupportAndStrategyIsReturnEmpty() throws IOException { + // Given + File file = new File("test.json"); + MetadataInputResolver metadataInputResolver = mock(MetadataInputResolver.class); + when(metadataInputResolver.supports(file)).thenReturn(false); + // When + MetadataInputResolverContext underTest = new MetadataInputResolverContext(List.of(metadataInputResolver)); + InputStream inputStream = underTest.getInputStreamFromFile(new SimpleProject(new File("."), "test-folder"), + file, InputFileResolutionStrategy.RETURN_EMPTY); + + // Then + assertThat(inputStream).isNotNull(); + assertThat(inputStream.read()).isEqualTo(-1); + } + + @Test + void getInputStreamFromFile_shouldReturnInputStreamContainingTheFileContent_whenResolverSupports() throws IOException { + // Given + File inputFile = new File("test.json"); + SimpleProject simpleProject = new SimpleProject(new File("."), "test-folder"); + MetadataInputResolver metadataInputResolver = mock(MetadataInputResolver.class); + when(metadataInputResolver.supports(inputFile)).thenReturn(true); + when(metadataInputResolver.resolveInputStream(simpleProject, inputFile)) + .thenReturn(new ByteArrayInputStream("Hello World".getBytes())); + + // When + MetadataInputResolverContext underTest = new MetadataInputResolverContext(List.of(metadataInputResolver)); + InputStream inputStream = underTest.getInputStreamFromFile(simpleProject, + inputFile, InputFileResolutionStrategy.RETURN_EMPTY); + + // Then + assertThat(inputStream).hasContent("Hello World"); + } +} \ No newline at end of file diff --git a/spring-configuration-property-documenter-core/src/test/java/org/rodnansol/core/generator/writer/DocumenterTest.java b/spring-configuration-property-documenter-core/src/test/java/org/rodnansol/core/generator/writer/DocumenterTest.java index 683de4b..e5382f9 100644 --- a/spring-configuration-property-documenter-core/src/test/java/org/rodnansol/core/generator/writer/DocumenterTest.java +++ b/spring-configuration-property-documenter-core/src/test/java/org/rodnansol/core/generator/writer/DocumenterTest.java @@ -7,6 +7,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.rodnansol.core.generator.reader.MetadataReader; +import org.rodnansol.core.generator.resolver.InputFileResolutionStrategy; import org.rodnansol.core.generator.resolver.MetadataInputResolverContext; import org.rodnansol.core.generator.template.data.MainTemplateData; import org.rodnansol.core.generator.template.data.Property; @@ -76,7 +77,7 @@ void readMetadataAndGenerateRenderedFile_shouldWriteContentToFile() throws IOExc new PropertyGroup("group1", "type", "sourceType", List.of(new Property("org.rodnansol.value", "java.lang.String"))), new PropertyGroup("group2", "type", "sourceType", List.of(new Property("org.rodnansol.another-value", "java.lang.String"))) ); - when(metadataInputResolverContext.getInputStreamFromFile(project, inputFile)).thenReturn(inputStream); + when(metadataInputResolverContext.getInputStreamFromFile(project, inputFile, InputFileResolutionStrategy.RETURN_EMPTY)).thenReturn(inputStream); when(metadataReader.readPropertiesAsPropertyGroupList(inputStream)).thenReturn(propertyGroups); when(templateCompiler.compileTemplate(eq(singleTemplate), any())).thenReturn("Hello World"); when(templateCompiler.getMemoryStore()).thenReturn(mock(TemplateCompilerMemoryStore.class)); diff --git a/spring-configuration-property-documenter-gradle-plugin/pom.xml b/spring-configuration-property-documenter-gradle-plugin/pom.xml index fb587cb..807fc3c 100644 --- a/spring-configuration-property-documenter-gradle-plugin/pom.xml +++ b/spring-configuration-property-documenter-gradle-plugin/pom.xml @@ -106,15 +106,23 @@ - - - gradle - https://repo.gradle.org/gradle/libs-releases-local/ - - - google - https://maven.google.com/ - - + + + gradle-build + + true + + + + gradle + https://repo.gradle.org/gradle/libs-releases-local/ + + + google + https://maven.google.com/ + + + + diff --git a/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/AggregationInput.java b/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/AggregationInput.java index af65920..d40178a 100644 --- a/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/AggregationInput.java +++ b/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/AggregationInput.java @@ -9,6 +9,7 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import java.util.StringJoiner; /** * Class representing an input in the gradle.build's task configuration. @@ -144,14 +145,14 @@ public void setIncludedGroups(List includedGroups) { @Override public String toString() { - return "AggregationInput{" + - "excludedProperties=" + excludedProperties + - ", includedProperties=" + includedProperties + - ", excludedGroups=" + excludedGroups + - ", includedGroups=" + includedGroups + - ", name='" + name + '\'' + - ", description='" + description + '\'' + - ", input=" + input + - '}'; + return new StringJoiner(", ", AggregationInput.class.getSimpleName() + "[", "]") + .add("excludedProperties=" + excludedProperties) + .add("includedProperties=" + includedProperties) + .add("excludedGroups=" + excludedGroups) + .add("includedGroups=" + includedGroups) + .add("name='" + name + "'") + .add("description='" + description + "'") + .add("input=" + input) + .toString(); } } diff --git a/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/GenerateAndAggregateDocumentsTask.java b/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/GenerateAndAggregateDocumentsTask.java index 0b18a2a..a7cbdc2 100644 --- a/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/GenerateAndAggregateDocumentsTask.java +++ b/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/GenerateAndAggregateDocumentsTask.java @@ -33,6 +33,7 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.StringJoiner; import java.util.stream.Collectors; /** @@ -177,6 +178,16 @@ public abstract class GenerateAndAggregateDocumentsTask extends ConventionTask { @Option(option = "footerTemplate", description = "Template file to be used in the footer section generation") private String footerTemplate; + /** + * Define if the process should fail if the given input file is not found. + * + * @since 0.7.0 + */ + @Input + @Optional + @Option(option = "failOnMissingInput", description = "Fail if the input file is missing") + private boolean failOnMissingInput = true; + @TaskAction public void execute() { LOGGER.info("Creating aggregation based on the following inputs:[{}]", metadataInputs); @@ -191,6 +202,7 @@ private CreateAggregationCommand createAggregationCommand() { CreateAggregationCommand createAggregationCommand = new CreateAggregationCommand(gradleProject, documentName, combinedInputs, type, getActualTemplateCustomization(), outputFile); createAggregationCommand.setDescription(documentDescription); createAggregationCommand.setCustomTemplate(new CustomTemplate(headerTemplate, contentTemplate, footerTemplate)); + createAggregationCommand.setFailOnMissingInput(failOnMissingInput); return createAggregationCommand; } @@ -312,6 +324,14 @@ public List getMetadataInputs() { return metadataInputs; } + public boolean isFailOnMissingInput() { + return failOnMissingInput; + } + + public void setFailOnMissingInput(boolean failOnMissingInput) { + this.failOnMissingInput = failOnMissingInput; + } + /** * DSL entry point for the {@link GenerateAndAggregateDocumentsTask#markdownCustomization} field. */ @@ -370,4 +390,23 @@ public void metadata(Closure closure) { } } + @Override + public String toString() { + return new StringJoiner(", ", GenerateAndAggregateDocumentsTask.class.getSimpleName() + "[", "]") + .add("metadataInputs=" + metadataInputs) + .add("documentName='" + documentName + "'") + .add("documentDescription='" + documentDescription + "'") + .add("type=" + type) + .add("htmlCustomization=" + htmlCustomization) + .add("markdownCustomization=" + markdownCustomization) + .add("asciiDocCustomization=" + asciiDocCustomization) + .add("xmlCustomization=" + xmlCustomization) + .add("outputFile=" + outputFile) + .add("templateCompilerName='" + templateCompilerName + "'") + .add("headerTemplate='" + headerTemplate + "'") + .add("contentTemplate='" + contentTemplate + "'") + .add("footerTemplate='" + footerTemplate + "'") + .add("failOnMissingInput=" + failOnMissingInput) + .toString(); + } } diff --git a/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/GeneratePropertyDocumentTask.java b/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/GeneratePropertyDocumentTask.java index 28fca14..3161a66 100644 --- a/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/GeneratePropertyDocumentTask.java +++ b/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/GeneratePropertyDocumentTask.java @@ -27,6 +27,7 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.StringJoiner; /** * Task to generate a single document. @@ -90,10 +91,9 @@ public abstract class GeneratePropertyDocumentTask extends ConventionTask { * * @since 0.5.0 */ - @InputFile - @Optional @Option(option = "metadataInput", description = "Metadata input file") private File metadataInput = new File("build/classes/java/main/META-INF/spring-configuration-metadata.json"); + /** * Output file. * @@ -103,6 +103,7 @@ public abstract class GeneratePropertyDocumentTask extends ConventionTask { @Optional @Option(option = "outputFile", description = "Output file") private File outputFile; + /** * Define if the process should fail on an error or not. * @@ -111,7 +112,7 @@ public abstract class GeneratePropertyDocumentTask extends ConventionTask { @Input @Optional @Option(option = "failOnError", description = "Fail on error or not") - private boolean failOnError = true; + private Boolean failOnError = true; /** * Template compiler class's fully qualified name . *

@@ -192,6 +193,16 @@ public abstract class GeneratePropertyDocumentTask extends ConventionTask { @Internal private XmlTemplateCustomization xmlCustomization = new XmlTemplateCustomization(); + /** + * Define if the process should fail if the given input file is not found. + * + * @since 0.7.0 + */ + @Input + @Optional + @Option(option = "failOnMissingInput", description = "Fail if the input file is missing") + private Boolean failOnMissingInput = true; + @TaskAction public void execute() { try { @@ -210,7 +221,8 @@ public void execute() { private DocumentGenerationAction setupAction() { Project project = getProject(); GradleProject gradleProject = ProjectFactory.ofGradleProject(project.getProjectDir(), project.getName(), List.of()); - DocumentGenerationAction documentGenerationAction = new DocumentGenerationAction(gradleProject, documentName, getActualTemplateCustomization(), type, metadataInput); + DocumentGenerationAction documentGenerationAction = new DocumentGenerationAction(gradleProject, documentName, + getActualTemplateCustomization(), type, metadataInput); documentGenerationAction.setTemplateCompilerName(templateCompilerName); documentGenerationAction.setDescription(documentDescription); documentGenerationAction.setTemplate(template); @@ -219,6 +231,7 @@ private DocumentGenerationAction setupAction() { documentGenerationAction.setIncludedGroups(includedGroups); documentGenerationAction.setExcludedProperties(excludedProperties); documentGenerationAction.setIncludedProperties(includedProperties); + documentGenerationAction.setFailOnMissingInput(failOnMissingInput); return documentGenerationAction; } @@ -268,6 +281,8 @@ public void setType(TemplateType type) { this.type = type; } + @InputFile + @Optional public File getMetadataInput() { return metadataInput; } @@ -284,14 +299,6 @@ public void setOutputFile(File outputFile) { this.outputFile = outputFile; } - public Boolean getFailOnError() { - return failOnError; - } - - public void setFailOnError(Boolean failOnError) { - this.failOnError = failOnError; - } - public String getTemplateCompilerName() { return templateCompilerName; } @@ -348,26 +355,43 @@ public XmlTemplateCustomization getXmlCustomization() { return xmlCustomization; } + public Boolean getFailOnError() { + return failOnError; + } + + public void setFailOnError(Boolean failOnError) { + this.failOnError = failOnError; + } + + public Boolean getFailOnMissingInput() { + return failOnMissingInput; + } + + public void setFailOnMissingInput(Boolean failOnMissingInput) { + this.failOnMissingInput = failOnMissingInput; + } + @Override public String toString() { - return "GenerateDocumentTask{" + - "documentName='" + documentName + '\'' + - ", documentDescription='" + documentDescription + '\'' + - ", template='" + template + '\'' + - ", type='" + type + '\'' + - ", metadataInput=" + metadataInput + - ", outputFile=" + outputFile + - ", failOnError=" + failOnError + - ", templateCompilerName='" + templateCompilerName + '\'' + - ", excludedProperties=" + excludedProperties + - ", includedProperties=" + includedProperties + - ", excludedGroups=" + excludedGroups + - ", includedGroups=" + includedGroups + - ", asciiDocCustomization=" + asciiDocCustomization + - ", htmlCustomization=" + htmlCustomization + - ", markdownCustomization=" + markdownCustomization + - ", xmlCustomization=" + xmlCustomization + - "} " + super.toString(); + return new StringJoiner(", ", GeneratePropertyDocumentTask.class.getSimpleName() + "[", "]") + .add("documentName='" + documentName + "'") + .add("documentDescription='" + documentDescription + "'") + .add("template='" + template + "'") + .add("type=" + type) + .add("metadataInput=" + metadataInput) + .add("outputFile=" + outputFile) + .add("failOnError=" + failOnError) + .add("templateCompilerName='" + templateCompilerName + "'") + .add("excludedProperties=" + excludedProperties) + .add("includedProperties=" + includedProperties) + .add("excludedGroups=" + excludedGroups) + .add("includedGroups=" + includedGroups) + .add("asciiDocCustomization=" + asciiDocCustomization) + .add("htmlCustomization=" + htmlCustomization) + .add("markdownCustomization=" + markdownCustomization) + .add("xmlCustomization=" + xmlCustomization) + .add("failOnMissingInput=" + failOnMissingInput) + .toString(); } /** diff --git a/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/AbstractTemplateCustomization.java b/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/AbstractTemplateCustomization.java index e40fa38..9d0b854 100644 --- a/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/AbstractTemplateCustomization.java +++ b/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/AbstractTemplateCustomization.java @@ -6,6 +6,7 @@ import java.io.Serializable; import java.util.Objects; +import java.util.StringJoiner; /** * Class represents a template customization object. @@ -192,17 +193,17 @@ public int hashCode() { @Override public String toString() { - return "AbstractTemplateCustomization{" + - "tocTitle='" + tocTitle + '\'' + - ", headerEnabled=" + headerEnabled + - ", tableOfContentsEnabled=" + tableOfContentsEnabled + - ", includeUnknownGroup=" + includeUnknownGroup + - ", unknownGroupLocalization='" + unknownGroupLocalization + '\'' + - ", includeGenerationDate=" + includeGenerationDate + - ", removeEmptyGroups=" + removeEmptyGroups + - ", locale='" + locale + '\'' + - ", contentCustomization=" + contentCustomization + - ", compactMode=" + templateMode + - '}'; + return new StringJoiner(", ", AbstractTemplateCustomization.class.getSimpleName() + "[", "]") + .add("tocTitle='" + tocTitle + "'") + .add("headerEnabled=" + headerEnabled) + .add("tableOfContentsEnabled=" + tableOfContentsEnabled) + .add("includeUnknownGroup=" + includeUnknownGroup) + .add("unknownGroupLocalization='" + unknownGroupLocalization + "'") + .add("includeGenerationDate=" + includeGenerationDate) + .add("removeEmptyGroups=" + removeEmptyGroups) + .add("locale='" + locale + "'") + .add("contentCustomization=" + contentCustomization) + .add("templateMode=" + templateMode) + .toString(); } } diff --git a/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/AsciiDocTemplateCustomization.java b/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/AsciiDocTemplateCustomization.java index 6f2defa..e902555 100644 --- a/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/AsciiDocTemplateCustomization.java +++ b/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/AsciiDocTemplateCustomization.java @@ -1,6 +1,7 @@ package org.rodnansol.gradle.tasks.customization; import java.util.Objects; +import java.util.StringJoiner; /** * Class representing extra customizations for the AsciiDoc template. @@ -64,16 +65,19 @@ public int hashCode() { @Override public String toString() { - return "AsciiDocTemplateCustomization{" + - "tocPlacement=" + tocPlacement + - ", tocLevels=" + tocLevels + - ", headerEnabled=" + headerEnabled + - ", tableOfContentsEnabled=" + tableOfContentsEnabled + - ", includeUnknownGroup=" + includeUnknownGroup + - ", unknownGroupLocalization='" + unknownGroupLocalization + '\'' + - ", includeGenerationDate=" + includeGenerationDate + - ", removeEmptyGroups=" + removeEmptyGroups + - ", locale='" + locale + '\'' + - "} " + super.toString(); + return new StringJoiner(", ", AsciiDocTemplateCustomization.class.getSimpleName() + "[", "]") + .add("tocPlacement=" + tocPlacement) + .add("tocLevels=" + tocLevels) + .add("tocTitle='" + tocTitle + "'") + .add("headerEnabled=" + headerEnabled) + .add("tableOfContentsEnabled=" + tableOfContentsEnabled) + .add("includeUnknownGroup=" + includeUnknownGroup) + .add("unknownGroupLocalization='" + unknownGroupLocalization + "'") + .add("includeGenerationDate=" + includeGenerationDate) + .add("removeEmptyGroups=" + removeEmptyGroups) + .add("locale='" + locale + "'") + .add("contentCustomization=" + contentCustomization) + .add("templateMode=" + templateMode) + .toString(); } } diff --git a/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/ContentCustomization.java b/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/ContentCustomization.java index 63c2806..7c53038 100644 --- a/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/ContentCustomization.java +++ b/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/ContentCustomization.java @@ -2,6 +2,7 @@ import java.io.Serializable; import java.util.Objects; +import java.util.StringJoiner; /** * Class containing header customization data. @@ -125,14 +126,14 @@ public int hashCode() { @Override public String toString() { - return "ContentCustomization{" + - "includeClass=" + includeClass + - ", includeKey=" + includeKey + - ", includeType=" + includeType + - ", includeDescription=" + includeDescription + - ", includeDefaultValue=" + includeDefaultValue + - ", includeDeprecation=" + includeDeprecation + - ", includeEnvFormat=" + includeEnvFormat + - '}'; + return new StringJoiner(", ", ContentCustomization.class.getSimpleName() + "[", "]") + .add("includeClass=" + includeClass) + .add("includeKey=" + includeKey) + .add("includeType=" + includeType) + .add("includeDescription=" + includeDescription) + .add("includeDefaultValue=" + includeDefaultValue) + .add("includeDeprecation=" + includeDeprecation) + .add("includeEnvFormat=" + includeEnvFormat) + .toString(); } } diff --git a/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/HtmlTemplateCustomization.java b/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/HtmlTemplateCustomization.java index b8591c7..d108481 100644 --- a/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/HtmlTemplateCustomization.java +++ b/spring-configuration-property-documenter-gradle-plugin/src/main/java/org/rodnansol/gradle/tasks/customization/HtmlTemplateCustomization.java @@ -1,6 +1,7 @@ package org.rodnansol.gradle.tasks.customization; import java.util.Objects; +import java.util.StringJoiner; /** * Class representing HTML customizations. @@ -149,4 +150,29 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(super.hashCode(), backgroundColor, linkColor, collapsibleHoverColor, codeColor, evenTableRowColor, lastTableRowColor, tableRowColor, tableRowBorderColor, textColor); } + + @Override + public String toString() { + return new StringJoiner(", ", HtmlTemplateCustomization.class.getSimpleName() + "[", "]") + .add("backgroundColor='" + backgroundColor + "'") + .add("linkColor='" + linkColor + "'") + .add("collapsibleHoverColor='" + collapsibleHoverColor + "'") + .add("codeColor='" + codeColor + "'") + .add("evenTableRowColor='" + evenTableRowColor + "'") + .add("lastTableRowColor='" + lastTableRowColor + "'") + .add("tableRowColor='" + tableRowColor + "'") + .add("tableRowBorderColor='" + tableRowBorderColor + "'") + .add("textColor='" + textColor + "'") + .add("tocTitle='" + tocTitle + "'") + .add("headerEnabled=" + headerEnabled) + .add("tableOfContentsEnabled=" + tableOfContentsEnabled) + .add("includeUnknownGroup=" + includeUnknownGroup) + .add("unknownGroupLocalization='" + unknownGroupLocalization + "'") + .add("includeGenerationDate=" + includeGenerationDate) + .add("removeEmptyGroups=" + removeEmptyGroups) + .add("locale='" + locale + "'") + .add("contentCustomization=" + contentCustomization) + .add("templateMode=" + templateMode) + .toString(); + } } diff --git a/spring-configuration-property-documenter-maven-plugin/src/main/java/org/rodnansol/maven/GenerateAndAggregateDocumentsMojo.java b/spring-configuration-property-documenter-maven-plugin/src/main/java/org/rodnansol/maven/GenerateAndAggregateDocumentsMojo.java index fd33087..e13abd2 100644 --- a/spring-configuration-property-documenter-maven-plugin/src/main/java/org/rodnansol/maven/GenerateAndAggregateDocumentsMojo.java +++ b/spring-configuration-property-documenter-maven-plugin/src/main/java/org/rodnansol/maven/GenerateAndAggregateDocumentsMojo.java @@ -156,6 +156,14 @@ public class GenerateAndAggregateDocumentsMojo extends AbstractMojo { @Parameter(property = "footerTemplate") String footerTemplate; + /** + * Define if the process should fail if the given input file is not found. + * + * @since 0.7.0 + */ + @Parameter(property = "failOnMissingInput", defaultValue = "true") + boolean failOnMissingInput; + @Override public void execute() { AggregationDocumenter aggregationDocumenter = new AggregationDocumenter(MetadataReader.INSTANCE, TemplateCompilerFactory.getInstance(templateCompilerName), MetadataInputResolverContext.INSTANCE, PropertyGroupFilterService.INSTANCE); @@ -169,6 +177,7 @@ private CreateAggregationCommand createAggregationCommand() { CreateAggregationCommand createAggregationCommand = new CreateAggregationCommand(mavenProject, name, combinedInputs, type, getActualTemplateCustomization(), outputFile); createAggregationCommand.setDescription(description); createAggregationCommand.setCustomTemplate(new CustomTemplate(headerTemplate, contentTemplate, footerTemplate)); + createAggregationCommand.setFailOnMissingInput(failOnMissingInput); return createAggregationCommand; } diff --git a/spring-configuration-property-documenter-maven-plugin/src/main/java/org/rodnansol/maven/GeneratePropertyDocumentMojo.java b/spring-configuration-property-documenter-maven-plugin/src/main/java/org/rodnansol/maven/GeneratePropertyDocumentMojo.java index 046116a..8a51234 100644 --- a/spring-configuration-property-documenter-maven-plugin/src/main/java/org/rodnansol/maven/GeneratePropertyDocumentMojo.java +++ b/spring-configuration-property-documenter-maven-plugin/src/main/java/org/rodnansol/maven/GeneratePropertyDocumentMojo.java @@ -175,6 +175,14 @@ public class GeneratePropertyDocumentMojo extends AbstractMojo { @Parameter(property = "includedGroups") List includedGroups = new ArrayList<>(); + /** + * Define if the process should fail if the given input file is not found. + * + * @since 0.7.0 + */ + @Parameter(property = "failOnMissingInput", defaultValue = "true") + boolean failOnMissingInput; + @Override public void execute() {