mirror of
https://github.com/lightbend/config.git
synced 2025-01-15 23:01:05 +08:00
Address ConfigNode PR feedback
Address various PR feedback, including: * Remove unused map from ConfigNodeComplexValue * Stop caching KeyValue indexes in ConfigNodeComplexValue * Return an Iterable<Token> for the children() methods in ConfigNodeComplexValue and ConfigNodeKeyValue * Change all ConfigNode classes to implement AbstractConfigNode * Remove the constructor and the token instance variable from AbstractConfigNode. Make the render() method final and have it use a new tokens() method which returns the list of tokens contained by the node. * Stop caching values in ConfigNodeKeyValue
This commit is contained in:
parent
3166db4d72
commit
e695543bf1
@ -1,15 +1,16 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import com.typesafe.config.ConfigNode;
|
||||
import java.util.Collection;
|
||||
|
||||
abstract class AbstractConfigNode implements ConfigNode {
|
||||
final private Token token;
|
||||
|
||||
AbstractConfigNode(Token t) {
|
||||
token = t;
|
||||
}
|
||||
|
||||
public String render() {
|
||||
return token.tokenText();
|
||||
abstract Collection<Token> tokens();
|
||||
final public String render() {
|
||||
StringBuilder origText = new StringBuilder();
|
||||
Iterable<Token> tokens = tokens();
|
||||
for (Token t : tokens) {
|
||||
origText.append(t.tokenText());
|
||||
}
|
||||
return origText.toString();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
// This is gross. We currently have a class that doesn't do anything, but is needed
|
||||
// to distinguish certain types of nodes from other types. This is required if we want
|
||||
// to be referencing the AbstractConfigNode class in implementation rather than the
|
||||
// ConfigNode interface, as we can't cast an AbstractConfigNode to an interface
|
||||
abstract class AbstractConfigNodeValue extends AbstractConfigNode {
|
||||
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
final class ConfigNodeBasic extends AbstractConfigNode{
|
||||
ConfigNodeBasic(Token t) {
|
||||
super(t);
|
||||
}
|
||||
}
|
@ -4,63 +4,54 @@ import com.typesafe.config.ConfigNode;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
final class ConfigNodeComplexValue implements ConfigNode, ConfigNodeValue {
|
||||
private ArrayList<ConfigNode> children;
|
||||
final private LinkedHashMap<Path, Integer> map = new LinkedHashMap<>();
|
||||
final ArrayList<Integer> keyValueIndexes;
|
||||
final class ConfigNodeComplexValue extends AbstractConfigNodeValue {
|
||||
final private ArrayList<AbstractConfigNode> children;
|
||||
|
||||
ConfigNodeComplexValue(Collection<ConfigNode> children) {
|
||||
ConfigNodeComplexValue(Collection<AbstractConfigNode> children) {
|
||||
this.children = new ArrayList(children);
|
||||
keyValueIndexes = new ArrayList<Integer>();
|
||||
|
||||
// Construct the list of indexes of Key-Value nodes. Do this
|
||||
// in reverse order, since all but the final duplicate will be removed.
|
||||
for (int i = this.children.size() - 1; i >= 0; i--) {
|
||||
ConfigNode currNode = this.children.get(i);
|
||||
if (currNode instanceof ConfigNodeKeyValue) {
|
||||
keyValueIndexes.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<ConfigNode> children() {
|
||||
public Iterable<AbstractConfigNode> children() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public String render() {
|
||||
StringBuilder renderedText = new StringBuilder();
|
||||
for (ConfigNode child : children) {
|
||||
renderedText.append(child.render());
|
||||
protected Collection<Token> tokens() {
|
||||
ArrayList<Token> tokens = new ArrayList();
|
||||
for (AbstractConfigNode child : children) {
|
||||
tokens.addAll(child.tokens());
|
||||
}
|
||||
return renderedText.toString();
|
||||
return tokens;
|
||||
}
|
||||
|
||||
protected ConfigNodeComplexValue changeValueOnPath(Path desiredPath, ConfigNodeValue value) {
|
||||
ArrayList<ConfigNode> childrenCopy = (ArrayList<ConfigNode>)(children.clone());
|
||||
protected ConfigNodeComplexValue changeValueOnPath(Path desiredPath, AbstractConfigNodeValue value) {
|
||||
ArrayList<AbstractConfigNode> childrenCopy = new ArrayList(children);
|
||||
boolean replaced = value == null;
|
||||
ConfigNodeKeyValue node;
|
||||
Path key;
|
||||
for (Integer keyValIndex : keyValueIndexes) {
|
||||
node = (ConfigNodeKeyValue)children.get(keyValIndex.intValue());
|
||||
for (int i = children.size() - 1; i >= 0; i--) {
|
||||
if (!(children.get(i) instanceof ConfigNodeKeyValue)) {
|
||||
continue;
|
||||
}
|
||||
node = (ConfigNodeKeyValue)children.get(i);
|
||||
key = Path.newPath(node.key().render());
|
||||
if (key.equals(desiredPath)) {
|
||||
if (!replaced) {
|
||||
childrenCopy.set(keyValIndex.intValue(), node.replaceValue(value));
|
||||
childrenCopy.set(i, node.replaceValue(value));
|
||||
replaced = true;
|
||||
}
|
||||
else
|
||||
childrenCopy.remove(keyValIndex.intValue());
|
||||
childrenCopy.remove(i);
|
||||
} else if (desiredPath.startsWith(key)) {
|
||||
if (node.value() instanceof ConfigNodeComplexValue) {
|
||||
Path remainingPath = desiredPath.subPath(key.length());
|
||||
if (!replaced) {
|
||||
node = node.replaceValue(((ConfigNodeComplexValue) node.value()).changeValueOnPath(remainingPath, value));
|
||||
if (node.render() != children.get(keyValIndex.intValue()).render())
|
||||
if (node.render() != children.get(i).render())
|
||||
replaced = true;
|
||||
childrenCopy.set(keyValIndex.intValue(), node);
|
||||
childrenCopy.set(i, node);
|
||||
} else {
|
||||
node = node.replaceValue(((ConfigNodeComplexValue) node.value()).removeValueOnPath(remainingPath));
|
||||
childrenCopy.set(keyValIndex.intValue(), node);
|
||||
childrenCopy.set(i, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -68,20 +59,20 @@ final class ConfigNodeComplexValue implements ConfigNode, ConfigNodeValue {
|
||||
return new ConfigNodeComplexValue(childrenCopy);
|
||||
}
|
||||
|
||||
public ConfigNodeComplexValue setValueOnPath(Path desiredPath, ConfigNodeValue value) {
|
||||
public ConfigNodeComplexValue setValueOnPath(Path desiredPath, AbstractConfigNodeValue value) {
|
||||
ConfigNodeComplexValue node = changeValueOnPath(desiredPath, value);
|
||||
|
||||
// If the desired Path did not exist, add it
|
||||
if (node.render().equals(render())) {
|
||||
ArrayList<ConfigNode> childrenCopy = (ArrayList<ConfigNode>)children.clone();
|
||||
ArrayList<ConfigNode> newNodes = new ArrayList<ConfigNode>();
|
||||
newNodes.add(new ConfigNodeBasic(Tokens.newLine(null)));
|
||||
ArrayList<AbstractConfigNode> childrenCopy = new ArrayList<AbstractConfigNode>(children);
|
||||
ArrayList<AbstractConfigNode> newNodes = new ArrayList();
|
||||
newNodes.add(new ConfigNodeSingleToken(Tokens.newLine(null)));
|
||||
newNodes.add(new ConfigNodeKey(Tokens.newUnquotedText(null, desiredPath.render())));
|
||||
newNodes.add(new ConfigNodeBasic(Tokens.newIgnoredWhitespace(null, " ")));
|
||||
newNodes.add(new ConfigNodeBasic(Tokens.COLON));
|
||||
newNodes.add(new ConfigNodeBasic(Tokens.newIgnoredWhitespace(null, " ")));
|
||||
newNodes.add(new ConfigNodeSingleToken(Tokens.newIgnoredWhitespace(null, " ")));
|
||||
newNodes.add(new ConfigNodeSingleToken(Tokens.COLON));
|
||||
newNodes.add(new ConfigNodeSingleToken(Tokens.newIgnoredWhitespace(null, " ")));
|
||||
newNodes.add(value);
|
||||
newNodes.add(new ConfigNodeBasic(Tokens.newLine(null)));
|
||||
newNodes.add(new ConfigNodeSingleToken(Tokens.newLine(null)));
|
||||
childrenCopy.add(new ConfigNodeKeyValue(newNodes));
|
||||
node = new ConfigNodeComplexValue(childrenCopy);
|
||||
}
|
||||
|
@ -1,7 +1,15 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
final class ConfigNodeKey extends AbstractConfigNode {
|
||||
Token token;
|
||||
ConfigNodeKey(Token t) {
|
||||
super(t);
|
||||
token = t;
|
||||
}
|
||||
|
||||
protected Collection<Token> tokens() {
|
||||
return Collections.singletonList(token);
|
||||
}
|
||||
}
|
||||
|
@ -1,48 +1,52 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import com.typesafe.config.ConfigException;
|
||||
import com.typesafe.config.ConfigNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public class ConfigNodeKeyValue implements ConfigNode{
|
||||
final private ArrayList<ConfigNode> children;
|
||||
private int configNodeValueIndex;
|
||||
private ConfigNodeKey key;
|
||||
private ConfigNodeValue value;
|
||||
public class ConfigNodeKeyValue extends AbstractConfigNode {
|
||||
final private ArrayList<AbstractConfigNode> children;
|
||||
|
||||
public ConfigNodeKeyValue(Collection<ConfigNode> children) {
|
||||
this.children = new ArrayList<ConfigNode>(children);
|
||||
for (int i = 0; i < this.children.size(); i++) {
|
||||
ConfigNode currNode = this.children.get(i);
|
||||
if (currNode instanceof ConfigNodeKey) {
|
||||
key = (ConfigNodeKey)currNode;
|
||||
} else if (currNode instanceof ConfigNodeValue) {
|
||||
value = (ConfigNodeValue)currNode;
|
||||
configNodeValueIndex = i;
|
||||
public ConfigNodeKeyValue(Collection<AbstractConfigNode> children) {
|
||||
this.children = new ArrayList(children);
|
||||
}
|
||||
|
||||
protected Collection<Token> tokens() {
|
||||
ArrayList<Token> tokens = new ArrayList();
|
||||
for (AbstractConfigNode child : children) {
|
||||
tokens.addAll(child.tokens());
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
public ConfigNodeKeyValue replaceValue(AbstractConfigNodeValue newValue) {
|
||||
ArrayList<AbstractConfigNode> childrenCopy = new ArrayList(children);
|
||||
for (int i = 0; i < childrenCopy.size(); i++) {
|
||||
if (childrenCopy.get(i) instanceof AbstractConfigNodeValue) {
|
||||
childrenCopy.set(i, newValue);
|
||||
return new ConfigNodeKeyValue(childrenCopy);
|
||||
}
|
||||
}
|
||||
throw new ConfigException.BugOrBroken("KeyValue node doesn't have a value");
|
||||
}
|
||||
|
||||
public String render() {
|
||||
StringBuilder renderedText = new StringBuilder();
|
||||
for (ConfigNode child : children) {
|
||||
renderedText.append(child.render());
|
||||
public AbstractConfigNodeValue value() {
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
if (children.get(i) instanceof AbstractConfigNodeValue) {
|
||||
return (AbstractConfigNodeValue)children.get(i);
|
||||
}
|
||||
}
|
||||
return renderedText.toString();
|
||||
}
|
||||
|
||||
public ConfigNodeKeyValue replaceValue(ConfigNodeValue newValue) {
|
||||
ArrayList<ConfigNode> newChildren = (ArrayList<ConfigNode>)(children.clone());
|
||||
newChildren.set(configNodeValueIndex, newValue);
|
||||
return new ConfigNodeKeyValue(newChildren);
|
||||
}
|
||||
|
||||
public ConfigNodeValue value() {
|
||||
return value;
|
||||
throw new ConfigException.BugOrBroken("KeyValue node doesn't have a value");
|
||||
}
|
||||
|
||||
public ConfigNodeKey key() {
|
||||
return key;
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
if (children.get(i) instanceof ConfigNodeKey) {
|
||||
return (ConfigNodeKey)children.get(i);
|
||||
}
|
||||
}
|
||||
throw new ConfigException.BugOrBroken("KeyValue node doesn't have a key");
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,18 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* This class represents a leaf ConfigNode. This type of ConfigNode has no children.
|
||||
*/
|
||||
class ConfigNodeSimpleValue extends AbstractConfigNode implements ConfigNodeValue {
|
||||
class ConfigNodeSimpleValue extends AbstractConfigNodeValue {
|
||||
Token token;
|
||||
ConfigNodeSimpleValue(Token value) {
|
||||
super(value);
|
||||
token = value;
|
||||
}
|
||||
|
||||
protected Collection<Token> tokens() {
|
||||
return Collections.singletonList(token);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
final class ConfigNodeSingleToken extends AbstractConfigNode{
|
||||
Token token;
|
||||
ConfigNodeSingleToken(Token t) {
|
||||
token = t;
|
||||
}
|
||||
|
||||
protected Collection<Token> tokens() {
|
||||
return Collections.singletonList(token);
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import com.typesafe.config.ConfigNode;
|
||||
|
||||
public interface ConfigNodeValue extends ConfigNode {
|
||||
public String render();
|
||||
}
|
@ -21,7 +21,7 @@ class ConfigNodeTest extends TestUtils {
|
||||
assertEquals(node.render(), token.tokenText())
|
||||
}
|
||||
|
||||
private def keyValueNodeTest(key: ConfigNodeKey, value: ConfigNodeValue, trailingWhitespace: ConfigNodeBasic, newValue: ConfigNodeValue) {
|
||||
private def keyValueNodeTest(key: ConfigNodeKey, value: AbstractConfigNodeValue, trailingWhitespace: ConfigNodeSingleToken, newValue: AbstractConfigNodeValue) {
|
||||
val keyValNode = nodeKeyValuePair(key, value, trailingWhitespace)
|
||||
assertEquals(key.render() + " : " + value.render() + trailingWhitespace.render(), keyValNode.render())
|
||||
assertEquals(key.render, keyValNode.key().render())
|
||||
@ -32,7 +32,7 @@ class ConfigNodeTest extends TestUtils {
|
||||
assertEquals(newValue.render(), newKeyValNode.value().render())
|
||||
}
|
||||
|
||||
private def topLevelValueReplaceTest(value: ConfigNodeValue, newValue: ConfigNodeValue, key: Token = tokenString("foo")) {
|
||||
private def topLevelValueReplaceTest(value: AbstractConfigNodeValue, newValue: AbstractConfigNodeValue, key: Token = tokenString("foo")) {
|
||||
val complexNodeChildren = List(nodeOpenBrace,
|
||||
nodeKeyValuePair(nodeWhitespace(" "), configNodeKey(key),value, nodeWhitespace(" ")),
|
||||
nodeCloseBrace)
|
||||
@ -45,7 +45,7 @@ class ConfigNodeTest extends TestUtils {
|
||||
assertEquals(finalText, newNode.render())
|
||||
}
|
||||
|
||||
private def replaceDuplicatesTest(value1: ConfigNodeValue, value2: ConfigNodeValue, value3: ConfigNodeValue) {
|
||||
private def replaceDuplicatesTest(value1: AbstractConfigNodeValue, value2: AbstractConfigNodeValue, value3: AbstractConfigNodeValue) {
|
||||
val key = nodeUnquotedKey("foo")
|
||||
val keyValPair1 = nodeKeyValuePair(key, value1)
|
||||
val keyValPair2 = nodeKeyValuePair(key, value2)
|
||||
@ -58,7 +58,7 @@ class ConfigNodeTest extends TestUtils {
|
||||
assertEquals(finalText, complexNode.setValueOnPath(Path.newPath("foo"), nodeInt(15)).render())
|
||||
}
|
||||
|
||||
private def nonExistentPathTest(value: ConfigNodeValue) {
|
||||
private def nonExistentPathTest(value: AbstractConfigNodeValue) {
|
||||
val node = configNodeComplexValue(List(nodeKeyValuePair(nodeUnquotedKey("bar"), nodeInt(15))))
|
||||
assertEquals("bar : 15", node.render())
|
||||
val newNode = node.setValueOnPath(Path.newPath("foo"), value)
|
||||
|
@ -672,33 +672,33 @@ abstract trait TestUtils {
|
||||
}
|
||||
|
||||
def configNodeBasic(value: Token) = {
|
||||
new ConfigNodeBasic(value: Token)
|
||||
new ConfigNodeSingleToken(value: Token)
|
||||
}
|
||||
|
||||
def configNodeComplexValue(nodes: List[ConfigNode]) = {
|
||||
def configNodeComplexValue(nodes: List[AbstractConfigNode]) = {
|
||||
new ConfigNodeComplexValue(nodes.asJavaCollection)
|
||||
}
|
||||
|
||||
def nodeColon = new ConfigNodeBasic(Tokens.COLON)
|
||||
def nodeSpace = new ConfigNodeBasic(tokenUnquoted(" "))
|
||||
def nodeOpenBrace = new ConfigNodeBasic(Tokens.OPEN_CURLY)
|
||||
def nodeCloseBrace = new ConfigNodeBasic(Tokens.CLOSE_CURLY)
|
||||
def nodeOpenBracket = new ConfigNodeBasic(Tokens.OPEN_SQUARE)
|
||||
def nodeCloseBracket = new ConfigNodeBasic(Tokens.CLOSE_SQUARE)
|
||||
def nodeComma = new ConfigNodeBasic(Tokens.COMMA)
|
||||
def nodeLine(line: Integer) = new ConfigNodeBasic(tokenLine(line))
|
||||
def nodeWhitespace(whitespace: String) = new ConfigNodeBasic(tokenWhitespace(whitespace))
|
||||
def nodeColon = new ConfigNodeSingleToken(Tokens.COLON)
|
||||
def nodeSpace = new ConfigNodeSingleToken(tokenUnquoted(" "))
|
||||
def nodeOpenBrace = new ConfigNodeSingleToken(Tokens.OPEN_CURLY)
|
||||
def nodeCloseBrace = new ConfigNodeSingleToken(Tokens.CLOSE_CURLY)
|
||||
def nodeOpenBracket = new ConfigNodeSingleToken(Tokens.OPEN_SQUARE)
|
||||
def nodeCloseBracket = new ConfigNodeSingleToken(Tokens.CLOSE_SQUARE)
|
||||
def nodeComma = new ConfigNodeSingleToken(Tokens.COMMA)
|
||||
def nodeLine(line: Integer) = new ConfigNodeSingleToken(tokenLine(line))
|
||||
def nodeWhitespace(whitespace: String) = new ConfigNodeSingleToken(tokenWhitespace(whitespace))
|
||||
def nodeQuotedKey(key: String) = configNodeKey(tokenString(key))
|
||||
def nodeUnquotedKey(key: String) = configNodeKey(tokenUnquoted(key))
|
||||
def nodeKeyValuePair(key: ConfigNodeKey, value: ConfigNodeValue) = {
|
||||
def nodeKeyValuePair(key: ConfigNodeKey, value: AbstractConfigNodeValue) = {
|
||||
val nodes = List(key, nodeSpace, nodeColon, nodeSpace, value)
|
||||
new ConfigNodeKeyValue(nodes.asJavaCollection)
|
||||
}
|
||||
def nodeKeyValuePair(key: ConfigNodeKey, value: ConfigNodeValue, trailingWhitespace: ConfigNodeBasic) = {
|
||||
def nodeKeyValuePair(key: ConfigNodeKey, value: AbstractConfigNodeValue, trailingWhitespace: ConfigNodeSingleToken) = {
|
||||
val nodes = List(key, nodeSpace, nodeColon, nodeSpace, value, trailingWhitespace)
|
||||
new ConfigNodeKeyValue(nodes.asJavaCollection)
|
||||
}
|
||||
def nodeKeyValuePair(leadingWhitespace: ConfigNodeBasic, key: ConfigNodeKey, value: ConfigNodeValue, trailingWhitespace: ConfigNodeBasic) = {
|
||||
def nodeKeyValuePair(leadingWhitespace: ConfigNodeSingleToken, key: ConfigNodeKey, value: AbstractConfigNodeValue, trailingWhitespace: ConfigNodeSingleToken) = {
|
||||
val nodes = List(leadingWhitespace, key, nodeSpace, nodeColon, nodeSpace, value, trailingWhitespace)
|
||||
new ConfigNodeKeyValue(nodes.asJavaCollection)
|
||||
}
|
||||
@ -708,8 +708,8 @@ abstract trait TestUtils {
|
||||
def nodeDouble(value: Double) = new ConfigNodeSimpleValue(tokenDouble(value))
|
||||
def nodeTrue = new ConfigNodeSimpleValue(tokenTrue)
|
||||
def nodeFalse = new ConfigNodeSimpleValue(tokenFalse)
|
||||
def nodeCommentHash(text: String) = new ConfigNodeBasic(tokenCommentHash(text))
|
||||
def nodeCommentDoubleSlash(text: String) = new ConfigNodeBasic(tokenCommentDoubleSlash(text))
|
||||
def nodeCommentHash(text: String) = new ConfigNodeSingleToken(tokenCommentHash(text))
|
||||
def nodeCommentDoubleSlash(text: String) = new ConfigNodeSingleToken(tokenCommentDoubleSlash(text))
|
||||
def nodeUnquotedText(text: String) = new ConfigNodeSimpleValue(tokenUnquoted(text))
|
||||
def nodeNull = new ConfigNodeSimpleValue(tokenNull)
|
||||
def nodeKeySubstitution(s: String) = new ConfigNodeSimpleValue(tokenKeySubstitution(s))
|
||||
|
Loading…
Reference in New Issue
Block a user