Add prefix to appendix property anchor links
Refactor property appendix generator code so that the complete section is generated and anchors follow the expected naming. Closes gh-26375
This commit is contained in:
parent
86a5c90d20
commit
34b288e5fe
|
@ -28,6 +28,7 @@ dependencies {
|
||||||
testImplementation("org.assertj:assertj-core:3.11.1")
|
testImplementation("org.assertj:assertj-core:3.11.1")
|
||||||
testImplementation("org.apache.logging.log4j:log4j-core:2.12.1")
|
testImplementation("org.apache.logging.log4j:log4j-core:2.12.1")
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter:5.6.0")
|
testImplementation("org.junit.jupiter:junit-jupiter:5.6.0")
|
||||||
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
}
|
}
|
||||||
|
|
||||||
checkstyle {
|
checkstyle {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors.
|
* Copyright 2012-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -21,36 +21,36 @@ package org.springframework.boot.build.context.properties;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
class AsciidocBuilder {
|
class Asciidoc {
|
||||||
|
|
||||||
private final StringBuilder content;
|
private final StringBuilder content;
|
||||||
|
|
||||||
AsciidocBuilder() {
|
Asciidoc() {
|
||||||
this.content = new StringBuilder();
|
this.content = new StringBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
AsciidocBuilder appendKey(Object... items) {
|
Asciidoc appendWithHardLineBreaks(Object... items) {
|
||||||
for (Object item : items) {
|
for (Object item : items) {
|
||||||
appendln("`+", item, "+` +");
|
appendln("`+", item, "+` +");
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsciidocBuilder newLine() {
|
Asciidoc appendln(Object... items) {
|
||||||
return append(System.lineSeparator());
|
|
||||||
}
|
|
||||||
|
|
||||||
AsciidocBuilder appendln(Object... items) {
|
|
||||||
return append(items).newLine();
|
return append(items).newLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
AsciidocBuilder append(Object... items) {
|
Asciidoc append(Object... items) {
|
||||||
for (Object item : items) {
|
for (Object item : items) {
|
||||||
this.content.append(item);
|
this.content.append(item);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Asciidoc newLine() {
|
||||||
|
return append(System.lineSeparator());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.content.toString();
|
return this.content.toString();
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2020 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.build.context.properties;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Table entry regrouping a list of configuration properties sharing the same description.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
*/
|
|
||||||
class CompoundConfigurationTableEntry extends ConfigurationTableEntry {
|
|
||||||
|
|
||||||
private final Set<String> configurationKeys;
|
|
||||||
|
|
||||||
private final String description;
|
|
||||||
|
|
||||||
CompoundConfigurationTableEntry(String key, String description) {
|
|
||||||
this.key = key;
|
|
||||||
this.description = description;
|
|
||||||
this.configurationKeys = new TreeSet<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void addConfigurationKeys(ConfigurationProperty... properties) {
|
|
||||||
Stream.of(properties).map(ConfigurationProperty::getName).forEach(this.configurationKeys::add);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void write(AsciidocBuilder builder) {
|
|
||||||
builder.append("|[[" + this.key + "]]<<" + this.key + ",");
|
|
||||||
this.configurationKeys.forEach(builder::appendKey);
|
|
||||||
builder.appendln(">>");
|
|
||||||
builder.newLine().appendln("|").appendln("|+++", this.description, "+++");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2021 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.build.context.properties;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table row regrouping a list of configuration properties sharing the same description.
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class CompoundRow extends Row {
|
||||||
|
|
||||||
|
private final Set<String> propertyNames;
|
||||||
|
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
CompoundRow(Snippet snippet, String prefix, String description) {
|
||||||
|
super(snippet, prefix);
|
||||||
|
this.description = description;
|
||||||
|
this.propertyNames = new TreeSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void addProperty(ConfigurationProperty property) {
|
||||||
|
this.propertyNames.add(property.getDisplayName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void write(Asciidoc asciidoc) {
|
||||||
|
asciidoc.append("|");
|
||||||
|
asciidoc.append("[[" + getAnchor() + "]]");
|
||||||
|
asciidoc.append("<<" + getAnchor() + ",");
|
||||||
|
this.propertyNames.forEach(asciidoc::appendWithHardLineBreaks);
|
||||||
|
asciidoc.appendln(">>");
|
||||||
|
asciidoc.appendln("|+++", this.description, "+++");
|
||||||
|
asciidoc.appendln("|");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,125 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2020 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.build.context.properties;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.gradle.api.file.FileCollection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write Asciidoc documents with configuration properties listings.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
* @since 2.0.0
|
|
||||||
*/
|
|
||||||
public class ConfigurationMetadataDocumentWriter {
|
|
||||||
|
|
||||||
public void writeDocument(Path outputDirectory, DocumentOptions options, FileCollection metadataFiles)
|
|
||||||
throws IOException {
|
|
||||||
assertValidOutputDirectory(outputDirectory);
|
|
||||||
if (!Files.exists(outputDirectory)) {
|
|
||||||
Files.createDirectory(outputDirectory);
|
|
||||||
}
|
|
||||||
List<ConfigurationTable> tables = createConfigTables(ConfigurationProperties.fromFiles(metadataFiles), options);
|
|
||||||
for (ConfigurationTable table : tables) {
|
|
||||||
writeConfigurationTable(table, outputDirectory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertValidOutputDirectory(Path outputDirPath) {
|
|
||||||
if (outputDirPath == null) {
|
|
||||||
throw new IllegalArgumentException("output path should not be null");
|
|
||||||
}
|
|
||||||
if (Files.exists(outputDirPath) && !Files.isDirectory(outputDirPath)) {
|
|
||||||
throw new IllegalArgumentException("output path already exists and is not a directory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ConfigurationTable> createConfigTables(Map<String, ConfigurationProperty> metadataProperties,
|
|
||||||
DocumentOptions options) {
|
|
||||||
List<ConfigurationTable> tables = new ArrayList<>();
|
|
||||||
List<String> unmappedKeys = metadataProperties.values().stream().filter((property) -> !property.isDeprecated())
|
|
||||||
.map(ConfigurationProperty::getName).collect(Collectors.toList());
|
|
||||||
Map<String, CompoundConfigurationTableEntry> overrides = getOverrides(metadataProperties, unmappedKeys,
|
|
||||||
options);
|
|
||||||
options.getMetadataSections().forEach((id, keyPrefixes) -> tables
|
|
||||||
.add(createConfigTable(metadataProperties, unmappedKeys, overrides, id, keyPrefixes)));
|
|
||||||
if (!unmappedKeys.isEmpty()) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"The following keys were not written to the documentation: " + String.join(", ", unmappedKeys));
|
|
||||||
}
|
|
||||||
if (!overrides.isEmpty()) {
|
|
||||||
throw new IllegalStateException("The following keys were not written to the documentation: "
|
|
||||||
+ String.join(", ", overrides.keySet()));
|
|
||||||
}
|
|
||||||
return tables;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, CompoundConfigurationTableEntry> getOverrides(
|
|
||||||
Map<String, ConfigurationProperty> metadataProperties, List<String> unmappedKeys, DocumentOptions options) {
|
|
||||||
Map<String, CompoundConfigurationTableEntry> overrides = new HashMap<>();
|
|
||||||
options.getOverrides().forEach((keyPrefix, description) -> {
|
|
||||||
CompoundConfigurationTableEntry entry = new CompoundConfigurationTableEntry(keyPrefix, description);
|
|
||||||
List<String> matchingKeys = unmappedKeys.stream().filter((key) -> key.startsWith(keyPrefix))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
for (String matchingKey : matchingKeys) {
|
|
||||||
entry.addConfigurationKeys(metadataProperties.get(matchingKey));
|
|
||||||
}
|
|
||||||
overrides.put(keyPrefix, entry);
|
|
||||||
unmappedKeys.removeAll(matchingKeys);
|
|
||||||
});
|
|
||||||
return overrides;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConfigurationTable createConfigTable(Map<String, ConfigurationProperty> metadataProperties,
|
|
||||||
List<String> unmappedKeys, Map<String, CompoundConfigurationTableEntry> overrides, String id,
|
|
||||||
List<String> keyPrefixes) {
|
|
||||||
ConfigurationTable table = new ConfigurationTable(id);
|
|
||||||
for (String keyPrefix : keyPrefixes) {
|
|
||||||
List<String> matchingOverrides = overrides.keySet().stream()
|
|
||||||
.filter((overrideKey) -> overrideKey.startsWith(keyPrefix)).collect(Collectors.toList());
|
|
||||||
matchingOverrides.forEach((match) -> table.addEntry(overrides.remove(match)));
|
|
||||||
}
|
|
||||||
List<String> matchingKeys = unmappedKeys.stream()
|
|
||||||
.filter((key) -> keyPrefixes.stream().anyMatch(key::startsWith)).collect(Collectors.toList());
|
|
||||||
for (String matchingKey : matchingKeys) {
|
|
||||||
ConfigurationProperty property = metadataProperties.get(matchingKey);
|
|
||||||
table.addEntry(new SingleConfigurationTableEntry(property));
|
|
||||||
}
|
|
||||||
unmappedKeys.removeAll(matchingKeys);
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeConfigurationTable(ConfigurationTable table, Path outputDirectory) throws IOException {
|
|
||||||
Path outputFilePath = outputDirectory.resolve(table.getId() + ".adoc");
|
|
||||||
Files.deleteIfExists(outputFilePath);
|
|
||||||
Files.createFile(outputFilePath);
|
|
||||||
try (OutputStream outputStream = Files.newOutputStream(outputFilePath)) {
|
|
||||||
outputStream.write(table.toAsciidocTable().getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -17,14 +17,13 @@
|
||||||
package org.springframework.boot.build.context.properties;
|
package org.springframework.boot.build.context.properties;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.stream.Stream;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
@ -33,35 +32,40 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
* {@code META-INF/spring-configuration-metadata.json} files.
|
* {@code META-INF/spring-configuration-metadata.json} files.
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
final class ConfigurationProperties {
|
final class ConfigurationProperties {
|
||||||
|
|
||||||
private ConfigurationProperties() {
|
private final Map<String, ConfigurationProperty> byName;
|
||||||
|
|
||||||
|
private ConfigurationProperties(List<ConfigurationProperty> properties) {
|
||||||
|
Map<String, ConfigurationProperty> byName = new LinkedHashMap<>();
|
||||||
|
for (ConfigurationProperty property : properties) {
|
||||||
|
byName.put(property.getName(), property);
|
||||||
|
}
|
||||||
|
this.byName = Collections.unmodifiableMap(byName);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigurationProperty get(String propertyName) {
|
||||||
|
return this.byName.get(propertyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<ConfigurationProperty> stream() {
|
||||||
|
return this.byName.values().stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
static Map<String, ConfigurationProperty> fromFiles(Iterable<File> files) {
|
static ConfigurationProperties fromFiles(Iterable<File> files) {
|
||||||
List<ConfigurationProperty> configurationProperties = new ArrayList<>();
|
|
||||||
try {
|
try {
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
List<ConfigurationProperty> properties = new ArrayList<>();
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
try (Reader reader = new FileReader(file)) {
|
|
||||||
Map<String, Object> json = objectMapper.readValue(file, Map.class);
|
Map<String, Object> json = objectMapper.readValue(file, Map.class);
|
||||||
List<Map<String, Object>> properties = (List<Map<String, Object>>) json.get("properties");
|
for (Map<String, Object> property : (List<Map<String, Object>>) json.get("properties")) {
|
||||||
for (Map<String, Object> property : properties) {
|
properties.add(ConfigurationProperty.fromJsonProperties(property));
|
||||||
String name = (String) property.get("name");
|
|
||||||
String type = (String) property.get("type");
|
|
||||||
Object defaultValue = property.get("defaultValue");
|
|
||||||
String description = (String) property.get("description");
|
|
||||||
boolean deprecated = property.containsKey("deprecated");
|
|
||||||
configurationProperties
|
|
||||||
.add(new ConfigurationProperty(name, type, defaultValue, description, deprecated));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return new ConfigurationProperties(properties);
|
||||||
return configurationProperties.stream()
|
|
||||||
.collect(Collectors.toMap(ConfigurationProperty::getName, Function.identity()));
|
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
throw new RuntimeException("Failed to load configuration metadata", ex);
|
throw new RuntimeException("Failed to load configuration metadata", ex);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2019-2020 the original author or authors.
|
* Copyright 2019-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,12 +16,14 @@
|
||||||
|
|
||||||
package org.springframework.boot.build.context.properties;
|
package org.springframework.boot.build.context.properties;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A configuration property.
|
* A configuration property.
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
*/
|
*/
|
||||||
public class ConfigurationProperty {
|
class ConfigurationProperty {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
@ -45,23 +47,27 @@ public class ConfigurationProperty {
|
||||||
this.deprecated = deprecated;
|
this.deprecated = deprecated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
String getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getType() {
|
String getDisplayName() {
|
||||||
|
return (getType() != null && getType().startsWith("java.util.Map")) ? getName() + ".*" : getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
String getType() {
|
||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getDefaultValue() {
|
Object getDefaultValue() {
|
||||||
return this.defaultValue;
|
return this.defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDescription() {
|
String getDescription() {
|
||||||
return this.description;
|
return this.description;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDeprecated() {
|
boolean isDeprecated() {
|
||||||
return this.deprecated;
|
return this.deprecated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,4 +76,13 @@ public class ConfigurationProperty {
|
||||||
return "ConfigurationProperty [name=" + this.name + ", type=" + this.type + "]";
|
return "ConfigurationProperty [name=" + this.name + ", type=" + this.type + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ConfigurationProperty fromJsonProperties(Map<String, Object> property) {
|
||||||
|
String name = (String) property.get("name");
|
||||||
|
String type = (String) property.get("type");
|
||||||
|
Object defaultValue = property.get("defaultValue");
|
||||||
|
String description = (String) property.get("description");
|
||||||
|
boolean deprecated = property.containsKey("deprecated");
|
||||||
|
return new ConfigurationProperty(name, type, defaultValue, description, deprecated);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,12 +28,13 @@ import org.gradle.api.tasks.PathSensitive;
|
||||||
import org.gradle.api.tasks.PathSensitivity;
|
import org.gradle.api.tasks.PathSensitivity;
|
||||||
import org.gradle.api.tasks.TaskAction;
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
|
||||||
import org.springframework.boot.build.context.properties.DocumentOptions.Builder;
|
import org.springframework.boot.build.context.properties.Snippet.Config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link Task} used to document auto-configuration classes.
|
* {@link Task} used to document auto-configuration classes.
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
public class DocumentConfigurationProperties extends DefaultTask {
|
public class DocumentConfigurationProperties extends DefaultTask {
|
||||||
|
|
||||||
|
@ -62,42 +63,159 @@ public class DocumentConfigurationProperties extends DefaultTask {
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
void documentConfigurationProperties() throws IOException {
|
void documentConfigurationProperties() throws IOException {
|
||||||
Builder builder = DocumentOptions.builder();
|
Snippets snippets = new Snippets(this.configurationPropertyMetadata);
|
||||||
builder.addSection("core")
|
snippets.add("application-properties.core", "Core Properties", this::corePrefixes);
|
||||||
.withKeyPrefixes("debug", "trace", "logging", "spring.aop", "spring.application",
|
snippets.add("application-properties.cache", "Cache Properties", this::cachePrefixes);
|
||||||
"spring.autoconfigure", "spring.banner", "spring.beaninfo", "spring.codec", "spring.config",
|
snippets.add("application-properties.mail", "Mail Properties", this::mailPrefixes);
|
||||||
"spring.info", "spring.jmx", "spring.lifecycle", "spring.main", "spring.messages", "spring.pid",
|
snippets.add("application-properties.json", "JSON Properties", this::jsonPrefixes);
|
||||||
"spring.profiles", "spring.quartz", "spring.reactor", "spring.task",
|
snippets.add("application-properties.data", "Data Properties", this::dataPrefixes);
|
||||||
"spring.mandatory-file-encoding", "info", "spring.output.ansi.enabled")
|
snippets.add("application-properties.transaction", "Transaction Properties", this::transactionPrefixes);
|
||||||
.addSection("mail").withKeyPrefixes("spring.mail", "spring.sendgrid").addSection("cache")
|
snippets.add("application-properties.data-migration", "Data Migration Properties", this::dataMigrationPrefixes);
|
||||||
.withKeyPrefixes("spring.cache").addSection("server").withKeyPrefixes("server").addSection("web")
|
snippets.add("application-properties.integration", "Integration Properties", this::integrationPrefixes);
|
||||||
.withKeyPrefixes("spring.hateoas", "spring.http", "spring.servlet", "spring.jersey", "spring.mvc",
|
snippets.add("application-properties.web", "Web Properties", this::webPrefixes);
|
||||||
"spring.netty", "spring.resources", "spring.session", "spring.web", "spring.webflux")
|
snippets.add("application-properties.templating", "Templating Properties", this::templatePrefixes);
|
||||||
.addSection("json").withKeyPrefixes("spring.jackson", "spring.gson").addSection("rsocket")
|
snippets.add("application-properties.server", "Server Properties", this::serverPrefixes);
|
||||||
.withKeyPrefixes("spring.rsocket").addSection("templating")
|
snippets.add("application-properties.security", "Security Properties", this::securityPrefixes);
|
||||||
.withKeyPrefixes("spring.freemarker", "spring.groovy", "spring.mustache", "spring.thymeleaf")
|
snippets.add("application-properties.rsocket", "RSocket Properties", this::rsocketPrefixes);
|
||||||
.addOverride("spring.groovy.template.configuration", "See GroovyMarkupConfigurer")
|
snippets.add("application-properties.actuator", "Actuator Properties", this::actuatorPrefixes);
|
||||||
.addSection("security").withKeyPrefixes("spring.security").addSection("data-migration")
|
snippets.add("application-properties.devtools", "Devtools Properties", this::devtoolsPrefixes);
|
||||||
.withKeyPrefixes("spring.flyway", "spring.liquibase", "spring.sql.init").addSection("data")
|
snippets.add("application-properties.testing", "Testing Properties", this::testingPrefixes);
|
||||||
.withKeyPrefixes("spring.couchbase", "spring.elasticsearch", "spring.h2", "spring.influx",
|
snippets.writeTo(this.outputDir.toPath());
|
||||||
"spring.ldap", "spring.mongodb", "spring.neo4j", "spring.redis", "spring.dao", "spring.data",
|
}
|
||||||
"spring.datasource", "spring.jooq", "spring.jdbc", "spring.jpa", "spring.r2dbc")
|
|
||||||
.addOverride("spring.datasource.oracleucp",
|
private void corePrefixes(Config config) {
|
||||||
"Oracle UCP specific settings bound to an instance of Oracle UCP's PoolDataSource")
|
config.accept("debug");
|
||||||
.addOverride("spring.datasource.dbcp2",
|
config.accept("trace");
|
||||||
"Commons DBCP2 specific settings bound to an instance of DBCP2's BasicDataSource")
|
config.accept("logging");
|
||||||
.addOverride("spring.datasource.tomcat",
|
config.accept("spring.aop");
|
||||||
"Tomcat datasource specific settings bound to an instance of Tomcat JDBC's DataSource")
|
config.accept("spring.application");
|
||||||
.addOverride("spring.datasource.hikari",
|
config.accept("spring.autoconfigure");
|
||||||
"Hikari specific settings bound to an instance of Hikari's HikariDataSource")
|
config.accept("spring.banner");
|
||||||
.addSection("transaction").withKeyPrefixes("spring.jta", "spring.transaction").addSection("integration")
|
config.accept("spring.beaninfo");
|
||||||
.withKeyPrefixes("spring.activemq", "spring.artemis", "spring.batch", "spring.integration",
|
config.accept("spring.codec");
|
||||||
"spring.jms", "spring.kafka", "spring.rabbitmq", "spring.hazelcast", "spring.webservices")
|
config.accept("spring.config");
|
||||||
.addSection("actuator").withKeyPrefixes("management").addSection("devtools")
|
config.accept("spring.info");
|
||||||
.withKeyPrefixes("spring.devtools").addSection("testing").withKeyPrefixes("spring.test");
|
config.accept("spring.jmx");
|
||||||
DocumentOptions options = builder.build();
|
config.accept("spring.lifecycle");
|
||||||
new ConfigurationMetadataDocumentWriter().writeDocument(this.outputDir.toPath(), options,
|
config.accept("spring.main");
|
||||||
this.configurationPropertyMetadata);
|
config.accept("spring.messages");
|
||||||
|
config.accept("spring.pid");
|
||||||
|
config.accept("spring.profiles");
|
||||||
|
config.accept("spring.quartz");
|
||||||
|
config.accept("spring.reactor");
|
||||||
|
config.accept("spring.task");
|
||||||
|
config.accept("spring.mandatory-file-encoding");
|
||||||
|
config.accept("info");
|
||||||
|
config.accept("spring.output.ansi.enabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cachePrefixes(Config config) {
|
||||||
|
config.accept("spring.cache");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mailPrefixes(Config config) {
|
||||||
|
config.accept("spring.mail");
|
||||||
|
config.accept("spring.sendgrid");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void jsonPrefixes(Config config) {
|
||||||
|
config.accept("spring.jackson");
|
||||||
|
config.accept("spring.gson");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dataPrefixes(Config config) {
|
||||||
|
config.accept("spring.couchbase");
|
||||||
|
config.accept("spring.elasticsearch");
|
||||||
|
config.accept("spring.h2");
|
||||||
|
config.accept("spring.influx");
|
||||||
|
config.accept("spring.ldap");
|
||||||
|
config.accept("spring.mongodb");
|
||||||
|
config.accept("spring.neo4j");
|
||||||
|
config.accept("spring.redis");
|
||||||
|
config.accept("spring.dao");
|
||||||
|
config.accept("spring.data");
|
||||||
|
config.accept("spring.datasource");
|
||||||
|
config.accept("spring.jooq");
|
||||||
|
config.accept("spring.jdbc");
|
||||||
|
config.accept("spring.jpa");
|
||||||
|
config.accept("spring.r2dbc");
|
||||||
|
config.accept("spring.datasource.oracleucp",
|
||||||
|
"Oracle UCP specific settings bound to an instance of Oracle UCP's PoolDataSource");
|
||||||
|
config.accept("spring.datasource.dbcp2",
|
||||||
|
"Commons DBCP2 specific settings bound to an instance of DBCP2's BasicDataSource");
|
||||||
|
config.accept("spring.datasource.tomcat",
|
||||||
|
"Tomcat datasource specific settings bound to an instance of Tomcat JDBC's DataSource");
|
||||||
|
config.accept("spring.datasource.hikari",
|
||||||
|
"Hikari specific settings bound to an instance of Hikari's HikariDataSource");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void transactionPrefixes(Config prefix) {
|
||||||
|
prefix.accept("spring.jta");
|
||||||
|
prefix.accept("spring.transaction");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dataMigrationPrefixes(Config prefix) {
|
||||||
|
prefix.accept("spring.flyway");
|
||||||
|
prefix.accept("spring.liquibase");
|
||||||
|
prefix.accept("spring.sql.init");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void integrationPrefixes(Config prefix) {
|
||||||
|
prefix.accept("spring.activemq");
|
||||||
|
prefix.accept("spring.artemis");
|
||||||
|
prefix.accept("spring.batch");
|
||||||
|
prefix.accept("spring.integration");
|
||||||
|
prefix.accept("spring.jms");
|
||||||
|
prefix.accept("spring.kafka");
|
||||||
|
prefix.accept("spring.rabbitmq");
|
||||||
|
prefix.accept("spring.hazelcast");
|
||||||
|
prefix.accept("spring.webservices");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void webPrefixes(Config prefix) {
|
||||||
|
prefix.accept("spring.hateoas");
|
||||||
|
prefix.accept("spring.http");
|
||||||
|
prefix.accept("spring.servlet");
|
||||||
|
prefix.accept("spring.jersey");
|
||||||
|
prefix.accept("spring.mvc");
|
||||||
|
prefix.accept("spring.netty");
|
||||||
|
prefix.accept("spring.resources");
|
||||||
|
prefix.accept("spring.session");
|
||||||
|
prefix.accept("spring.web");
|
||||||
|
prefix.accept("spring.webflux");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void templatePrefixes(Config prefix) {
|
||||||
|
prefix.accept("spring.freemarker");
|
||||||
|
prefix.accept("spring.groovy");
|
||||||
|
prefix.accept("spring.mustache");
|
||||||
|
prefix.accept("spring.thymeleaf");
|
||||||
|
prefix.accept("spring.groovy.template.configuration", "See GroovyMarkupConfigurer");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void serverPrefixes(Config prefix) {
|
||||||
|
prefix.accept("server");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void securityPrefixes(Config prefix) {
|
||||||
|
prefix.accept("spring.security");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rsocketPrefixes(Config prefix) {
|
||||||
|
prefix.accept("spring.rsocket");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actuatorPrefixes(Config prefix) {
|
||||||
|
prefix.accept("management");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void devtoolsPrefixes(Config prefix) {
|
||||||
|
prefix.accept("spring.devtools");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testingPrefixes(Config prefix) {
|
||||||
|
prefix.accept("spring.test");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,98 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2020 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.build.context.properties;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Options for generating documentation for configuration properties.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
* @since 2.0.0
|
|
||||||
*/
|
|
||||||
public final class DocumentOptions {
|
|
||||||
|
|
||||||
private final Map<String, List<String>> metadataSections;
|
|
||||||
|
|
||||||
private final Map<String, String> overrides;
|
|
||||||
|
|
||||||
private DocumentOptions(Map<String, List<String>> metadataSections, Map<String, String> overrides) {
|
|
||||||
this.metadataSections = metadataSections;
|
|
||||||
this.overrides = overrides;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, List<String>> getMetadataSections() {
|
|
||||||
return this.metadataSections;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, String> getOverrides() {
|
|
||||||
return this.overrides;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Builder builder() {
|
|
||||||
return new Builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builder for DocumentOptions.
|
|
||||||
*/
|
|
||||||
public static class Builder {
|
|
||||||
|
|
||||||
Map<String, List<String>> metadataSections = new HashMap<>();
|
|
||||||
|
|
||||||
Map<String, String> overrides = new HashMap<>();
|
|
||||||
|
|
||||||
SectionSpec addSection(String name) {
|
|
||||||
return new SectionSpec(this, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
Builder addOverride(String keyPrefix, String description) {
|
|
||||||
this.overrides.put(keyPrefix, description);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
DocumentOptions build() {
|
|
||||||
return new DocumentOptions(this.metadataSections, this.overrides);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration for a documentation section listing properties for a specific theme.
|
|
||||||
*/
|
|
||||||
public static class SectionSpec {
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
private final Builder builder;
|
|
||||||
|
|
||||||
SectionSpec(Builder builder, String name) {
|
|
||||||
this.builder = builder;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
Builder withKeyPrefixes(String... keyPrefixes) {
|
|
||||||
this.builder.metadataSections.put(this.name, Arrays.asList(keyPrefixes));
|
|
||||||
return this.builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors.
|
* Copyright 2012-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,20 +17,22 @@
|
||||||
package org.springframework.boot.build.context.properties;
|
package org.springframework.boot.build.context.properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class for entries in {@link ConfigurationTable}.
|
* Abstract class for rows in {@link Table}.
|
||||||
*
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
abstract class ConfigurationTableEntry implements Comparable<ConfigurationTableEntry> {
|
abstract class Row implements Comparable<Row> {
|
||||||
|
|
||||||
protected String key;
|
private final Snippet snippet;
|
||||||
|
|
||||||
String getKey() {
|
private final String id;
|
||||||
return this.key;
|
|
||||||
|
protected Row(Snippet snippet, String id) {
|
||||||
|
this.snippet = snippet;
|
||||||
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract void write(AsciidocBuilder builder);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) {
|
if (this == obj) {
|
||||||
|
@ -39,18 +41,24 @@ abstract class ConfigurationTableEntry implements Comparable<ConfigurationTableE
|
||||||
if (obj == null || getClass() != obj.getClass()) {
|
if (obj == null || getClass() != obj.getClass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ConfigurationTableEntry other = (ConfigurationTableEntry) obj;
|
Row other = (Row) obj;
|
||||||
return this.key.equals(other.key);
|
return this.id.equals(other.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return this.key.hashCode();
|
return this.id.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(ConfigurationTableEntry other) {
|
public int compareTo(Row other) {
|
||||||
return this.key.compareTo(other.getKey());
|
return this.id.compareTo(other.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getAnchor() {
|
||||||
|
return this.snippet.getAnchor() + "." + this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract void write(Asciidoc asciidoc);
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors.
|
* Copyright 2012-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -20,24 +20,22 @@ import java.util.Arrays;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table entry containing a single configuration property.
|
* Table row containing a single configuration property.
|
||||||
*
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
class SingleConfigurationTableEntry extends ConfigurationTableEntry {
|
class SingleRow extends Row {
|
||||||
|
|
||||||
|
private final String displayName;
|
||||||
|
|
||||||
private final String description;
|
private final String description;
|
||||||
|
|
||||||
private final String defaultValue;
|
private final String defaultValue;
|
||||||
|
|
||||||
private final String anchor;
|
SingleRow(Snippet snippet, ConfigurationProperty property) {
|
||||||
|
super(snippet, property.getName());
|
||||||
SingleConfigurationTableEntry(ConfigurationProperty property) {
|
this.displayName = property.getDisplayName();
|
||||||
this.key = property.getName();
|
|
||||||
this.anchor = this.key;
|
|
||||||
if (property.getType() != null && property.getType().startsWith("java.util.Map")) {
|
|
||||||
this.key += ".*";
|
|
||||||
}
|
|
||||||
this.description = property.getDescription();
|
this.description = property.getDescription();
|
||||||
this.defaultValue = getDefaultValue(property.getDefaultValue());
|
this.defaultValue = getDefaultValue(property.getDefaultValue());
|
||||||
}
|
}
|
||||||
|
@ -54,14 +52,25 @@ class SingleConfigurationTableEntry extends ConfigurationTableEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void write(AsciidocBuilder builder) {
|
void write(Asciidoc asciidoc) {
|
||||||
builder.appendln("|[[" + this.anchor + "]]<<" + this.anchor + ",`+", this.key, "+`>>");
|
asciidoc.append("|");
|
||||||
writeDefaultValue(builder);
|
asciidoc.append("[[" + getAnchor() + "]]");
|
||||||
writeDescription(builder);
|
asciidoc.appendln("<<" + getAnchor() + ",`+", this.displayName, "+`>>");
|
||||||
builder.appendln();
|
writeDescription(asciidoc);
|
||||||
|
writeDefaultValue(asciidoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeDefaultValue(AsciidocBuilder builder) {
|
private void writeDescription(Asciidoc builder) {
|
||||||
|
if (this.description == null || this.description.isEmpty()) {
|
||||||
|
builder.appendln("|");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String cleanedDescription = this.description.replace("|", "\\|").replace("<", "<").replace(">", ">");
|
||||||
|
builder.appendln("|+++", cleanedDescription, "+++");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeDefaultValue(Asciidoc builder) {
|
||||||
String defaultValue = (this.defaultValue != null) ? this.defaultValue : "";
|
String defaultValue = (this.defaultValue != null) ? this.defaultValue : "";
|
||||||
if (defaultValue.isEmpty()) {
|
if (defaultValue.isEmpty()) {
|
||||||
builder.appendln("|");
|
builder.appendln("|");
|
||||||
|
@ -72,14 +81,4 @@ class SingleConfigurationTableEntry extends ConfigurationTableEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeDescription(AsciidocBuilder builder) {
|
|
||||||
if (this.description == null || this.description.isEmpty()) {
|
|
||||||
builder.append("|");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
String cleanedDescription = this.description.replace("|", "\\|").replace("<", "<").replace(">", ">");
|
|
||||||
builder.append("|+++", cleanedDescription, "+++");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021-2021 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.build.context.properties;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A configuration properties snippet.
|
||||||
|
*
|
||||||
|
* @author Brian Clozed
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class Snippet {
|
||||||
|
|
||||||
|
private final String anchor;
|
||||||
|
|
||||||
|
private final String title;
|
||||||
|
|
||||||
|
private final Set<String> prefixes;
|
||||||
|
|
||||||
|
private final Map<String, String> overrides;
|
||||||
|
|
||||||
|
Snippet(String anchor, String title, Consumer<Config> config) {
|
||||||
|
Set<String> prefixes = new LinkedHashSet<>();
|
||||||
|
Map<String, String> overrides = new LinkedHashMap<>();
|
||||||
|
if (config != null) {
|
||||||
|
config.accept(new Config() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(String prefix) {
|
||||||
|
prefixes.add(prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(String prefix, String description) {
|
||||||
|
overrides.put(prefix, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.anchor = anchor;
|
||||||
|
this.title = title;
|
||||||
|
this.prefixes = prefixes;
|
||||||
|
this.overrides = overrides;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getAnchor() {
|
||||||
|
return this.anchor;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getTitle() {
|
||||||
|
return this.title;
|
||||||
|
}
|
||||||
|
|
||||||
|
void forEachPrefix(Consumer<String> action) {
|
||||||
|
this.prefixes.forEach(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void forEachOverride(BiConsumer<String, String> action) {
|
||||||
|
this.overrides.forEach(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to configure the snippet.
|
||||||
|
*/
|
||||||
|
interface Config {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept the given prefix using the meta-data description.
|
||||||
|
* @param prefix the prefix to accept
|
||||||
|
*/
|
||||||
|
void accept(String prefix);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept the given prefix with a defined description.
|
||||||
|
* @param prefix the prefix to accept
|
||||||
|
* @param description the description to use
|
||||||
|
*/
|
||||||
|
void accept(String prefix, String description);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021-2021 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.build.context.properties;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.gradle.api.file.FileCollection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration properties snippets.
|
||||||
|
*
|
||||||
|
* @author Brian Clozed
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class Snippets {
|
||||||
|
|
||||||
|
private final ConfigurationProperties properties;
|
||||||
|
|
||||||
|
private final List<Snippet> snippets = new ArrayList<>();
|
||||||
|
|
||||||
|
Snippets(FileCollection configurationPropertyMetadata) {
|
||||||
|
this.properties = ConfigurationProperties.fromFiles(configurationPropertyMetadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(String anchor, String title, Consumer<Snippet.Config> config) {
|
||||||
|
this.snippets.add(new Snippet(anchor, title, config));
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeTo(Path outputDirectory) throws IOException {
|
||||||
|
createDirectory(outputDirectory);
|
||||||
|
Set<String> remaining = this.properties.stream().filter((property) -> !property.isDeprecated())
|
||||||
|
.map(ConfigurationProperty::getName).collect(Collectors.toSet());
|
||||||
|
for (Snippet snippet : this.snippets) {
|
||||||
|
Set<String> written = writeSnippet(outputDirectory, snippet, remaining);
|
||||||
|
remaining.removeAll(written);
|
||||||
|
}
|
||||||
|
if (!remaining.isEmpty()) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"The following keys were not written to the documentation: " + String.join(", ", remaining));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> writeSnippet(Path outputDirectory, Snippet snippet, Set<String> remaining) throws IOException {
|
||||||
|
Table table = new Table();
|
||||||
|
Set<String> added = new HashSet<>();
|
||||||
|
snippet.forEachOverride((prefix, description) -> {
|
||||||
|
CompoundRow row = new CompoundRow(snippet, prefix, description);
|
||||||
|
remaining.stream().filter((candidate) -> candidate.startsWith(prefix)).forEach((name) -> {
|
||||||
|
if (added.add(name)) {
|
||||||
|
row.addProperty(this.properties.get(name));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
table.addRow(row);
|
||||||
|
});
|
||||||
|
snippet.forEachPrefix((prefix) -> {
|
||||||
|
remaining.stream().filter((candidate) -> candidate.startsWith(prefix)).forEach((name) -> {
|
||||||
|
if (added.add(name)) {
|
||||||
|
table.addRow(new SingleRow(snippet, this.properties.get(name)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Asciidoc asciidoc = getAsciidoc(snippet, table);
|
||||||
|
writeAsciidoc(outputDirectory, snippet, asciidoc);
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Asciidoc getAsciidoc(Snippet snippet, Table table) {
|
||||||
|
Asciidoc asciidoc = new Asciidoc();
|
||||||
|
asciidoc.appendln("[[" + snippet.getAnchor() + "]]");
|
||||||
|
asciidoc.appendln("== ", snippet.getTitle());
|
||||||
|
table.write(asciidoc);
|
||||||
|
return asciidoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeAsciidoc(Path outputDirectory, Snippet snippet, Asciidoc asciidoc) throws IOException {
|
||||||
|
String[] parts = (snippet.getAnchor()).split("\\.");
|
||||||
|
Path path = outputDirectory;
|
||||||
|
for (int i = 0; i < parts.length; i++) {
|
||||||
|
String name = (i < parts.length - 1) ? parts[i] : parts[i] + ".adoc";
|
||||||
|
path = path.resolve(name);
|
||||||
|
}
|
||||||
|
createDirectory(path.getParent());
|
||||||
|
Files.deleteIfExists(path);
|
||||||
|
try (OutputStream outputStream = Files.newOutputStream(path)) {
|
||||||
|
outputStream.write(asciidoc.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createDirectory(Path path) throws IOException {
|
||||||
|
assertValidOutputDirectory(path);
|
||||||
|
if (!Files.exists(path)) {
|
||||||
|
Files.createDirectory(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertValidOutputDirectory(Path path) {
|
||||||
|
if (path == null) {
|
||||||
|
throw new IllegalArgumentException("Directory path should not be null");
|
||||||
|
}
|
||||||
|
if (Files.exists(path) && !Files.isDirectory(path)) {
|
||||||
|
throw new IllegalArgumentException("Path already exists and is not a directory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
package org.springframework.boot.build.context.properties;
|
package org.springframework.boot.build.context.properties;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
@ -25,36 +24,24 @@ import java.util.TreeSet;
|
||||||
*
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
*/
|
*/
|
||||||
class ConfigurationTable {
|
class Table {
|
||||||
|
|
||||||
private final String id;
|
private final Set<Row> rows = new TreeSet<>();
|
||||||
|
|
||||||
private final Set<ConfigurationTableEntry> entries;
|
void addRow(Row row) {
|
||||||
|
this.rows.add(row);
|
||||||
ConfigurationTable(String id) {
|
|
||||||
this.id = id;
|
|
||||||
this.entries = new TreeSet<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String getId() {
|
void write(Asciidoc asciidoc) {
|
||||||
return this.id;
|
asciidoc.appendln("[cols=\"4,3,3\", options=\"header\"]");
|
||||||
}
|
asciidoc.appendln("|===");
|
||||||
|
asciidoc.appendln("|Name|Description|Default Value");
|
||||||
void addEntry(ConfigurationTableEntry... entries) {
|
asciidoc.appendln();
|
||||||
this.entries.addAll(Arrays.asList(entries));
|
this.rows.forEach((entry) -> {
|
||||||
}
|
entry.write(asciidoc);
|
||||||
|
asciidoc.appendln();
|
||||||
String toAsciidocTable() {
|
|
||||||
AsciidocBuilder builder = new AsciidocBuilder();
|
|
||||||
builder.appendln("[cols=\"4,3,3\", options=\"header\"]");
|
|
||||||
builder.appendln("|===");
|
|
||||||
builder.appendln("|Key|Default Value|Description");
|
|
||||||
builder.appendln();
|
|
||||||
this.entries.forEach((entry) -> {
|
|
||||||
entry.write(builder);
|
|
||||||
builder.appendln();
|
|
||||||
});
|
});
|
||||||
return builder.appendln("|===").toString();
|
asciidoc.appendln("|===");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,47 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2020 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.build.context.properties;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link CompoundConfigurationTableEntry}.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
*/
|
|
||||||
public class CompoundConfigurationTableEntryTests {
|
|
||||||
|
|
||||||
private static final String NEWLINE = System.lineSeparator();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void simpleProperty() {
|
|
||||||
ConfigurationProperty firstProp = new ConfigurationProperty("spring.test.first", "java.lang.String");
|
|
||||||
ConfigurationProperty secondProp = new ConfigurationProperty("spring.test.second", "java.lang.String");
|
|
||||||
ConfigurationProperty thirdProp = new ConfigurationProperty("spring.test.third", "java.lang.String");
|
|
||||||
CompoundConfigurationTableEntry entry = new CompoundConfigurationTableEntry("spring.test",
|
|
||||||
"This is a description.");
|
|
||||||
entry.addConfigurationKeys(firstProp, secondProp, thirdProp);
|
|
||||||
AsciidocBuilder builder = new AsciidocBuilder();
|
|
||||||
entry.write(builder);
|
|
||||||
assertThat(builder.toString()).isEqualTo("|[[spring.test]]<<spring.test,`+spring.test.first+` +" + NEWLINE
|
|
||||||
+ "`+spring.test.second+` +" + NEWLINE + "`+spring.test.third+` +" + NEWLINE + ">>" + NEWLINE + NEWLINE
|
|
||||||
+ "|" + NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2021 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.build.context.properties;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link CompoundRow}.
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
*/
|
||||||
|
public class CompoundRowTests {
|
||||||
|
|
||||||
|
private static final String NEWLINE = System.lineSeparator();
|
||||||
|
|
||||||
|
private static final Snippet SNIPPET = new Snippet("my", "title", null);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void simpleProperty() {
|
||||||
|
CompoundRow row = new CompoundRow(SNIPPET, "spring.test", "This is a description.");
|
||||||
|
row.addProperty(new ConfigurationProperty("spring.test.first", "java.lang.String"));
|
||||||
|
row.addProperty(new ConfigurationProperty("spring.test.second", "java.lang.String"));
|
||||||
|
row.addProperty(new ConfigurationProperty("spring.test.third", "java.lang.String"));
|
||||||
|
Asciidoc asciidoc = new Asciidoc();
|
||||||
|
row.write(asciidoc);
|
||||||
|
assertThat(asciidoc.toString()).isEqualTo("|[[my.spring.test]]<<my.spring.test,`+spring.test.first+` +"
|
||||||
|
+ NEWLINE + "`+spring.test.second+` +" + NEWLINE + "`+spring.test.third+` +" + NEWLINE + ">>" + NEWLINE
|
||||||
|
+ "|+++This is a description.+++" + NEWLINE + "|" + NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -18,7 +18,6 @@ package org.springframework.boot.build.context.properties;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@ -33,7 +32,7 @@ class ConfigurationPropertiesTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void whenJsonHasAnIntegerDefaultValueThenItRemainsAnIntegerWhenRead() {
|
void whenJsonHasAnIntegerDefaultValueThenItRemainsAnIntegerWhenRead() {
|
||||||
Map<String, ConfigurationProperty> properties = ConfigurationProperties
|
ConfigurationProperties properties = ConfigurationProperties
|
||||||
.fromFiles(Arrays.asList(new File("src/test/resources/spring-configuration-metadata.json")));
|
.fromFiles(Arrays.asList(new File("src/test/resources/spring-configuration-metadata.json")));
|
||||||
assertThat(properties.get("example.counter").getDefaultValue()).isEqualTo(0);
|
assertThat(properties.get("example.counter").getDefaultValue()).isEqualTo(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2021 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.build.context.properties;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link ConfigurationTable}.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
*/
|
|
||||||
public class ConfigurationTableTests {
|
|
||||||
|
|
||||||
private static final String NEWLINE = System.lineSeparator();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void simpleTable() {
|
|
||||||
ConfigurationTable table = new ConfigurationTable("test");
|
|
||||||
ConfigurationProperty first = new ConfigurationProperty("spring.test.prop", "java.lang.String", "something",
|
|
||||||
"This is a description.", false);
|
|
||||||
ConfigurationProperty second = new ConfigurationProperty("spring.test.other", "java.lang.String", "other value",
|
|
||||||
"This is another description.", false);
|
|
||||||
table.addEntry(new SingleConfigurationTableEntry(first));
|
|
||||||
table.addEntry(new SingleConfigurationTableEntry(second));
|
|
||||||
assertThat(table.toAsciidocTable()).isEqualTo("[cols=\"4,3,3\", options=\"header\"]" + NEWLINE + "|==="
|
|
||||||
+ NEWLINE + "|Key|Default Value|Description" + NEWLINE + NEWLINE
|
|
||||||
+ "|[[spring.test.other]]<<spring.test.other,`+spring.test.other+`>>" + NEWLINE + "|`+other value+`"
|
|
||||||
+ NEWLINE + "|+++This is another description.+++" + NEWLINE + NEWLINE
|
|
||||||
+ "|[[spring.test.prop]]<<spring.test.prop,`+spring.test.prop+`>>" + NEWLINE + "|`+something+`"
|
|
||||||
+ NEWLINE + "|+++This is a description.+++" + NEWLINE + NEWLINE + "|===" + NEWLINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2020 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.build.context.properties;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link SingleConfigurationTableEntry}.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
*/
|
|
||||||
public class SingleConfigurationTableEntryTests {
|
|
||||||
|
|
||||||
private static final String NEWLINE = System.lineSeparator();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void simpleProperty() {
|
|
||||||
ConfigurationProperty property = new ConfigurationProperty("spring.test.prop", "java.lang.String", "something",
|
|
||||||
"This is a description.", false);
|
|
||||||
SingleConfigurationTableEntry entry = new SingleConfigurationTableEntry(property);
|
|
||||||
AsciidocBuilder builder = new AsciidocBuilder();
|
|
||||||
entry.write(builder);
|
|
||||||
assertThat(builder.toString()).isEqualTo("|[[spring.test.prop]]<<spring.test.prop,`+spring.test.prop+`>>"
|
|
||||||
+ NEWLINE + "|`+something+`" + NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void noDefaultValue() {
|
|
||||||
ConfigurationProperty property = new ConfigurationProperty("spring.test.prop", "java.lang.String", null,
|
|
||||||
"This is a description.", false);
|
|
||||||
SingleConfigurationTableEntry entry = new SingleConfigurationTableEntry(property);
|
|
||||||
AsciidocBuilder builder = new AsciidocBuilder();
|
|
||||||
entry.write(builder);
|
|
||||||
assertThat(builder.toString()).isEqualTo("|[[spring.test.prop]]<<spring.test.prop,`+spring.test.prop+`>>"
|
|
||||||
+ NEWLINE + "|" + NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void defaultValueWithPipes() {
|
|
||||||
ConfigurationProperty property = new ConfigurationProperty("spring.test.prop", "java.lang.String",
|
|
||||||
"first|second", "This is a description.", false);
|
|
||||||
SingleConfigurationTableEntry entry = new SingleConfigurationTableEntry(property);
|
|
||||||
AsciidocBuilder builder = new AsciidocBuilder();
|
|
||||||
entry.write(builder);
|
|
||||||
assertThat(builder.toString()).isEqualTo("|[[spring.test.prop]]<<spring.test.prop,`+spring.test.prop+`>>"
|
|
||||||
+ NEWLINE + "|`+first\\|second+`" + NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void defaultValueWithBackslash() {
|
|
||||||
ConfigurationProperty property = new ConfigurationProperty("spring.test.prop", "java.lang.String",
|
|
||||||
"first\\second", "This is a description.", false);
|
|
||||||
SingleConfigurationTableEntry entry = new SingleConfigurationTableEntry(property);
|
|
||||||
AsciidocBuilder builder = new AsciidocBuilder();
|
|
||||||
entry.write(builder);
|
|
||||||
assertThat(builder.toString()).isEqualTo("|[[spring.test.prop]]<<spring.test.prop,`+spring.test.prop+`>>"
|
|
||||||
+ NEWLINE + "|`+first\\\\second+`" + NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void descriptionWithPipe() {
|
|
||||||
ConfigurationProperty property = new ConfigurationProperty("spring.test.prop", "java.lang.String", null,
|
|
||||||
"This is a description with a | pipe.", false);
|
|
||||||
SingleConfigurationTableEntry entry = new SingleConfigurationTableEntry(property);
|
|
||||||
AsciidocBuilder builder = new AsciidocBuilder();
|
|
||||||
entry.write(builder);
|
|
||||||
assertThat(builder.toString()).isEqualTo("|[[spring.test.prop]]<<spring.test.prop,`+spring.test.prop+`>>"
|
|
||||||
+ NEWLINE + "|" + NEWLINE + "|+++This is a description with a \\| pipe.+++" + NEWLINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void mapProperty() {
|
|
||||||
ConfigurationProperty property = new ConfigurationProperty("spring.test.prop",
|
|
||||||
"java.util.Map<java.lang.String,java.lang.String>", null, "This is a description.", false);
|
|
||||||
SingleConfigurationTableEntry entry = new SingleConfigurationTableEntry(property);
|
|
||||||
AsciidocBuilder builder = new AsciidocBuilder();
|
|
||||||
entry.write(builder);
|
|
||||||
assertThat(builder.toString()).isEqualTo("|[[spring.test.prop]]<<spring.test.prop,`+spring.test.prop.*+`>>"
|
|
||||||
+ NEWLINE + "|" + NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void listProperty() {
|
|
||||||
String[] defaultValue = new String[] { "first", "second", "third" };
|
|
||||||
ConfigurationProperty property = new ConfigurationProperty("spring.test.prop",
|
|
||||||
"java.util.List<java.lang.String>", defaultValue, "This is a description.", false);
|
|
||||||
SingleConfigurationTableEntry entry = new SingleConfigurationTableEntry(property);
|
|
||||||
AsciidocBuilder builder = new AsciidocBuilder();
|
|
||||||
entry.write(builder);
|
|
||||||
assertThat(builder.toString()).isEqualTo(
|
|
||||||
"|[[spring.test.prop]]<<spring.test.prop,`+spring.test.prop+`>>" + NEWLINE + "|`+first," + NEWLINE
|
|
||||||
+ "second," + NEWLINE + "third+`" + NEWLINE + "|+++This is a description.+++" + NEWLINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2021 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.build.context.properties;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link SingleRow}.
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
*/
|
||||||
|
public class SingleRowTests {
|
||||||
|
|
||||||
|
private static final String NEWLINE = System.lineSeparator();
|
||||||
|
|
||||||
|
private static final Snippet SNIPPET = new Snippet("my", "title", null);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void simpleProperty() {
|
||||||
|
ConfigurationProperty property = new ConfigurationProperty("spring.test.prop", "java.lang.String", "something",
|
||||||
|
"This is a description.", false);
|
||||||
|
SingleRow row = new SingleRow(SNIPPET, property);
|
||||||
|
Asciidoc asciidoc = new Asciidoc();
|
||||||
|
row.write(asciidoc);
|
||||||
|
assertThat(asciidoc.toString()).isEqualTo("|[[my.spring.test.prop]]<<my.spring.test.prop,`+spring.test.prop+`>>"
|
||||||
|
+ NEWLINE + "|+++This is a description.+++" + NEWLINE + "|`+something+`" + NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void noDefaultValue() {
|
||||||
|
ConfigurationProperty property = new ConfigurationProperty("spring.test.prop", "java.lang.String", null,
|
||||||
|
"This is a description.", false);
|
||||||
|
SingleRow row = new SingleRow(SNIPPET, property);
|
||||||
|
Asciidoc asciidoc = new Asciidoc();
|
||||||
|
row.write(asciidoc);
|
||||||
|
assertThat(asciidoc.toString()).isEqualTo("|[[my.spring.test.prop]]<<my.spring.test.prop,`+spring.test.prop+`>>"
|
||||||
|
+ NEWLINE + "|+++This is a description.+++" + NEWLINE + "|" + NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void defaultValueWithPipes() {
|
||||||
|
ConfigurationProperty property = new ConfigurationProperty("spring.test.prop", "java.lang.String",
|
||||||
|
"first|second", "This is a description.", false);
|
||||||
|
SingleRow row = new SingleRow(SNIPPET, property);
|
||||||
|
Asciidoc asciidoc = new Asciidoc();
|
||||||
|
row.write(asciidoc);
|
||||||
|
assertThat(asciidoc.toString()).isEqualTo("|[[my.spring.test.prop]]<<my.spring.test.prop,`+spring.test.prop+`>>"
|
||||||
|
+ NEWLINE + "|+++This is a description.+++" + NEWLINE + "|`+first\\|second+`" + NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void defaultValueWithBackslash() {
|
||||||
|
ConfigurationProperty property = new ConfigurationProperty("spring.test.prop", "java.lang.String",
|
||||||
|
"first\\second", "This is a description.", false);
|
||||||
|
SingleRow row = new SingleRow(SNIPPET, property);
|
||||||
|
Asciidoc asciidoc = new Asciidoc();
|
||||||
|
row.write(asciidoc);
|
||||||
|
assertThat(asciidoc.toString()).isEqualTo("|[[my.spring.test.prop]]<<my.spring.test.prop,`+spring.test.prop+`>>"
|
||||||
|
+ NEWLINE + "|+++This is a description.+++" + NEWLINE + "|`+first\\\\second+`" + NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void descriptionWithPipe() {
|
||||||
|
ConfigurationProperty property = new ConfigurationProperty("spring.test.prop", "java.lang.String", null,
|
||||||
|
"This is a description with a | pipe.", false);
|
||||||
|
SingleRow row = new SingleRow(SNIPPET, property);
|
||||||
|
Asciidoc asciidoc = new Asciidoc();
|
||||||
|
row.write(asciidoc);
|
||||||
|
assertThat(asciidoc.toString()).isEqualTo("|[[my.spring.test.prop]]<<my.spring.test.prop,`+spring.test.prop+`>>"
|
||||||
|
+ NEWLINE + "|+++This is a description with a \\| pipe.+++" + NEWLINE + "|" + NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void mapProperty() {
|
||||||
|
ConfigurationProperty property = new ConfigurationProperty("spring.test.prop",
|
||||||
|
"java.util.Map<java.lang.String,java.lang.String>", null, "This is a description.", false);
|
||||||
|
SingleRow row = new SingleRow(SNIPPET, property);
|
||||||
|
Asciidoc asciidoc = new Asciidoc();
|
||||||
|
row.write(asciidoc);
|
||||||
|
assertThat(asciidoc.toString())
|
||||||
|
.isEqualTo("|[[my.spring.test.prop]]<<my.spring.test.prop,`+spring.test.prop.*+`>>" + NEWLINE
|
||||||
|
+ "|+++This is a description.+++" + NEWLINE + "|" + NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listProperty() {
|
||||||
|
String[] defaultValue = new String[] { "first", "second", "third" };
|
||||||
|
ConfigurationProperty property = new ConfigurationProperty("spring.test.prop",
|
||||||
|
"java.util.List<java.lang.String>", defaultValue, "This is a description.", false);
|
||||||
|
SingleRow row = new SingleRow(SNIPPET, property);
|
||||||
|
Asciidoc asciidoc = new Asciidoc();
|
||||||
|
row.write(asciidoc);
|
||||||
|
assertThat(asciidoc.toString()).isEqualTo("|[[my.spring.test.prop]]<<my.spring.test.prop,`+spring.test.prop+`>>"
|
||||||
|
+ NEWLINE + "|+++This is a description.+++" + NEWLINE + "|`+first," + NEWLINE + "second," + NEWLINE
|
||||||
|
+ "third+`" + NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2021 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.build.context.properties;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link Table}.
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
*/
|
||||||
|
public class TableTests {
|
||||||
|
|
||||||
|
private static final String NEWLINE = System.lineSeparator();
|
||||||
|
|
||||||
|
private static final Snippet SNIPPET = new Snippet("my", "title", null);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void simpleTable() {
|
||||||
|
Table table = new Table();
|
||||||
|
table.addRow(new SingleRow(SNIPPET, new ConfigurationProperty("spring.test.prop", "java.lang.String",
|
||||||
|
"something", "This is a description.", false)));
|
||||||
|
table.addRow(new SingleRow(SNIPPET, new ConfigurationProperty("spring.test.other", "java.lang.String",
|
||||||
|
"other value", "This is another description.", false)));
|
||||||
|
Asciidoc asciidoc = new Asciidoc();
|
||||||
|
table.write(asciidoc);
|
||||||
|
// @formatter:off
|
||||||
|
assertThat(asciidoc.toString()).isEqualTo(
|
||||||
|
"[cols=\"4,3,3\", options=\"header\"]" + NEWLINE +
|
||||||
|
"|===" + NEWLINE +
|
||||||
|
"|Name|Description|Default Value" + NEWLINE + NEWLINE +
|
||||||
|
"|[[my.spring.test.other]]<<my.spring.test.other,`+spring.test.other+`>>" + NEWLINE +
|
||||||
|
"|+++This is another description.+++" + NEWLINE +
|
||||||
|
"|`+other value+`" + NEWLINE + NEWLINE +
|
||||||
|
"|[[my.spring.test.prop]]<<my.spring.test.prop,`+spring.test.prop+`>>" + NEWLINE +
|
||||||
|
"|+++This is a description.+++" + NEWLINE +
|
||||||
|
"|`+something+`" + NEWLINE + NEWLINE +
|
||||||
|
"|===" + NEWLINE);
|
||||||
|
// @formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -218,7 +218,7 @@ task documentVersionProperties(type: org.springframework.boot.build.constraints.
|
||||||
|
|
||||||
task documentConfigurationProperties(type: org.springframework.boot.build.context.properties.DocumentConfigurationProperties) {
|
task documentConfigurationProperties(type: org.springframework.boot.build.context.properties.DocumentConfigurationProperties) {
|
||||||
configurationPropertyMetadata = configurations.configurationProperties
|
configurationPropertyMetadata = configurations.configurationProperties
|
||||||
outputDir = file("${buildDir}/docs/generated/application-properties/documented-application-properties/")
|
outputDir = file("${buildDir}/docs/generated/")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask) {
|
tasks.withType(org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask) {
|
||||||
|
|
|
@ -762,3 +762,19 @@ executable-jar-alternatives=executable-jar.alternatives
|
||||||
dependency-versions=dependency-versions
|
dependency-versions=dependency-versions
|
||||||
dependency-versions-coordinates=dependency-versions.coordinates
|
dependency-versions-coordinates=dependency-versions.coordinates
|
||||||
dependency-versions-properties=dependency-versions.properties
|
dependency-versions-properties=dependency-versions.properties
|
||||||
|
core-properties=application-properties.core
|
||||||
|
cache-properties=application-properties.cache
|
||||||
|
mail-properties=application-properties.mail
|
||||||
|
json-properties=application-properties.json
|
||||||
|
data-properties=application-properties.data
|
||||||
|
transaction-properties=application-properties.transaction
|
||||||
|
data-migration-properties=application-properties.data-migration
|
||||||
|
integration-properties=application-properties.integration
|
||||||
|
web-properties=application-properties.web
|
||||||
|
templating-properties=application-properties.templating
|
||||||
|
server-properties=application-properties.server
|
||||||
|
security-properties=application-properties.security
|
||||||
|
rsocket-properties=application-properties.rsocket
|
||||||
|
actuator-properties=application-properties.actuator
|
||||||
|
devtools-properties=application-properties.devtools
|
||||||
|
testing-properties=application-properties.testing
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[appendix]
|
[appendix]
|
||||||
[[application-properties]]
|
[[application-properties]]
|
||||||
= Common Application properties
|
= Common Application Properties
|
||||||
include::attributes.adoc[]
|
include::attributes.adoc[]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.actuator]]
|
|
||||||
== Actuator Properties [[actuator-properties]]
|
|
||||||
include::documented-application-properties/actuator.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.cache]]
|
|
||||||
== Cache Properties [[cache-properties]]
|
|
||||||
include::documented-application-properties/cache.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.core]]
|
|
||||||
== Core Properties [[core-properties]]
|
|
||||||
include::documented-application-properties/core.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.data-migration]]
|
|
||||||
== Data Migration Properties [[data-migration-properties]]
|
|
||||||
include::documented-application-properties/data-migration.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.data]]
|
|
||||||
== Data Properties [[data-properties]]
|
|
||||||
include::documented-application-properties/data.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.devtools]]
|
|
||||||
== Devtools Properties [[devtools-properties]]
|
|
||||||
include::documented-application-properties/devtools.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.integration]]
|
|
||||||
== Integration Properties [[integration-properties]]
|
|
||||||
include::documented-application-properties/integration.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.json]]
|
|
||||||
== JSON Properties [[json-properties]]
|
|
||||||
include::documented-application-properties/json.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.mail]]
|
|
||||||
== Mail Properties [[mail-properties]]
|
|
||||||
include::documented-application-properties/mail.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.rsocket]]
|
|
||||||
== RSocket Properties [[rsocket-properties]]
|
|
||||||
include::documented-application-properties/rsocket.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.security]]
|
|
||||||
== Security Properties [[security-properties]]
|
|
||||||
include::documented-application-properties/security.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.server]]
|
|
||||||
== Server Properties [[server-properties]]
|
|
||||||
include::documented-application-properties/server.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.templating]]
|
|
||||||
== Templating Properties [[templating-properties]]
|
|
||||||
include::documented-application-properties/templating.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.testing]]
|
|
||||||
== Testing Properties [[testing-properties]]
|
|
||||||
include::documented-application-properties/testing.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.transaction]]
|
|
||||||
== Transaction Properties [[transaction-properties]]
|
|
||||||
include::documented-application-properties/transaction.adoc[]
|
|
|
@ -1,3 +0,0 @@
|
||||||
[[application-properties.web]]
|
|
||||||
== Web Properties [[web-properties]]
|
|
||||||
include::documented-application-properties/web.adoc[]
|
|
Loading…
Reference in New Issue