diff --git a/src/main/java/ch/jalu/configme/resource/PropertyPathTraverser.java b/src/main/java/ch/jalu/configme/resource/PropertyPathTraverser.java
index ef4be049..4e9c223c 100644
--- a/src/main/java/ch/jalu/configme/resource/PropertyPathTraverser.java
+++ b/src/main/java/ch/jalu/configme/resource/PropertyPathTraverser.java
@@ -1,7 +1,5 @@
package ch.jalu.configme.resource;
-import ch.jalu.configme.configurationdata.ConfigurationData;
-import ch.jalu.configme.utils.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -9,70 +7,57 @@
/**
* Helper class for the export of properties: it keeps track of the previously traversed property
- * and returns which path parts are new and defines the level of indentation.
+ * and returns which path parts are new.
*
- * For example if the property for path {@code config.datasource.mysql.type} was exported and we now
+ * For example, if the property for path {@code config.datasource.mysql.type} was exported and we now
* encounter the property for path {@code config.datasource.driver.version}, the newly encountered
* sections are {@code driver} and {@code version}.
*/
-public class PropertyPathTraverser { // todo: delete?
+public class PropertyPathTraverser {
- private final ConfigurationData configurationData;
/** Contains all path elements besides the last, e.g. {datasource, mysql} for "datasource.mysql.table". */
- private List parentPathElements = new ArrayList<>(0);
+ private String parentPathElements;
private boolean isFirstProperty = true;
- public PropertyPathTraverser(@NotNull ConfigurationData configurationData) {
- this.configurationData = configurationData;
- }
-
- /**
- * Returns all path elements for the given property that have not been traversed yet.
- *
- * @param pathElements all elements that make up the path of the property
- * @return the new path elements
- */
- public @NotNull List getPathElements(@NotNull List pathElements) {
- List commonPathParts = CollectionUtils.filterCommonStart(
- parentPathElements, pathElements.subList(0, pathElements.size() - 1));
- List newPathParts = CollectionUtils.getRange(pathElements, commonPathParts.size());
-
- parentPathElements = pathElements.subList(0, pathElements.size() - 1);
+ public @NotNull List getPathElements(@NotNull String path) {
+ String[] pathParts = path.split("\\.");
+ int totalParts = pathParts.length;
+ int indentationOfFirstNewPart = returnIndentationOfFirstNewPathPart(path);
+ parentPathElements = path;
+
+ StringBuilder fullPathBuilder = new StringBuilder();
+ List pathElements = new ArrayList<>(totalParts);
+ int indentation = 0;
+ for (int i = 0; i < totalParts; ++i) {
+ fullPathBuilder.append(pathParts[i]);
+ PathElement element = new PathElement(indentation, pathParts[i], fullPathBuilder.toString(), isFirstProperty);
+ element.setEndOfPath(i == totalParts - 1);
+ element.setFirstOfGroup(indentationOfFirstNewPart == indentation);
+ pathElements.add(element);
- int indentationLevel = commonPathParts.size();
- String prefix = commonPathParts.isEmpty() ? "" : String.join(".", commonPathParts) + ".";
- return convertToPathElements(indentationLevel, prefix, newPathParts);
- }
-
- private @NotNull List convertToPathElements(int indentation, @NotNull String prefix,
- @NotNull List elements) {
- List pathElements = new ArrayList<>(elements.size());
- for (String element : elements) {
- List comments = isFirstProperty
- ? getCommentsIncludingRoot(prefix + element)
- : configurationData.getCommentsForSection(prefix + element);
- pathElements.add(new PathElement(indentation, element, comments, isFirstProperty));
- isFirstProperty = false;
- prefix += element + ".";
++indentation;
+ fullPathBuilder.append(".");
+ isFirstProperty = false;
}
- pathElements.get(0).setFirstOfGroup(true);
+ parentPathElements = path;
return pathElements;
}
- private @NotNull List getCommentsIncludingRoot(@NotNull String path) {
- List rootComments = configurationData.getCommentsForSection("");
- if ("".equals(path)) {
- return rootComments;
+ private int returnIndentationOfFirstNewPathPart(String path) {
+ if (parentPathElements == null) {
+ return 0;
}
- List sectionComments = configurationData.getCommentsForSection(path);
- // One or the other list might be empty, but we only do this once so we can ignore performance considerations
- if (sectionComments.isEmpty()) {
- return rootComments;
+
+ int minLength = Math.min(parentPathElements.length(), path.length());
+ int i = 0;
+ int indentation = 0;
+ while (i < minLength && path.charAt(i) == parentPathElements.charAt(i)) {
+ if (path.charAt(i) == '.') {
+ ++indentation;
+ }
+ ++i;
}
- List allComments = new ArrayList<>(rootComments);
- allComments.addAll(sectionComments);
- return allComments;
+ return indentation;
}
/**
@@ -83,15 +68,16 @@ public static class PathElement {
private final int indentationLevel;
private final String name;
- private List comments;
+ private final String fullPath;
private final boolean isFirstElement;
private boolean isFirstOfGroup;
+ private boolean isEndOfPath;
- public PathElement(int indentationLevel, @NotNull String name, @NotNull List comments,
+ public PathElement(int indentationLevel, @NotNull String name, @NotNull String fullPath,
boolean isFirstElement) {
this.indentationLevel = indentationLevel;
this.name = name;
- this.comments = comments;
+ this.fullPath = fullPath;
this.isFirstElement = isFirstElement;
}
@@ -103,17 +89,8 @@ public int getIndentationLevel() {
return name;
}
- public @NotNull List getComments() {
- return comments;
- }
-
- public void addComments(@NotNull List commentsToAdd) {
- if (!commentsToAdd.isEmpty()) {
- if (comments.getClass() != ArrayList.class) {
- comments = new ArrayList<>(comments);
- }
- comments.addAll(commentsToAdd);
- }
+ public @NotNull String getFullPath() {
+ return fullPath;
}
public boolean isFirstElement() {
@@ -127,6 +104,13 @@ public boolean isFirstOfGroup() {
void setFirstOfGroup(boolean firstOfGroup) {
isFirstOfGroup = firstOfGroup;
}
- }
+ public boolean isEndOfPath() {
+ return isEndOfPath;
+ }
+
+ void setEndOfPath(boolean isEndOfPath) {
+ this.isEndOfPath = isEndOfPath;
+ }
+ }
}
diff --git a/src/main/java/ch/jalu/configme/resource/YamlFileResource.java b/src/main/java/ch/jalu/configme/resource/YamlFileResource.java
index d7a0f2c6..a8274260 100644
--- a/src/main/java/ch/jalu/configme/resource/YamlFileResource.java
+++ b/src/main/java/ch/jalu/configme/resource/YamlFileResource.java
@@ -22,12 +22,10 @@
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
-import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
@@ -38,13 +36,11 @@
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
-import static ch.jalu.configme.utils.CollectionUtils.getLastElementOrThrow;
-
public class YamlFileResource implements PropertyResource {
private final Path path;
private final @NotNull YamlFileResourceOptions options;
- private final String indentationSpace;
+ private final int indentationSize;
private @Nullable Yaml yamlObject;
public YamlFileResource(@NotNull Path path) {
@@ -54,7 +50,7 @@ public YamlFileResource(@NotNull Path path) {
public YamlFileResource(@NotNull Path path, @NotNull YamlFileResourceOptions options) {
this.path = path;
this.options = options;
- this.indentationSpace = options.getIndentation();
+ this.indentationSize = options.getIndentationSize();
}
/**
@@ -117,7 +113,7 @@ Node toNodeRecursive() {
}
MappingNode mappingNode = new MappingNode(Tag.MAP, entryNodes, DumperOptions.FlowStyle.BLOCK);
- List comLines = createCommentLines(comments.stream());
+ List comLines = createCommentLines(comments);
mappingNode.setBlockComments(comLines);
return mappingNode;
}
@@ -128,23 +124,23 @@ public void exportProperties(@NotNull ConfigurationData configurationData) {
List> properties = configurationData.getProperties();
Container root = new Container(configurationData.getCommentsForSection(""));
+ PropertyPathTraverser pathTraverser = new PropertyPathTraverser();
+
for (Property> property : properties) {
Object exportValue = getExportValue(property, configurationData);
if (exportValue != null) {
Container container = root;
- String[] pathElems = property.getPath().split("\\.");
- for (int i = 0; i < pathElems.length - 1; ++i) {
- String pathElem = pathElems[i];
- final int j = i;
- container = container.getChildContainer(pathElem, () -> {
- String fulPath = IntStream.rangeClosed(0, j)
- .mapToObj(c -> pathElems[c])
- .collect(Collectors.joining("."));
- return configurationData.getCommentsForSection(fulPath);
- });
+ List pathElements = pathTraverser.getPathElements(property.getPath());
+ for (PathElement pathElement : pathElements) {
+ if (pathElement.isEndOfPath()) {
+ int emptyLines = options.getNumberOfEmptyLinesBefore(pathElement);
+ container.putValue(pathElement.getName(),
+ toYamlNode(exportValue, property.getPath(), configurationData, emptyLines));
+ } else {
+ container = container.getChildContainer(pathElement.getName(),
+ () -> getCommentsForPathElement(configurationData, pathElement));
+ }
}
- container.putValue(pathElems[pathElems.length - 1],
- toYamlNode(exportValue, property.getPath(), configurationData));
}
}
@@ -155,7 +151,6 @@ public void exportProperties(@NotNull ConfigurationData configurationData) {
rootNode = root.toNodeRecursive();
}
-
try (OutputStream os = Files.newOutputStream(path);
OutputStreamWriter writer = new OutputStreamWriter(os, options.getCharset())) {
getYamlObject().serialize(rootNode, writer);
@@ -166,22 +161,35 @@ public void exportProperties(@NotNull ConfigurationData configurationData) {
}
}
- // todo: empty line config no longer respected
- private Node toYamlNode(Object obj, String path, ConfigurationData configurationData) {
+ @NotNull
+ private List getCommentsForPathElement(@NotNull ConfigurationData configurationData,
+ @NotNull PathElement pathElement) {
+ return Stream.concat(
+ IntStream.range(0, options.getNumberOfEmptyLinesBefore(pathElement)).mapToObj(i -> "\n"),
+ configurationData.getCommentsForSection(pathElement.getFullPath()).stream())
+ .collect(Collectors.toList());
+ }
+
+ private Node toYamlNode(Object obj, String path, ConfigurationData configurationData, int emptyLines) {
Object value = obj;
+ List newLines = Collections.emptyList();
List additionalComments = Collections.emptyList();
if (obj instanceof ValueWithComments) {
ValueWithComments valueWithComments = (ValueWithComments) obj;
value = valueWithComments.getValue();
additionalComments = valueWithComments.getComments();
}
+ if (emptyLines > 0) {
+ newLines = IntStream.range(0, emptyLines).mapToObj(i -> "\n").collect(Collectors.toList());
+ }
+
if (value instanceof Enum>) {
value = ((Enum>) value).name();
}
if (value instanceof Number || value instanceof String || value instanceof Boolean) {
List confDataComments = configurationData.getCommentsForSection(path);
- List comLines = createCommentLines(Stream.concat(confDataComments.stream(), additionalComments.stream()));
+ List comLines = createCommentLines(newLines, confDataComments, additionalComments);
Tag tag = Tag.STR;
if (value instanceof Integer || value instanceof Short || value instanceof Long) {
@@ -198,7 +206,7 @@ private Node toYamlNode(Object obj, String path, ConfigurationData configuration
} else if (value instanceof Iterable> || value instanceof Object[]) {
List confDataComments = configurationData.getCommentsForSection(path);
- List comLines = createCommentLines(Stream.concat(confDataComments.stream(), additionalComments.stream()));
+ List comLines = createCommentLines(newLines, confDataComments, additionalComments);
Stream> stream;
if (value instanceof Iterable>) {
@@ -210,7 +218,7 @@ private Node toYamlNode(Object obj, String path, ConfigurationData configuration
List values = stream
.map(val ->
// todo counter
- toYamlNode(val, String.join(".", combinePathElementsAndMapEntryKey(pathParts, "0")), configurationData))
+ toYamlNode(val, String.join(".", combinePathElementsAndMapEntryKey(pathParts, "0")), configurationData, 0))
.collect(Collectors.toList());
SequenceNode sequenceNode = new SequenceNode(Tag.SEQ, values, DumperOptions.FlowStyle.BLOCK);
@@ -218,7 +226,7 @@ private Node toYamlNode(Object obj, String path, ConfigurationData configuration
return sequenceNode;
} else if (value instanceof Map, ?>) {
List confDataComments = configurationData.getCommentsForSection(path);
- List comLines = createCommentLines(Stream.concat(confDataComments.stream(), additionalComments.stream()));
+ List comLines = createCommentLines(newLines, confDataComments, additionalComments);
List pathParts = Arrays.asList(path.split("\\."));
List nodeEntries = new ArrayList<>();
@@ -226,7 +234,7 @@ private Node toYamlNode(Object obj, String path, ConfigurationData configuration
ScalarNode keyNode =
new ScalarNode(Tag.STR, entry.getKey(), null, null, DumperOptions.ScalarStyle.PLAIN);
Node valueNode = toYamlNode(entry.getValue(),
- String.join(".", combinePathElementsAndMapEntryKey(pathParts, entry.getKey())), configurationData);
+ String.join(".", combinePathElementsAndMapEntryKey(pathParts, entry.getKey())), configurationData, 0);
if (!valueNode.getBlockComments().isEmpty()) {
keyNode.setBlockComments(valueNode.getBlockComments());
valueNode.setBlockComments(Collections.emptyList());
@@ -243,9 +251,10 @@ private Node toYamlNode(Object obj, String path, ConfigurationData configuration
}
}
- @NotNull
- private static List createCommentLines(Stream commentEntries) {
- return commentEntries
+ @SafeVarargs
+ private static @NotNull List createCommentLines(@NotNull List... commentEntries) {
+ return Arrays.stream(commentEntries)
+ .flatMap(List::stream)
.map(comment -> comment.equals("\n")
? new CommentLine(null, null, "", CommentType.BLANK_LINE)
: new CommentLine(null, null, " " + comment, CommentType.BLOCK))
@@ -262,87 +271,6 @@ private static List createCommentLines(Stream commentEntrie
return path.toFile();
}
- /**
- * Exports the given value at the provided path.
- *
- * @param writer the file writer to write with
- * @param pathTraverser the path traverser (e.g. keeps track of which path elements are new)
- * @param pathElements all elements that make up the path to the value
- * @param exportValue the value to export
- * @throws IOException .
- */
- protected void exportValue(@NotNull Writer writer, @NotNull PropertyPathTraverser pathTraverser,
- @NotNull List pathElements, @Nullable Object exportValue) throws IOException {
- if (exportValue == null) {
- return;
- }
-
- Object value = exportValue;
- List additionalComments = Collections.emptyList();
- if (exportValue instanceof ValueWithComments) {
- value = ((ValueWithComments) exportValue).getValue();
- additionalComments = ((ValueWithComments) exportValue).getComments();
- }
-
- if (value instanceof Map, ?> && !((Map, ?>) value).isEmpty()) {
- final Map mapValue = (Map) value;
-
- for (Map.Entry entry : mapValue.entrySet()) {
- List pathElementsForEntry = combinePathElementsAndMapEntryKey(pathElements, entry.getKey());
- exportValue(writer, pathTraverser, pathElementsForEntry, entry.getValue());
- }
- } else {
- List newPathElements = pathTraverser.getPathElements(pathElements);
- if (!additionalComments.isEmpty()) {
- getLastElementOrThrow(newPathElements).addComments(additionalComments);
- }
- final boolean isRootProperty = newPathElements.size() == 1 && "".equals(newPathElements.get(0).getName());
-
- for (PathElement pathElement : newPathElements) {
- writeIndentingBetweenLines(writer, pathElement);
- writeComments(writer, pathElement.getIndentationLevel(), pathElement);
- writer.append(getNewLineIfNotFirstElement(pathElement));
- if (!isRootProperty) {
- writer.append(indent(pathElement.getIndentationLevel()))
- .append(escapePathElementIfNeeded(pathElement.getName()))
- .append(":");
- }
- }
- if (!isRootProperty) {
- writer.append(" ");
- }
-
- writer.append(toYamlIndented(value, newPathElements.get(newPathElements.size() - 1).getIndentationLevel()));
- }
- }
-
- /**
- * Writes the given comment lines as YAML comments at the given indentation level.
- *
- * @param writer the writer to write with
- * @param indentation the level at which the comment lines should be indented
- * @param pathElement the path element for which the comments are being generated
- * @throws IOException .
- */
- protected void writeComments(@NotNull Writer writer, int indentation,
- @NotNull PathElement pathElement) throws IOException {
- if (pathElement.getComments().isEmpty()) {
- return;
- }
-
- String lineStart = pathElement.isFirstElement() ? "" : "\n";
- String commentStart = indent(indentation) + "# ";
- for (String comment : pathElement.getComments()) {
- writer.append(lineStart);
- lineStart = "\n";
-
- if (!"\n".equals(comment)) {
- writer.append(commentStart)
- .append(comment);
- }
- }
- }
-
/**
* Combines two path element sources to a new list of path elements: the list of path elements that were given
* from the parent context and the map entry key from which one or more path elements should be derived.
@@ -365,108 +293,6 @@ protected List combinePathElementsAndMapEntryKey(List parentPath
.collect(Collectors.toList());
}
- private void writeIndentingBetweenLines(@NotNull Writer writer,
- @NotNull PathElement pathElement) throws IOException {
- int numberOfEmptyLines = options.getNumberOfEmptyLinesBefore(pathElement);
- for (int i = 0; i < numberOfEmptyLines; ++i) {
- writer.append("\n");
- }
- }
-
- private @NotNull String getNewLineIfNotFirstElement(@NotNull PathElement pathElement) {
- return pathElement.isFirstElement() && pathElement.getComments().isEmpty() ? "" : "\n";
- }
-
- /**
- * Returns the value in its YAML representation with an indentation of the given level. Proper indentation
- * should be applied to all lines except for the first one (such that this method's return value can simply
- * be appended to a properly indented property prefix like {@code name:}).
- *
- * @param value the value to convert to YAML
- * @param indent level of indentation to use
- * @return the value as YAML at the given indentation level
- */
- protected @NotNull String toYamlIndented(@Nullable Object value, int indent) {
- String representation = toYaml(value);
- String[] lines = representation.split("\\n");
- return String.join("\n" + indent(indent), lines);
- }
-
- /**
- * Returns the YAML representation for the given value (belonging to the given value).
- * This method returns the YAML representation of the value only (does not include the key)
- * with no indentation (will be applied afterwards with the appropriate level).
- *
- * @param value the value to transform as YAML
- * @return the YAML representation of the value
- */
- protected String toYaml(@Nullable Object value) {
- if (value instanceof String) {
- return getYamlObject().dump(value);
- }
-
- if (value instanceof Collection>) {
- return streamToYaml(((Collection>) value).stream());
- } else if (value instanceof Object[]) {
- return streamToYaml(Arrays.stream((Object[]) value));
- } else if (value instanceof ValueWithComments) {
- ValueWithComments vwc = (ValueWithComments) value;
- StringBuilder result = new StringBuilder();
- vwc.getComments().forEach(com -> result.append("\n# ").append(com));
- result.append("\n- ").append(getYamlObject().dump(vwc.getValue()));
- return result.toString();
- }
-
- return getYamlObject().dump(value);
- }
-
- protected String streamToYaml(Stream> stream) {
- StringBuilder result = new StringBuilder();
- Yaml yaml = getYamlObject();
- stream.forEach(elem -> {
- if (elem instanceof ValueWithComments) {
- ValueWithComments vwc = (ValueWithComments) elem;
- vwc.getComments().forEach(com -> result.append("\n# ").append(com));
- result.append("\n- ").append(yaml.dump(vwc.getValue()));
- } else {
- result.append("\n- ").append(yaml.dump(elem));
- }
- });
-
- if (result.length() == 0) {
- return "[]";
- }
- return result.toString();
- }
-
- /**
- * Returns a String of whitespace for indentation in YAML at the given level.
- *
- * @param level the desired level of indentation
- * @return whitespace to prepend to a line for proper indentation
- */
- protected String indent(int level) {
- switch (level) {
- case 0: return "";
- case 1: return indentationSpace;
- case 2: return indentationSpace + indentationSpace;
- case 3: return indentationSpace + indentationSpace + indentationSpace;
- case 4: return indentationSpace + indentationSpace + indentationSpace + indentationSpace;
- case 5: return indentationSpace + indentationSpace + indentationSpace + indentationSpace + indentationSpace;
- default: // proceed
- }
-
- final StringBuilder result = new StringBuilder(level * indentationSpace.length());
- for (int i = 0; i < level; ++i) {
- result.append(indentationSpace);
- }
- return result.toString();
- }
-
- protected @NotNull String escapePathElementIfNeeded(@NotNull String path) {
- return getYamlObject().dump(path).trim();
- }
-
/**
* Called at the end of {@link #exportProperties}, regardless whether the execution was successful or not.
*/
@@ -491,7 +317,7 @@ protected void onWriteComplete() {
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
options.setAllowUnicode(true);
options.setProcessComments(true);
- options.setIndent(indentationSpace.length()); // todo
+ options.setIndent(indentationSize);
return new Yaml(options);
}
diff --git a/src/main/java/ch/jalu/configme/resource/YamlFileResourceOptions.java b/src/main/java/ch/jalu/configme/resource/YamlFileResourceOptions.java
index 76e55986..d0e8939e 100644
--- a/src/main/java/ch/jalu/configme/resource/YamlFileResourceOptions.java
+++ b/src/main/java/ch/jalu/configme/resource/YamlFileResourceOptions.java
@@ -53,20 +53,6 @@ public boolean splitDotPaths() {
return splitDotPaths;
}
- /**
- * @return the indentation to use for one level
- */
- public @NotNull String getIndentation() {
- if (indentationSize == 4) {
- return " ";
- }
- StringBuilder sb = new StringBuilder(indentationSize);
- for (int i = 0; i < indentationSize; ++i) {
- sb.append(" ");
- }
- return sb.toString();
- }
-
protected final @Nullable ToIntFunction getIndentFunction() {
return numberOfLinesBeforeFunction;
}
diff --git a/src/main/java/ch/jalu/configme/utils/CollectionUtils.java b/src/main/java/ch/jalu/configme/utils/CollectionUtils.java
index eb7547ad..c886e8a3 100644
--- a/src/main/java/ch/jalu/configme/utils/CollectionUtils.java
+++ b/src/main/java/ch/jalu/configme/utils/CollectionUtils.java
@@ -48,12 +48,4 @@ private CollectionUtils() {
}
return commonStart;
}
-
- public static @NotNull T getLastElementOrThrow(@NotNull List list) {
- int lastIndex = list.size() - 1;
- if (lastIndex < 0) {
- throw new IllegalStateException("Expected non-empty list to get last element");
- }
- return list.get(lastIndex);
- }
}
diff --git a/src/test/java/ch/jalu/configme/beanmapper/BeanMapOnRootLevelTest.java b/src/test/java/ch/jalu/configme/beanmapper/BeanMapOnRootLevelTest.java
index 99d814f8..8573aabf 100644
--- a/src/test/java/ch/jalu/configme/beanmapper/BeanMapOnRootLevelTest.java
+++ b/src/test/java/ch/jalu/configme/beanmapper/BeanMapOnRootLevelTest.java
@@ -74,6 +74,7 @@ void shouldHaveEmptyMapIfFileIsEmptyMap() throws IOException {
@Test
void shouldLoadMapFromFile() throws IOException {
+ // given
String yaml = "medium:\n"
+ "\n name: \"med\"\n"
+ "\n lore:\n"
@@ -96,6 +97,7 @@ void shouldLoadMapFromFile() throws IOException {
@Test
void shouldExportValuesAsEmptyMap() throws IOException {
+ // given
String yaml = "medium:\n"
+ "\n name: \"med\"\n"
+ "\n lore:\n"
@@ -118,6 +120,7 @@ void shouldExportValuesAsEmptyMap() throws IOException {
@Test
void shouldExportValuesAsEmptyMapIncludingComments() throws IOException {
+ // given
String yaml = "medium:\n"
+ "\n name: \"med\"\n"
+ "\n lore:\n"
diff --git a/src/test/java/ch/jalu/configme/beanmapper/BeanWithCollectionOfBeanTypeTest.java b/src/test/java/ch/jalu/configme/beanmapper/BeanWithCollectionOfBeanTypeTest.java
index 1ae72854..a32495f7 100644
--- a/src/test/java/ch/jalu/configme/beanmapper/BeanWithCollectionOfBeanTypeTest.java
+++ b/src/test/java/ch/jalu/configme/beanmapper/BeanWithCollectionOfBeanTypeTest.java
@@ -74,16 +74,13 @@ void shouldSerializeProperly() throws IOException {
List lines = Files.readAllLines(file);
assertThat(lines, contains(
"message-key:",
- " # HTML color",
" color: blue",
" text: outside",
" extra:",
- " - # HTML color",
- " color: green",
+ " - color: green",
" text: inner1",
" extra: []",
- " - # HTML color",
- " color: blue",
+ " - color: blue",
" text: inner2",
" extra: []"
));
@@ -156,7 +153,6 @@ public static final class PropertyHolder implements SettingsHolder {
public static class ChatComponent {
- @Comment("HTML color")
private String color;
private String text;
private List extra = new ArrayList<>();
diff --git a/src/test/java/ch/jalu/configme/resource/PropertyPathTraverserTest.java b/src/test/java/ch/jalu/configme/resource/PropertyPathTraverserTest.java
index 9ad32990..70f8c012 100644
--- a/src/test/java/ch/jalu/configme/resource/PropertyPathTraverserTest.java
+++ b/src/test/java/ch/jalu/configme/resource/PropertyPathTraverserTest.java
@@ -1,98 +1,118 @@
package ch.jalu.configme.resource;
-import ch.jalu.configme.configurationdata.ConfigurationData;
import org.junit.jupiter.api.Test;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Mockito.mock;
/**
* Test for {@link PropertyPathTraverser}.
*/
class PropertyPathTraverserTest {
- private ConfigurationData configurationData = mock(ConfigurationData.class);
-
- private PropertyPathTraverser propertyPathTraverser = new PropertyPathTraverser(configurationData);
+ private final PropertyPathTraverser propertyPathTraverser = new PropertyPathTraverser();
@Test
void shouldReturnPathElements() {
- // given
- given(configurationData.getCommentsForSection("")).willReturn(Collections.singletonList("root comment"));
- given(configurationData.getCommentsForSection("prop.test")).willReturn(Collections.singletonList("prop.test comment"));
-
- // when
- List result = propertyPathTraverser.getPathElements(Arrays.asList("prop", "test"));
+ // given / when
+ List result = propertyPathTraverser.getPathElements("prop.test");
// then
assertThat(result, hasSize(2));
+
assertThat(result.get(0).getName(), equalTo("prop"));
- assertThat(result.get(0).getComments(), contains("root comment"));
+ assertThat(result.get(0).getFullPath(), equalTo("prop"));
assertThat(result.get(0).getIndentationLevel(), equalTo(0));
+ assertThat(result.get(0).isFirstElement(), equalTo(true));
+ assertThat(result.get(0).isFirstOfGroup(), equalTo(true));
+ assertThat(result.get(0).isEndOfPath(), equalTo(false));
+
assertThat(result.get(1).getName(), equalTo("test"));
- assertThat(result.get(1).getComments(), contains("prop.test comment"));
+ assertThat(result.get(1).getFullPath(), equalTo("prop.test"));
assertThat(result.get(1).getIndentationLevel(), equalTo(1));
+ assertThat(result.get(1).isFirstElement(), equalTo(false));
+ assertThat(result.get(1).isFirstOfGroup(), equalTo(false));
+ assertThat(result.get(1).isEndOfPath(), equalTo(true));
}
@Test
void shouldCombineRootCommentWithThatOfParent() {
- // given
- given(configurationData.getCommentsForSection("")).willReturn(Arrays.asList("root1", "root2"));
- given(configurationData.getCommentsForSection("prop")).willReturn(Collections.singletonList("prop 1"));
-
- // when
- List result = propertyPathTraverser.getPathElements(Arrays.asList("prop", "test"));
+ // given / when
+ List result = propertyPathTraverser.getPathElements("prop.test");
// then
assertThat(result, hasSize(2));
+
assertThat(result.get(0).getName(), equalTo("prop"));
- assertThat(result.get(0).getComments(), contains("root1", "root2", "prop 1"));
+ assertThat(result.get(0).getFullPath(), equalTo("prop"));
assertThat(result.get(0).getIndentationLevel(), equalTo(0));
+ assertThat(result.get(0).isFirstElement(), equalTo(true));
+ assertThat(result.get(0).isFirstOfGroup(), equalTo(true));
+ assertThat(result.get(0).isEndOfPath(), equalTo(false));
+
assertThat(result.get(1).getName(), equalTo("test"));
- assertThat(result.get(1).getComments(), empty());
+ assertThat(result.get(1).getFullPath(), equalTo("prop.test"));
assertThat(result.get(1).getIndentationLevel(), equalTo(1));
+ assertThat(result.get(1).isFirstElement(), equalTo(false));
+ assertThat(result.get(1).isFirstOfGroup(), equalTo(false));
+ assertThat(result.get(1).isEndOfPath(), equalTo(true));
}
@Test
void shouldHandleEmptyStringPath() {
- // given
- given(configurationData.getCommentsForSection("")).willReturn(Arrays.asList("c1", "d2", "e3"));
-
- // when
- List result = propertyPathTraverser.getPathElements(Collections.singletonList(""));
+ // given / when
+ List result = propertyPathTraverser.getPathElements("");
// then
assertThat(result, hasSize(1));
assertThat(result.get(0).getName(), equalTo(""));
- assertThat(result.get(0).getComments(), contains("c1", "d2", "e3"));
+ assertThat(result.get(0).getFullPath(), equalTo(""));
assertThat(result.get(0).getIndentationLevel(), equalTo(0));
+ assertThat(result.get(0).isFirstElement(), equalTo(true));
+ assertThat(result.get(0).isFirstOfGroup(), equalTo(true));
+ assertThat(result.get(0).isEndOfPath(), equalTo(true));
}
@Test
- void shouldReturnOnlyNewElements() {
+ void shouldReturnAllElements() {
// given
- given(configurationData.getCommentsForSection("some.longer.path")).willReturn(Collections.singletonList("The comment"));
- propertyPathTraverser.getPathElements(Arrays.asList("some", "longer", "test"));
+ propertyPathTraverser.getPathElements("some.longer.test");
// when
- List result = propertyPathTraverser.getPathElements(Arrays.asList("some", "longer", "path", "value"));
+ List result = propertyPathTraverser.getPathElements("some.longer.path.value");
// then
- assertThat(result, hasSize(2));
- assertThat(result.get(0).getName(), equalTo("path"));
- assertThat(result.get(0).getComments(), contains("The comment"));
- assertThat(result.get(0).getIndentationLevel(), equalTo(2));
- assertThat(result.get(1).getName(), equalTo("value"));
- assertThat(result.get(1).getComments(), empty());
- assertThat(result.get(1).getIndentationLevel(), equalTo(3));
+ assertThat(result, hasSize(4));
+
+ assertThat(result.get(0).getName(), equalTo("some"));
+ assertThat(result.get(0).getFullPath(), equalTo("some"));
+ assertThat(result.get(0).getIndentationLevel(), equalTo(0));
+ assertThat(result.get(0).isFirstElement(), equalTo(false)); // because "some.longer.test" was already visited
+ assertThat(result.get(0).isFirstOfGroup(), equalTo(false));
+ assertThat(result.get(0).isEndOfPath(), equalTo(false));
+
+ assertThat(result.get(1).getName(), equalTo("longer"));
+ assertThat(result.get(1).getFullPath(), equalTo("some.longer"));
+ assertThat(result.get(1).getIndentationLevel(), equalTo(1));
+ assertThat(result.get(1).isFirstElement(), equalTo(false));
+ assertThat(result.get(1).isFirstOfGroup(), equalTo(false));
+ assertThat(result.get(1).isEndOfPath(), equalTo(false));
+
+ assertThat(result.get(2).getName(), equalTo("path"));
+ assertThat(result.get(2).getFullPath(), equalTo("some.longer.path"));
+ assertThat(result.get(2).getIndentationLevel(), equalTo(2));
+ assertThat(result.get(2).isFirstElement(), equalTo(false));
+ assertThat(result.get(2).isFirstOfGroup(), equalTo(true));
+ assertThat(result.get(2).isEndOfPath(), equalTo(false));
+
+ assertThat(result.get(3).getName(), equalTo("value"));
+ assertThat(result.get(3).getFullPath(), equalTo("some.longer.path.value"));
+ assertThat(result.get(3).getIndentationLevel(), equalTo(3));
+ assertThat(result.get(3).isFirstElement(), equalTo(false));
+ assertThat(result.get(3).isFirstOfGroup(), equalTo(false));
+ assertThat(result.get(3).isEndOfPath(), equalTo(true));
}
}
diff --git a/src/test/java/ch/jalu/configme/resource/YamlFileResourceNewLineTest.java b/src/test/java/ch/jalu/configme/resource/YamlFileResourceNewLineTest.java
index 5eb1f368..3a5c374d 100644
--- a/src/test/java/ch/jalu/configme/resource/YamlFileResourceNewLineTest.java
+++ b/src/test/java/ch/jalu/configme/resource/YamlFileResourceNewLineTest.java
@@ -138,7 +138,7 @@ void shouldExportWithRootCommentAndNewLineEverywhere() throws IOException {
"",
"second:",
" a: 2",
- "",
+ " ",
" # b comm",
" b: 3"));
}
diff --git a/src/test/java/ch/jalu/configme/resource/YamlFileResourceOptionsTest.java b/src/test/java/ch/jalu/configme/resource/YamlFileResourceOptionsTest.java
index 4a1a1897..a15b4c9f 100644
--- a/src/test/java/ch/jalu/configme/resource/YamlFileResourceOptionsTest.java
+++ b/src/test/java/ch/jalu/configme/resource/YamlFileResourceOptionsTest.java
@@ -6,7 +6,6 @@
import java.nio.charset.StandardCharsets;
import java.util.function.ToIntFunction;
-import static java.util.Collections.emptyList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.nullValue;
@@ -32,10 +31,9 @@ void shouldKeepConfiguredValues() {
// then
assertThat(options.getCharset(), equalTo(StandardCharsets.UTF_16BE));
assertThat(options.getIndentFunction(), equalTo(lineFunction));
- PathElement pathElement = new PathElement(3, "test", emptyList(), false);
+ PathElement pathElement = new PathElement(3, "test", "test", false);
assertThat(options.getNumberOfEmptyLinesBefore(pathElement), equalTo(3));
assertThat(options.getIndentationSize(), equalTo(2));
- assertThat(options.getIndentation(), equalTo(" "));
assertThat(options.splitDotPaths(), equalTo(false));
}
@@ -48,8 +46,7 @@ void shouldCreateOptionsWithDefaults() {
assertThat(options.getCharset(), equalTo(StandardCharsets.UTF_8));
assertThat(options.getIndentFunction(), nullValue());
assertThat(options.getIndentationSize(), equalTo(4));
- assertThat(options.getIndentation(), equalTo(" "));
- PathElement pathElement = new PathElement(3, "test", emptyList(), false);
+ PathElement pathElement = new PathElement(3, "test", "test", false);
assertThat(options.getNumberOfEmptyLinesBefore(pathElement), equalTo(0));
assertThat(options.splitDotPaths(), equalTo(true));
}
diff --git a/src/test/java/ch/jalu/configme/resource/YamlFileResourceTest.java b/src/test/java/ch/jalu/configme/resource/YamlFileResourceTest.java
index 5fb34775..9a96493e 100644
--- a/src/test/java/ch/jalu/configme/resource/YamlFileResourceTest.java
+++ b/src/test/java/ch/jalu/configme/resource/YamlFileResourceTest.java
@@ -381,10 +381,10 @@ void shouldExportWithCustomIndentationSize() throws IOException {
" - beige",
" - gray",
" dustLevel: 2.4",
- "",
+ " ",
" # Cool features",
"",
- " # Contains cool settings",
+ " # Contains cool settings",
" cool:",
" # Enable cool features?",
" enabled: true",
diff --git a/src/test/resources/beanmapper/nested_chat_component_complex_expected.yml b/src/test/resources/beanmapper/nested_chat_component_complex_expected.yml
index 04a85728..ae9ec040 100644
--- a/src/test/resources/beanmapper/nested_chat_component_complex_expected.yml
+++ b/src/test/resources/beanmapper/nested_chat_component_complex_expected.yml
@@ -2,15 +2,16 @@ message-key:
color: green
text: outside
extra:
- - color: yellow
- text: inner1
- extra: []
- - color: blue
- text: inner2
- extra:
- - color: red
- text: level2 text
+ - color: yellow
+ text: inner1
extra: []
+ - color: blue
+ text: inner2
+ extra:
+ - color: red
+ text: level2 text
+ extra: []
+ # Optional: additional info
conditionalElem:
color: orange
text: orange extension
@@ -24,15 +25,16 @@ message-key:
med:
color: gray
text: med text
- extra:
- - color: green
- text: med child
- extra: []
+ extra:
+ - color: green
+ text: med child
+ extra: []
conditionals: {}
high:
color: black
text: high text
extra: []
+ # Optional: additional info
conditionalElem:
color: teal
text: teal addition
diff --git a/src/test/resources/config-export-expected.yml b/src/test/resources/config-export-expected.yml
index 637adb08..eed9deae 100644
--- a/src/test/resources/config-export-expected.yml
+++ b/src/test/resources/config-export-expected.yml
@@ -25,10 +25,10 @@ features:
- beige
- gray
dustLevel: 2.4
-
+
# Cool features
- # Contains cool settings
+ # Contains cool settings
cool:
# Enable cool features?
enabled: true
@@ -42,4 +42,4 @@ security:
forbiddenNames:
- admin
- staff
- - moderator
+ - moderator
\ No newline at end of file