mirror of
https://github.com/lightbend/config.git
synced 2025-03-22 15:20:26 +08:00
Modify duplicate removal
Modify the ConfigDocument duplicate removal so that multi-element paths beginning with the desired path whose value should be set are always removed as duplicates.
This commit is contained in:
parent
97bd1f60c0
commit
d6c9f632ab
@ -1,11 +1,9 @@
|
|||||||
package com.typesafe.config.impl;
|
package com.typesafe.config.impl;
|
||||||
|
|
||||||
import com.typesafe.config.ConfigException;
|
|
||||||
import com.typesafe.config.ConfigSyntax;
|
import com.typesafe.config.ConfigSyntax;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
final class ConfigNodeObject extends ConfigNodeComplexValue {
|
final class ConfigNodeObject extends ConfigNodeComplexValue {
|
||||||
ConfigNodeObject(Collection<AbstractConfigNode> children) {
|
ConfigNodeObject(Collection<AbstractConfigNode> children) {
|
||||||
@ -44,39 +42,38 @@ final class ConfigNodeObject extends ConfigNodeComplexValue {
|
|||||||
childrenCopy.remove(i);
|
childrenCopy.remove(i);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}else if (!(childrenCopy.get(i) instanceof ConfigNodeField)) {
|
} else if (!(childrenCopy.get(i) instanceof ConfigNodeField)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ConfigNodeField node = (ConfigNodeField)childrenCopy.get(i);
|
ConfigNodeField node = (ConfigNodeField) childrenCopy.get(i);
|
||||||
Path key = node.path().value();
|
Path key = node.path().value();
|
||||||
if (key.equals(desiredPath) || key.startsWith(desiredPath)) {
|
|
||||||
if (valueCopy == null) {
|
// Delete all multi-element paths that start with the desired path, since technically they are duplicates
|
||||||
childrenCopy.remove(i);
|
if ((valueCopy == null && key.equals(desiredPath))|| (key.startsWith(desiredPath) && !key.equals(desiredPath))) {
|
||||||
// Remove any whitespace or commas after the deleted setting
|
childrenCopy.remove(i);
|
||||||
for (int j = i; j < childrenCopy.size(); j++) {
|
// Remove any whitespace or commas after the deleted setting
|
||||||
if (childrenCopy.get(j) instanceof ConfigNodeSingleToken) {
|
for (int j = i; j < childrenCopy.size(); j++) {
|
||||||
Token t = ((ConfigNodeSingleToken) childrenCopy.get(j)).token();
|
if (childrenCopy.get(j) instanceof ConfigNodeSingleToken) {
|
||||||
if (Tokens.isIgnoredWhitespace(t) || t == Tokens.COMMA) {
|
Token t = ((ConfigNodeSingleToken) childrenCopy.get(j)).token();
|
||||||
childrenCopy.remove(j);
|
if (Tokens.isIgnoredWhitespace(t) || t == Tokens.COMMA) {
|
||||||
j--;
|
childrenCopy.remove(j);
|
||||||
} else {
|
j--;
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (key.equals(desiredPath)){
|
} else if (key.equals(desiredPath)) {
|
||||||
seenNonMatching = true;
|
seenNonMatching = true;
|
||||||
childrenCopy.set(i, node.replaceValue(value));
|
childrenCopy.set(i, node.replaceValue(value));
|
||||||
valueCopy = null;
|
valueCopy = null;
|
||||||
}
|
|
||||||
} else if (desiredPath.startsWith(key)) {
|
} else if (desiredPath.startsWith(key)) {
|
||||||
seenNonMatching = true;
|
seenNonMatching = true;
|
||||||
if (node.value() instanceof ConfigNodeObject) {
|
if (node.value() instanceof ConfigNodeObject) {
|
||||||
Path remainingPath = desiredPath.subPath(key.length());
|
Path remainingPath = desiredPath.subPath(key.length());
|
||||||
childrenCopy.set(i, node.replaceValue(((ConfigNodeObject)node.value()).changeValueOnPath(remainingPath, valueCopy, flavor)));
|
childrenCopy.set(i, node.replaceValue(((ConfigNodeObject) node.value()).changeValueOnPath(remainingPath, valueCopy, flavor)));
|
||||||
if (valueCopy != null && !node.equals(super.children.get(i)))
|
if (valueCopy != null && !node.equals(super.children.get(i)))
|
||||||
valueCopy = null;
|
valueCopy = null;
|
||||||
}
|
}
|
||||||
@ -84,11 +81,6 @@ final class ConfigNodeObject extends ConfigNodeComplexValue {
|
|||||||
seenNonMatching = true;
|
seenNonMatching = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since we've removed values and valid JSON does not allow trailing commas, remove a comma after the final setting
|
|
||||||
if (flavor == ConfigSyntax.JSON) {
|
|
||||||
|
|
||||||
}
|
|
||||||
return new ConfigNodeObject(childrenCopy);
|
return new ConfigNodeObject(childrenCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,8 +97,8 @@ final class ConfigNodeObject extends ConfigNodeComplexValue {
|
|||||||
ConfigNodeObject node = changeValueOnPath(desiredPath.value(), value, flavor);
|
ConfigNodeObject node = changeValueOnPath(desiredPath.value(), value, flavor);
|
||||||
|
|
||||||
// If the desired Path did not exist, add it
|
// If the desired Path did not exist, add it
|
||||||
if (node.equals(this)) {
|
if (!node.hasValue(desiredPath.value())) {
|
||||||
return addValueOnPath(desiredPath, value, flavor);
|
return node.addValueOnPath(desiredPath, value, flavor);
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ class ConfigDocumentTest extends TestUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
def configDocumentReplace() {
|
def configDocumentReplace {
|
||||||
// Can handle parsing/replacement with a very simple map
|
// Can handle parsing/replacement with a very simple map
|
||||||
configDocumentReplaceConfTest("""{"a":1}""", """{"a":2}""", "2", "a")
|
configDocumentReplaceConfTest("""{"a":1}""", """{"a":2}""", "2", "a")
|
||||||
configDocumentReplaceJsonTest("""{"a":1}""", """{"a":2}""", "2", "a")
|
configDocumentReplaceJsonTest("""{"a":1}""", """{"a":2}""", "2", "a")
|
||||||
@ -136,6 +136,21 @@ class ConfigDocumentTest extends TestUtils {
|
|||||||
"this is a concatenation 123 456 {a:b} [1,2,3] {a: this is another 123 concatenation null true}", "h.b.a")
|
"this is a concatenation 123 456 {a:b} [1,2,3] {a: this is another 123 concatenation null true}", "h.b.a")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def configDocumentMultiElementDuplicatesRemoved {
|
||||||
|
var origText = "{a: b, a.b.c: d, a: e}"
|
||||||
|
var configDoc = ConfigDocumentFactory.parseString(origText)
|
||||||
|
assertEquals("{a: 2}", configDoc.setValue("a", "2").render())
|
||||||
|
|
||||||
|
origText = "{a: b, a: e, a.b.c: d}"
|
||||||
|
configDoc = ConfigDocumentFactory.parseString(origText)
|
||||||
|
assertEquals("{a: 2, }", configDoc.setValue("a", "2").render())
|
||||||
|
|
||||||
|
origText = "{a.b.c: d}"
|
||||||
|
configDoc = ConfigDocumentFactory.parseString(origText)
|
||||||
|
assertEquals("{\na : 2\n}", configDoc.setValue("a", "2").render())
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
def configDocumentSetNewValueBraceRoot {
|
def configDocumentSetNewValueBraceRoot {
|
||||||
val origText = "{\n\t\"a\":\"b\",\n\t\"c\":\"d\"\n}"
|
val origText = "{\n\t\"a\":\"b\",\n\t\"c\":\"d\"\n}"
|
||||||
|
Loading…
Reference in New Issue
Block a user