in scripts/src/main/java/com/gu/typesafe/config/impl/ConfigNodeObject.java [166:275]
protected ConfigNodeObject addValueOnPath(com.gu.typesafe.config.impl.ConfigNodePath desiredPath, com.gu.typesafe.config.impl.AbstractConfigNodeValue value, com.gu.typesafe.config.ConfigSyntax flavor) {
Path path = desiredPath.value();
ArrayList<AbstractConfigNode> childrenCopy = new ArrayList<AbstractConfigNode>(super.children);
ArrayList<AbstractConfigNode> indentation = new ArrayList<AbstractConfigNode>(indentation());
// If the value we're inserting is a complex value, we'll need to indent it for insertion
com.gu.typesafe.config.impl.AbstractConfigNodeValue indentedValue;
if (value instanceof com.gu.typesafe.config.impl.ConfigNodeComplexValue && !indentation.isEmpty()) {
indentedValue = ((com.gu.typesafe.config.impl.ConfigNodeComplexValue) value).indentText(indentation.get(indentation.size() - 1));
} else {
indentedValue = value;
}
boolean sameLine = !(indentation.size() > 0 && indentation.get(0) instanceof com.gu.typesafe.config.impl.ConfigNodeSingleToken &&
com.gu.typesafe.config.impl.Tokens.isNewline(((com.gu.typesafe.config.impl.ConfigNodeSingleToken) indentation.get(0)).token()));
// If the path is of length greater than one, see if the value needs to be added further down
if (path.length() > 1) {
for (int i = super.children.size() - 1; i >= 0; i--) {
if (!(super.children.get(i) instanceof ConfigNodeField)) {
continue;
}
ConfigNodeField node = (ConfigNodeField) super.children.get(i);
Path key = node.path().value();
if (path.startsWith(key) && node.value() instanceof ConfigNodeObject) {
com.gu.typesafe.config.impl.ConfigNodePath remainingPath = desiredPath.subPath(key.length());
ConfigNodeObject newValue = (ConfigNodeObject) node.value();
childrenCopy.set(i, node.replaceValue(newValue.addValueOnPath(remainingPath, value, flavor)));
return new ConfigNodeObject(childrenCopy);
}
}
}
// Otherwise, construct the new setting
boolean startsWithBrace = !super.children.isEmpty() && super.children.get(0) instanceof com.gu.typesafe.config.impl.ConfigNodeSingleToken &&
((com.gu.typesafe.config.impl.ConfigNodeSingleToken) super.children.get(0)).token() == com.gu.typesafe.config.impl.Tokens.OPEN_CURLY;
ArrayList<AbstractConfigNode> newNodes = new ArrayList<AbstractConfigNode>();
newNodes.addAll(indentation);
newNodes.add(desiredPath.first());
newNodes.add(new com.gu.typesafe.config.impl.ConfigNodeSingleToken(com.gu.typesafe.config.impl.Tokens.newIgnoredWhitespace(null, " ")));
newNodes.add(new com.gu.typesafe.config.impl.ConfigNodeSingleToken(com.gu.typesafe.config.impl.Tokens.COLON));
newNodes.add(new com.gu.typesafe.config.impl.ConfigNodeSingleToken(com.gu.typesafe.config.impl.Tokens.newIgnoredWhitespace(null, " ")));
if (path.length() == 1) {
newNodes.add(indentedValue);
} else {
// If the path is of length greater than one add the required new objects along the path
ArrayList<AbstractConfigNode> newObjectNodes = new ArrayList<AbstractConfigNode>();
newObjectNodes.add(new com.gu.typesafe.config.impl.ConfigNodeSingleToken(com.gu.typesafe.config.impl.Tokens.OPEN_CURLY));
if (indentation.isEmpty()) {
newObjectNodes.add(new com.gu.typesafe.config.impl.ConfigNodeSingleToken(com.gu.typesafe.config.impl.Tokens.newLine(null)));
}
newObjectNodes.addAll(indentation);
newObjectNodes.add(new com.gu.typesafe.config.impl.ConfigNodeSingleToken(com.gu.typesafe.config.impl.Tokens.CLOSE_CURLY));
ConfigNodeObject newObject = new ConfigNodeObject(newObjectNodes);
newNodes.add(newObject.addValueOnPath(desiredPath.subPath(1), indentedValue, flavor));
}
// Combine these two cases so that we only have to iterate once
if (flavor == com.gu.typesafe.config.ConfigSyntax.JSON || startsWithBrace || sameLine) {
for (int i = childrenCopy.size() - 1; i >= 0; i--) {
// If we are in JSON or are adding a setting on the same line, we need to add a comma to the
// last setting
if ((flavor == com.gu.typesafe.config.ConfigSyntax.JSON || sameLine) && childrenCopy.get(i) instanceof ConfigNodeField) {
if (i+1 >= childrenCopy.size() ||
!(childrenCopy.get(i+1) instanceof com.gu.typesafe.config.impl.ConfigNodeSingleToken
&& ((com.gu.typesafe.config.impl.ConfigNodeSingleToken) childrenCopy.get(i+1)).token() == com.gu.typesafe.config.impl.Tokens.COMMA))
childrenCopy.add(i+1, new com.gu.typesafe.config.impl.ConfigNodeSingleToken(com.gu.typesafe.config.impl.Tokens.COMMA));
break;
}
// Add the value into the copy of the children map, keeping any whitespace/newlines
// before the close curly brace
if (startsWithBrace && childrenCopy.get(i) instanceof com.gu.typesafe.config.impl.ConfigNodeSingleToken &&
((com.gu.typesafe.config.impl.ConfigNodeSingleToken) childrenCopy.get(i)).token == com.gu.typesafe.config.impl.Tokens.CLOSE_CURLY) {
AbstractConfigNode previous = childrenCopy.get(i - 1);
if (previous instanceof com.gu.typesafe.config.impl.ConfigNodeSingleToken &&
com.gu.typesafe.config.impl.Tokens.isNewline(((com.gu.typesafe.config.impl.ConfigNodeSingleToken) previous).token())) {
childrenCopy.add(i - 1, new ConfigNodeField(newNodes));
i--;
} else if (previous instanceof com.gu.typesafe.config.impl.ConfigNodeSingleToken &&
com.gu.typesafe.config.impl.Tokens.isIgnoredWhitespace(((com.gu.typesafe.config.impl.ConfigNodeSingleToken) previous).token())) {
AbstractConfigNode beforePrevious = childrenCopy.get(i - 2);
if (sameLine) {
childrenCopy.add(i - 1, new ConfigNodeField(newNodes));
i--;
}
else if (beforePrevious instanceof com.gu.typesafe.config.impl.ConfigNodeSingleToken &&
com.gu.typesafe.config.impl.Tokens.isNewline(((com.gu.typesafe.config.impl.ConfigNodeSingleToken) beforePrevious).token())) {
childrenCopy.add(i - 2, new ConfigNodeField(newNodes));
i -= 2;
} else {
childrenCopy.add(i, new ConfigNodeField(newNodes));
}
}
else
childrenCopy.add(i, new ConfigNodeField(newNodes));
}
}
}
if (!startsWithBrace) {
if (!childrenCopy.isEmpty() && childrenCopy.get(childrenCopy.size() - 1) instanceof com.gu.typesafe.config.impl.ConfigNodeSingleToken &&
com.gu.typesafe.config.impl.Tokens.isNewline(((com.gu.typesafe.config.impl.ConfigNodeSingleToken) childrenCopy.get(childrenCopy.size() - 1)).token()))
childrenCopy.add(childrenCopy.size() - 1, new ConfigNodeField(newNodes));
else
childrenCopy.add(new ConfigNodeField(newNodes));
}
return new ConfigNodeObject(childrenCopy);
}