mirror of
https://github.com/lightbend/config.git
synced 2025-01-15 23:01:05 +08:00
Merge pull request #243 from acaly/set_origin
Add methods to create and set origin.
This commit is contained in:
commit
ce394080a1
@ -41,4 +41,6 @@ public interface ConfigList extends List<ConfigValue>, ConfigValue {
|
|||||||
@Override
|
@Override
|
||||||
List<Object> unwrapped();
|
List<Object> unwrapped();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
ConfigList withOrigin(ConfigOrigin origin);
|
||||||
}
|
}
|
||||||
|
@ -129,4 +129,7 @@ public interface ConfigObject extends ConfigValue, Map<String, ConfigValue> {
|
|||||||
* @return the new instance with the new map entry
|
* @return the new instance with the new map entry
|
||||||
*/
|
*/
|
||||||
ConfigObject withValue(String key, ConfigValue value);
|
ConfigObject withValue(String key, ConfigValue value);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
ConfigObject withOrigin(ConfigOrigin origin);
|
||||||
}
|
}
|
||||||
|
@ -79,4 +79,36 @@ public interface ConfigOrigin {
|
|||||||
* none
|
* none
|
||||||
*/
|
*/
|
||||||
public List<String> comments();
|
public List<String> comments();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code ConfigOrigin} based on this one, but with the given
|
||||||
|
* comments. Does not modify this instance or any {@code ConfigValue}s with
|
||||||
|
* this origin (since they are immutable). To set the returned origin to a
|
||||||
|
* {@code ConfigValue}, use {@link ConfigValue#withOrigin}.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Note that when the given comments are equal to the comments on this object,
|
||||||
|
* a new instance may not be created and {@code this} is returned directly.
|
||||||
|
*
|
||||||
|
* @param comments the comments used on the returned origin
|
||||||
|
* @return the ConfigOrigin with the given comments
|
||||||
|
*/
|
||||||
|
public ConfigOrigin withComments(List<String> comments);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code ConfigOrigin} based on this one, but with the given
|
||||||
|
* line number. This origin must be a FILE, URL or RESOURCE. Does not modify
|
||||||
|
* this instance or any {@code ConfigValue}s with this origin (since they are
|
||||||
|
* immutable). To set the returned origin to a {@code ConfigValue}, use
|
||||||
|
* {@link ConfigValue#withOrigin}.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Note that when the given lineNumber are equal to the lineNumber on this
|
||||||
|
* object, a new instance may not be created and {@code this} is returned
|
||||||
|
* directly.
|
||||||
|
*
|
||||||
|
* @param comments the comments used on the returned origin
|
||||||
|
* @return the created ConfigOrigin
|
||||||
|
*/
|
||||||
|
public ConfigOrigin withLineNumber(int lineNumber);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.typesafe.config;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import com.typesafe.config.impl.ConfigImpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class contains some static factory methods for building a {@link
|
||||||
|
* ConfigOrigin}. {@code ConfigOrigin}s are automatically created when you
|
||||||
|
* call other API methods to get a {@code ConfigValue} or {@code Config}.
|
||||||
|
* But you can also set the origin of an existing {@code ConfigValue}, using
|
||||||
|
* {@link ConfigValue#withOrigin(ConfigOrigin)}.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public final class ConfigOriginFactory {
|
||||||
|
private ConfigOriginFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the default origin for values when no other information is
|
||||||
|
* provided. This is the origin used in {@link ConfigValueFactory
|
||||||
|
* #fromAnyRef(Object)}.
|
||||||
|
*
|
||||||
|
* @return the default origin
|
||||||
|
*/
|
||||||
|
public static ConfigOrigin newSimple() {
|
||||||
|
return newSimple(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a origin with the given description.
|
||||||
|
*
|
||||||
|
* @param description brief description of what the origin is
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ConfigOrigin newSimple(String description) {
|
||||||
|
return ConfigImpl.newSimpleOrigin(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a file origin with the given filename.
|
||||||
|
*
|
||||||
|
* @param filename the filename of this origin
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ConfigOrigin newFile(String filename) {
|
||||||
|
return ConfigImpl.newFileOrigin(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a url origin with the given URL object.
|
||||||
|
*
|
||||||
|
* @param url the url of this origin
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ConfigOrigin newURL(URL url) {
|
||||||
|
return ConfigImpl.newURLOrigin(url);
|
||||||
|
}
|
||||||
|
}
|
@ -106,4 +106,14 @@ public interface ConfigValue extends ConfigMergeable {
|
|||||||
* @return a {@code Config} instance containing this value at the given key.
|
* @return a {@code Config} instance containing this value at the given key.
|
||||||
*/
|
*/
|
||||||
Config atKey(String key);
|
Config atKey(String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@code ConfigValue} based on this one, but with the given
|
||||||
|
* origin. This is useful when you are parsing a new format of file or setting
|
||||||
|
* comments for a single ConfigValue.
|
||||||
|
*
|
||||||
|
* @param origin the origin set on the returned value
|
||||||
|
* @return the new ConfigValue with the given origin
|
||||||
|
*/
|
||||||
|
ConfigValue withOrigin(ConfigOrigin origin);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ import com.typesafe.config.ConfigValue;
|
|||||||
import com.typesafe.config.ConfigValueType;
|
import com.typesafe.config.ConfigValueType;
|
||||||
|
|
||||||
abstract class AbstractConfigObject extends AbstractConfigValue implements ConfigObject, Container {
|
abstract class AbstractConfigObject extends AbstractConfigValue implements ConfigObject, Container {
|
||||||
|
|
||||||
final private SimpleConfig config;
|
final private SimpleConfig config;
|
||||||
|
|
||||||
protected AbstractConfigObject(ConfigOrigin origin) {
|
protected AbstractConfigObject(ConfigOrigin origin) {
|
||||||
@ -214,4 +213,9 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements Confi
|
|||||||
public ConfigValue remove(Object arg0) {
|
public ConfigValue remove(Object arg0) {
|
||||||
throw weAreImmutable("remove");
|
throw weAreImmutable("remove");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractConfigObject withOrigin(ConfigOrigin origin) {
|
||||||
|
return (AbstractConfigObject) super.withOrigin(origin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,6 +257,7 @@ abstract class AbstractConfigValue implements ConfigValue, MergeableValue {
|
|||||||
return mergedWithNonObject(Collections.singletonList(this), fallback);
|
return mergedWithNonObject(Collections.singletonList(this), fallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public AbstractConfigValue withOrigin(ConfigOrigin origin) {
|
public AbstractConfigValue withOrigin(ConfigOrigin origin) {
|
||||||
if (this.origin == origin)
|
if (this.origin == origin)
|
||||||
return this;
|
return this;
|
||||||
|
@ -5,6 +5,7 @@ package com.typesafe.config.impl;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -461,4 +462,24 @@ public class ConfigImpl {
|
|||||||
else
|
else
|
||||||
return new ConfigException.NotResolved(newMessage, original);
|
return new ConfigException.NotResolved(newMessage, original);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** For use ONLY by library internals, DO NOT TOUCH not guaranteed ABI */
|
||||||
|
public static ConfigOrigin newSimpleOrigin(String description) {
|
||||||
|
if (description == null) {
|
||||||
|
return defaultValueOrigin;
|
||||||
|
} else {
|
||||||
|
return SimpleConfigOrigin.newSimple(description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** For use ONLY by library internals, DO NOT TOUCH not guaranteed ABI */
|
||||||
|
public static ConfigOrigin newFileOrigin(String filename) {
|
||||||
|
return SimpleConfigOrigin.newFile(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** For use ONLY by library internals, DO NOT TOUCH not guaranteed ABI */
|
||||||
|
public static ConfigOrigin newURLOrigin(URL url) {
|
||||||
|
return SimpleConfigOrigin.newURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -424,7 +424,7 @@ final class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private SimpleConfigOrigin lineOrigin() {
|
private SimpleConfigOrigin lineOrigin() {
|
||||||
return ((SimpleConfigOrigin) baseOrigin).setLineNumber(lineNumber);
|
return ((SimpleConfigOrigin) baseOrigin).withLineNumber(lineNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigException parseError(String message) {
|
private ConfigException parseError(String message) {
|
||||||
@ -553,19 +553,19 @@ final class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the setComments(null) is to ensure comments are only
|
// the withComments(null) is to ensure comments are only
|
||||||
// on the exact leaf node they apply to.
|
// on the exact leaf node they apply to.
|
||||||
// a comment before "foo.bar" applies to the full setting
|
// a comment before "foo.bar" applies to the full setting
|
||||||
// "foo.bar" not also to "foo"
|
// "foo.bar" not also to "foo"
|
||||||
ListIterator<String> i = keys.listIterator(keys.size());
|
ListIterator<String> i = keys.listIterator(keys.size());
|
||||||
String deepest = i.previous();
|
String deepest = i.previous();
|
||||||
AbstractConfigObject o = new SimpleConfigObject(value.origin().setComments(null),
|
AbstractConfigObject o = new SimpleConfigObject(value.origin().withComments(null),
|
||||||
Collections.<String, AbstractConfigValue> singletonMap(
|
Collections.<String, AbstractConfigValue> singletonMap(
|
||||||
deepest, value));
|
deepest, value));
|
||||||
while (i.hasPrevious()) {
|
while (i.hasPrevious()) {
|
||||||
Map<String, AbstractConfigValue> m = Collections.<String, AbstractConfigValue> singletonMap(
|
Map<String, AbstractConfigValue> m = Collections.<String, AbstractConfigValue> singletonMap(
|
||||||
i.previous(), o);
|
i.previous(), o);
|
||||||
o = new SimpleConfigObject(value.origin().setComments(null), m);
|
o = new SimpleConfigObject(value.origin().withComments(null), m);
|
||||||
}
|
}
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
|
@ -451,4 +451,9 @@ final class SimpleConfigList extends AbstractConfigValue implements ConfigList,
|
|||||||
private Object writeReplace() throws ObjectStreamException {
|
private Object writeReplace() throws ObjectStreamException {
|
||||||
return new SerializedConfigValue(this);
|
return new SerializedConfigValue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SimpleConfigList withOrigin(ConfigOrigin origin) {
|
||||||
|
return (SimpleConfigList) super.withOrigin(origin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,8 @@ final class SimpleConfigOrigin implements ConfigOrigin {
|
|||||||
return newResource(resource, null);
|
return newResource(resource, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleConfigOrigin setLineNumber(int lineNumber) {
|
@Override
|
||||||
|
public SimpleConfigOrigin withLineNumber(int lineNumber) {
|
||||||
if (lineNumber == this.lineNumber && lineNumber == this.endLineNumber) {
|
if (lineNumber == this.lineNumber && lineNumber == this.endLineNumber) {
|
||||||
return this;
|
return this;
|
||||||
} else {
|
} else {
|
||||||
@ -84,7 +85,8 @@ final class SimpleConfigOrigin implements ConfigOrigin {
|
|||||||
this.originType, url != null ? url.toExternalForm() : null, this.commentsOrNull);
|
this.originType, url != null ? url.toExternalForm() : null, this.commentsOrNull);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleConfigOrigin setComments(List<String> comments) {
|
@Override
|
||||||
|
public SimpleConfigOrigin withComments(List<String> comments) {
|
||||||
if (ConfigImplUtil.equalsHandlingNull(comments, this.commentsOrNull)) {
|
if (ConfigImplUtil.equalsHandlingNull(comments, this.commentsOrNull)) {
|
||||||
return this;
|
return this;
|
||||||
} else {
|
} else {
|
||||||
@ -97,13 +99,13 @@ final class SimpleConfigOrigin implements ConfigOrigin {
|
|||||||
if (ConfigImplUtil.equalsHandlingNull(comments, this.commentsOrNull) || comments == null) {
|
if (ConfigImplUtil.equalsHandlingNull(comments, this.commentsOrNull) || comments == null) {
|
||||||
return this;
|
return this;
|
||||||
} else if (this.commentsOrNull == null) {
|
} else if (this.commentsOrNull == null) {
|
||||||
return setComments(comments);
|
return withComments(comments);
|
||||||
} else {
|
} else {
|
||||||
List<String> merged = new ArrayList<String>(comments.size()
|
List<String> merged = new ArrayList<String>(comments.size()
|
||||||
+ this.commentsOrNull.size());
|
+ this.commentsOrNull.size());
|
||||||
merged.addAll(comments);
|
merged.addAll(comments);
|
||||||
merged.addAll(this.commentsOrNull);
|
merged.addAll(this.commentsOrNull);
|
||||||
return setComments(merged);
|
return withComments(merged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,13 +113,13 @@ final class SimpleConfigOrigin implements ConfigOrigin {
|
|||||||
if (ConfigImplUtil.equalsHandlingNull(comments, this.commentsOrNull) || comments == null) {
|
if (ConfigImplUtil.equalsHandlingNull(comments, this.commentsOrNull) || comments == null) {
|
||||||
return this;
|
return this;
|
||||||
} else if (this.commentsOrNull == null) {
|
} else if (this.commentsOrNull == null) {
|
||||||
return setComments(comments);
|
return withComments(comments);
|
||||||
} else {
|
} else {
|
||||||
List<String> merged = new ArrayList<String>(comments.size()
|
List<String> merged = new ArrayList<String>(comments.size()
|
||||||
+ this.commentsOrNull.size());
|
+ this.commentsOrNull.size());
|
||||||
merged.addAll(this.commentsOrNull);
|
merged.addAll(this.commentsOrNull);
|
||||||
merged.addAll(comments);
|
merged.addAll(comments);
|
||||||
return setComments(merged);
|
return withComments(merged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ final class Tokenizer {
|
|||||||
this.allowComments = allowComments;
|
this.allowComments = allowComments;
|
||||||
this.buffer = new LinkedList<Integer>();
|
this.buffer = new LinkedList<Integer>();
|
||||||
lineNumber = 1;
|
lineNumber = 1;
|
||||||
lineOrigin = this.origin.setLineNumber(lineNumber);
|
lineOrigin = this.origin.withLineNumber(lineNumber);
|
||||||
tokens = new LinkedList<Token>();
|
tokens = new LinkedList<Token>();
|
||||||
tokens.add(Tokens.START);
|
tokens.add(Tokens.START);
|
||||||
whitespaceSaver = new WhitespaceSaver();
|
whitespaceSaver = new WhitespaceSaver();
|
||||||
@ -254,7 +254,7 @@ final class Tokenizer {
|
|||||||
|
|
||||||
private static ConfigOrigin lineOrigin(ConfigOrigin baseOrigin,
|
private static ConfigOrigin lineOrigin(ConfigOrigin baseOrigin,
|
||||||
int lineNumber) {
|
int lineNumber) {
|
||||||
return ((SimpleConfigOrigin) baseOrigin).setLineNumber(lineNumber);
|
return ((SimpleConfigOrigin) baseOrigin).withLineNumber(lineNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ONE char has always been consumed, either the # or the first /, but
|
// ONE char has always been consumed, either the # or the first /, but
|
||||||
@ -446,7 +446,7 @@ final class Tokenizer {
|
|||||||
else if (c == '\n') {
|
else if (c == '\n') {
|
||||||
// keep the line number accurate
|
// keep the line number accurate
|
||||||
lineNumber += 1;
|
lineNumber += 1;
|
||||||
lineOrigin = origin.setLineNumber(lineNumber);
|
lineOrigin = origin.withLineNumber(lineNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,7 +549,7 @@ final class Tokenizer {
|
|||||||
// newline tokens have the just-ended line number
|
// newline tokens have the just-ended line number
|
||||||
Token line = Tokens.newLine(lineOrigin);
|
Token line = Tokens.newLine(lineOrigin);
|
||||||
lineNumber += 1;
|
lineNumber += 1;
|
||||||
lineOrigin = origin.setLineNumber(lineNumber);
|
lineOrigin = origin.withLineNumber(lineNumber);
|
||||||
return line;
|
return line;
|
||||||
} else {
|
} else {
|
||||||
Token t;
|
Token t;
|
||||||
|
@ -663,8 +663,8 @@ class ConfigValueTest extends TestUtils {
|
|||||||
def configOriginFileAndLine() {
|
def configOriginFileAndLine() {
|
||||||
val hasFilename = SimpleConfigOrigin.newFile("foo")
|
val hasFilename = SimpleConfigOrigin.newFile("foo")
|
||||||
val noFilename = SimpleConfigOrigin.newSimple("bar")
|
val noFilename = SimpleConfigOrigin.newSimple("bar")
|
||||||
val filenameWithLine = hasFilename.setLineNumber(3)
|
val filenameWithLine = hasFilename.withLineNumber(3)
|
||||||
val noFilenameWithLine = noFilename.setLineNumber(4)
|
val noFilenameWithLine = noFilename.withLineNumber(4)
|
||||||
|
|
||||||
assertEquals("foo", hasFilename.filename())
|
assertEquals("foo", hasFilename.filename())
|
||||||
assertEquals("foo", filenameWithLine.filename())
|
assertEquals("foo", filenameWithLine.filename())
|
||||||
@ -866,10 +866,10 @@ class ConfigValueTest extends TestUtils {
|
|||||||
val combos = bases.flatMap({
|
val combos = bases.flatMap({
|
||||||
base =>
|
base =>
|
||||||
Seq(
|
Seq(
|
||||||
(base, base.setComments(Seq("this is a comment", "another one").asJava)),
|
(base, base.withComments(Seq("this is a comment", "another one").asJava)),
|
||||||
(base, base.setComments(null)),
|
(base, base.withComments(null)),
|
||||||
(base, base.setLineNumber(41)),
|
(base, base.withLineNumber(41)),
|
||||||
(base, SimpleConfigOrigin.mergeOrigins(base.setLineNumber(10), base.setLineNumber(20))))
|
(base, SimpleConfigOrigin.mergeOrigins(base.withLineNumber(10), base.withLineNumber(20))))
|
||||||
}) ++
|
}) ++
|
||||||
bases.sliding(2).map({ seq => (seq.head, seq.tail.head) }) ++
|
bases.sliding(2).map({ seq => (seq.head, seq.tail.head) }) ++
|
||||||
bases.sliding(3).map({ seq => (seq.head, seq.tail.tail.head) }) ++
|
bases.sliding(3).map({ seq => (seq.head, seq.tail.tail.head) }) ++
|
||||||
|
@ -888,7 +888,7 @@ class PublicApiTest extends TestUtils {
|
|||||||
def exceptionSerializable() {
|
def exceptionSerializable() {
|
||||||
// ArrayList is a serialization problem so we want to cover it in tests
|
// ArrayList is a serialization problem so we want to cover it in tests
|
||||||
val comments = new java.util.ArrayList(List("comment 1", "comment 2").asJava)
|
val comments = new java.util.ArrayList(List("comment 1", "comment 2").asJava)
|
||||||
val e = new ConfigException.WrongType(SimpleConfigOrigin.newSimple("an origin").setComments(comments),
|
val e = new ConfigException.WrongType(SimpleConfigOrigin.newSimple("an origin").withComments(comments),
|
||||||
"this is a message", new RuntimeException("this is a cause"))
|
"this is a message", new RuntimeException("this is a cause"))
|
||||||
val eCopy = checkSerializableNoMeaningfulEquals(e)
|
val eCopy = checkSerializableNoMeaningfulEquals(e)
|
||||||
assertTrue("messages equal after deserialize", e.getMessage.equals(eCopy.getMessage))
|
assertTrue("messages equal after deserialize", e.getMessage.equals(eCopy.getMessage))
|
||||||
|
@ -614,7 +614,7 @@ abstract trait TestUtils {
|
|||||||
def tokenDouble(d: Double) = Tokens.newDouble(fakeOrigin(), d, null)
|
def tokenDouble(d: Double) = Tokens.newDouble(fakeOrigin(), d, null)
|
||||||
def tokenInt(i: Int) = Tokens.newInt(fakeOrigin(), i, null)
|
def tokenInt(i: Int) = Tokens.newInt(fakeOrigin(), i, null)
|
||||||
def tokenLong(l: Long) = Tokens.newLong(fakeOrigin(), l, null)
|
def tokenLong(l: Long) = Tokens.newLong(fakeOrigin(), l, null)
|
||||||
def tokenLine(line: Int) = Tokens.newLine(fakeOrigin.setLineNumber(line))
|
def tokenLine(line: Int) = Tokens.newLine(fakeOrigin.withLineNumber(line))
|
||||||
def tokenComment(text: String) = Tokens.newComment(fakeOrigin(), text)
|
def tokenComment(text: String) = Tokens.newComment(fakeOrigin(), text)
|
||||||
|
|
||||||
private def tokenMaybeOptionalSubstitution(optional: Boolean, expression: Token*) = {
|
private def tokenMaybeOptionalSubstitution(optional: Boolean, expression: Token*) = {
|
||||||
|
Loading…
Reference in New Issue
Block a user