You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by an...@apache.org on 2018/12/15 23:19:24 UTC
[incubator-tamaya] 01/05: TAMAYA-372: Clarified default metadata
format.
This is an automated email from the ASF dual-hosted git repository.
anatole pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-tamaya.git
commit 6ab216df0ec6081cd35c1847048b6dab93d1b3bf
Author: Anatole Tresch <at...@gmail.com>
AuthorDate: Tue Dec 11 11:00:37 2018 +0100
TAMAYA-372: Clarified default metadata format.
---
.../apache/tamaya/spi/ConfigurationBuilder.java | 7 +-
.../apache/tamaya/spi/ConfigurationContext.java | 7 +-
.../org/apache/tamaya/spi/ConversionContext.java | 23 ++--
.../java/org/apache/tamaya/spi/FilterContext.java | 41 ++++---
.../java/org/apache/tamaya/spi/ObjectValue.java | 4 +-
.../java/org/apache/tamaya/spi/PropertyValue.java | 9 +-
.../java/org/apache/tamaya/ConfigurationTest.java | 69 +++++++++++-
.../java/org/apache/tamaya/InvocationRecorder.java | 76 +++++++++++++
.../java/org/apache/tamaya/TestConfiguration.java | 25 +++--
.../apache/tamaya/TestConfigurationProvider.java | 4 +-
.../apache/tamaya/spi/ConversionContextTest.java | 54 +++++++++
.../org/apache/tamaya/spi/FilterContextTest.java | 10 ++
.../org/apache/tamaya/spi/PropertyValueTest.java | 125 ++++++++++++++++++++-
.../spisupport/DefaultConfigurationBuilder.java | 8 +-
.../spisupport/DefaultConfigurationContext.java | 4 +-
.../tamaya/spisupport/DefaultMetaDataProvider.java | 86 ++++++++++----
.../apache/tamaya/spisupport/MetadataProvider.java | 27 +++--
.../tamaya/spisupport/PropertyFiltering.java | 3 +-
.../spisupport/MockedConfigurationContext.java | 2 +-
19 files changed, 491 insertions(+), 93 deletions(-)
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationBuilder.java b/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationBuilder.java
index b4d67ce..0e2d95f 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationBuilder.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationBuilder.java
@@ -105,18 +105,21 @@ public interface ConfigurationBuilder {
/**
* Adds (overrides existing value) the given sources as property sources.
+ *
+ * @param property the property key, not null,
* @param key the key, not null.
* @param value the value, not null.
* @return the current configuration builder.
*/
- ConfigurationBuilder setMeta(String key, String value);
+ ConfigurationBuilder setMeta(String property, String key, String value);
/**
* Adds (overrides existing value with same same keys) the given sources as property sources.
+ * @param property the property key, not null,
* @param metaData the metadata, not null.
* @return the current configuration builder.
*/
- ConfigurationBuilder setMeta(Map<String, String> metaData);
+ ConfigurationBuilder setMeta(String property, Map<String, String> metaData);
/**
* This method can be used for programmatically adding {@link PropertySource}s.
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java b/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java
index 86c3831..e762576 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java
@@ -34,9 +34,10 @@ public interface ConfigurationContext {
/**
* Get the metadata evaluated for this configuration.
- * @return the metadata accessor, never null.
+ * @param key the property key, not null.
+ * @return the metadata fpr this key, never null.
*/
- Map<String,String> getMetaData();
+ Map<String,String> getMetaData(String key);
/**
* Access the underlying {@link ServiceContext}.
@@ -149,7 +150,7 @@ public interface ConfigurationContext {
*/
ConfigurationContext EMPTY = new ConfigurationContext() {
@Override
- public Map<String,String> getMetaData() {
+ public Map<String,String> getMetaData(String key) {
return Collections.emptyMap();
}
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ConversionContext.java b/code/api/src/main/java/org/apache/tamaya/spi/ConversionContext.java
index ff321dc..cb4ae32 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/ConversionContext.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/ConversionContext.java
@@ -99,20 +99,18 @@ public class ConversionContext {
/**
- * Evaluate the current metadata from the given values. Later values hereby are more significant.
+ * Evaluate the metadata for the current target key from the given values. Later values hereby are more significant.
* @return the evaluated meta data map.
*/
public Map<String, String> getMeta() {
Map<String, String> metaMap = new HashMap<>();
- if(values.size()>0){
- String baseKey = values.get(0).getQualifiedKey()+".";
-
- values.forEach(val -> this.getConfiguration().getContext().getMetaData().entrySet().forEach(
- en -> {
- if(en.getKey().startsWith(baseKey)) {
- metaMap.put(en.getKey().substring(baseKey.length()), en.getValue());
- }
- }));
+ if(configuration!=null){
+ metaMap.putAll(configuration.getContext().getMetaData(key));
+ }
+ for(PropertyValue val:values){
+ if(key.equals(val.getQualifiedKey())){
+ metaMap.putAll(val.getMeta());
+ }
}
return metaMap;
}
@@ -161,7 +159,10 @@ public class ConversionContext {
*/
@Deprecated
public ConfigurationContext getConfigurationContext() {
- return getConfiguration().getContext();
+ if(configuration!=null) {
+ return configuration.getContext();
+ }
+ return ConfigurationContext.EMPTY;
}
/**
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/FilterContext.java b/code/api/src/main/java/org/apache/tamaya/spi/FilterContext.java
index e120744..cdf8652 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/FilterContext.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/FilterContext.java
@@ -21,18 +21,17 @@ package org.apache.tamaya.spi;
import org.apache.tamaya.Configuration;
import java.util.*;
-import java.util.function.Consumer;
/**
- * A filter context containing all the required values for implementing filtering.
+ * A filter configurationContext containing all the required values for implementing filtering.
*
* @see PropertyFilter
*/
public class FilterContext {
/** The key. */
private final List<PropertyValue> values;
- /** The current context. */
- private final ConfigurationContext context;
+ /** The current configurationContext. */
+ private final ConfigurationContext configurationContext;
@Experimental
private Map<String, PropertyValue> configEntries = new HashMap<>();
@Experimental
@@ -45,17 +44,17 @@ public class FilterContext {
*
* @param value the createValue under evaluation, not {@code null}.
* @param configEntries the raw configuration data available in the
- * current evaluation context, not {@code null}.
- * @param context the current context, not {@code null}.
+ * current evaluation configurationContext, not {@code null}.
+ * @param configurationContext the current configurationContext, not {@code null}.
*/
- public FilterContext(PropertyValue value, Map<String,PropertyValue> configEntries, ConfigurationContext context) {
+ public FilterContext(PropertyValue value, Map<String,PropertyValue> configEntries, ConfigurationContext configurationContext) {
Objects.requireNonNull(value, "Value must not be null.");
Objects.requireNonNull(configEntries, "Initial configuration entries must be not null.");
- Objects.requireNonNull(context, "Context must be not null.");
+ Objects.requireNonNull(configurationContext, "Context must be not null.");
this.singlePropertyScoped = false;
this.values = Collections.singletonList(Objects.requireNonNull(value));
- this.context = Objects.requireNonNull(context);
+ this.configurationContext = Objects.requireNonNull(configurationContext);
this.configEntries.putAll(configEntries);
this.configEntries = Collections.unmodifiableMap(this.configEntries);
}
@@ -64,14 +63,14 @@ public class FilterContext {
* Creates a new FilterContext, for filtering of a single createValue access
* using {@link Configuration#getProperties()}.
* @param value the createValue under evaluation, not {@code null}.
- * @param context the current context, not {@code null}.
+ * @param configurationContext the current configurationContext, not {@code null}.
*/
- public FilterContext(PropertyValue value, ConfigurationContext context) {
+ public FilterContext(PropertyValue value, ConfigurationContext configurationContext) {
Objects.requireNonNull(value, "Value must not be null.");
- Objects.requireNonNull(context, "Context must be not null.");
+ Objects.requireNonNull(configurationContext, "Context must be not null.");
this.singlePropertyScoped = true;
- this.context = Objects.requireNonNull(context);
+ this.configurationContext = Objects.requireNonNull(configurationContext);
this.values = Collections.singletonList(Objects.requireNonNull(value));
this.configEntries = Collections.unmodifiableMap(this.configEntries);
}
@@ -80,24 +79,24 @@ public class FilterContext {
* Creates a new FilterContext, for filtering of a single createValue access
* using {@link Configuration#getProperties()}.
* @param values the createValue under evaluation, not {@code null}.
- * @param context the current context, not {@code null}.
+ * @param configurationContext the current configurationContext, not {@code null}.
*/
- public FilterContext(List<PropertyValue> values, ConfigurationContext context) {
+ public FilterContext(List<PropertyValue> values, ConfigurationContext configurationContext) {
Objects.requireNonNull(values, "Value must not be null.");
- Objects.requireNonNull(context, "Context must be not null.");
+ Objects.requireNonNull(configurationContext, "Context must be not null.");
this.singlePropertyScoped = true;
- this.context = Objects.requireNonNull(context);
+ this.configurationContext = Objects.requireNonNull(configurationContext);
this.values = Collections.unmodifiableList(new ArrayList<>(values));
this.configEntries = Collections.unmodifiableMap(this.configEntries);
}
/**
- * Get the current context.
- * @return the current context, not {@code null}.
+ * Get the current configurationContext.
+ * @return the current configurationContext, not {@code null}.
*/
- public ConfigurationContext current(){
- return context;
+ public ConfigurationContext getConfigurationContext(){
+ return configurationContext;
}
/**
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ObjectValue.java b/code/api/src/main/java/org/apache/tamaya/spi/ObjectValue.java
index f7f6330..7d09eee 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/ObjectValue.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/ObjectValue.java
@@ -56,7 +56,7 @@ public final class ObjectValue extends PropertyValue{
* @return the createValue type, never null.
*/
public ValueType getValueType() {
- return ValueType.OBJECT;
+ return ValueType.MAP;
}
/**
@@ -305,7 +305,7 @@ public final class ObjectValue extends PropertyValue{
@Override
public String toString() {
- return "PropertyValue[OBJECT]{" +
+ return "PropertyValue[MAP]{" +
'\'' +getQualifiedKey() + '\'' +
(getValue()!=null?", createValue='" + getValue() + '\'':"") +
", size='" + getSize() + '\'' +
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java b/code/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java
index 9381f5e..048e4b2 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java
@@ -53,7 +53,7 @@ public class PropertyValue implements Serializable, Iterable<PropertyValue>{
*/
public enum ValueType{
/** A multi valued property value, which contains named child properties. */
- OBJECT,
+ MAP,
/** A multi valued property value, which contains unnamed child properties. */
ARRAY,
/** A simple value property. */
@@ -74,7 +74,7 @@ public class PropertyValue implements Serializable, Iterable<PropertyValue>{
Objects.requireNonNull(key, "Key must be given.");
Objects.requireNonNull(source, "Source must be given");
- return new PropertyValueBuilder(key, source);
+ return new PropertyValueBuilder(key, null).setSource(source);
}
/**
@@ -113,7 +113,7 @@ public class PropertyValue implements Serializable, Iterable<PropertyValue>{
}
/**
- * Creates a new createValue of type {@link ValueType#OBJECT}.
+ * Creates a new createValue of type {@link ValueType#MAP}.
* @param key the key, not {@code null}.
* @return a new createValue instance.
*/
@@ -569,8 +569,9 @@ public class PropertyValue implements Serializable, Iterable<PropertyValue>{
* Sets the new parent, used iternally when converting between value types.
* @param parent the parent value.
*/
- protected final void setParent(PropertyValue parent){
+ protected PropertyValue setParent(PropertyValue parent){
this.parent = parent;
+ return this;
}
diff --git a/code/api/src/test/java/org/apache/tamaya/ConfigurationTest.java b/code/api/src/test/java/org/apache/tamaya/ConfigurationTest.java
index 58811b4..d950c01 100644
--- a/code/api/src/test/java/org/apache/tamaya/ConfigurationTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/ConfigurationTest.java
@@ -19,9 +19,12 @@
package org.apache.tamaya;
import org.apache.tamaya.spi.ConfigurationBuilder;
+import org.apache.tamaya.spi.ConfigurationContext;
import org.junit.Test;
import org.mockito.Mockito;
+import java.math.BigDecimal;
+import java.util.Arrays;
import java.util.function.Function;
import java.util.function.UnaryOperator;
@@ -36,6 +39,26 @@ import static org.assertj.core.api.Assertions.*;
public class ConfigurationTest {
@Test
+ public void test_current() throws Exception {
+ assertThat(Configuration.current()).isNotNull();
+ }
+
+ @Test
+ public void test_current_classloader() throws Exception {
+ assertThat(Configuration.current(ClassLoader.getSystemClassLoader())).isNotNull();
+ }
+
+ @Test
+ public void test_release() throws Exception {
+ Configuration c1 = Configuration.current();
+ Configuration c2 = Configuration.current();
+ Configuration.releaseConfiguration(c2.getContext().getServiceContext().getClassLoader());
+ Configuration c3 = Configuration.current();
+ assertThat(c1).isSameAs(c2);
+ assertThat(c2).isNotSameAs(c3);
+ }
+
+ @Test
public void testget() throws Exception {
assertThat(Boolean.TRUE).isEqualTo(Configuration.current().get("booleanTrue", Boolean.class));
assertThat(Boolean.FALSE).isEqualTo(Configuration.current().get("booleanFalse", Boolean.class));
@@ -48,10 +71,33 @@ public class ConfigurationTest {
}
@Test
+ public void testget_Iterable() throws Exception {
+ assertThat(Configuration.current().get(Arrays.asList("String","foo"))).isEqualTo("aStringValue");
+ assertThat(Configuration.current().get(Arrays.asList("foo", "bar", "String"))).isEqualTo("aStringValue");
+ }
+
+ @Test
+ public void testget_Iterable_default() throws Exception {
+ assertThat("foo").isEqualTo(Configuration.current().getOrDefault(Arrays.asList("adasd","safsada"), "foo"));
+ assertThat("aStringValue").isEqualTo(Configuration.current().getOrDefault(Arrays.asList("foo1", "bar1", "String"), "foo"));
+ }
+
+ @Test
+ public void testget_Iterable_default_typed() throws Exception {
+ assertThat(25).isEqualTo(Configuration.current().getOrDefault(Arrays.asList("adasd","safsada"),Integer.class,25));
+ assertThat(BigDecimal.ZERO).isEqualTo(Configuration.current().getOrDefault(Arrays.asList("foo1", "bar1", "2.0"), BigDecimal.class, BigDecimal.ZERO));
+ }
+
+ @Test
+ public void testget_Iterable_with_Type() throws Exception {
+ assertThat(Boolean.TRUE).isEqualTo(Configuration.current().get(Arrays.asList("booleanTrue","booleanFalse"), Boolean.class));
+ assertThat(Boolean.TRUE).isEqualTo(Configuration.current().get(Arrays.asList("foo1", "bar1", "booleanTrue"), Boolean.class));
+ }
+
+ @Test
public void testGetBoolean() throws Exception {
assertThat(Configuration.current().get("booleanTrue", Boolean.class)).isTrue();
assertThat(Configuration.current().get("booleanFalse", Boolean.class)).isFalse();
- assertThat(Configuration.current().get("foorBar", Boolean.class)).isFalse();
}
@Test
@@ -133,4 +179,25 @@ public class ConfigurationTest {
ConfigurationBuilder result = Configuration.createConfigurationBuilder();
assertThat(result instanceof ConfigurationBuilder).isTrue();
}
+
+ @Test
+ public void testEmpty() {
+ Configuration c = Configuration.EMPTY;
+ assertThat(c).isNotNull();
+ assertThat(c.get("foo")).isNull();
+ assertThat(c.get("foo", Boolean.class)).isNull();
+ assertThat(c.get(Arrays.asList("foo", "bar"))).isNull();
+ assertThat(c.getOrDefault("foo", "")).isEqualTo("");
+ assertThat(c.getOrDefault("foo", Integer.class, 234)).isEqualTo(234);
+ assertThat(c.getOrDefault(Arrays.asList("foo", "bar"), "default")).isEqualTo("default");
+ assertThat(c.getOrDefault(Arrays.asList("foo", "bar"), Integer.class, 234)).isEqualTo(234);
+ assertThat(c.get(Arrays.asList("foo", "bar"), Integer.class)).isNull();
+ assertThat(c.getContext()).isEqualTo(ConfigurationContext.EMPTY);
+ assertThat(c.getOptional("kjhkjh")).isNotNull();
+ assertThat(c.getOptional("kjhkjh")).isNotPresent();
+ assertThat(c.getOptional("kjhkjh", Integer.class)).isNotNull();
+ assertThat(c.getOptional("kjhkjh", Integer.class)).isNotPresent();
+ assertThat(c.get("foo")).isNull();
+ assertThat(c.get("foo", Boolean.class)).isNull();
+ }
}
diff --git a/code/api/src/test/java/org/apache/tamaya/InvocationRecorder.java b/code/api/src/test/java/org/apache/tamaya/InvocationRecorder.java
new file mode 100644
index 0000000..a3ebdc7
--- /dev/null
+++ b/code/api/src/test/java/org/apache/tamaya/InvocationRecorder.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya;
+
+
+import org.junit.Assert;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class InvocationRecorder {
+
+ private List<Invocation> invocations = new ArrayList<>();
+
+ private Object record(Object instance, Method method, Object[] args) throws Throwable {
+ Invocation invocation = new Invocation(method.getName(), args);
+ this.invocations.add(invocation);
+ return method.invoke(instance, args);
+ }
+
+ public <T> T createProxy(Object instance, Class<T>... types) {
+ return (T) Proxy.newProxyInstance(
+ getClass().getClassLoader(), types,
+ (proxy,method,params) -> this.record(instance, method, params));
+ }
+
+ public void recordMethodCall(Object... params) {
+ Exception e = new Exception();
+ String methodName = e.getStackTrace()[1].getMethodName();
+ invocations.add(new Invocation(methodName, params));
+ }
+
+ public static final class Invocation{
+ public String methodName;
+ public Object[] params;
+
+ public Invocation(String methodName, Object[] params) {
+ this.methodName = methodName;
+ this.params = params;
+ }
+ }
+
+ public List<Invocation> getInvocations(){
+ return invocations;
+ }
+
+ public void assertInvocation(String method, Object... params){
+ for(Invocation invocation:invocations){
+ if(invocation.methodName.equals(method)){
+ if(Arrays.equals(invocation.params, params)){
+ return;
+ }
+ }
+ }
+ Assert.fail("No such invocation: "+method + Arrays.toString(params));
+ }
+}
diff --git a/code/api/src/test/java/org/apache/tamaya/TestConfiguration.java b/code/api/src/test/java/org/apache/tamaya/TestConfiguration.java
index cd6eeaf..d06753a 100644
--- a/code/api/src/test/java/org/apache/tamaya/TestConfiguration.java
+++ b/code/api/src/test/java/org/apache/tamaya/TestConfiguration.java
@@ -49,9 +49,7 @@ public class TestConfiguration implements Configuration {
VALUES.put("String", "aStringValue");
}
- @SuppressWarnings("unchecked")
- @Override
- public <T> T get(String key, TypeLiteral<T> type) {
+ private <T> T getInternal(String key, TypeLiteral<T> type) {
if (type.getRawType().equals(Long.class)) {
return (T) VALUES.get(key);
} else if (type.getRawType().equals(Integer.class)) {
@@ -67,18 +65,31 @@ public class TestConfiguration implements Configuration {
} else if (type.getRawType().equals(Boolean.class)) {
if ("booleanTrue".equals(key)) {
return (T) Boolean.TRUE;
- } else {
+ } else if ("booleanFalse".equals(key)) {
return (T) Boolean.FALSE;
}
} else if (type.getRawType().equals(String.class)) {
- return (T) VALUES.get(key);
+ Object value = VALUES.get(key);
+ if(value!=null){
+ return (T)String.valueOf(value);
+ }
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T get(String key, TypeLiteral<T> type) {
+ T t = getInternal(key, type);
+ if(t==null) {
+ throw new ConfigException("No such property: " + key);
}
- throw new ConfigException("No such property: " + key);
+ return t;
}
@Override
public <T> T getOrDefault(String key, TypeLiteral<T> type, T defaultValue) {
- T val = get(key, type);
+ T val = getInternal(key, type);
if (val == null) {
return defaultValue;
}
diff --git a/code/api/src/test/java/org/apache/tamaya/TestConfigurationProvider.java b/code/api/src/test/java/org/apache/tamaya/TestConfigurationProvider.java
index e5622e4..fae3c53 100644
--- a/code/api/src/test/java/org/apache/tamaya/TestConfigurationProvider.java
+++ b/code/api/src/test/java/org/apache/tamaya/TestConfigurationProvider.java
@@ -57,6 +57,8 @@ public class TestConfigurationProvider implements ConfigurationProviderSpi {
@Override
public Configuration releaseConfiguration(ClassLoader classloader) {
- return null;
+ Configuration prev = config;
+ config = new TestConfiguration();
+ return prev;
}
}
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/ConversionContextTest.java b/code/api/src/test/java/org/apache/tamaya/spi/ConversionContextTest.java
index 620b2b6..7e6110e 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/ConversionContextTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/ConversionContextTest.java
@@ -26,9 +26,11 @@ import org.junit.Test;
import java.net.InetAddress;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.*;
+import static org.junit.Assert.*;
/**
* Tests for {@link ConversionContext}, created by atsticks on 20.08.16.
@@ -97,6 +99,58 @@ public class ConversionContextTest {
assertThat(ctx.toString()).isEqualTo("ConversionContext{configuration=null, key='toString', targetType=TypeLiteral{type=interface java.util.List}, annotatedElement=null, supportedFormats=[0.0.0.0/nnn (MyConverter), x.x.x.x/yyy (MyConverter)]}");
}
+ @Test
+ public void testGetSetValues_Ellipse(){
+ ConversionContext ctx = new ConversionContext.Builder("toString", TypeLiteral.of(List.class))
+ .addSupportedFormats(MyConverter.class, "0.0.0.0/nnn", "x.x.x.x/yyy")
+ .setValues(PropertyValue.createValue("test", "value")).build();
+ assertNotNull(ctx.getValues());
+ assertEquals(ctx.getValues().size(), 1);
+ assertEquals("value", ctx.getValues().get(0).getValue());
+ assertEquals("test", ctx.getValues().get(0).getKey());
+ }
+
+ @Test
+ public void testGetSetValues_List(){
+ ConversionContext ctx = new ConversionContext.Builder("toString", TypeLiteral.of(List.class))
+ .addSupportedFormats(MyConverter.class, "0.0.0.0/nnn", "x.x.x.x/yyy")
+ .setValues(Collections.singletonList(PropertyValue.createValue("test", "value"))).build();
+ assertNotNull(ctx.getValues());
+ assertEquals(ctx.getValues().size(), 1);
+ assertEquals("value", ctx.getValues().get(0).getValue());
+ assertEquals("test", ctx.getValues().get(0).getKey());
+ }
+
+ @Test
+ public void testGetConfigurationContext(){
+ ConversionContext ctx = new ConversionContext.Builder("toString", TypeLiteral.of(List.class))
+ .addSupportedFormats(MyConverter.class, "0.0.0.0/nnn", "x.x.x.x/yyy")
+ .setValues(PropertyValue.createValue("test", "value")).build();
+ assertNotNull(ctx.getConfigurationContext());
+ }
+
+ @Test
+ public void testGetMeta(){
+ ConversionContext ctx = new ConversionContext.Builder("test", TypeLiteral.of(List.class))
+ .addSupportedFormats(MyConverter.class, "0.0.0.0/nnn", "x.x.x.x/yyy")
+ .setValues(PropertyValue.createValue("test", "value")
+ .setMeta("meta1", "val1").setMeta("meta2", "val2")).build();
+ assertNotNull(ctx.getMeta());
+ assertFalse(ctx.getMeta().isEmpty());
+ assertEquals(2, ctx.getMeta().size());
+ }
+
+ @Test
+ public void testBuilderToString() {
+ ConversionContext.Builder b = new ConversionContext.Builder("toString", TypeLiteral.of(List.class))
+ .addSupportedFormats(MyConverter.class, "0.0.0.0/nnn", "x.x.x.x/yyy");
+ assertNotNull(b.toString());
+ assertTrue(b.toString().contains("targetType=TypeLiteral{type=interface java.util.List}"));
+ assertTrue(b.toString().contains("supportedFormats=[0.0.0.0/nnn (MyConverter), x.x.x.x/yyy (MyConverter)]"));
+ assertTrue(b.toString().contains("annotatedElement"));
+ assertTrue(b.toString().contains("key='toString'"));
+ assertTrue(b.toString().contains("Builder"));
+ }
private static final AnnotatedElement MyAnnotatedElement = new AnnotatedElement() {
@Override
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/FilterContextTest.java b/code/api/src/test/java/org/apache/tamaya/spi/FilterContextTest.java
index 1b74f0b..24fed66 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/FilterContextTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/FilterContextTest.java
@@ -37,6 +37,16 @@ import static org.junit.Assert.assertNotNull;
*/
public class FilterContextTest {
+ @Test
+ public void constructorWithContext() {
+ PropertyValue val = new PropertyValue(null, "");
+ FilterContext ctx = new FilterContext(val, ConfigurationContext.EMPTY);
+ assertEquals(val, ctx.getProperty());
+ assertEquals(ConfigurationContext.EMPTY, ctx.getConfigurationContext());
+ assertNotNull(ctx.getConfigEntries());
+ assertEquals(1, ctx.getAllValues().size());
+ }
+
// @Test
// public void setNullContext() {
// FilterContext.set(null);
diff --git a/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueTest.java b/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueTest.java
index 035c458..6317714 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueTest.java
@@ -43,6 +43,14 @@ public class PropertyValueTest {
}
@Test
+ public void builder() throws Exception {
+ PropertyValueBuilder b = PropertyValue.builder("a", "b");
+ assertNotNull(b);
+ assertEquals("a", b.key);
+ assertEquals("b", b.source);
+ }
+
+ @Test
public void testOf(){
assertThat(PropertyValue.of("k", "v", "testGetKey")).isNotNull();
}
@@ -116,6 +124,41 @@ public class PropertyValueTest {
}
@Test
+ public void testMap() throws Exception {
+ Map<String, String> map = new HashMap<>();
+ map.put("a", "b");
+ map.put("b", "c");
+ Map<String, PropertyValue> result = PropertyValue.map(map, "source");
+ assertNotNull(result);
+ assertEquals(map.size(), result.size());
+ for(PropertyValue pv:result.values()){
+ assertEquals("source", pv.getMetaEntry("source"));
+ }
+ assertEquals("b", map.get("a"));
+ assertEquals("c", map.get("b"));
+ }
+
+ @Test
+ public void testMap_WithMeta() throws Exception {
+ Map<String, String> map = new HashMap<>();
+ map.put("a", "b");
+ map.put("b", "c");
+ Map<String, String> meta = new HashMap<>();
+ meta.put("m1", "m1v");
+ meta.put("m2", "m2v");
+ Map<String, PropertyValue> result = PropertyValue.map(map, "source", meta);
+ assertNotNull(result);
+ assertEquals(map.size(), result.size());
+ for(PropertyValue pv:result.values()){
+ assertEquals("source", pv.getMetaEntry("source"));
+ assertEquals("m1v", pv.getMeta("m1"));
+ assertEquals("m2v", pv.getMeta("m2"));
+ }
+ assertEquals("b", map.get("a"));
+ assertEquals("c", map.get("b"));
+ }
+
+ @Test
public void testHashCode(){
assertThat(PropertyValue.of("k", "v", "testGetKey").hashCode()).isEqualTo(PropertyValue.of("k", "v", "testGetKey").hashCode());
assertThat(PropertyValue.of("k", "v", "testGetKey").hashCode()).isNotSameAs(PropertyValue.of("k1", "v", "testGetKey").hashCode());
@@ -260,6 +303,39 @@ public class PropertyValueTest {
}
@Test
+ public void isImmutable() {
+ PropertyValue n = PropertyValue.createValue("", "");
+ assertFalse(n.isImmutable());
+ n.immutable();
+ assertTrue(n.isImmutable());
+ assertFalse(n.mutable().isImmutable());
+ }
+
+ @Test
+ public void isRoot() {
+ PropertyValue n = PropertyValue.createValue("", "");
+ assertTrue(n.isRoot());
+ n = PropertyValue.createValue("", "").setParent(n);
+ assertFalse(n.isRoot());
+ }
+
+ @Test(expected=IllegalStateException.class)
+ public void checkImmutableChangeThrowsExceotion() {
+ PropertyValue n = PropertyValue.createValue("", "");
+ n.immutable();
+ n.setValue("jhgjg");
+ }
+
+ @Test
+ public void checkMutable() {
+ PropertyValue n = PropertyValue.createValue("", "");
+ n.immutable();
+ n = n.mutable();
+ n.setValue("jhgjg");
+ assertEquals("jhgjg", n.getValue());
+ }
+
+ @Test
public void getParent() {
ObjectValue n = PropertyValue.createObject("");
assertNull(n.getParent());
@@ -268,6 +344,53 @@ public class PropertyValueTest {
assertNotNull(n.getField("b").getParent());
}
+ @Test
+ public void size(){
+ PropertyValue n = PropertyValue.createValue("key", "");
+ assertEquals(0, n.getSize());
+ assertFalse(n.iterator().hasNext());
+ }
+
+ @Test
+ public void setValue() {
+ PropertyValue n = PropertyValue.createValue("key", "");
+ assertEquals("", n.getValue());
+ n.setValue("jhgjg");
+ assertEquals("jhgjg", n.getValue());
+ }
+
+ @Test
+ public void setKey() {
+ PropertyValue n = PropertyValue.createValue("key", "");
+ assertEquals("key", n.getKey());
+ n.setKey("jhgjg");
+ assertEquals("jhgjg", n.getKey());
+ }
+
+ @Test
+ public void toBuilder() {
+ PropertyValue n = PropertyValue.createValue("key", "");
+ assertNotNull(n.toBuilder());
+ }
+
+ @Test
+ public void toPropertyValue() {
+ PropertyValue n = PropertyValue.createValue("key", "");
+ assertTrue(n == n.toPropertyValue());
+ }
+
+ @Test
+ public void toObjectValue() {
+ PropertyValue n = PropertyValue.createValue("key", "");
+ assertNotNull(n.toObjectValue());
+ }
+
+ @Test
+ public void toListValue() {
+ PropertyValue n = PropertyValue.createValue("key", "");
+ assertNotNull(n.toListValue());
+ }
+
// @Test
// public void getChildren_Filtered() {
// PropertyValue n = PropertyValue.createObject();
@@ -345,7 +468,7 @@ public class PropertyValueTest {
n.setField("a", "aVal");
n.setField("b.b2.b3", "b3Val");
n.setFieldList("c").addValue("cVal1");
- assertEquals("PropertyValue[OBJECT]{'', size='3'}", n.toString());
+ assertEquals("PropertyValue[MAP]{'', size='3'}", n.toString());
}
}
\ No newline at end of file
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilder.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilder.java
index 1276daa..95c4d50 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilder.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationBuilder.java
@@ -122,14 +122,14 @@ public class DefaultConfigurationBuilder implements ConfigurationBuilder {
}
@Override
- public ConfigurationBuilder setMeta(String key, String value){
- this.metaDataProvider.setMeta(key, value);
+ public ConfigurationBuilder setMeta(String property, String key, String value){
+ this.metaDataProvider.setMeta(property, key, value);
return this;
}
@Override
- public ConfigurationBuilder setMeta(Map<String, String> metaData){
- this.metaDataProvider.setMeta(metaData);
+ public ConfigurationBuilder setMeta(String property, Map<String, String> metaData){
+ this.metaDataProvider.setMeta(property, metaData);
return this;
}
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java
index a6d9612..1c58419 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java
@@ -103,8 +103,8 @@ public class DefaultConfigurationContext implements ConfigurationContext {
@Override
- public Map<String,String> getMetaData() {
- return metaDataProvider.getMetaData();
+ public Map<String,String> getMetaData(String key) {
+ return metaDataProvider.getMetaData(key);
}
@Override
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultMetaDataProvider.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultMetaDataProvider.java
index cc43360..c1c5be1 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultMetaDataProvider.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultMetaDataProvider.java
@@ -25,19 +25,21 @@ import org.apache.tamaya.spi.PropertyValue;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.logging.Logger;
/**
* Default metadata provider implementation, which searches for all kind of entries
- * starting with {@code [META]}. All matching key/values are added to the
- * meta data map, hereby reoving the key prefix.
+ * formatted as {@code [(META)key].metaKey=metaValue}. All matching key/values are added to the
+ * meta data map for the given key as {@code metaKey=metaValue} meta entries.
*/
public class DefaultMetaDataProvider implements MetadataProvider {
- private static final String META_PREFIX = "[META]";
+ private static final Logger LOG = Logger.getLogger(DefaultMetaDataProvider.class.getName());
+ private static final String META_PREFIX = "[(META)";
private ConfigurationContext context;
- private Map<String, String> additionalProperties = new ConcurrentHashMap<>();
+ private Map<String, Map<String, String>> additionalProperties = new ConcurrentHashMap<>();
private AtomicLong lastHash = new AtomicLong();
- private Map<String, String> propertyCache = new HashMap<>();
+ private Map<String, Map<String, String>> propertyCache = new HashMap<>();
@Override
public MetadataProvider init(ConfigurationContext context) {
@@ -46,50 +48,88 @@ public class DefaultMetaDataProvider implements MetadataProvider {
}
@Override
- public Map<String, String> getMetaData() {
+ public Map<String, String> getMetaData(String property) {
long configHash = Objects.hash(context.getPropertySources().toArray());
if(configHash!=lastHash.get()){
lastHash.set(configHash);
propertyCache = loadMetaProperties();
}
- return propertyCache;
+ Map<String, String> meta = propertyCache.get(property);
+ if(meta==null){
+ return Collections.emptyMap();
+ }
+ return Collections.unmodifiableMap(meta);
}
- private Map<String, String> loadMetaProperties() {
- Map<String, String> result = new HashMap<>();
+ private Map<String, Map<String, String> > loadMetaProperties() {
+ Map<String, Map<String, String> > result = new HashMap<>();
for(PropertySource ps:context.getPropertySources()){
ps.getProperties().values().forEach(v -> {
- loadMetaData(v, result);
+ Map<String, String> meta = result.computeIfAbsent(v.getKey(), k -> new HashMap<>());
+ meta.putAll(v.getMeta());
+ if(v.getQualifiedKey().toUpperCase(Locale.ENGLISH).startsWith(META_PREFIX)){
+ loadExplicitMetadata(v);
+ }
});
}
- result.putAll(additionalProperties);
+ // Override with manual properties
+ for(Map.Entry<String,Map<String, String>> en: additionalProperties.entrySet()) {
+ Map<String, String> meta = result.get(en.getKey());
+ meta.putAll(en.getValue());
+ }
return Collections.unmodifiableMap(result);
}
/**
- * Iterates all values and it's children and adds all meta-entries found.
- * @param value the starting value.
- * @param result the result map to add/override values found.
+ * Iterates all values and it's children and adds all meta-entries found in the configuration
+ * (entries starting with {@code [(META)}).
*/
- private void loadMetaData(PropertyValue value, Map<String, String> result) {
+ private void loadExplicitMetadata(PropertyValue value) {
String key = value.getQualifiedKey();
- if(key.toUpperCase(Locale.ENGLISH).startsWith(META_PREFIX)){
- if(value.getValue()!=null){
- result.put(key.substring(META_PREFIX.length()), value.getValue());
+ if(value.getValue()!=null){
+ String[] keyValue = getMetaKeys(key);
+ if(keyValue==null){
+ LOG.warning("Encountered invalid META-ENTRY: " + key);
+ }else {
+ Map<String, String> meta = additionalProperties.computeIfAbsent(keyValue[0], k -> new HashMap<>());
+ meta.put(keyValue[1], value.getValue());
}
- value.iterator().forEachRemaining(v -> loadMetaData(v, result));
}
}
+ private String[] getMetaKeys(String fullKey) {
+ String strippedKey = fullKey.substring(META_PREFIX.length());
+ int index = strippedKey.lastIndexOf(']');
+ if(index<0){
+ // invalid meta key
+ return null;
+ }
+ String[] result = new String[2];
+ result[0] = strippedKey.substring(0,index);
+ result[1] = strippedKey.substring(index+1);
+ if(result[1].startsWith(".")){
+ result[1] = result[1].substring(1);
+ }
+ return result;
+ }
+
+ @Override
+ public MetadataProvider setMeta(String property, String key, String value) {
+ additionalProperties.computeIfAbsent(property, p -> new HashMap<>())
+ .put(key, value);
+ return this;
+ }
+
@Override
- public MetadataProvider setMeta(String key, String value) {
- additionalProperties.put(key, value);
+ public MetadataProvider setMeta(String property, Map<String, String> metaData) {
+ additionalProperties.computeIfAbsent(property, p -> new HashMap<>())
+ .putAll(metaData);
return this;
}
@Override
- public MetadataProvider setMeta(Map<String, String> metaData) {
- additionalProperties.putAll(metaData);
+ public MetadataProvider reset(String property) {
+ additionalProperties.remove(property);
return this;
}
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/MetadataProvider.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/MetadataProvider.java
index b5040fa..9f80dec 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/MetadataProvider.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/MetadataProvider.java
@@ -25,7 +25,7 @@ import java.util.Map;
/**
* This interface allows to plugin different metadata mechanism. The default implementation
* does load metadata information along the same property sources hierarchy as configuration.
- * MetaData entries are identified by a {@code [META]} prefix. Alternate implementations can
+ * MetaData entries are in the format {@code [(META)key].metakey=metavalue}. Alternate implementations can
* choose whatever is appropriate, including loading metadata from external sources.
*/
public interface MetadataProvider {
@@ -39,31 +39,42 @@ public interface MetadataProvider {
MetadataProvider init(ConfigurationContext context);
/**
- * Access the current metadata for the given configuration context. The MetaData will be
- * accessible from {@link ConfigurationContext#getMetaData()}. Note that the metadata must not
+ * Access the current metadata for the given configuration context and key. The MetaData will be
+ * accessible from {@link ConfigurationContext#getMetaData(String)}. Note that the metadata must not
* to be cached by it's consumers, so caching/optimazitation is delegated to this implementation.
+ * @param key the property key, not null.
* @return the (immutable) metadata of this configuration context.
*/
- Map<String,String> getMetaData();
+ Map<String,String> getMetaData(String key);
/**
* Adds additional metadata. This metadata entries typically override all entries
* from alternate sources.
*
- * @param key the key, not null.
- * @param value the value, not null.
+ * @param property the property key, not null.
+ * @param key the metadata key, not null.
+ * @param value the metadata value, not null.
* @return this instance, for chaining.
*/
- MetadataProvider setMeta(String key, String value);
+ MetadataProvider setMeta(String property, String key, String value);
/**
* Adds additional metadata. This metadata entries typically override all entries
* from alternate sources.
*
+ * @param property the property key, not null.
* @param metaData the metadata to set/replace.
* @return this instance, for chaining.
*/
- MetadataProvider setMeta(Map<String, String> metaData);
+ MetadataProvider setMeta(String property, Map<String, String> metaData);
+
+ /**
+ * Resets metadata for a property, which means it reloads metadata based on the given context and
+ *
+ * param property the property key, not null.
+ * @return this instance, for chaining.
+ */
+ MetadataProvider reset(String property);
/**
* Resets this instance, which means it reloads metadata based on the given context and
diff --git a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java
index 8df6a21..c6943bf 100644
--- a/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java
+++ b/code/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java
@@ -21,7 +21,6 @@ package org.apache.tamaya.spisupport;
import org.apache.tamaya.spi.*;
import java.util.*;
-import java.util.logging.Filter;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -103,7 +102,7 @@ public final class PropertyFiltering{
for (int i = 0; i < MAX_FILTER_LOOPS; i++) {
int changes = 0;
- for (PropertyFilter filter : context.current().getPropertyFilters()) {
+ for (PropertyFilter filter : context.getConfigurationContext().getPropertyFilters()) {
String value = filteredValue!=null?filteredValue.getValue():null;
filteredValue = filter.filterProperty(filteredValue, context);
String newValue = filteredValue!=null?filteredValue.getValue():null;
diff --git a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/MockedConfigurationContext.java b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/MockedConfigurationContext.java
index 02f1ede..0f941bf 100644
--- a/code/spi-support/src/test/java/org/apache/tamaya/spisupport/MockedConfigurationContext.java
+++ b/code/spi-support/src/test/java/org/apache/tamaya/spisupport/MockedConfigurationContext.java
@@ -40,7 +40,7 @@ public class MockedConfigurationContext implements ConfigurationContext {
}
@Override
- public Map<String, String> getMetaData() {
+ public Map<String, String> getMetaData(String key) {
return metaData;
}