Skip to content

Commit

Permalink
HelpConfigCommand: Help for configs #2
Browse files Browse the repository at this point in the history
* Maps of Maps
* Maps of Lists
* refactoring common pieces
  • Loading branch information
andrus committed Dec 31, 2016
1 parent 989ca6e commit 7abb606
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
import io.bootique.meta.config.ConfigValueMetadata;

import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

Expand All @@ -30,8 +32,7 @@ public ConfigSectionGenerator(ConsoleAppender out) {

@Override
public Object visitObjectMetadata(ConfigObjectMetadata metadata) {
printTypeHeader(metadata);
out.println(metadata.getName(), ":");
printTypeHeader(metadata, false);

List<ConfigMetadataNode> sortedChildren = metadata.getProperties()
.stream()
Expand All @@ -58,28 +59,13 @@ public Object visitObjectMetadata(ConfigObjectMetadata metadata) {

@Override
public Object visitValueMetadata(ConfigValueMetadata metadata) {

printTypeHeader(metadata);

if (metadata.getType() != null) {
printText(metadata.getName(), ": ", sampleValue(metadata.getType()));
} else {
printText(metadata.getName(), ": ?");
}
printTypeHeader(metadata, true);
return null;
}

@Override
public Object visitListMetadata(ConfigListMetadata metadata) {

// TODO: decipher collection type... for now hardcoding List type
printText("# Type: List");

if (metadata.getDescription() != null) {
printText("# ", metadata.getDescription());
}

printText(metadata.getName(), ":");
printTypeHeader(metadata, false);

// TODO: should support multiple element types (from META-INF/services/PolymorphicConfiguration)
metadata.getElementType().accept(new ConfigSectionListChildGenerator(withOffset(DEFAULT_OFFSET)));
Expand All @@ -89,18 +75,11 @@ public Object visitListMetadata(ConfigListMetadata metadata) {

@Override
public Object visitMapMetadata(ConfigMapMetadata metadata) {

// TODO: decipher collection type... for now hardcoding List type
printText("# Type: Map");

if (metadata.getDescription() != null) {
printText("# ", metadata.getDescription());
}

printText(metadata.getName(), ":");
printTypeHeader(metadata, false);

// TODO: should support multiple element types (from META-INF/services/PolymorphicConfiguration)
metadata.getValuesType().accept(new ConfigSectionMapChildGenerator(metadata.getKeysType(), withOffset(DEFAULT_OFFSET)));
metadata.getValuesType().accept(
new ConfigSectionMapChildGenerator(metadata.getKeysType(), withOffset(DEFAULT_OFFSET)));

return null;
}
Expand All @@ -109,23 +88,30 @@ protected ConfigSectionGenerator withOffset(int offset) {
return new ConfigSectionGenerator(out.withOffset(offset));
}

protected void printText(String... parts) {
out.println(parts);
protected void println(String... phrases) {
out.println(phrases);
}

protected void println() {
out.println();
}

protected void printTypeHeader(ConfigValueMetadata metadata) {
protected void printTypeHeader(ConfigValueMetadata metadata, boolean asValue) {
Type valueType = metadata.getType();

if (valueType != null) {
printText("# Type: ", typeLabel(valueType));
println("# Type: ", typeLabel(valueType));
}

if (metadata.getDescription() != null) {
printText("# ", metadata.getDescription());
println("# ", metadata.getDescription());
}

if (asValue) {
String valueLabel = metadata.getType() != null ? sampleValue(metadata.getType()) : "?";
println(metadata.getName(), ": ", valueLabel);
} else {
println(metadata.getName(), ":");
}
}

Expand Down Expand Up @@ -186,6 +172,18 @@ protected String typeLabel(Type type) {
case "java.lang.String":
return "String";
default:

if(type instanceof Class) {
Class<?> classType = (Class<?>) type;
if(Map.class.isAssignableFrom(classType)) {
return "Map";
}
// TODO: decipher collection type... for now hardcoding List type
else if(Collection.class.isAssignableFrom(classType)) {
return "List";
}
}

return typeName;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public Object visitValueMetadata(ConfigValueMetadata metadata) {
printTypeHeader(metadata);

String line = metadata.getType() != null ? parent.sampleValue(metadata.getType()) : "?";
parent.printText(" ", line);
parent.println(" ", line);
return null;
}

Expand Down Expand Up @@ -64,11 +64,11 @@ protected void printTypeHeader(ConfigValueMetadata metadata) {
Type valueType = metadata.getType();

if (valueType != null) {
parent.printText("- # Element type: ", parent.typeLabel(valueType));
parent.println("- # Element type: ", parent.typeLabel(valueType));
}

if (metadata.getDescription() != null) {
parent.printText(" # ", metadata.getDescription());
parent.println(" # ", metadata.getDescription());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.bootique.help.config;

import io.bootique.meta.MetadataNode;
import io.bootique.meta.config.ConfigListMetadata;
import io.bootique.meta.config.ConfigMapMetadata;
import io.bootique.meta.config.ConfigMetadataNode;
import io.bootique.meta.config.ConfigMetadataVisitor;
import io.bootique.meta.config.ConfigObjectMetadata;
Expand All @@ -24,20 +26,13 @@ public ConfigSectionMapChildGenerator(Class<?> keysType, ConfigSectionGenerator

@Override
public Object visitValueMetadata(ConfigValueMetadata metadata) {
printTypeHeader(metadata);

String keyLabel = parent.sampleValue(keysType);
String line = metadata.getType() != null ? parent.sampleValue(metadata.getType()) : "?";
parent.printText(keyLabel, ": ", line);
printTypeHeader(metadata, true);
return null;
}

@Override
public Object visitObjectMetadata(ConfigObjectMetadata metadata) {
printTypeHeader(metadata);

String keyLabel = parent.sampleValue(keysType);
parent.printText(keyLabel, ":");
printTypeHeader(metadata, false);

List<ConfigMetadataNode> sortedChildren = metadata.getProperties()
.stream()
Expand All @@ -62,19 +57,47 @@ public Object visitObjectMetadata(ConfigObjectMetadata metadata) {
return null;
}

// TODO: visit list and map...
@Override
public Object visitMapMetadata(ConfigMapMetadata metadata) {
printTypeHeader(metadata, false);

protected void printTypeHeader(ConfigValueMetadata metadata) {
// TODO: should support multiple element types (from META-INF/services/PolymorphicConfiguration)
ConfigSectionGenerator childGenerator = parent.withOffset(ConfigSectionGenerator.DEFAULT_OFFSET);
metadata.getValuesType().accept(
new ConfigSectionMapChildGenerator(metadata.getKeysType(), childGenerator));

parent.printText("# Keys type: ", parent.typeLabel(keysType));
return null;
}

@Override
public Object visitListMetadata(ConfigListMetadata metadata) {
printTypeHeader(metadata, false);

// TODO: should support multiple element types (from META-INF/services/PolymorphicConfiguration)
ConfigSectionGenerator childGenerator = parent.withOffset(ConfigSectionGenerator.DEFAULT_OFFSET);
metadata.getElementType().accept(new ConfigSectionListChildGenerator(childGenerator));

return null;
}

protected void printTypeHeader(ConfigValueMetadata metadata, boolean asValue) {

parent.println("# Keys type: ", parent.typeLabel(keysType));

Type valueType = metadata.getType();
if (valueType != null) {
parent.printText("# Values type: ", parent.typeLabel(valueType));
parent.println("# Values type: ", parent.typeLabel(valueType));
}

if (metadata.getDescription() != null) {
parent.printText("# ", metadata.getDescription());
parent.println("# ", metadata.getDescription());
}

if (asValue) {
String valueLabel = metadata.getType() != null ? parent.sampleValue(metadata.getType()) : "?";
parent.println(parent.sampleValue(keysType), ": ", valueLabel);
} else {
parent.println(parent.sampleValue(keysType), ":");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public void testVisitMapOfValues() {
}

@Test
public void testVisitMapOfObjects() {
public void testVisitObjectWithMapOfObjects() {

ConfigObjectMetadata mapMd = ConfigObjectMetadata.builder()
.type(ConfigRoot2.class)
Expand Down Expand Up @@ -173,6 +173,87 @@ public void testVisitMapOfObjects() {
);
}

@Test
public void testVisitMapOfMapsOfObjects() {

ConfigObjectMetadata objectMd = ConfigObjectMetadata.builder()
.type(ConfigRoot2.class)
.addProperty(ConfigValueMetadata.builder("p4").type(String.class).build())
.addProperty(ConfigValueMetadata.builder("p3").type(Boolean.TYPE).build())
.build();

ConfigMapMetadata subMapMd = ConfigMapMetadata
.builder()
.description("Submap description")
.keysType(String.class)
.valuesType(objectMd)
.build();

ConfigMapMetadata rootMapMd = ConfigMapMetadata
.builder("root")
.description("Root map")
.keysType(String.class)
.valuesType(subMapMd)
.build();

assertLines(rootMapMd,
"# Type: Map",
"# Root map",
"root:",
" # Keys type: String",
" # Values type: Map",
" # Submap description",
" <string>:",
" # Keys type: String",
" # Values type: io.bootique.help.config.ConfigSectionGeneratorTest$ConfigRoot2",
" <string>:",
" # Type: boolean",
" p3: <true|false>",
"",
" # Type: String",
" p4: <string>"
);
}

@Test
public void testVisitMapOfListsOfObjects() {

ConfigObjectMetadata objectMd = ConfigObjectMetadata.builder()
.type(ConfigRoot2.class)
.addProperty(ConfigValueMetadata.builder("p4").type(String.class).build())
.addProperty(ConfigValueMetadata.builder("p3").type(Boolean.TYPE).build())
.build();

ConfigListMetadata subListMd = ConfigListMetadata
.builder()
.description("Sublist description")
.elementType(objectMd)
.build();

ConfigMapMetadata rootMapMd = ConfigMapMetadata
.builder("root")
.description("Root map")
.keysType(String.class)
.valuesType(subListMd)
.build();

assertLines(rootMapMd,
"# Type: Map",
"# Root map",
"root:",
" # Keys type: String",
" # Values type: List",
" # Sublist description",
" <string>:",
" - # Element type: io.bootique.help.config.ConfigSectionGeneratorTest$ConfigRoot2",
" # Type: boolean",
" p3: <true|false>",
"",
" # Type: String",
" p4: <string>"
);
}

public static class ConfigRoot1 {

}
Expand Down

0 comments on commit 7abb606

Please sign in to comment.