Skip to content

Commit

Permalink
reworked commented-out key detection; added field default handling to…
Browse files Browse the repository at this point in the history
… AConfigSection; adjusted tests
  • Loading branch information
BlvckBytes committed Sep 21, 2024
1 parent b45ad7f commit 380466b
Show file tree
Hide file tree
Showing 13 changed files with 144 additions and 30 deletions.
63 changes: 43 additions & 20 deletions src/main/java/me/blvckbytes/bbconfigmapper/YamlConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,29 @@

public class YamlConfig implements IConfig {

private static class LocateNodeResult {
private final @Nullable Node node;
private final boolean markedForExpressions;
private final Stack<MappingNode> containerStack;

private LocateNodeResult(
@Nullable Node node,
boolean markedForExpressions,
Stack<MappingNode> containerStack
) {
this.node = node;
this.markedForExpressions = markedForExpressions;
this.containerStack = containerStack;
}

@Nullable MappingNode getLastContainer() {
if (containerStack.isEmpty())
return null;

return containerStack.pop();
}
}

/*
TODO: Add more debug logging calls to capture all details
*/
Expand Down Expand Up @@ -309,7 +332,7 @@ private boolean isKeyCommentedOut(String key, Node container) {
// For lists, on the ScalarNode-s of items
// If a comment is at the end of the file, it'll be an EndComment on the root MappingNode

Predicate<CommentLine> commentedKeyMatcher = (comment) -> comment.getValue().trim().startsWith(key + ": ");
Predicate<CommentLine> commentedKeyMatcher = (comment) -> comment.getValue().trim().startsWith(key + ":");

// Possibly, a key which is not the last has been commented out
if (container instanceof MappingNode) {
Expand Down Expand Up @@ -368,15 +391,11 @@ public int extendMissingKeys(YamlConfig other) {
return false;

String key = ((ScalarNode) tuple.getKeyNode()).getValue();
int lastPathDotIndex = pathOfTuple.lastIndexOf('.');

if (lastPathDotIndex > 0) {
String parentPath = pathOfTuple.substring(0, lastPathDotIndex);
Node parentNode = locateNode(parentPath, false, false).a;
LocateNodeResult locateResult = locateNode(pathOfTuple, true, false);
Node parentNode = locateResult.getLastContainer();

if (isKeyCommentedOut(key, parentNode))
return false;
}
if (parentNode != null && isKeyCommentedOut(key, parentNode))
return false;

MappingNode container = locateContainerNode(pathOfTuple, true).a;
List<NodeTuple> containerTuples = container.getValue();
Expand Down Expand Up @@ -433,8 +452,8 @@ private int forEachKeyPathRecursively(MappingNode node, @Nullable String parentP
public @Nullable Object get(@Nullable String path) {
logger.log(Level.FINEST, () -> DebugLogSource.YAML + "Object at path=" + path + " has been requested");

Tuple<@Nullable Node, Boolean> target = locateNode(path, false, false);
Object value = target.a == null ? null : unwrapNode(target.a, target.b);
LocateNodeResult target = locateNode(path, false, false);
Object value = target.node == null ? null : unwrapNode(target.node, target.markedForExpressions);

logger.log(Level.FINEST, () -> DebugLogSource.YAML + "Returning content of path=" + path + " with value=" + value);

Expand Down Expand Up @@ -487,7 +506,7 @@ public boolean exists(@Nullable String path) {

// For a key to exist, it's path has to exist within the
// config, even if it points at a null value
boolean exists = locateNode(path, true, false).a != null;
boolean exists = locateNode(path, true, false).node != null;

logger.log(Level.FINEST, () -> DebugLogSource.YAML + "Returning existence value for path=" + path + " of exists=" + exists);

Expand All @@ -498,7 +517,7 @@ public boolean exists(@Nullable String path) {
public void attachComment(@Nullable String path, List<String> lines, boolean self) {
logger.log(Level.FINEST, () -> DebugLogSource.YAML + "Attaching a comment to path=" + path + " (self=" + self + ") of lines=" + lines + " has been requested");

Node target = locateNode(path, self, false).a;
Node target = locateNode(path, self, false).node;

if (target == null)
throw new IllegalStateException("Cannot attach a comment to a non-existing path");
Expand All @@ -517,7 +536,7 @@ public void attachComment(@Nullable String path, List<String> lines, boolean sel
public @Nullable List<String> readComment(@Nullable String path, boolean self) {
logger.log(Level.FINEST, () -> DebugLogSource.YAML + "Reading the comment at path=" + path + " (self=" + self + ") has been requested");

Node target = locateNode(path, self, false).a;
Node target = locateNode(path, self, false).node;

if (target == null)
return null;
Expand Down Expand Up @@ -554,7 +573,7 @@ private Tuple<MappingNode, String> locateContainerNode(String keyPath, boolean f
// Look up the container by the path provided before the last dot (in force mapping creation mode)
else {
keyPart = keyPath.substring(lastDotIndex + 1);
container = (MappingNode) locateNode(keyPath.substring(0, lastDotIndex), false, forceCreateMappings).a;
container = (MappingNode) locateNode(keyPath.substring(0, lastDotIndex), false, forceCreateMappings).node;
}

if (container == null || StringUtils.isBlank(keyPart))
Expand Down Expand Up @@ -690,9 +709,9 @@ private NodeTuple createNewTuple(@Nullable Node keyNode, @Nullable String key, N
* @return A tuple of the target node or null if the target node didn't exist
* as well as a boolean marking whether this path was marked for expressions
*/
private @NotNull Tuple<@Nullable Node, Boolean> locateNode(@Nullable String path, boolean self, boolean forceCreateMappings) {
private @NotNull LocateNodeResult locateNode(@Nullable String path, boolean self, boolean forceCreateMappings) {
if (path == null)
return new Tuple<>(rootNode, false);
return new LocateNodeResult(rootNode, false, null);

// Keys should never contain any whitespace
path = path.trim();
Expand All @@ -702,6 +721,7 @@ private NodeTuple createNewTuple(@Nullable Node keyNode, @Nullable String key, N

Node node = rootNode;
boolean markedForExpressions = false;
Stack<MappingNode> containerStack = new Stack<>();

int endIndex = path.indexOf('.'), beginIndex = 0;

Expand All @@ -716,9 +736,12 @@ private NodeTuple createNewTuple(@Nullable Node keyNode, @Nullable String key, N

// Not a mapping node, cannot look up a path-part, the key has to be invalid
if (!(node instanceof MappingNode))
return new Tuple<>(null, markedForExpressions);
return new LocateNodeResult(null, markedForExpressions, containerStack);

MappingNode mapping = (MappingNode) node;

containerStack.push(mapping);

NodeTuple keyValueTuple = locateKey(mapping, pathPart);
boolean markedAlready = expressionMarkerSuffix != null && pathPart.endsWith(expressionMarkerSuffix);

Expand Down Expand Up @@ -750,7 +773,7 @@ private NodeTuple createNewTuple(@Nullable Node keyNode, @Nullable String key, N

// Current path-part does not exist
if (keyValueTuple == null)
return new Tuple<>(null, markedForExpressions);
return new LocateNodeResult(null, markedForExpressions, containerStack);

// On the last iteration and the key itself has been requested
if (endIndex == path.length() && self)
Expand All @@ -770,7 +793,7 @@ private NodeTuple createNewTuple(@Nullable Node keyNode, @Nullable String key, N
break;
}

return new Tuple<>(node, markedForExpressions);
return new LocateNodeResult(node, markedForExpressions, containerStack);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,27 @@
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Field;
import java.util.List;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public abstract class AConfigSection {

private static class DefaultSupplier {
private final Supplier<Object> supplier;
private final Set<String> fieldExceptions;

public DefaultSupplier(Supplier<Object> supplier, Set<String> fieldExceptions) {
this.supplier = supplier;
this.fieldExceptions = fieldExceptions;
}
}

private final EvaluationEnvironmentBuilder baseEnvironment;
private final Map<Class<?>, DefaultSupplier> fieldDefaultSuppliers;

public AConfigSection(EvaluationEnvironmentBuilder baseEnvironment) {
this.fieldDefaultSuppliers = new HashMap<>();
this.baseEnvironment = baseEnvironment;
}

Expand All @@ -60,14 +74,29 @@ public EvaluationEnvironmentBuilder getBaseEnvironment() {
* @param field Target field
* @return Value to use as a default
*/
public @Nullable Object defaultFor(Field field) throws Exception {
public @Nullable Object defaultFor(Field field) {
return null;
}

/**
* Called when parsing of the section is completed
* and no more changes will be applied
*/
public void afterParsing(List<Field> fields) throws Exception {}
public void afterParsing(List<Field> fields) throws Exception {
for (Field field : fields) {
if (field.get(this) != null)
continue;

DefaultSupplier defaultSupplier = fieldDefaultSuppliers.get(field.getType());

if (defaultSupplier == null || defaultSupplier.fieldExceptions.contains(field.getName()))
continue;

field.set(this, defaultSupplier.supplier.get());
}
}

protected void registerFieldDefault(Class<?> type, Supplier<Object> supplier, String... fieldExceptions) {
fieldDefaultSuppliers.put(type, new DefaultSupplier(supplier, Arrays.stream(fieldExceptions).collect(Collectors.toSet())));
}
}
5 changes: 3 additions & 2 deletions src/test/java/me/blvckbytes/bbconfigmapper/TestHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ public void assertSave(String fileName, YamlConfig config) throws Exception {
StringWriter writer = new StringWriter();
assertDoesNotThrow(() -> config.save(writer));
List<String> fileContents = Files.readAllLines(Paths.get("src/test/resources/save/" + fileName));
List<String> writerContents = Arrays.asList(writer.toString().split("\n"));
assertLinesMatch(fileContents, writerContents);
String writerString = writer.toString();
List<String> writerContents = Arrays.asList(writerString.split("\n"));
assertLinesMatch(fileContents, writerContents, "written: \n" + writerString);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void shouldExtendKeysWithScalarValues() throws Exception {

@Test
public void shouldNotExtendCommentedKeys() throws Exception {
char[] caseSuffixes = {'a', 'b', 'c'};
char[] caseSuffixes = {'a', 'b', 'c', 'd'};

for (char caseSuffix : caseSuffixes) {
YamlConfig baseConfig = helper.makeConfig("commented_keys_base_" + caseSuffix + ".yml");
Expand Down
7 changes: 6 additions & 1 deletion src/test/resources/commented_keys_base_a.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@ a:
# e: 4
f: 5
g:
h: 2
h: 2
i:
j:
k: 1
l: 2
m: 3
7 changes: 6 additions & 1 deletion src/test/resources/commented_keys_base_b.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@ a:
# e: 4
f: 5
g:
h: 2
h: 2
i:
j:
k: 1
l: 2
m: 3
7 changes: 6 additions & 1 deletion src/test/resources/commented_keys_base_c.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@ a:
e: 4
f: 5
g:
# h: 2
# h: 2
i:
j:
k: 1
l: 2
m: 3
13 changes: 13 additions & 0 deletions src/test/resources/commented_keys_base_d.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
a:
b: 1
c: 2
d: 3
e: 4
f: 5
g:
h: 2
#i:
# j:
# k: 1
# l: 2
# m: 3
5 changes: 5 additions & 0 deletions src/test/resources/commented_keys_extension.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ a:
f: 5
g:
h: 2
i:
j:
k: 1
l: 2
m: 3
5 changes: 5 additions & 0 deletions src/test/resources/save/commented_keys_save_a.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ a:
f: 5
g:
h: 2
i:
j:
k: 1
l: 2
m: 3
5 changes: 5 additions & 0 deletions src/test/resources/save/commented_keys_save_b.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ a:
f: 5
g:
h: 2
i:
j:
k: 1
l: 2
m: 3
7 changes: 6 additions & 1 deletion src/test/resources/save/commented_keys_save_c.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@ a:
e: 4
f: 5
g:
# h: 2
# h: 2
i:
j:
k: 1
l: 2
m: 3
13 changes: 13 additions & 0 deletions src/test/resources/save/commented_keys_save_d.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
a:
b: 1
c: 2
d: 3
e: 4
f: 5
g:
h: 2
#i:
# j:
# k: 1
# l: 2
# m: 3

0 comments on commit 380466b

Please sign in to comment.