- Adapted OSGI deps. - Defined clear resolvability of packages, removing redundancies. - Refactored parts of TypeLiteral into util class.
Signed-off-by: Anatole Tresch <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/09472084 Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/09472084 Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/09472084 Branch: refs/heads/configjsr Commit: 0947208464bc5ba32c62525a541a61c497fe9a9e Parents: 0be1acb Author: Anatole Tresch <[email protected]> Authored: Mon Feb 5 01:10:12 2018 +0100 Committer: Anatole Tresch <[email protected]> Committed: Mon Feb 5 01:10:12 2018 +0100 ---------------------------------------------------------------------- code/base/bnd.bnd | 3 +- .../org/apache/tamaya/base/ConfigContext.java | 156 +++++++ .../tamaya/base/ConfigContextSupplier.java | 42 ++ .../org/apache/tamaya/base/ConfigValue.java | 209 ++++++++++ .../apache/tamaya/base/ConfigValueBuilder.java | 179 ++++++++ .../base/ConfigValueCombinationPolicy.java | 71 ++++ .../org/apache/tamaya/base/DefaultConfig.java | 4 +- .../tamaya/base/DefaultConfigBuilder.java | 4 +- .../tamaya/base/DefaultServiceContext.java | 2 - .../org/apache/tamaya/base/Experimental.java | 32 ++ .../org/apache/tamaya/base/ServiceContext.java | 147 +++++++ .../tamaya/base/ServiceContextManager.java | 118 ++++++ .../apache/tamaya/base/TamayaConfigBuilder.java | 333 +++++++++++++++ .../java/org/apache/tamaya/base/TypeUtils.java | 136 +++++++ .../base/configsource/ConfigSourceManager.java | 5 +- .../JavaConfigurationConfigSource.java | 2 +- .../PropertiesResourceConfigSource.java | 2 +- .../tamaya/base/convert/ConversionContext.java | 2 - .../tamaya/base/convert/ConverterManager.java | 7 +- .../org/apache/tamaya/base/filter/Filter.java | 51 +++ .../tamaya/base/filter/FilterComparator.java | 2 - .../tamaya/base/filter/FilterContext.java | 2 - .../tamaya/base/filter/FilterManager.java | 6 +- .../tamaya/base/filter/RegexPropertyFilter.java | 3 - .../org/apache/tamaya/spi/ConfigContext.java | 154 ------- .../tamaya/spi/ConfigContextSupplier.java | 47 --- .../java/org/apache/tamaya/spi/ConfigValue.java | 209 ---------- .../apache/tamaya/spi/ConfigValueBuilder.java | 179 -------- .../spi/ConfigValueCombinationPolicy.java | 71 ---- .../org/apache/tamaya/spi/Experimental.java | 32 -- .../main/java/org/apache/tamaya/spi/Filter.java | 51 --- .../org/apache/tamaya/spi/ServiceContext.java | 147 ------- .../tamaya/spi/ServiceContextManager.java | 118 ------ .../tamaya/spi/StandaloneConfigContext.java | 292 ------------- .../spi/StandaloneConfigContextBuilder.java | 407 ------------------- .../apache/tamaya/spi/TamayaConfigBuilder.java | 332 --------------- .../java/org/apache/tamaya/spi/TypeLiteral.java | 225 ---------- .../org/apache/tamaya/spi/package-info.java | 23 -- .../tamaya/base/DefaultConfigBuilderTest.java | 10 +- .../apache/tamaya/base/DefaultConfigTest.java | 1 - .../tamaya/base/TestConfigurationProvider.java | 5 +- .../base/configsource/EnumConverterTest.java | 1 - .../tamaya/base/convert/EnumConverterTest.java | 3 - .../base/services/DefaultServiceContext.java | 2 +- .../tamaya/filter/FilterComparatorTest.java | 3 +- .../org.apache.tamaya.base.ServiceContext | 19 + .../org.apache.tamaya.spi.ServiceContext | 19 - code/compat/bnd.bnd | 3 +- .../java/org/apache/tamaya/Configuration.java | 10 +- .../apache/tamaya/ConfigurationProvider.java | 1 + .../apache/tamaya/spi/ConfigurationBuilder.java | 1 + .../apache/tamaya/spi/ConfigurationContext.java | 2 + .../tamaya/spi/ConfigurationContextBuilder.java | 2 + .../org/apache/tamaya/spi/FilterContext.java | 1 + .../org/apache/tamaya/spi/PropertyFilter.java | 3 +- .../java/org/apache/tamaya/spi/TypeLiteral.java | 225 ++++++++++ .../tamaya/spisupport/DefaultConfiguration.java | 2 +- .../spisupport/DefaultConfigurationBuilder.java | 1 + .../spisupport/DefaultConfigurationContext.java | 1 + .../DefaultConfigurationContextBuilder.java | 1 + .../spisupport/PropertyConverterManager.java | 2 +- .../JavaConfigurationPropertySource.java | 2 +- .../PropertiesResourcePropertySource.java | 2 +- .../org/apache/tamaya/TestConfiguration.java | 2 +- .../java/org/apache/tamaya/TypeLiteralTest.java | 14 +- .../tamaya/spi/ConversionContextTest.java | 1 + .../apache/tamaya/spi/FilterContextTest.java | 2 +- .../tamaya/spi/ServiceContextManagerTest.java | 2 + .../apache/tamaya/spi/ServiceContextTest.java | 2 + .../apache/tamaya/spi/TestServiceContext.java | 4 +- .../org.apache.tamaya.base.ServiceContext | 19 + .../org.apache.tamaya.spi.ServiceContext | 19 - code/core/bnd.bnd | 3 +- .../org/apache/tamaya/core/OSGIActivator.java | 4 +- .../apache/tamaya/core/OSGIServiceContext.java | 2 +- .../core/TamayaConfigProviderResolver.java | 5 +- .../tamaya/core/converters/ConvertQuery.java | 4 +- .../org.apache.tamaya.base.ServiceContext | 19 + .../org.apache.tamaya.spi.ConfigValueEvaluator | 19 - .../org.apache.tamaya.spi.ServiceContext | 19 - ...pache.tamaya.spisupport.ConfigValueEvaluator | 19 + .../core/TamayaConfigProviderResolverTest.java | 4 +- .../apache/tamaya/core/testdata/TestFilter.java | 3 +- .../core/testdata/TestRemovingFilter.java | 3 +- .../org.apache.tamaya.base.filter.Filter | 20 + .../services/org.apache.tamaya.spi.Filter | 20 - 86 files changed, 1867 insertions(+), 2469 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/bnd.bnd ---------------------------------------------------------------------- diff --git a/code/base/bnd.bnd b/code/base/bnd.bnd index cc6472d..41ce9eb 100644 --- a/code/base/bnd.bnd +++ b/code/base/bnd.bnd @@ -23,8 +23,7 @@ Export-Package: \ org.apache.tamaya.base,\ org.apache.tamaya.base.configsource,\ org.apache.tamaya.base.convert,\ - org.apache.tamaya.base.filter,\ - org.apache.tamaya.spi + org.apache.tamaya.base.filter Import-Package: \ javax.config,\ javax.config.spi,\ http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/ConfigContext.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/ConfigContext.java b/code/base/src/main/java/org/apache/tamaya/base/ConfigContext.java new file mode 100644 index 0000000..eb6a16d --- /dev/null +++ b/code/base/src/main/java/org/apache/tamaya/base/ConfigContext.java @@ -0,0 +1,156 @@ +/* + * 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.base; + +import org.apache.tamaya.base.filter.Filter; + +import javax.config.spi.ConfigSource; +import javax.config.spi.Converter; +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * Central SPI for programmatically dealing with the setup of the configuration system. + * This includes adding and enlisting {@link javax.config.spi.ConfigSource}s, + * managing {@link javax.config.spi.Converter}s, ConfigFilters, etc. + */ +public interface ConfigContext { + + /** + * This method returns the current list of registered PropertySources ordered via their ordinal. + * PropertySources with a lower ordinal come last. The PropertySource with the + * highest ordinal comes first. + * If two PropertySources have the same ordinal number they will get sorted + * using their class name just to ensure the user at least gets the same ordering + * after a JVM restart, hereby names before are added last. + * PropertySources are loaded when this method is called the first time, which basically is + * when the first time configuration is accessed. + * + * @return a sorted list of registered PropertySources. The returned list need not be modifiable + */ + List<ConfigSource> getSources(); + +// /** +// * Access a {@link ConfigSource} using its (unique) name. +// * @param name the propoerty source's name, not {@code null}. +// * @return the propoerty source found, or {@code null}. +// */ +// default ConfigSource getSource(String name) { +// for(ConfigSource ps: getSources()){ +// if(name.equals(ps.getName())){ +// return ps; +// } +// } +// return null; +// } + + /** + * Access the current PropertyFilter instances. + * @return the list of registered PropertyFilters, never null. + */ + List<Filter> getFilters(); + + /** + * <p> + * This method returns the Map of registered PropertyConverters + * per type. + * The List for each type is ordered via their {@link javax.annotation.Priority} and + * cladd name. + * </p> + * + * <p>A simplified scenario could be like:</p> + * <pre> + * { + * Date.class -> {StandardDateConverter, TimezoneDateConverter, MyCustomDateConverter } + * Boolean.class -> {StandardBooleanConverter, FrenchBooleanConverter} + * Integer.class -> {DynamicDefaultConverter} + * } + * </pre> + * + * @return map with sorted list of registered PropertySources per type. + */ + Map<Type, List<Converter>> getConverters(); + + /** + * <p> + * This method returns the registered PropertyConverters for a given type. + * The List for each type is ordered via their {@link javax.annotation.Priority}. + * </p> + * + * <p> + * PropertyConverters with a higher Priority come first. The PropertyConverter with the + * lowest Priority comes last. + * If two PropertyConverter have the same ordinal number they will get sorted + * using their class name just to ensure the user at least gets the same ordering + * after a JVM restart. + * </p> + * + * <p> + * Additionally if a PropertyProvider is accessed, which is not registered the implementation + * should try to figure out, if there could be a default implementation as follows:</p> + * <ol> + * <li>Look for static factory methods: {@code of(String), valueOf(String), getInstance(String), + * instanceOf(String), fomr(String)}</li> + * <li>Look for a matching constructor: {@code T(String)}.</li> + * </ol> + * + * <p> + * If a correspoding factory method or constructor could be found, a corresponding + * PropertyConverter should be created and registered automatically for the given + * type. + * </p> + * + * <p> The scenario could be like:</p> + * + * <pre> + * { + * Date.class -> {MyCustomDateConverter,StandardDateConverter, TimezoneDateConverter} + * Boolean.class -> {StandardBooleanConverter, FrenchBooleanConverter} + * Integer.class -> {DynamicDefaultConverter} + * } + * </pre> + * + * <p> + * The converters returned for a type should be used as a chain, whereas the result of the + * first converters that is able to convert the configured value, is taken as the chain's result. + * No more converters are called after a converters has successfully converted the input into + * the required target type. + * </p> + * + * @param type type of the desired converters + * @return a sorted list of registered PropertySources per type, or null. + */ + default List<Converter> getConverters(Type type){ + return Optional.ofNullable(getConverters().get(type)).orElse(Collections.emptyList()); + } + + /** + * Access the {@link ConfigValueCombinationPolicy} used to evaluate the final + * property values. + * @return the {@link ConfigValueCombinationPolicy} used, never null. + */ + default ConfigValueCombinationPolicy getConfigValueCombinationPolicy(){ + return ConfigValueCombinationPolicy.DEFAULT_OVERRIDING_POLICY; + } + +} + http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/ConfigContextSupplier.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/ConfigContextSupplier.java b/code/base/src/main/java/org/apache/tamaya/base/ConfigContextSupplier.java new file mode 100644 index 0000000..9e3be69 --- /dev/null +++ b/code/base/src/main/java/org/apache/tamaya/base/ConfigContextSupplier.java @@ -0,0 +1,42 @@ +/* + * 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.base; + +import javax.config.spi.ConfigSource; +import javax.config.spi.Converter; + +/** + * Central SPI for programmatically dealing with the setup of the configuration system. + * This includes adding and enlisting {@link ConfigSource}s, + * managing {@link Converter}s, ConfigFilters, etc. + */ +@FunctionalInterface +public interface ConfigContextSupplier { + + /** + * Make an instance of a configuration accessible for use with Apache Tamaya specific extensions. + * In most cases it should be sufficient to implement this interfance on your implementation of + * {@link javax.config.Config}. + * + * @return the corresponding configuration context, never null. + */ + ConfigContext getConfigContext(); + +} + http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/ConfigValue.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/ConfigValue.java b/code/base/src/main/java/org/apache/tamaya/base/ConfigValue.java new file mode 100644 index 0000000..697f79a --- /dev/null +++ b/code/base/src/main/java/org/apache/tamaya/base/ConfigValue.java @@ -0,0 +1,209 @@ +/* + * 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.base; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Class modelling the result of a request for a property value. A property value is basically identified by its key. + * There might be reasons, where one want to further analyze, which PropertySources provided a value and which not, so + * it is possible to create a PropertyValue with a null value. Nevertheless in all cases the provider source (typically + * the name of the PropertySource) must be set. + */ +public final class ConfigValue implements Serializable{ + private static final long serialVersionUID = 1L; + /** The requested key. */ + private String key; + /** The value. */ + private String value; + /** Additional metadata provided by the provider. */ + private String metaEntry; + + ConfigValue(ConfigValueBuilder builder){ + this.key = Objects.requireNonNull(builder.key); + this.value = Objects.requireNonNull(builder.value); + this.metaEntry = builder.metaEntry; + } + + /** + * Creates a new instance + * @param key the key, not {@code null}. + * @param value the value, not {@code null}. + * @param metaEntry the source, typically the name of the {@link javax.config.spi.ConfigSource} providing + * the value, not {@code null}. + */ + private ConfigValue(String key, String value, String metaEntry){ + this.key = Objects.requireNonNull(key, "Key is required."); + this.value = Objects.requireNonNull(value, "Value is required."); + this.metaEntry = metaEntry; + } + + /** + * The requested key. + * @return the, key never {@code null}. + */ + public String getKey() { + return key; + } + + /** + * The value. + * @return the value, in case a value is null it is valid to return {#code null} as result for + * {@link javax.config.spi.ConfigSource#getValue(String)}}. + */ + public String getValue() { + return this.value; + } + + /** + * Creates a full configuration map for this key, value pair and all its meta context data. This map + * is also used for subsequent processing, like value filtering. + * @return the property value entry map. + */ + public String getMetaEntry() { + return metaEntry; + } + + /** + * Creates a new builder instance. + * @param key the key, not {@code null}. + * @return a new builder instance. + */ + public static ConfigValueBuilder builder(String key){ + Objects.requireNonNull(key, "Key must be given."); + return new ConfigValueBuilder(key); + } + + /** + * Creates a new builder instance. + * @param key the key, not {@code null}. + * @param value the property value, not {@code null}. + * @return a new builder instance. + */ + public static ConfigValueBuilder builder(String key, String value) { + Objects.requireNonNull(key, "Key must be given."); + Objects.requireNonNull(value, "Value must be given"); + return new ConfigValueBuilder(key, value); + } + + + /** + * Creates a new PropertyValue without any metadata.. + * @param key the key, not {@code null}. + * @param value the value. + * @param metaEntry the metaEntry, typically the name of the {@link javax.config.spi.ConfigSource} + * providing the value, not {@code null}. + * @return a new property value instance, or {@code null}, + * if the value passed is {@code null}.. + */ + public static ConfigValue of(String key, String value, String metaEntry) { + if (value==null) { + return null; + } + return new ConfigValue(key, value, metaEntry); + } + + /** + * Creates a new builder instance based on this item. + * @return a new builder, never null. + */ + public ConfigValueBuilder toBuilder() { + return new ConfigValueBuilder(this.getKey()) + .setValue(this.getValue()) + .setMetaEntry(this.metaEntry); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ConfigValue)) return false; + ConfigValue that = (ConfigValue) o; + return Objects.equals(getKey(), that.getKey()) && + Objects.equals(getValue(), that.getValue()) && + Objects.equals(getMetaEntry(), that.getMetaEntry()); + } + + @Override + public int hashCode() { + return Objects.hash(getKey(), getValue(), + getMetaEntry()); + } + + @Override + public String toString() { + return "PropertyValue{" + + "key='" + key + '\'' + + ", value='" + value + '\'' + + ", metaEntry='" + metaEntry + '\'' + + '}'; + } + + /** + * Maps a map of {@code Map<String,String>} to a {@code Map<String,PropertyValue>}. + * @param config the String based map, not {@code null}. + * @return the corresponding value based map. + */ + public static Map<String,ConfigValue> map(Map<String, String> config) { + Map<String,ConfigValue> result = new HashMap<>(config.size()); + for(Map.Entry<String,String> en:config.entrySet()){ + result.put(en.getKey(), ConfigValue.of(en.getKey(), en.getValue(), config.get(en.getKey()+"[meta]"))); + } + return result; + } + + /** + * Maps a map of {@code Map<String,String>} to a {@code Map<String,PropertyValue>}. + * + * @param config the String based map, not {@code null}. + * @param source the source name, not {@code null}. + * @param metaData additional metadata, not {@code null}. + * @return the corresponding value based map. + */ + public static Map<String,ConfigValue> map(Map<String, String> config, String source, + Map<String,String> metaData) { + Objects.requireNonNull(config, "Config must be given."); + Objects.requireNonNull(source, "Source must be given."); + Objects.requireNonNull(metaData, "Meta data must be given."); + + Map<String,ConfigValue> result = new HashMap<>(config.size()); + + for(Map.Entry<String,String> en:config.entrySet()){ + ConfigValue value = new ConfigValueBuilder(en.getKey(), source).setValue(en.getValue()) + .addMetaEntries(metaData).build(); + result.put(en.getKey(), value); + } + return result; + } + + public Map<? extends String, ? extends String> asMap() { + Map<String,String> map = new HashMap<>(); + map.put(key, value); + map.put(key+"[meta]", this.metaEntry); + return map; + } + + public static ConfigValue of(String key, Map<String, String> rawProperties) { + String value = rawProperties.get(key); + String meta = rawProperties.get(key+"[meta]"); + return new ConfigValue(key, value, meta); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/ConfigValueBuilder.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/ConfigValueBuilder.java b/code/base/src/main/java/org/apache/tamaya/base/ConfigValueBuilder.java new file mode 100644 index 0000000..259a5be --- /dev/null +++ b/code/base/src/main/java/org/apache/tamaya/base/ConfigValueBuilder.java @@ -0,0 +1,179 @@ +/* + * 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.base; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.*; + +/** + * Builder to create a {@link ConfigValue} instance. + */ +public class ConfigValueBuilder { + /** The key accessed. */ + String key; + /** The property value. */ + String value; + /** additional metadata entries (optional). */ + String metaEntry; + + /** + * Create a new builder instance, for a given set of parameters. + * Before calling build at least a {@link #value} and its {@link #metaEntry} + * must be set. + */ + ConfigValueBuilder(String key){ + this.key = Objects.requireNonNull(key); + } + + /** + * Create a new builder instance, for a given set of parameters. + * @param key to access a property value, not {@code null}. + * @param value property value. + */ + ConfigValueBuilder(String key, String value) { + this.key = Objects.requireNonNull(key); + this.value = Objects.requireNonNull(value); + } + + /** + * Create a new builder instance, for a given set of parameters. + * + * @param key to access a property value. + * @param value the value, not {@code null}. If a value is {@code null} + * {@link javax.config.spi.ConfigSource#getValue(String)} should return {@code null}. + * @param metaEntry property metaEntry. + */ + ConfigValueBuilder(String key, String value, String metaEntry) { + this.key = Objects.requireNonNull(key); + this.value = value; + this.metaEntry = Objects.requireNonNull(metaEntry); + } + + /** + * Replaces/sets the context data. + * @param metaEntry the context data to be applied. + * @return the builder for chaining. + */ + public ConfigValueBuilder setMetaEntry(String metaEntry) { + this.metaEntry = metaEntry; + return this; + } + + /** + * Add an additional context data information. + * @param key the context data key, not {@code null}. + * @param value the context value, not {@code null} (will be converted to String). + * @return the builder for chaining. + */ + public ConfigValueBuilder addMetaEntry(String key, String value) { + Objects.requireNonNull(key, "Meta key must be given."); + Objects.requireNonNull(value, "Meta value must be given."); + if(metaEntry==null){ + metaEntry = key+"="+value; + }else{ + metaEntry = "\n" + key+"="+value; + } + return this; + } + + /** + * Adds the context data given. + * @param metaEntries the context data to be applied, not {@code null}. + * @return the builder for chaining. + */ + public ConfigValueBuilder addMetaEntries(Map<String, String> metaEntries) { + Properties props = new Properties(); + props.putAll(metaEntries); + StringWriter stringWriter = new StringWriter(); + try { + props.store(stringWriter, null); + stringWriter.flush(); + if(metaEntry==null){ + metaEntry = stringWriter.toString(); + }else{ + metaEntry += '\n' + stringWriter.toString(); + } + } catch (IOException e) { + e.printStackTrace(); + } + return this; + } + + /** + * Adds the context data given as JSON object. + * @param meta the context data in JSON format, not {@code null}. + * @return the builder for chaining. + */ + public ConfigValueBuilder addMetaEntry(String meta) { + if(metaEntry==null){ + metaEntry = meta; + }else{ + metaEntry += '\n' + meta; + } + return this; + } + + /** + * Get the value's context data. + * @return the context data, not {@code null}. + */ + public String getMetaEntry() { + return metaEntry; + } + + /** + * Sets a new key. + * @param key the new key, not {@code null}. + * @return the builder for chaining. + */ + public ConfigValueBuilder setKey(String key) { + this.key = Objects.requireNonNull(key); + return this; + } + + /** + * Sets a new value. + * @param value the new value, not {@code null}. + * @return the builder for chaining. + */ + public ConfigValueBuilder setValue(String value) { + this.value = Objects.requireNonNull(value, "Value must be given."); + + return this; + } + + /** + * Creates a new immutable {@link ConfigValue}. + * @return a new immutable {@link ConfigValue}, never {@code null}. + */ + public ConfigValue build(){ + return new ConfigValue(this); + } + + @Override + public String toString() { + return "PropertyValueBuilder{" + + "key='" + key + '\'' + + "value='" + value + '\'' + + ", metaEntry=" + metaEntry + + '}'; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/ConfigValueCombinationPolicy.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/ConfigValueCombinationPolicy.java b/code/base/src/main/java/org/apache/tamaya/base/ConfigValueCombinationPolicy.java new file mode 100644 index 0000000..8005da7 --- /dev/null +++ b/code/base/src/main/java/org/apache/tamaya/base/ConfigValueCombinationPolicy.java @@ -0,0 +1,71 @@ +/* + * 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.base; + + +import javax.config.Config; +import javax.config.spi.ConfigSource; + +/** + * Policy that determines how the final value of a configuration entry is evaluated. An instances of this + * interface can be registered to get control how multiple PropertySources are combined. This is useful in cases + * where the default overriding policy as implemented in {@link #DEFAULT_OVERRIDING_POLICY} is not matching + * the need of the current application, e.g. then entries containing multiple values should be combined to new + * values instead of overridden. + */ +public interface ConfigValueCombinationPolicy { + + /** + * Default overriding collector, where each existing entry ({@code current} is overridden by a subsequent non-null + * entry evaluated by {@code propertySource.get(key)}. + */ + ConfigValueCombinationPolicy DEFAULT_OVERRIDING_POLICY = (currentValue, key, propertySource) -> { + String value = propertySource.getValue(key); + String meta = propertySource.getValue(key+"[meta]"); + return value!=null? value:currentValue; + }; + + /** + * @deprecated Use {@linkplain #DEFAULT_OVERRIDING_POLICY} instead. Will be removed in 1.0. + */ + @Deprecated + ConfigValueCombinationPolicy DEFAULT_OVERRIDING_COLLECTOR = DEFAULT_OVERRIDING_POLICY; + + + /** + * Method that is called for each value evaluated by a PropertySource for the given key. This method is called + * either when a single key is accessed, e.g. by calling {@code org.apache.tamaya.Configuration.getXXX}, but also + * when the full configuration property map is accessed by calling + * {@link Config#getPropertyNames()}}. + * + * @param currentValue the current value, including metadata entries. If no such key is present the current value + * is null. + * The collector should either combine the existing value with value from {@code currentValue} + * or replace the value in {@code currentValue} with {@code valueRead}, hereby returning the + * result to be used as new {@code currentValue}. + * @param key The current key to be evaluated. + * @param propertySource The PropertySource that may return an value for the given key. The PropertySource given + * may be evaluated for additional meta-data, how the given values are to be combined. + * Note that the value returned by a PropertySource can be null. In that case + * {@code currentValue} should be returned in almost all cases. + * @return the value to be used for future evaluation, including metadata entries. + */ + String collect(String currentValue, String key, ConfigSource propertySource); + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/DefaultConfig.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/DefaultConfig.java b/code/base/src/main/java/org/apache/tamaya/base/DefaultConfig.java index 665a605..2549474 100644 --- a/code/base/src/main/java/org/apache/tamaya/base/DefaultConfig.java +++ b/code/base/src/main/java/org/apache/tamaya/base/DefaultConfig.java @@ -21,10 +21,8 @@ package org.apache.tamaya.base; import org.apache.tamaya.base.configsource.ConfigSourceManager; import org.apache.tamaya.base.convert.ConverterManager; -import org.apache.tamaya.spi.ConfigValue; -import org.apache.tamaya.spi.Filter; +import org.apache.tamaya.base.filter.Filter; import org.apache.tamaya.base.filter.FilterManager; -import org.apache.tamaya.spi.*; import javax.config.Config; import javax.config.spi.ConfigSource; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/DefaultConfigBuilder.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/DefaultConfigBuilder.java b/code/base/src/main/java/org/apache/tamaya/base/DefaultConfigBuilder.java index 5a71ba4..6422c88 100644 --- a/code/base/src/main/java/org/apache/tamaya/base/DefaultConfigBuilder.java +++ b/code/base/src/main/java/org/apache/tamaya/base/DefaultConfigBuilder.java @@ -20,10 +20,8 @@ package org.apache.tamaya.base; import org.apache.tamaya.base.configsource.*; import org.apache.tamaya.base.convert.ConverterManager; +import org.apache.tamaya.base.filter.Filter; import org.apache.tamaya.base.filter.FilterManager; -import org.apache.tamaya.spi.TamayaConfigBuilder; -import org.apache.tamaya.spi.*; -import org.apache.tamaya.spi.Filter; import javax.config.Config; import javax.config.spi.ConfigSource; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/DefaultServiceContext.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/DefaultServiceContext.java b/code/base/src/main/java/org/apache/tamaya/base/DefaultServiceContext.java index 752fd3c..1411257 100644 --- a/code/base/src/main/java/org/apache/tamaya/base/DefaultServiceContext.java +++ b/code/base/src/main/java/org/apache/tamaya/base/DefaultServiceContext.java @@ -18,8 +18,6 @@ */ package org.apache.tamaya.base; -import org.apache.tamaya.spi.ServiceContext; - import javax.annotation.Priority; import java.io.IOException; import java.net.URL; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/Experimental.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/Experimental.java b/code/base/src/main/java/org/apache/tamaya/base/Experimental.java new file mode 100644 index 0000000..1e28ccb --- /dev/null +++ b/code/base/src/main/java/org/apache/tamaya/base/Experimental.java @@ -0,0 +1,32 @@ +/* + * 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.base; + +import java.lang.annotation.*; + +/** + * This is a simple annotation for flaging out functionality or features the Tamaya team is not sure if it is already + * stabilized, so use it with some caution. + */ +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, + ElementType.TYPE}) +public @interface Experimental { +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/ServiceContext.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/ServiceContext.java b/code/base/src/main/java/org/apache/tamaya/base/ServiceContext.java new file mode 100644 index 0000000..c439a94 --- /dev/null +++ b/code/base/src/main/java/org/apache/tamaya/base/ServiceContext.java @@ -0,0 +1,147 @@ +/* + * 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.base; + +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; +import java.util.List; + + +/** + * This class models the component that is managing the lifecycle current the + * services used by the Configuration API. + */ +public interface ServiceContext { + + /** + * @return ordinal of the ServiceContext. The one with the highest ordinal will be taken. + */ + int ordinal(); + + static ClassLoader defaultClassLoader(){ + ClassLoader classloader = Thread.currentThread().getContextClassLoader(); + if(classloader==null){ + classloader = ServiceContextManager.class.getClassLoader(); + } + return classloader; + } + + /** + * Access a service singleton via its type. + * If multiple implementations for the very serviceType exist then + * the one with the highest {@link javax.annotation.Priority} will be used. + * + * @param <T> the type of the service type. + * @param serviceType the service type. + * @return The instance to be used, or {@code null} + * @throws IllegalArgumentException if there are multiple service implementations with the maximum priority. + */ + default <T> T getService(Class<T> serviceType){ + return getService(serviceType, defaultClassLoader()); + } + + /** + * Access a service singleton via its type. + * If multiple implementations for the very serviceType exist then + * the one with the highest {@link javax.annotation.Priority} will be used. + * + * @param <T> the type of the service type. + * @param serviceType the service type. + * @param classLoader the class loader to be considered. + * @return The instance to be used, or {@code null} + * @throws IllegalArgumentException if there are multiple service implementations with the maximum priority. + */ + <T> T getService(Class<T> serviceType, ClassLoader classLoader); + + /** + * Factory method to create a type, hereby a new instance is created on each access. + * If multiple implementations for the very serviceType exist then + * the one with the highest {@link javax.annotation.Priority} will be used as the base + * for creating subsequent instances. + * + * @param <T> the type of the service type. + * @param serviceType the service type. + * @return The new instance to be used, or {@code null} + * @throws IllegalArgumentException if there are multiple service implementations with the maximum priority. + */ + default <T> T create(Class<T> serviceType){ + return create(serviceType, defaultClassLoader()); + } + + /** + * Factory method to create a type, hereby a new instance is created on each access. + * If multiple implementations for the very serviceType exist then + * the one with the highest {@link javax.annotation.Priority} will be used as the base + * for creating subsequent instances. + * + * @param <T> the type of the service type. + * @param serviceType the service type. + * @param classLoader the class loader to be considered. + * @return The new instance to be used, or {@code null} + * @throws IllegalArgumentException if there are multiple service implementations with the maximum priority. + */ + <T> T create(Class<T> serviceType, ClassLoader classLoader); + + + /** + * Access a list current services, given its type. The bootstrap mechanism should + * order the instance for precedence, hereby the most significant should be + * first in order. + * + * @param serviceType + * the service type. + * @param <T> the type of the list element returned by this method + * @return The instance to be used, never {@code null} + */ + default <T> List<T> getServices(Class<T> serviceType){ + return getServices(serviceType, defaultClassLoader()); + } + + /** + * Access a list current services, given its type. The bootstrap mechanism should + * order the instance for precedence, hereby the most significant should be + * first in order. + * + * @param serviceType + * the service type. + * @param <T> the type of the list element returned by this method + * @return The instance to be used, never {@code null} + */ + <T> List<T> getServices(Class<T> serviceType, ClassLoader classLoader); + + /** + * Loads resources from the current runtime context. This method allows to use runtime + * specific code to load resources, e.g. within OSGI environments. + * @param resource the resource, not {@code null}. + * @param cl the desired classloader context, if null, the current thread context classloader is used. + * @return the resources found + * @throws IOException if load fails. + */ + Enumeration<URL> getResources(String resource, ClassLoader cl) throws IOException; + + /** + * Loads a resource from the current runtime context. This method allows to use runtime + * specific code to load a resource, e.g. within OSGI environments. + * @param resource the resource, not {@code null}. + * @param cl the desired classloader context, if null, the current thread context classloader is used. + * @return the resource found, or {@code null}. + */ + URL getResource(String resource, ClassLoader cl); +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/ServiceContextManager.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/ServiceContextManager.java b/code/base/src/main/java/org/apache/tamaya/base/ServiceContextManager.java new file mode 100644 index 0000000..50e0c3d --- /dev/null +++ b/code/base/src/main/java/org/apache/tamaya/base/ServiceContextManager.java @@ -0,0 +1,118 @@ +/* + * 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.base; + +import java.util.Objects; +import java.util.ServiceLoader; +import java.util.logging.Level; +import java.util.logging.Logger; + + +/** + * This singleton provides access to the services available in the current {@link ServiceContext}. The + * behaviour can be adapted, by calling {@link ServiceContextManager#set(ServiceContext)} before accessing any + * services. + */ +public final class ServiceContextManager { + + /** + * The logger used. + */ + private static final Logger LOG = Logger.getLogger(ServiceContextManager.class.getName()); + + /** + * The ServiceProvider used. + */ + private static volatile ServiceContext serviceContextProviderDelegate; + + /** + * Private singletons constructor. + */ + private ServiceContextManager() { + } + + /** + * Load the {@link ServiceContext} to be used. + * + * @return {@link ServiceContext} to be used for loading the services. + */ + private static ServiceContext loadDefaultServiceProvider() { + ServiceContext highestServiceContext = null; + try { + int highestOrdinal = 0; + for (ServiceContext serviceContext : ServiceLoader.load(ServiceContext.class)) { + if (highestServiceContext == null) { + highestServiceContext = serviceContext; + } else if (serviceContext.ordinal() > highestOrdinal) { + highestServiceContext = serviceContext; + highestOrdinal = serviceContext.ordinal(); + } + } + } catch (Exception e) { + throw new IllegalStateException("ServiceContext not loadable", e); + } + if (highestServiceContext == null) { + throw new IllegalStateException("No ServiceContext found"); + } + LOG.info("Using Service Context of type: " + highestServiceContext.getClass().getName()); + return highestServiceContext; + } + + /** + * Replace the current {@link ServiceContext} in use. + * + * @param serviceContextProvider the new {@link ServiceContext}, not {@code null}. + * @return the currently used context after setting it. + */ + public static ServiceContext set(ServiceContext serviceContextProvider) { + Objects.requireNonNull(serviceContextProvider); + ServiceContext currentContext = ServiceContextManager.serviceContextProviderDelegate; + + synchronized (ServiceContextManager.class) { + if (ServiceContextManager.serviceContextProviderDelegate == null) { + ServiceContextManager.serviceContextProviderDelegate = serviceContextProvider; + LOG.log(Level.INFO, "Using ServiceProvider: " + serviceContextProvider.getClass().getName()); + } else { + LOG.log(Level.WARNING, "Replacing ServiceProvider " + + ServiceContextManager.serviceContextProviderDelegate.getClass().getName() + + " with: " + serviceContextProvider.getClass().getName()); + ServiceContextManager.serviceContextProviderDelegate = serviceContextProvider; + } + } + + return currentContext; + } + + /** + * Ge {@link ServiceContext}. If necessary the {@link ServiceContext} will be laziliy loaded. + * + * @return the {@link ServiceContext} used. + */ + public static ServiceContext getServiceContext(){ + if (serviceContextProviderDelegate == null) { + synchronized (ServiceContextManager.class) { + if (serviceContextProviderDelegate == null) { + serviceContextProviderDelegate = loadDefaultServiceProvider(); + } + } + } + return serviceContextProviderDelegate; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/TamayaConfigBuilder.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/TamayaConfigBuilder.java b/code/base/src/main/java/org/apache/tamaya/base/TamayaConfigBuilder.java new file mode 100644 index 0000000..40ebe94 --- /dev/null +++ b/code/base/src/main/java/org/apache/tamaya/base/TamayaConfigBuilder.java @@ -0,0 +1,333 @@ +/* + * 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.base; + +import org.apache.tamaya.base.filter.Filter; +import org.apache.tamaya.base.ConfigValueCombinationPolicy; + +import javax.config.spi.ConfigBuilder; +import javax.config.spi.ConfigSource; +import javax.config.spi.Converter; +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +/** + * A builder for creating new or adapting instances of {@link javax.config.Config}. + * Builders can be obtained in exactly two ways: + * <ol> + * <li>By accessing an empty builder instance from + * {@link javax.config.spi.ConfigProviderResolver#getBuilder()}.</li> + * </ol> + */ +public interface TamayaConfigBuilder extends ConfigBuilder, ConfigContextSupplier { + + /** + * Create a new empty configuration builder. + * @return + */ + static TamayaConfigBuilder create() { + return new DefaultConfigBuilder(); + } + + static TamayaConfigBuilder create(ConfigContextSupplier contextSupplier){ + return new DefaultConfigBuilder(contextSupplier.getConfigContext()); + } + + static TamayaConfigBuilder from(ConfigBuilder configBuilder){ + if(configBuilder instanceof TamayaConfigBuilder) { + return (TamayaConfigBuilder) configBuilder; + }else if(configBuilder instanceof ConfigContextSupplier){ + return create((ConfigContextSupplier)configBuilder); + } + throw new IllegalArgumentException("Builder must implement ConfigContextSupplier."); + } + + /** + * This method can be used for programmatically adding {@link ConfigSource}s. + * Hereby the property source is added to the tail of property sources with + * lowest priority regardless of its current ordinal value. To sort the property + * sources based on their ordinals call {@link #sortSources}. + * + * @param propertySources the PropertySources to add + * @return this builder, for chaining, never null. + * @throws IllegalArgumentException If a property source with a given name already + * exists. + */ + TamayaConfigBuilder withSources(Collection<ConfigSource> propertySources); + + /** + * Removes the given property sources, if existing. The existing order of property + * sources is preserved. + * + * @param propertySources the property sources to remove, not {@code null}. + * @return the builder for chaining. + */ + TamayaConfigBuilder removeSources(ConfigSource... propertySources); + + /** + * Removes the given property sources, if existing. The existing order of property + * sources is preserved. + * + * @param propertySources the property sources to remove, not {@code null}. + * @return the builder for chaining. + */ + TamayaConfigBuilder removeSources(Collection<ConfigSource> propertySources); + + /** + * Increases the priority of the given property source, by moving it towards the end + * of the chain of property sources. If the property source given is already at the end + * this method has no effect. This operation does not change any ordinal values. + * + * @param propertySource the property source to be incresed regarding its significance. + * @return the builder for chaining. + * @throws IllegalArgumentException If no such property source exists in the current + * chain. + */ + TamayaConfigBuilder increasePriority(ConfigSource propertySource); + + /** + * Decreases the priority of the given property source, by moving it towards the start + * of the chain of property sources. If the property source given is already the first + * this method has no effect. This operation does not change any ordinal values. + * + * @param propertySource the property source to be decresed regarding its significance. + * @return the builder for chaining. + * @throws IllegalArgumentException If no such property source exists in the current + * chain. + */ + TamayaConfigBuilder decreasePriority(ConfigSource propertySource); + + /** + * Increases the priority of the given property source to be maximal, by moving it to + * the tail of the of property source chain. If the property source given is + * already the last item this method has no effect. This operation does not change + * any ordinal values. + * + * @param propertySource the property source to be maximized regarding its significance. + * @return the builder for chaining. + * @throws IllegalArgumentException If no such property source exists in the current + * chain. + */ + TamayaConfigBuilder highestPriority(ConfigSource propertySource); + + /** + * Decreases the priority of the given property source to be minimal, by moving it to + * the start of the chain of property source chain. If the property source given is + * already the first item this method has no effect. This operation does not change + * any ordinal values. + * + * @param propertySource the property source to be minimized regarding its significance. + * @return the builder for chaining. + * @throws IllegalArgumentException If no such property source exists in the current + * chain. + */ + TamayaConfigBuilder lowestPriority(ConfigSource propertySource); + + /** + * Access the current chain of property sources. Items at the end of the list have + * precedence/more significance. + * + * @return the property source chain, never {@code null}. + */ + List<ConfigSource> getSources(); + + /** + * Sorts the current registered property sources using the given comparator. + * + * NOTE: property sources at the beginning have minimal significance. + * + * @param comparator the comparator to be used, not {@code null}. + * @return this instance for chaining. + */ + TamayaConfigBuilder sortSources(Comparator<ConfigSource> comparator); + + /** + * Adds the given PropertyFilter instances, hereby the instances are added + * to the end of the list with highest priority. The ordering of existing + * property filters remains unchanged. To sort the property + * filters call {@link #sortFilter}. + * + * @param filters the filters to add + * @return this builder, for chaining, never null. + */ + TamayaConfigBuilder withFilters(Filter... filters); + + /** + * Adds the given PropertyFilter instances, hereby the instances are added + * to the end of the list with highest priority. The ordering of existing + * property filters remains unchanged. To sort the property + * filters call {@link #sortFilter}. + * + * @param filters the filters to add + * @return this builder, for chaining, never null. + */ + TamayaConfigBuilder withFilters(Collection<Filter> filters); + + /** + * Add all registered (default) property filters to the context built. + * @return this builder, for chaining, never null. + */ + TamayaConfigBuilder addDiscoveredFilters(); + + /** + * Removes the given PropertyFilter instances, if existing. The order of the remaining + * filters is preserved. + * + * @param filters the filter to remove + * @return this builder, for chaining, never null. + */ + TamayaConfigBuilder removeFilters(Filter... filters); + + /** + * Removes the given PropertyFilter instances, if existing. The order of the remaining + * filters is preserved. + * + * @param filters the filter to remove + * @return this builder, for chaining, never null. + */ + TamayaConfigBuilder removeFilters(Collection<Filter> filters); + + /** + * Access the current chain of property filters. Items at the end of the list have + * precedence/more significance. + * + * @return the property source chain, never {@code null}. + */ + List<Filter> getFilters(); + + /** + * This method can be used for adding {@link Converter}s. + * Converters are added at the end after any existing converters. + * For converters already registered for the current target type the + * method has no effect. + * + * @param converters the converters to add for this type + * @return this builder, for chaining, never null. + */ + TamayaConfigBuilder withConverters(Collection<Converter<?>> converters); + + /** + * This method can be used for adding {@link Converter}s. + * Converters are added at the end after any existing converters. + * For converters already registered for the current target type the + * method has no effect. + * + * @param typeToConvert the type for which the converters is for + * @param converters the converters to add for this type + * @param <T> the target type. + * @return this builder, for chaining, never null. + */ + <T> TamayaConfigBuilder withConverters(Class<T> typeToConvert, Converter<T>... converters); + + /** + * This method can be used for adding {@link Converter}s. + * Converters are added at the end after any existing converters. + * For converters already registered for the current target type the + * method has no effect. + * + * @param typeToConvert the type for which the converters is for + * @param converters the converters to add for this type + * @param <T> the target type. + * @return this builder, for chaining, never null. + */ + <T> TamayaConfigBuilder withConverters(Class<T> typeToConvert, Collection<Converter<T>> converters); + + + /** + * Removes the given PropertyConverter instances for the given type, + * if existing. + * + * @param typeToConvert the type which the converters is for + * @param converters the converters to remove + * @param <T> the target type. + * @return this builder, for chaining, never null. + */ + <T> TamayaConfigBuilder removeConverters(Class<T> typeToConvert, Converter<T>... converters); + + /** + * Removes the given PropertyConverter instances for the given type, + * if existing. + * + * @param typeToConvert the type which the converters is for + * @param converters the converters to remove + * @param <T> the target type. + * @return this builder, for chaining, never null. + */ + <T> TamayaConfigBuilder removeConverters(Class<T> typeToConvert, Collection<Converter<T>> converters); + + /** + * Removes all converters for the given type, which actually renders a given type + * unsupported for type conversion. + * + * @param typeToConvert the type which the converters is for + * @return this builder, for chaining, never null. + */ + <T> TamayaConfigBuilder removeConverters(Class<T> typeToConvert); + + /** + * Access the current registered property converters. + * + * @return the current registered property converters. + */ + Map<Type, List<Converter>> getConverter(); + + /** + * Sets the {@link ConfigValueCombinationPolicy} used to evaluate the final + * property values. + * + * @param policy the {@link ConfigValueCombinationPolicy} used, not {@code null}. + * @return this builder, for chaining, never null. + */ + TamayaConfigBuilder withPropertyValueCombinationPolicy(ConfigValueCombinationPolicy policy); + + /** + * Sorts the current registered property filters using the given comparator. + * + * NOTE: property filters at the beginning have minimal significance. + * + * @param comparator the comparator to be used, not {@code null}. + * @return this instance for chaining. + */ + TamayaConfigBuilder sortFilter(Comparator<Filter> comparator); + + @Override + TamayaConfigBuilder addDefaultSources(); + + @Override + TamayaConfigBuilder addDiscoveredSources(); + + @Override + TamayaConfigBuilder addDiscoveredConverters(); + + @Override + TamayaConfigBuilder forClassLoader(ClassLoader loader); + + @Override + TamayaConfigBuilder withSources(ConfigSource... sources); + + @Override + TamayaConfigBuilder withConverters(Converter<?>... converters); + + <T> TamayaConfigBuilder withConverter(Class<T> type, Converter<T> converter); + +} + http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/TypeUtils.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/TypeUtils.java b/code/base/src/main/java/org/apache/tamaya/base/TypeUtils.java new file mode 100644 index 0000000..f07d8a4 --- /dev/null +++ b/code/base/src/main/java/org/apache/tamaya/base/TypeUtils.java @@ -0,0 +1,136 @@ +/* + * 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.base; + +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Objects; + +/** + * Utility class for type handling. + */ +public final class TypeUtils { + + private static final Type[] EMPTY_TYPE_ARRAY = new Type[0]; + + /** + * Singleton constructor. + */ + private TypeUtils() { + } + + + /** + * Checks the current implemented generic interfaces and evaluates the given single type parameter. + * + * @param clazz the class to check, not {@code null}. + * @param interfaceType the interface type to be checked, not {@code null}. + * @return the generic type parameters, or an empty array, if it cannot be evaluated. + */ + public static Type[] getInterfaceTypeParameters(Class<?> clazz, Class<?> interfaceType) { + Objects.requireNonNull(clazz, "Class parameter must be given."); + Objects.requireNonNull(interfaceType, "Interface parameter must be given."); + + for (Type type : clazz.getGenericInterfaces()) { + if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) type; + if(parameterizedType.getRawType().equals(interfaceType)){ + return parameterizedType.getActualTypeArguments(); + } + } + } + return EMPTY_TYPE_ARRAY; + } + + /** + * Method that checks the class's type for a generic interface implementation type. + * + * @param type the type, not {@code null}. + * @return the generic type parameter of the given single type generic interfaceType, or an empty array. + */ + public static Type[] getTypeParameters(Type type) { + Objects.requireNonNull(type, "Type must be given."); + + if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) type; + return parameterizedType.getActualTypeArguments(); + } + return EMPTY_TYPE_ARRAY; + } + + /** + * Returns basic raw Java type. + * + * @return the actual type represented by this object + */ + @SuppressWarnings("unchecked") + public final Class getRawType(Type type) { + if (type instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType) type; + return (Class) pt.getRawType(); + } else if (type instanceof GenericArrayType) { + return Object[].class; + } else if (type instanceof Class) { + return (Class) type; + } else { + throw new RuntimeException("Illegal type for the Type Literal Class"); + } + } + + /** + * Returns actual type arguments, if present. + * + * @return the actual type represented by defined class, or an empty array. + */ + public static final Type[] getActualTypeArguments(Type type) { + if (type instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType) type; + return pt.getActualTypeArguments(); + } + return new Type[0]; + } + + + /** + * Get the actual parametrized types for a given parametrized super class type. + * @param type the type, not null. + * @param parametrizedClass the parametrized super class. + * @return the types, or an empty array. + * @throws IllegalArgumentException if no super class is an instance of the required parametrized type. + */ + public static Type[] getActualTypeArguments(Class type, Class parametrizedClass) { + if (type == null) { + throw new RuntimeException("Class parameter type can not be null"); + } + + Type superClazz = type.getGenericSuperclass(); + + if (superClazz instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType) superClazz; + return pt.getActualTypeArguments(); + } else if (superClazz.equals(Object.class)) { + throw new IllegalArgumentException("Super class must be parametrized type"); + } else { + return getActualTypeArguments((Class<?>) superClazz, parametrizedClass); + } + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/configsource/ConfigSourceManager.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/configsource/ConfigSourceManager.java b/code/base/src/main/java/org/apache/tamaya/base/configsource/ConfigSourceManager.java index eff7e55..09f6b5b 100644 --- a/code/base/src/main/java/org/apache/tamaya/base/configsource/ConfigSourceManager.java +++ b/code/base/src/main/java/org/apache/tamaya/base/configsource/ConfigSourceManager.java @@ -18,8 +18,11 @@ */ package org.apache.tamaya.base.configsource; +import org.apache.tamaya.base.ConfigValueCombinationPolicy; import org.apache.tamaya.base.FormatUtils; -import org.apache.tamaya.spi.*; +import org.apache.tamaya.base.ServiceContext; +import org.apache.tamaya.base.ServiceContextManager; +import org.apache.tamaya.base.filter.Filter; import javax.config.Config; import javax.config.spi.ConfigSource; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/configsource/JavaConfigurationConfigSource.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/configsource/JavaConfigurationConfigSource.java b/code/base/src/main/java/org/apache/tamaya/base/configsource/JavaConfigurationConfigSource.java index 6fb3fc8..46c254d 100644 --- a/code/base/src/main/java/org/apache/tamaya/base/configsource/JavaConfigurationConfigSource.java +++ b/code/base/src/main/java/org/apache/tamaya/base/configsource/JavaConfigurationConfigSource.java @@ -18,7 +18,7 @@ */ package org.apache.tamaya.base.configsource; -import org.apache.tamaya.spi.ServiceContextManager; +import org.apache.tamaya.base.ServiceContextManager; import javax.config.spi.ConfigSource; import java.io.IOException; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/configsource/PropertiesResourceConfigSource.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/configsource/PropertiesResourceConfigSource.java b/code/base/src/main/java/org/apache/tamaya/base/configsource/PropertiesResourceConfigSource.java index 4e974df..2c7b05c 100644 --- a/code/base/src/main/java/org/apache/tamaya/base/configsource/PropertiesResourceConfigSource.java +++ b/code/base/src/main/java/org/apache/tamaya/base/configsource/PropertiesResourceConfigSource.java @@ -18,7 +18,7 @@ */ package org.apache.tamaya.base.configsource; -import org.apache.tamaya.spi.ServiceContextManager; +import org.apache.tamaya.base.ServiceContextManager; import java.io.InputStream; import java.net.URL; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/convert/ConversionContext.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/convert/ConversionContext.java b/code/base/src/main/java/org/apache/tamaya/base/convert/ConversionContext.java index df16eda..457a9d4 100644 --- a/code/base/src/main/java/org/apache/tamaya/base/convert/ConversionContext.java +++ b/code/base/src/main/java/org/apache/tamaya/base/convert/ConversionContext.java @@ -18,8 +18,6 @@ */ package org.apache.tamaya.base.convert; -import org.apache.tamaya.spi.TypeLiteral; - import javax.config.Config; import javax.config.spi.Converter; import java.lang.reflect.AnnotatedElement; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/convert/ConverterManager.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/convert/ConverterManager.java b/code/base/src/main/java/org/apache/tamaya/base/convert/ConverterManager.java index f22f0ca..e8b28d5 100644 --- a/code/base/src/main/java/org/apache/tamaya/base/convert/ConverterManager.java +++ b/code/base/src/main/java/org/apache/tamaya/base/convert/ConverterManager.java @@ -20,10 +20,9 @@ package org.apache.tamaya.base.convert; import org.apache.tamaya.base.FormatUtils; import org.apache.tamaya.base.PriorityServiceComparator; -import org.apache.tamaya.spi.ConfigContext; -import org.apache.tamaya.spi.ConfigContextSupplier; -import org.apache.tamaya.spi.ServiceContext; -import org.apache.tamaya.spi.ServiceContextManager; +import org.apache.tamaya.base.ConfigContextSupplier; +import org.apache.tamaya.base.ServiceContext; +import org.apache.tamaya.base.ServiceContextManager; import javax.config.Config; import javax.config.spi.Converter; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/filter/Filter.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/filter/Filter.java b/code/base/src/main/java/org/apache/tamaya/base/filter/Filter.java new file mode 100644 index 0000000..76d46de --- /dev/null +++ b/code/base/src/main/java/org/apache/tamaya/base/filter/Filter.java @@ -0,0 +1,51 @@ +/* + * 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.base.filter; + + +/** + * <p>Interface for filtering the current map of properties during the evaluation of the chain of PropertySources. + * Filters can be registered using the {@link org.apache.tamaya.base.ServiceContext}. The ordinal + * hereby is defined by the corresponding {@code @Priority} annotation.</p> + * <p>Filters </p> + */ +@FunctionalInterface +public interface Filter { + + /** + * <p>Maps the current {@code valueToBeFiltered} value to a new value. The resulting value will be used as the result + * passed to the user.</p> + * <p>If a filter is currently not available, it should just pass the input map to the method's + * output.</p> + * <p>Returning {@code null} will remove the entry.</p> + * <h3>Implementation specification</h3> + * Implementations of this class must be + * <ul> + * <li>reentrant</li> + * <li>thread-safe</li> + * </ul> + * @param key the key, not null. + * @param value the value to be filtered, which also can be {@code null} if removed by another filter. + * @return the filtered value, or {@code null} if the value should be removed alltogether. + * @see org.apache.tamaya.base.ConfigValue + * @see org.apache.tamaya.base.ConfigValueBuilder + */ + String filterProperty(String key, String value); + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/filter/FilterComparator.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/filter/FilterComparator.java b/code/base/src/main/java/org/apache/tamaya/base/filter/FilterComparator.java index dd2bd49..caf0ffb 100644 --- a/code/base/src/main/java/org/apache/tamaya/base/filter/FilterComparator.java +++ b/code/base/src/main/java/org/apache/tamaya/base/filter/FilterComparator.java @@ -18,8 +18,6 @@ */ package org.apache.tamaya.base.filter; -import org.apache.tamaya.spi.Filter; - import javax.annotation.Priority; import java.io.Serializable; import java.util.Comparator; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/filter/FilterContext.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/filter/FilterContext.java b/code/base/src/main/java/org/apache/tamaya/base/filter/FilterContext.java index cdbcba5..d17a666 100644 --- a/code/base/src/main/java/org/apache/tamaya/base/filter/FilterContext.java +++ b/code/base/src/main/java/org/apache/tamaya/base/filter/FilterContext.java @@ -18,8 +18,6 @@ */ package org.apache.tamaya.base.filter; -import org.apache.tamaya.spi.Filter; - import javax.config.Config; import java.util.HashMap; import java.util.Map; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/filter/FilterManager.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/filter/FilterManager.java b/code/base/src/main/java/org/apache/tamaya/base/filter/FilterManager.java index 361f47c..ab52b59 100644 --- a/code/base/src/main/java/org/apache/tamaya/base/filter/FilterManager.java +++ b/code/base/src/main/java/org/apache/tamaya/base/filter/FilterManager.java @@ -19,10 +19,8 @@ package org.apache.tamaya.base.filter; import org.apache.tamaya.base.FormatUtils; -import org.apache.tamaya.spi.Filter; -import org.apache.tamaya.spi.ConfigValue; -import org.apache.tamaya.spi.ServiceContext; -import org.apache.tamaya.spi.ServiceContextManager; +import org.apache.tamaya.base.ServiceContext; +import org.apache.tamaya.base.ServiceContextManager; import javax.config.Config; import java.util.*; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/base/filter/RegexPropertyFilter.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/base/filter/RegexPropertyFilter.java b/code/base/src/main/java/org/apache/tamaya/base/filter/RegexPropertyFilter.java index 3e46803..9210247 100644 --- a/code/base/src/main/java/org/apache/tamaya/base/filter/RegexPropertyFilter.java +++ b/code/base/src/main/java/org/apache/tamaya/base/filter/RegexPropertyFilter.java @@ -18,9 +18,6 @@ */ package org.apache.tamaya.base.filter; -import org.apache.tamaya.spi.ConfigValue; -import org.apache.tamaya.spi.Filter; - import java.util.Arrays; import java.util.List; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/09472084/code/base/src/main/java/org/apache/tamaya/spi/ConfigContext.java ---------------------------------------------------------------------- diff --git a/code/base/src/main/java/org/apache/tamaya/spi/ConfigContext.java b/code/base/src/main/java/org/apache/tamaya/spi/ConfigContext.java deleted file mode 100644 index 7c77e12..0000000 --- a/code/base/src/main/java/org/apache/tamaya/spi/ConfigContext.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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.spi; - -import javax.config.spi.ConfigSource; -import javax.config.spi.Converter; -import java.lang.reflect.Type; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -/** - * Central SPI for programmatically dealing with the setup of the configuration system. - * This includes adding and enlisting {@link javax.config.spi.ConfigSource}s, - * managing {@link javax.config.spi.Converter}s, ConfigFilters, etc. - */ -public interface ConfigContext { - - /** - * This method returns the current list of registered PropertySources ordered via their ordinal. - * PropertySources with a lower ordinal come last. The PropertySource with the - * highest ordinal comes first. - * If two PropertySources have the same ordinal number they will get sorted - * using their class name just to ensure the user at least gets the same ordering - * after a JVM restart, hereby names before are added last. - * PropertySources are loaded when this method is called the first time, which basically is - * when the first time configuration is accessed. - * - * @return a sorted list of registered PropertySources. The returned list need not be modifiable - */ - List<ConfigSource> getSources(); - -// /** -// * Access a {@link ConfigSource} using its (unique) name. -// * @param name the propoerty source's name, not {@code null}. -// * @return the propoerty source found, or {@code null}. -// */ -// default ConfigSource getSource(String name) { -// for(ConfigSource ps: getSources()){ -// if(name.equals(ps.getName())){ -// return ps; -// } -// } -// return null; -// } - - /** - * Access the current PropertyFilter instances. - * @return the list of registered PropertyFilters, never null. - */ - List<Filter> getFilters(); - - /** - * <p> - * This method returns the Map of registered PropertyConverters - * per type. - * The List for each type is ordered via their {@link javax.annotation.Priority} and - * cladd name. - * </p> - * - * <p>A simplified scenario could be like:</p> - * <pre> - * { - * Date.class -> {StandardDateConverter, TimezoneDateConverter, MyCustomDateConverter } - * Boolean.class -> {StandardBooleanConverter, FrenchBooleanConverter} - * Integer.class -> {DynamicDefaultConverter} - * } - * </pre> - * - * @return map with sorted list of registered PropertySources per type. - */ - Map<Type, List<Converter>> getConverters(); - - /** - * <p> - * This method returns the registered PropertyConverters for a given type. - * The List for each type is ordered via their {@link javax.annotation.Priority}. - * </p> - * - * <p> - * PropertyConverters with a higher Priority come first. The PropertyConverter with the - * lowest Priority comes last. - * If two PropertyConverter have the same ordinal number they will get sorted - * using their class name just to ensure the user at least gets the same ordering - * after a JVM restart. - * </p> - * - * <p> - * Additionally if a PropertyProvider is accessed, which is not registered the implementation - * should try to figure out, if there could be a default implementation as follows:</p> - * <ol> - * <li>Look for static factory methods: {@code of(String), valueOf(String), getInstance(String), - * instanceOf(String), fomr(String)}</li> - * <li>Look for a matching constructor: {@code T(String)}.</li> - * </ol> - * - * <p> - * If a correspoding factory method or constructor could be found, a corresponding - * PropertyConverter should be created and registered automatically for the given - * type. - * </p> - * - * <p> The scenario could be like:</p> - * - * <pre> - * { - * Date.class -> {MyCustomDateConverter,StandardDateConverter, TimezoneDateConverter} - * Boolean.class -> {StandardBooleanConverter, FrenchBooleanConverter} - * Integer.class -> {DynamicDefaultConverter} - * } - * </pre> - * - * <p> - * The converters returned for a type should be used as a chain, whereas the result of the - * first converters that is able to convert the configured value, is taken as the chain's result. - * No more converters are called after a converters has successfully converted the input into - * the required target type. - * </p> - * - * @param type type of the desired converters - * @return a sorted list of registered PropertySources per type, or null. - */ - default List<Converter> getConverters(Type type){ - return Optional.ofNullable(getConverters().get(type)).orElse(Collections.emptyList()); - } - - /** - * Access the {@link ConfigValueCombinationPolicy} used to evaluate the final - * property values. - * @return the {@link ConfigValueCombinationPolicy} used, never null. - */ - default ConfigValueCombinationPolicy getConfigValueCombinationPolicy(){ - return ConfigValueCombinationPolicy.DEFAULT_OVERRIDING_POLICY; - } - -} -
