tamaya-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From anat...@apache.org
Subject [5/7] incubator-tamaya git commit: Reimplemented (also simjplified) Tamaya core completely based on latest JSR API. Moved prior Tamaya API into compat module.
Date Sun, 10 Dec 2017 22:07:13 GMT
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java
new file mode 100644
index 0000000..2c300ad
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java
@@ -0,0 +1,277 @@
+/*
+ * 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.spisupport;
+
+import org.apache.tamaya.spi.TypeLiteral;
+import org.apache.tamaya.spi.*;
+
+import java.util.*;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.logging.Logger;
+
+/**
+ * Default implementation of a simple ConfigurationContext.
+ */
+public class DefaultConfigurationContext implements ConfigurationContext {
+
+    /** The logger used. */
+    private final static Logger LOG = Logger.getLogger(DefaultConfigurationContext.class.getName());
+
+    /**
+     * Subcomponent handling {@link PropertyConverter} instances.
+     */
+    private final PropertyConverterManager propertyConverterManager = new PropertyConverterManager();
+
+    /**
+     * The current unmodifiable list of loaded {@link PropertySource} instances.
+     */
+    private List<PropertySource> immutablePropertySources;
+
+    /**
+     * The current unmodifiable list of loaded {@link PropertyFilter} instances.
+     */
+    private List<PropertyFilter> immutablePropertyFilters;
+
+    /**
+     * The overriding policy used when combining PropertySources registered to evalute the final configuration
+     * values.
+     */
+    private PropertyValueCombinationPolicy propertyValueCombinationPolicy;
+
+    /**
+     * Lock for internal synchronization.
+     */
+    private final ReentrantReadWriteLock propertySourceLock = new ReentrantReadWriteLock();
+
+    @SuppressWarnings("unchecked")
+	protected DefaultConfigurationContext(DefaultConfigurationContextBuilder builder) {
+        List<PropertySource> propertySources = new ArrayList<>();
+        // first we load all PropertySources which got registered via java.util.ServiceLoader
+        propertySources.addAll(builder.propertySources);
+        // now sort them according to their ordinal values
+        immutablePropertySources = Collections.unmodifiableList(propertySources);
+
+        // as next step we pick up the PropertyFilters pretty much the same way
+        List<PropertyFilter> propertyFilters = new ArrayList<>(builder.getPropertyFilters());
+        immutablePropertyFilters = Collections.unmodifiableList(propertyFilters);
+
+        // Finally add the converters
+        for(Map.Entry<TypeLiteral<?>, Collection<PropertyConverter<?>>> en:builder.getPropertyConverter().entrySet()) {
+            for (@SuppressWarnings("rawtypes") PropertyConverter converter : en.getValue()) {
+                this.propertyConverterManager.register(en.getKey(), converter);
+            }
+        }
+        LOG.info("Registered " + propertyConverterManager.getPropertyConverters().size() + " property converters: " +
+                propertyConverterManager.getPropertyConverters());
+
+        propertyValueCombinationPolicy = builder.combinationPolicy;
+        if(propertyValueCombinationPolicy==null){
+            propertyValueCombinationPolicy = ServiceContextManager.getServiceContext().getService(PropertyValueCombinationPolicy.class);
+        }
+        if(propertyValueCombinationPolicy==null){
+            propertyValueCombinationPolicy = PropertyValueCombinationPolicy.DEFAULT_OVERRIDING_COLLECTOR;
+        }
+        LOG.info("Using PropertyValueCombinationPolicy: " + propertyValueCombinationPolicy);
+    }
+
+
+    @Deprecated
+    @Override
+    public void addPropertySources(PropertySource... propertySourcesToAdd) {
+        Lock writeLock = propertySourceLock.writeLock();
+        try {
+            writeLock.lock();
+            List<PropertySource> newPropertySources = new ArrayList<>(this.immutablePropertySources);
+            newPropertySources.addAll(Arrays.asList(propertySourcesToAdd));
+            Collections.sort(newPropertySources, PropertySourceComparator.getInstance());
+
+            this.immutablePropertySources = Collections.unmodifiableList(newPropertySources);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof DefaultConfigurationContext)){
+            return false;
+        }
+
+        DefaultConfigurationContext that = (DefaultConfigurationContext) o;
+
+        if (!propertyConverterManager.equals(that.propertyConverterManager)) {
+            return false;
+        }
+        if (!immutablePropertySources.equals(that.immutablePropertySources)) {
+            return false;
+        }
+        if (!immutablePropertyFilters.equals(that.immutablePropertyFilters)) {
+            return false;
+        }
+        return getPropertyValueCombinationPolicy().equals(that.getPropertyValueCombinationPolicy());
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = propertyConverterManager.hashCode();
+        result = 31 * result + immutablePropertySources.hashCode();
+        result = 31 * result + immutablePropertyFilters.hashCode();
+        result = 31 * result + getPropertyValueCombinationPolicy().hashCode();
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder b = new StringBuilder("ConfigurationContext{\n");
+        b.append("  Property Sources\n");
+        b.append("  ----------------\n");
+        if(immutablePropertySources.isEmpty()){
+            b.append("  No property sources loaded.\n\n");
+        }else {
+            b.append("  CLASS                         NAME                                                                  ORDINAL SCANNABLE SIZE    STATE     ERROR\n\n");
+            for (PropertySource ps : immutablePropertySources) {
+                b.append("  ");
+                appendFormatted(b, ps.getClass().getSimpleName(), 30);
+                appendFormatted(b, ps.getName(), 70);
+                appendFormatted(b, String.valueOf(PropertySourceComparator.getOrdinal(ps)), 8);
+                appendFormatted(b, String.valueOf(ps.isScannable()), 10);
+                if (ps.isScannable()) {
+                    appendFormatted(b, String.valueOf(ps.getProperties().size()), 8);
+                } else {
+                    appendFormatted(b, "-", 8);
+                }
+                PropertyValue state = ps.get("_state");
+                if(state==null){
+                    appendFormatted(b, "OK", 10);
+                }else {
+                    appendFormatted(b, state.getValue(), 10);
+                    if("ERROR".equals(state.getValue())){
+                        PropertyValue val = ps.get("_exception");
+                        if(val!=null) {
+                            appendFormatted(b, val.getValue(), 30);
+                        }
+                    }
+                }
+                b.append('\n');
+            }
+            b.append("\n");
+        }
+        b.append("  Property Filters\n");
+        b.append("  ----------------\n");
+        if(immutablePropertyFilters.isEmpty()){
+            b.append("  No property filters loaded.\n\n");
+        }else {
+            b.append("  CLASS                         INFO\n\n");
+            for (PropertyFilter filter : getPropertyFilters()) {
+                b.append("  ");
+                appendFormatted(b, filter.getClass().getSimpleName(), 30);
+                b.append(removeNewLines(filter.toString()));
+                b.append('\n');
+            }
+            b.append("\n\n");
+        }
+        b.append("  Property Converters\n");
+        b.append("  -------------------\n");
+        b.append("  CLASS                         TYPE                          INFO\n\n");
+        for(Map.Entry<TypeLiteral<?>, List<PropertyConverter<?>>> converterEntry:getPropertyConverters().entrySet()){
+            for(PropertyConverter converter: converterEntry.getValue()){
+                b.append("  ");
+                appendFormatted(b, converter.getClass().getSimpleName(), 30);
+                appendFormatted(b, converterEntry.getKey().getRawType().getSimpleName(), 30);
+                b.append(removeNewLines(converter.toString()));
+                b.append('\n');
+            }
+        }
+        b.append("\n\n");
+        b.append("  PropertyValueCombinationPolicy: " + getPropertyValueCombinationPolicy().getClass().getName()).append('\n');
+        b.append('}');
+        return b.toString();
+    }
+
+    private void appendFormatted(StringBuilder b, String text, int length) {
+        int padding;
+        if(text.length() <= (length)){
+            b.append(text);
+            padding = length - text.length();
+        }else{
+            b.append(text.substring(0, length-1));
+            padding = 1;
+        }
+        for(int i=0;i<padding;i++){
+            b.append(' ');
+        }
+    }
+
+    private String removeNewLines(String s) {
+        return s.replace('\n', ' ').replace('\r', ' ');
+    }
+
+
+    @Override
+    public List<PropertySource> getPropertySources() {
+        return immutablePropertySources;
+    }
+
+    @Override
+    public PropertySource getPropertySource(String name) {
+        for(PropertySource ps:getPropertySources()){
+            if(name.equals(ps.getName())){
+                return ps;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public <T> void addPropertyConverter(TypeLiteral<T> typeToConvert, PropertyConverter<T> propertyConverter) {
+        propertyConverterManager.register(typeToConvert, propertyConverter);
+        LOG.info("Added PropertyConverter: " + propertyConverter.getClass().getName());
+    }
+
+    @Override
+    public Map<TypeLiteral<?>, List<PropertyConverter<?>>> getPropertyConverters() {
+        return propertyConverterManager.getPropertyConverters();
+    }
+
+    @Override
+    public <T> List<PropertyConverter<T>> getPropertyConverters(TypeLiteral<T> targetType) {
+        return propertyConverterManager.getPropertyConverters(targetType);
+    }
+
+    @Override
+    public List<PropertyFilter> getPropertyFilters() {
+        return immutablePropertyFilters;
+    }
+
+    @Override
+    public PropertyValueCombinationPolicy getPropertyValueCombinationPolicy(){
+        return propertyValueCombinationPolicy;
+    }
+
+    @Override
+    public ConfigurationContextBuilder toBuilder() {
+        return new DefaultConfigurationContextBuilder(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContextBuilder.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContextBuilder.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContextBuilder.java
new file mode 100644
index 0000000..0ee54da
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContextBuilder.java
@@ -0,0 +1,431 @@
+/*
+ * 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.spisupport;
+
+import org.apache.tamaya.spi.TypeLiteral;
+import org.apache.tamaya.spi.*;
+import org.apache.tamaya.spisupport.propertysource.CLIPropertySource;
+import org.apache.tamaya.spisupport.propertysource.EnvironmentPropertySource;
+import org.apache.tamaya.spisupport.propertysource.JavaConfigurationPropertySource;
+import org.apache.tamaya.spisupport.propertysource.SystemPropertySource;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.*;
+import java.util.logging.Logger;
+
+/**
+ * Default implementation of {@link ConfigurationContextBuilder}.
+ */
+public class DefaultConfigurationContextBuilder implements ConfigurationContextBuilder {
+
+    private static final Logger LOG = Logger.getLogger(DefaultConfigurationContextBuilder.class.getName());
+
+    protected List<PropertyFilter> propertyFilters = new ArrayList<>();
+    protected List<PropertySource> propertySources = new ArrayList<>();
+    protected PropertyValueCombinationPolicy combinationPolicy = PropertyValueCombinationPolicy.DEFAULT_OVERRIDING_POLICY;
+    protected Map<TypeLiteral<?>, Collection<PropertyConverter<?>>> propertyConverters = new HashMap<>();
+
+    /**
+     * Flag if the config has already been built.
+     * Configuration can be built only once
+     */
+    private boolean built;
+
+
+
+    /**
+     * Creates a new builder instance.
+     */
+    public DefaultConfigurationContextBuilder() {
+    }
+
+    /**
+     * Creates a new builder instance initializing it with the given context.
+     * @param context the context to be used, not null.
+     */
+    public DefaultConfigurationContextBuilder(ConfigurationContext context) {
+        this.propertyConverters.putAll(context.getPropertyConverters());
+        this.propertyFilters.addAll(context.getPropertyFilters());
+        for(PropertySource ps:context.getPropertySources()) {
+            addPropertySources(ps);
+        }
+        this.combinationPolicy = context.getPropertyValueCombinationPolicy();
+    }
+
+    /**
+     * Allows to reset configuration context during unit tests.
+     */
+    public final ConfigurationContextBuilder resetWithConfigurationContext(ConfigurationContext configurationContext) {
+        checkBuilderState();
+        //noinspection deprecation
+        this.propertyFilters.clear();
+        this.propertyFilters.addAll(configurationContext.getPropertyFilters());
+        this.propertySources.clear();
+        for(PropertySource ps:configurationContext.getPropertySources()) {
+            addPropertySources(ps);
+        }
+        this.propertyConverters.clear();
+        this.propertyConverters.putAll(configurationContext.getPropertyConverters());
+        this.combinationPolicy = configurationContext.getPropertyValueCombinationPolicy();
+        return this;
+    }
+
+
+    @Override
+    public ConfigurationContextBuilder setContext(ConfigurationContext context) {
+        checkBuilderState();
+        this.propertyConverters.putAll(context.getPropertyConverters());
+        for(PropertySource ps:context.getPropertySources()){
+            this.propertySources.add(ps);
+        }
+        this.propertyFilters.addAll(context.getPropertyFilters());
+        this.combinationPolicy = context.getPropertyValueCombinationPolicy();
+        return this;
+    }
+
+    @Override
+    public final ConfigurationContextBuilder addPropertySources(PropertySource... sources){
+        return addPropertySources(Arrays.asList(sources));
+    }
+
+    @Override
+    public ConfigurationContextBuilder addPropertySources(Collection<PropertySource> sources){
+        checkBuilderState();
+        for(PropertySource source:sources) {
+            if (!this.propertySources.contains(source)) {
+                this.propertySources.add(source);
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationContextBuilder addDefaultPropertySources() {
+        checkBuilderState();
+        List<PropertySource> propertySources = new ArrayList<>();
+        addCorePropertyResources(propertySources);
+        for(PropertySource ps: ServiceContextManager.getServiceContext().getServices(PropertySource.class)) {
+            if(!propertySources.contains(ps)){
+                propertySources.add(ps);
+            }
+        }
+        for(PropertySourceProvider provider:
+                ServiceContextManager.getServiceContext().getServices(PropertySourceProvider.class)){
+                propertySources.addAll(provider.getPropertySources());
+        }
+        Collections.sort(propertySources, PropertySourceComparator.getInstance());
+        return addPropertySources(propertySources);
+    }
+
+    protected void addCorePropertyResources(List<PropertySource> propertySources) {
+        for(PropertySource ps: new PropertySource[]{
+                new EnvironmentPropertySource(),
+                new JavaConfigurationPropertySource(),
+                new CLIPropertySource(),
+                new SystemPropertySource()
+        }){
+            if(!propertySources.contains(ps)){
+                propertySources.add(ps);
+            }
+        }
+    }
+
+    @Override
+    public ConfigurationContextBuilder addDefaultPropertyFilters() {
+        checkBuilderState();
+        for(PropertyFilter pf:ServiceContextManager.getServiceContext().getServices(PropertyFilter.class)){
+            addPropertyFilters(pf);
+        }
+        return this;
+    }
+
+    @Override
+    public DefaultConfigurationContextBuilder addDefaultPropertyConverters() {
+        checkBuilderState();
+        addCorePropertyConverters();
+        for(Map.Entry<TypeLiteral, Collection<PropertyConverter>> en:getDefaultPropertyConverters().entrySet()){
+            for(PropertyConverter pc: en.getValue()) {
+                addPropertyConverters(en.getKey(), pc);
+            }
+        }
+        return this;
+    }
+
+    @SuppressWarnings("unchecked")
+	protected void addCorePropertyConverters() {
+        // should be overridden by subclasses.
+    }
+
+    @Override
+    public final ConfigurationContextBuilder removePropertySources(PropertySource... propertySources) {
+        return removePropertySources(Arrays.asList(propertySources));
+    }
+
+    @Override
+    public ConfigurationContextBuilder removePropertySources(Collection<PropertySource> propertySources) {
+        checkBuilderState();
+        this.propertySources.removeAll(propertySources);
+        return this;
+    }
+
+    protected PropertySource getPropertySource(String name) {
+        for(PropertySource ps:propertySources){
+            if(ps.getName().equals(name)){
+                return ps;
+            }
+        }
+        throw new IllegalArgumentException("No such PropertySource: "+name);
+    }
+
+    @Override
+    public List<PropertySource> getPropertySources() {
+        return Collections.unmodifiableList(this.propertySources);
+    }
+
+    @Override
+    public ConfigurationContextBuilder increasePriority(PropertySource propertySource) {
+        checkBuilderState();
+        int index = propertySources.indexOf(propertySource);
+        if(index<0){
+            throw new IllegalArgumentException("No such PropertySource: " + propertySource);
+        }
+        if(index<(propertySources.size()-1)){
+            propertySources.remove(propertySource);
+            propertySources.add(index+1, propertySource);
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationContextBuilder decreasePriority(PropertySource propertySource) {
+        checkBuilderState();
+        int index = propertySources.indexOf(propertySource);
+        if(index<0){
+            throw new IllegalArgumentException("No such PropertySource: " + propertySource);
+        }
+        if(index>0){
+            propertySources.remove(propertySource);
+            propertySources.add(index-1, propertySource);
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationContextBuilder highestPriority(PropertySource propertySource) {
+        checkBuilderState();
+        int index = propertySources.indexOf(propertySource);
+        if(index<0){
+            throw new IllegalArgumentException("No such PropertySource: " + propertySource);
+        }
+        if(index<(propertySources.size()-1)){
+            propertySources.remove(propertySource);
+            propertySources.add(propertySource);
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationContextBuilder lowestPriority(PropertySource propertySource) {
+        checkBuilderState();
+        int index = propertySources.indexOf(propertySource);
+        if(index<0){
+            throw new IllegalArgumentException("No such PropertySource: " + propertySource);
+        }
+        if(index>0){
+            propertySources.remove(propertySource);
+            propertySources.add(0, propertySource);
+        }
+        return this;
+    }
+
+    @Override
+    public final ConfigurationContextBuilder addPropertyFilters(PropertyFilter... filters){
+        return addPropertyFilters(Arrays.asList(filters));
+    }
+
+    @Override
+    public final ConfigurationContextBuilder addPropertyFilters(Collection<PropertyFilter> filters){
+        checkBuilderState();
+        for(PropertyFilter f:filters) {
+            if (!this.propertyFilters.contains(f)) {
+                this.propertyFilters.add(f);
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public final ConfigurationContextBuilder removePropertyFilters(PropertyFilter... filters) {
+        return removePropertyFilters(Arrays.asList(filters));
+    }
+
+    @Override
+    public final ConfigurationContextBuilder removePropertyFilters(Collection<PropertyFilter> filters) {
+        checkBuilderState();
+        this.propertyFilters.removeAll(filters);
+        return this;
+    }
+
+
+    @Override
+    public final <T> ConfigurationContextBuilder removePropertyConverters(TypeLiteral<T> typeToConvert,
+                                                                    @SuppressWarnings("unchecked") PropertyConverter<T>... converters) {
+        return removePropertyConverters(typeToConvert, Arrays.asList(converters));
+    }
+
+    @Override
+    public final <T> ConfigurationContextBuilder removePropertyConverters(TypeLiteral<T> typeToConvert,
+                                                                    Collection<PropertyConverter<T>> converters) {
+        Collection<PropertyConverter<?>> subConverters = this.propertyConverters.get(typeToConvert);
+        if(subConverters!=null) {
+            subConverters.removeAll(converters);
+        }
+        return this;
+    }
+
+    @Override
+    public final ConfigurationContextBuilder removePropertyConverters(TypeLiteral<?> typeToConvert) {
+        this.propertyConverters.remove(typeToConvert);
+        return this;
+    }
+
+
+    @Override
+    public final ConfigurationContextBuilder setPropertyValueCombinationPolicy(PropertyValueCombinationPolicy combinationPolicy){
+        checkBuilderState();
+        this.combinationPolicy = Objects.requireNonNull(combinationPolicy);
+        return this;
+    }
+
+
+    @Override
+    public <T> ConfigurationContextBuilder addPropertyConverters(TypeLiteral<T> type, PropertyConverter<T>... propertyConverters){
+        checkBuilderState();
+        Objects.requireNonNull(type);
+        Objects.requireNonNull(propertyConverters);
+        Collection<PropertyConverter<?>> converters = this.propertyConverters.get(type);
+        if(converters==null){
+            converters = new ArrayList<>();
+            this.propertyConverters.put(type, converters);
+        }
+        for(PropertyConverter<T> propertyConverter:propertyConverters) {
+            if (!converters.contains(propertyConverter)) {
+                converters.add(propertyConverter);
+            } else {
+                LOG.warning("Converter ignored, already registered: " + propertyConverter);
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public <T> ConfigurationContextBuilder addPropertyConverters(TypeLiteral<T> type, Collection<PropertyConverter<T>> propertyConverters){
+        checkBuilderState();
+        Objects.requireNonNull(type);
+        Objects.requireNonNull(propertyConverters);
+        Collection<PropertyConverter<?>> converters = this.propertyConverters.get(type);
+        if(converters==null){
+            converters = new ArrayList<>();
+            this.propertyConverters.put(type, converters);
+        }
+        for(PropertyConverter<T> propertyConverter:propertyConverters) {
+            if (!converters.contains(propertyConverter)) {
+                converters.add(propertyConverter);
+            } else {
+                LOG.warning("Converter ignored, already registered: " + propertyConverter);
+            }
+        }
+        return this;
+    }
+
+    protected ConfigurationContextBuilder loadDefaults() {
+        checkBuilderState();
+        this.combinationPolicy = PropertyValueCombinationPolicy.DEFAULT_OVERRIDING_COLLECTOR;
+        addDefaultPropertySources();
+        addDefaultPropertyFilters();
+        addDefaultPropertyConverters();
+        return this;
+    }
+
+
+    protected Map<TypeLiteral, Collection<PropertyConverter>> getDefaultPropertyConverters() {
+        Map<TypeLiteral, Collection<PropertyConverter>> result = new HashMap<>();
+        for (PropertyConverter conv : ServiceContextManager.getServiceContext().getServices(
+                PropertyConverter.class)) {
+            for(Type type:conv.getClass().getGenericInterfaces()){
+                if(type instanceof ParameterizedType){
+                    ParameterizedType pt = (ParameterizedType)type;
+                    if(PropertyConverter.class.equals(((ParameterizedType) type).getRawType())){
+                        TypeLiteral target = TypeLiteral.of(pt.getActualTypeArguments()[0]);
+                        Collection<PropertyConverter> convList = result.get(target);
+                        if (convList == null) {
+                            convList = new ArrayList<>();
+                            result.put(target, convList);
+                        }
+                        convList.add(conv);
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+
+    /**
+     * Builds a new configuration based on the configuration of this builder instance.
+     *
+     * @return a new {@link org.apache.tamaya.Configuration configuration instance},
+     *         never {@code null}.
+     */
+    @Override
+    public ConfigurationContext build() {
+        checkBuilderState();
+        built = true;
+        return new DefaultConfigurationContext(this);
+    }
+
+    @Override
+    public ConfigurationContextBuilder sortPropertyFilter(Comparator<PropertyFilter> comparator) {
+        Collections.sort(propertyFilters, comparator);
+        return this;
+    }
+
+    @Override
+    public ConfigurationContextBuilder sortPropertySources(Comparator<PropertySource> comparator) {
+        Collections.sort(propertySources, comparator);
+        return this;
+    }
+
+    private void checkBuilderState() {
+        if (built) {
+            throw new IllegalStateException("Configuration has already been build.");
+        }
+    }
+
+    @Override
+    public List<PropertyFilter> getPropertyFilters() {
+        return propertyFilters;
+    }
+
+    @Override
+    public Map<TypeLiteral<?>, Collection<PropertyConverter<?>>> getPropertyConverter() {
+        return Collections.unmodifiableMap(this.propertyConverters);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/EnumConverter.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/EnumConverter.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/EnumConverter.java
new file mode 100644
index 0000000..1dd00c0
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/EnumConverter.java
@@ -0,0 +1,39 @@
+/*
+ * 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.spisupport;
+
+import org.apache.tamaya.spi.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+/**
+ * Converter, converting from String to tge given enum type.
+ */
+public class EnumConverter<T extends Enum> implements PropertyConverter<T>{
+
+    private org.apache.tamaya.base.convert.EnumConverter<T> converter;
+
+    public EnumConverter(Class<T> enumType){
+        converter = new org.apache.tamaya.base.convert.EnumConverter<>(enumType);
+    }
+
+    @Override
+    public T convert(String value, ConversionContext context) {
+        return converter.convert(value);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java
new file mode 100644
index 0000000..dbef51f
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java
@@ -0,0 +1,84 @@
+/*
+ * 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.spisupport;
+
+import javax.annotation.Priority;
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Comparator implementation for odering services loaded based on their increasing priority values.
+ */
+public class PriorityServiceComparator implements Comparator<Object>, Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final PriorityServiceComparator INSTANCE = new PriorityServiceComparator();
+
+    /** Singleton constructor. */
+    private PriorityServiceComparator(){}
+
+    /**
+     * Get the shared instance of the comparator.
+     * @return the shared instance, never null.
+     */
+    public static PriorityServiceComparator getInstance(){
+        return INSTANCE;
+    }
+
+    @Override
+    public int compare(Object o1, Object o2) {
+        int prio = getPriority(o1) - getPriority(o2);
+        if (prio < 0) {
+            return 1;
+        } else if (prio > 0) {
+            return -1;
+        } else {
+            return o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName());
+        }
+    }
+
+    /**
+     * Checks the given instance for a @Priority annotation. If present the annotation's value is evaluated. If no such
+     * annotation is present, a default priority {@code 1} is returned.
+     *
+     * @param o the instance, not {@code null}.
+     * @return a priority, by default 1.
+     */
+    public static int getPriority(Object o) {
+        return getPriority(o.getClass());
+    }
+
+    /**
+     * Checks the given type optionally annotated with a @Priority. If present the annotation's value is evaluated.
+     * If no such annotation is present, a default priority {@code 1} is returned.
+     *
+     * @param type the type, not {@code null}.
+     * @return a priority, by default 1.
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public static int getPriority(Class type) {
+        int prio = 1;
+		Priority priority = (Priority)type.getAnnotation(Priority.class);
+        if (priority != null) {
+            prio = priority.value();
+        }
+        return prio;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java
new file mode 100644
index 0000000..7bc8d26
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java
@@ -0,0 +1,472 @@
+/*
+ * 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.spisupport;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.spi.TypeLiteral;
+import org.apache.tamaya.base.PriorityServiceComparator;
+import org.apache.tamaya.spi.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+import org.apache.tamaya.spi.ServiceContextManager;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Manager that deals with {@link PropertyConverter} instances.
+ * This class is thread-safe.
+ */
+public class PropertyConverterManager {
+    /**
+     * The logger used.
+     */
+    private static final Logger LOG = Logger.getLogger(PropertyConverterManager.class.getName());
+    /**
+     * The registered converters.
+     */
+    private final Map<TypeLiteral<?>, List<PropertyConverter<?>>> converters = new ConcurrentHashMap<>();
+    /**
+     * The transitive converters.
+     */
+    private final Map<TypeLiteral<?>, List<PropertyConverter<?>>> transitiveConverters = new ConcurrentHashMap<>();
+    /**
+     * The lock used.
+     */
+    private final ReadWriteLock lock = new ReentrantReadWriteLock();
+
+    private static final Comparator<Object> PRIORITY_COMPARATOR = new Comparator<Object>() {
+
+        @Override
+        public int compare(Object o1, Object o2) {
+            int prio = org.apache.tamaya.base.PriorityServiceComparator.getPriority(o1) - PriorityServiceComparator.getPriority(o2);
+            if (prio < 0) {
+                return 1;
+            } else if (prio > 0) {
+                return -1;
+            } else {
+                return o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName());
+            }
+        }
+    };
+
+    /**
+     * Constructor.
+     */
+    public PropertyConverterManager() {
+        this(false);
+    }
+
+    public PropertyConverterManager(boolean init) {
+        if (init) {
+            initConverters();
+        }
+    }
+
+    /**
+     * Registers the default converters provided out of the box.
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    protected void initConverters() {
+        for (PropertyConverter conv : ServiceContextManager.getServiceContext().getServices(PropertyConverter.class)) {
+            Type type = TypeLiteral.getGenericInterfaceTypeParameters(conv.getClass(), PropertyConverter.class)[0];
+            register(TypeLiteral.of(type), conv);
+        }
+    }
+
+    /**
+     * Registers a new converters instance.
+     *
+     * @param targetType the target type, not {@code null}.
+     * @param converter  the converters, not {@code null}.
+     * @param <T>        the type.
+     */
+    @SuppressWarnings("unchecked")
+    public <T> void register(TypeLiteral<T> targetType, PropertyConverter<T> converter) {
+        Objects.requireNonNull(converter);
+        Lock writeLock = lock.writeLock();
+        try {
+            writeLock.lock();
+			List<PropertyConverter<?>> converters = List.class.cast(this.converters.get(targetType));
+            if(converters!=null && converters.contains(converter)){
+                return;
+            }
+            List<PropertyConverter<?>> newConverters = new ArrayList<>();
+            if (converters != null) {
+                newConverters.addAll(converters);
+            }
+            if(!newConverters.contains(converter)) {
+                newConverters.add(converter);
+            }
+            Collections.sort(newConverters, PRIORITY_COMPARATOR);
+            this.converters.put(targetType, Collections.unmodifiableList(newConverters));
+            // evaluate transitive closure for all inherited supertypes and implemented interfaces
+            // direct implemented interfaces
+            for (Class<?> ifaceType : targetType.getRawType().getInterfaces()) {
+                converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(ifaceType)));
+                newConverters = new ArrayList<>();
+                if (converters != null) {
+                    newConverters.addAll(converters);
+                }
+                newConverters.add(converter);
+                Collections.sort(newConverters, PRIORITY_COMPARATOR);
+                this.transitiveConverters.put(TypeLiteral.of(ifaceType), Collections.unmodifiableList(newConverters));
+            }
+            Class<?> superClass = targetType.getRawType().getSuperclass();
+            while (superClass != null && !superClass.equals(Object.class)) {
+                converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(superClass)));
+                newConverters = new ArrayList<>();
+                if (converters != null) {
+                    newConverters.addAll(converters);
+                }
+                newConverters.add(converter);
+                Collections.sort(newConverters, PRIORITY_COMPARATOR);
+                this.transitiveConverters.put(TypeLiteral.of(superClass), Collections.unmodifiableList(newConverters));
+                for (Class<?> ifaceType : superClass.getInterfaces()) {
+                    converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(ifaceType)));
+                    newConverters = new ArrayList<>();
+                    if (converters != null) {
+                        newConverters.addAll(converters);
+                    }
+                    newConverters.add(converter);
+                    Collections.sort(newConverters, PRIORITY_COMPARATOR);
+                    this.transitiveConverters.put(TypeLiteral.of(ifaceType), Collections.unmodifiableList(newConverters));
+                }
+                superClass = superClass.getSuperclass();
+            }
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    /**
+     * Allows to evaluate if a given target type is supported.
+     *
+     * @param targetType the target type, not {@code null}.
+     * @return true, if a converters for the given type is registered, or a default one can be created.
+     */
+    public boolean isTargetTypeSupported(TypeLiteral<?> targetType) {
+        return converters.containsKey(targetType) || transitiveConverters.containsKey(targetType) || createDefaultPropertyConverter(targetType) != null;
+    }
+
+    /**
+     * Get a map of all property converters currently registered. This will not contain the converters that
+     * may be created, when an instance is adapted, which provides a String constructor or compatible
+     * factory methods taking a single String instance.
+     *
+     * @return the current map of instantiated and registered converters.
+     * @see #createDefaultPropertyConverter(TypeLiteral)
+     */
+    public Map<TypeLiteral<?>, List<PropertyConverter<?>>> getPropertyConverters() {
+        Lock readLock = lock.readLock();
+        try {
+            readLock.lock();
+            return new HashMap<>(this.converters);
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    /**
+     * Get the list of all current registered converters for the given target type.
+     * If not converters are registered, they component tries to create and addSources a dynamic
+     * converters based on String constructor or static factory methods available.
+     * The converters provided are of the following type and returned in the following order:
+     * <ul>
+     * <li>Converters mapped explicitly to the required target type are returned first, ordered
+     * by decreasing priority. This means, if explicit converters are registered these are used
+     * primarily for converting a value.</li>
+     * <li>The target type of each explicitly registered converters also can be transitively mapped to
+     * 1) all directly implemented interfaces, 2) all its superclasses (except Object), 3) all the interfaces
+     * implemented by its superclasses. These groups of transitive converters is returned similarly in the
+     * order as mentioned, whereas also here a priority based decreasing ordering is applied.</li>
+     * <li>java.lang wrapper classes and native types are automatically mapped.</li>
+     * <li>If no explicit converters are registered, for Enum types a default implementation is provided that
+     * compares the configuration values with the different enum members defined (cases sensitive mapping).</li>
+     * </ul>
+     * <p>
+     * So given that list above directly registered mappings always are tried first, before any transitive mapping
+     * should be used. Also in all cases @Priority annotations are honored for ordering of the converters in place.
+     * Transitive conversion is supported for all directly implemented interfaces (including inherited ones) and
+     * the inheritance hierarchy (exception Object). Superinterfaces of implemented interfaces are ignored.
+     *
+     * @param targetType the target type, not {@code null}.
+     * @param <T>        the type class
+     * @return the ordered list of converters (may be empty for not convertible types).
+     * @see #createDefaultPropertyConverter(TypeLiteral)
+     */
+    public <T> List<PropertyConverter<T>> getPropertyConverters(TypeLiteral<T> targetType) {
+        Lock readLock = lock.readLock();
+        List<PropertyConverter<T>> converterList = new ArrayList<>();
+        // direct mapped converters
+        try {
+            readLock.lock();
+            addConvertersToList(List.class.cast(this.converters.get(targetType)), converterList);
+            addConvertersToList(List.class.cast(this.transitiveConverters.get(targetType)), converterList);
+        } finally {
+            readLock.unlock();
+        }
+        // handling of java.lang wrapper classes
+        TypeLiteral<T> boxedType = mapBoxedType(targetType);
+        if (boxedType != null) {
+            try {
+                readLock.lock();
+                addConvertersToList(List.class.cast(this.converters.get(boxedType)), converterList);
+            } finally {
+                readLock.unlock();
+            }
+        }
+        if (converterList.isEmpty() && !TypeLiteral.of(String.class).equals(targetType)) {
+            // adding any converters created on the fly, e.g. for enum types.
+            PropertyConverter<T> defaultConverter = createDefaultPropertyConverter(targetType);
+            if (defaultConverter != null) {
+                register(targetType, defaultConverter);
+                try {
+                    readLock.lock();
+                    addConvertersToList(List.class.cast(this.converters.get(targetType)), converterList);
+                } finally {
+                    readLock.unlock();
+                }
+            }
+        }
+        // check for parametrized types, ignoring param type
+        // direct mapped converters
+        if(targetType.getType()!=null) {
+            try {
+                readLock.lock();
+                addConvertersToList(List.class.cast(this.converters.get(
+                        TypeLiteral.of(targetType.getRawType()))), converterList);
+            } finally {
+                readLock.unlock();
+            }
+        }
+        return converterList;
+    }
+
+    private <T> void addConvertersToList(Collection<PropertyConverter<T>> converters, List<PropertyConverter<T>> converterList) {
+        if (converters != null) {
+            for(PropertyConverter<T> conv:converters) {
+                if(!converterList.contains(conv)) {
+                    converterList.add(conv);
+                }
+            }
+        }
+    }
+
+    /**
+     * Maps native types to the corresponding boxed types.
+     *
+     * @param targetType the native type.
+     * @param <T>        the type
+     * @return the boxed type, or null.
+     */
+    @SuppressWarnings("unchecked")
+	private <T> TypeLiteral<T> mapBoxedType(TypeLiteral<T> targetType) {
+        Type parameterType = targetType.getType();
+        if (parameterType == int.class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Integer.class));
+        }
+        if (parameterType == short.class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Short.class));
+        }
+        if (parameterType == byte.class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Byte.class));
+        }
+        if (parameterType == long.class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Long.class));
+        }
+        if (parameterType == boolean.class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Boolean.class));
+        }
+        if (parameterType == char.class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Character.class));
+        }
+        if (parameterType == float.class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Float.class));
+        }
+        if (parameterType == double.class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Double.class));
+        }
+        if (parameterType == int[].class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Integer[].class));
+        }
+        if (parameterType == short[].class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Short[].class));
+        }
+        if (parameterType == byte[].class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Byte[].class));
+        }
+        if (parameterType == long[].class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Long[].class));
+        }
+        if (parameterType == boolean.class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Boolean.class));
+        }
+        if (parameterType == char[].class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Character[].class));
+        }
+        if (parameterType == float[].class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Float[].class));
+        }
+        if (parameterType == double[].class) {
+            return TypeLiteral.class.cast(TypeLiteral.of(Double[].class));
+        }
+        return null;
+    }
+
+    /**
+     * Creates a dynamic PropertyConverter for the given target type.
+     *
+     * @param targetType the target type
+     * @param <T>        the type class
+     * @return a new converters, or null.
+     */
+    protected <T> PropertyConverter<T> createDefaultPropertyConverter(final TypeLiteral<T> targetType) {
+        if (Enum.class.isAssignableFrom(targetType.getRawType())) {
+            return new EnumConverter(targetType.getRawType());
+        }
+        PropertyConverter<T> converter = null;
+        final Method factoryMethod = getFactoryMethod(targetType.getRawType(), "of", "valueOf", "instanceOf", "getInstance", "from", "fromString", "parse");
+        if (factoryMethod != null) {
+            converter = new DefaultPropertyConverter<>(factoryMethod, targetType.getRawType());
+        }
+        if (converter == null) {
+            final Constructor<T> constr;
+            try {
+                constr = targetType.getRawType().getDeclaredConstructor(String.class);
+            } catch (NoSuchMethodException e) {
+                LOG.log(Level.FINEST, "No matching constrctor for " + targetType, e);
+                return null;
+            }
+            converter = new PropertyConverter<T>() {
+                    @Override
+                    public T convert(String value, ConversionContext context) {
+                        AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                            @Override
+                            public Object run() {
+                                AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                                    @Override
+                                    public Object run() {
+                                        constr.setAccessible(true);
+                                        return null;
+                                    }
+                                });
+                                return null;
+                            }
+                        });
+                        try {
+                            return constr.newInstance(value);
+                        } catch (Exception e) {
+                            LOG.log(Level.SEVERE, "Error creating new PropertyConverter instance " + targetType, e);
+                        }
+                        return null;
+                    }
+                };
+        }
+        return converter;
+    }
+
+    /**
+     * Tries to evaluate a factory method that can be used to create an instance based on a String.
+     *
+     * @param type        the target type
+     * @param methodNames the possible static method names
+     * @return the first method found, or null.
+     */
+    private Method getFactoryMethod(Class<?> type, String... methodNames) {
+        Method m;
+        for (String name : methodNames) {
+            try {
+                m = type.getDeclaredMethod(name, String.class);
+                return m;
+            } catch (NoSuchMethodException | RuntimeException e) {
+                LOG.finest("No such factory method found on type: " + type.getName() + ", methodName: " + name);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof PropertyConverterManager)) {
+            return false;
+        }
+        PropertyConverterManager that = (PropertyConverterManager) o;
+        return converters.equals(that.converters);
+
+    }
+
+    @Override
+    public int hashCode() {
+        return converters.hashCode();
+    }
+
+    /**
+     * Default converters im√ľ√∂ementation perfoming several lookups for String converion
+     * option.
+     * @param <T>
+     */
+    private static class DefaultPropertyConverter<T> implements PropertyConverter<T> {
+
+        private final Method factoryMethod;
+        private final Class<T> targetType;
+
+        DefaultPropertyConverter(Method factoryMethod, Class<T> targetType){
+            this.factoryMethod = Objects.requireNonNull(factoryMethod);
+            this.targetType =  Objects.requireNonNull(targetType);
+        }
+
+        @Override
+        public T convert(String value, ConversionContext context) {
+            context.addSupportedFormats(getClass(), "<String -> "+factoryMethod.toGenericString());
+
+            if (!Modifier.isStatic(factoryMethod.getModifiers())) {
+                throw new ConfigException(factoryMethod.toGenericString() +
+                        " is not a static method. Only static " +
+                        "methods can be used as factory methods.");
+            }
+            try {
+                AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                    @Override
+                    public Object run() {
+                        factoryMethod.setAccessible(true);
+                        return null;
+                    }
+                });
+                Object invoke = factoryMethod.invoke(null, value);
+                return targetType.cast(invoke);
+            } catch (Exception e) {
+                throw new ConfigException("Failed to decode '" + value + "'", e);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java
new file mode 100644
index 0000000..20eef63
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java
@@ -0,0 +1,72 @@
+/*
+ * 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.spisupport;
+
+import org.apache.tamaya.spi.PropertyFilter;
+
+import javax.annotation.Priority;
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Comparator for PropertyFilters based on their priority annotations.
+ */
+public final class PropertyFilterComparator implements Comparator<PropertyFilter>, Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final PropertyFilterComparator INSTANCE = new PropertyFilterComparator();
+
+    /**
+     * Get the shared instance of the comparator.
+     * @return the shared instance, never null.
+     */
+    public static PropertyFilterComparator getInstance(){
+        return INSTANCE;
+    }
+
+    private PropertyFilterComparator(){}
+
+    /**
+     * Compare 2 filters for ordering the filter chain.
+     *
+     * @param filter1 the first filter
+     * @param filter2 the second filter
+     * @return the comparison result
+     */
+    private int comparePropertyFilters(PropertyFilter filter1, PropertyFilter filter2) {
+        Priority prio1 = filter1.getClass().getAnnotation(Priority.class);
+        Priority prio2 = filter2.getClass().getAnnotation(Priority.class);
+        int ord1 = prio1 != null ? prio1.value() : 0;
+        int ord2 = prio2 != null ? prio2.value() : 0;
+
+        if (ord1 < ord2) {
+            return -1;
+        } else if (ord1 > ord2) {
+            return 1;
+        } else {
+            return filter1.getClass().getName().compareTo(filter2.getClass().getName());
+        }
+    }
+
+    @Override
+    public int compare(PropertyFilter filter1, PropertyFilter filter2) {
+        return comparePropertyFilters(filter1, filter2);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java
new file mode 100644
index 0000000..af69899
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java
@@ -0,0 +1,123 @@
+/*
+ * 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.spisupport;
+
+import org.apache.tamaya.spi.ConfigurationContext;
+import org.apache.tamaya.spi.FilterContext;
+import org.apache.tamaya.spi.PropertyFilter;
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Implementation of the Configuration API. This class uses the current {@link ConfigurationContext} to evaluate the
+ * chain of {@link org.apache.tamaya.spi.PropertySource} and {@link PropertyFilter}
+ * instance to evaluate the current Configuration.
+ */
+public final class PropertyFiltering{
+    /**
+     * The logger.
+     */
+    private static final Logger LOG = Logger.getLogger(PropertyFiltering.class.getName());
+    /**
+     * The maximal number of filter cycles performed before aborting.
+     */
+    private static final int MAX_FILTER_LOOPS = 10;
+
+    /**
+     * Private singleton constructor.
+     */
+    private PropertyFiltering(){}
+
+    /**
+     * Filters a single value.
+     * @param value the raw value, not {@code null}.
+     * @param context the context
+     * @return the filtered value, including {@code null}.
+     */
+    public static PropertyValue applyFilter(PropertyValue value, ConfigurationContext context) {
+        FilterContext filterContext = new FilterContext(value, context);
+        return filterValue(filterContext);
+    }
+
+    /**
+     * Filters all properties.
+     * @param rawProperties the unfiltered properties, not {@code null}.
+     * @param context the context
+     * @return the filtered value, inclusing null.
+     */
+    public static Map<String, PropertyValue> applyFilters(Map<String, PropertyValue> rawProperties, ConfigurationContext context) {
+        Map<String, PropertyValue> result = new HashMap<>();
+        // Apply filters to values, prevent values filtered to null!
+        for (Map.Entry<String, PropertyValue> entry : rawProperties.entrySet()) {
+            FilterContext filterContext = new FilterContext(entry.getValue(), rawProperties, context);
+            PropertyValue filtered = filterValue(filterContext);
+            if(filtered!=null){
+                result.put(filtered.getKey(), filtered);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Basic filter logic.
+     * @param context the filter context, not {@code null}.
+     * @return the filtered value.
+     */
+    private static PropertyValue filterValue(FilterContext context) {
+        PropertyValue inputValue = context.getProperty();
+        PropertyValue filteredValue = inputValue;
+
+        for (int i = 0; i < MAX_FILTER_LOOPS; i++) {
+            int changes = 0;
+            for (PropertyFilter filter : context.getContext().getPropertyFilters()) {
+                filteredValue = filter.filterProperty(inputValue, context);
+                if (filteredValue != null && !filteredValue.equals(inputValue)) {
+                    changes++;
+                    LOG.finest("Filter - " + inputValue + " -> " + filteredValue + " by " + filter);
+                }
+                if(filteredValue==null){
+                    LOG.finest("Filter removed entry - " + inputValue + ": " + filter);
+                    break;
+                }else{
+                    inputValue = filteredValue;
+                }
+            }
+            if (changes == 0) {
+                LOG.finest("Finishing filter loop, no changes detected.");
+                break;
+            } else if (filteredValue == null) {
+                break;
+            } else {
+                if (i == (MAX_FILTER_LOOPS - 1)) {
+                    if (LOG.isLoggable(Level.WARNING)) {
+                        LOG.warning("Maximal filter loop count reached, aborting filter evaluation after cycles: " + i);
+                    }
+                } else {
+                    LOG.finest("Repeating filter loop, changes detected: " + changes);
+                }
+            }
+        }
+        return filteredValue;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java
new file mode 100644
index 0000000..e9511b5
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java
@@ -0,0 +1,120 @@
+/*
+ * 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.spisupport;
+
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+
+import javax.annotation.Priority;
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.logging.Logger;
+
+/**
+ * Comparator for ordering of PropertySources based on their ordinal method and class name.
+ */
+public class PropertySourceComparator implements Comparator<PropertySource>, Serializable {
+    /** serial version UID. */
+    private static final long serialVersionUID = 1L;
+
+    private static final Logger LOG = Logger.getLogger(PropertySourceComparator.class.getName());
+
+    private static final PropertySourceComparator INSTANCE = new PropertySourceComparator();
+
+    private String alternativeOrdinalKey;
+
+    /** Singleton constructor. */
+    private PropertySourceComparator(){}
+
+    /**
+     * Get the shared instance of the comparator.
+     * @return the shared instance, never null.
+     */
+    public static PropertySourceComparator getInstance(){
+        return INSTANCE;
+    }
+
+
+    /**
+     * Order property source reversely, the most important comes first.
+     *
+     * @param source1 the first PropertySource
+     * @param source2 the second PropertySource
+     * @return the comparison result.
+     */
+    private int comparePropertySources(PropertySource source1, PropertySource source2) {
+        if (getOrdinal(source1) < getOrdinal(source2)) {
+            return -1;
+        } else if (getOrdinal(source1) > getOrdinal(source2)) {
+            return 1;
+        } else {
+            return source1.getClass().getName().compareTo(source2.getClass().getName());
+        }
+    }
+
+    /**
+     * Evaluates an ordinal value from a {@link PropertySource}, Hereby the ordinal of type {@code int}
+     * is evaluated as follows:
+     * <ol>
+     *     <li>It evaluates the {@code String} value for {@link PropertySource#TAMAYA_ORDINAL} and tries
+     *     to convert it to an {@code int} value, using {@link Integer#parseInt(String)}.</li>
+     *     <li>It tries to find and evaluate a method {@code int getOrdinal()}.</li>
+     *     <li>It tries to find and evaluate a static field {@code int ORDINAL}.</li>
+     *     <li>It tries to find and evaluate a class level {@link Priority} annotation.</li>
+     *     <li>It uses the default priority ({@code 0}.</li>
+     * </ol>
+     * @param propertySource the property source, not {@code null}.
+     * @return the ordinal value to compare the property source.
+     */
+    public static int getOrdinal(PropertySource propertySource) {
+        return getOrdinal(propertySource, null);
+    }
+
+    public static int getOrdinal(PropertySource propertySource, String alternativeOrdinalKey) {
+        if(alternativeOrdinalKey!=null) {
+            PropertyValue ordinalValue = propertySource.get(alternativeOrdinalKey);
+            if (ordinalValue != null) {
+                try {
+                    return Integer.parseInt(ordinalValue.getValue().trim());
+                } catch (Exception e) {
+                    LOG.finest("Failed to parse ordinal from " + alternativeOrdinalKey +
+                            " in " + propertySource.getName() + ": " + ordinalValue.getValue());
+                }
+            }
+        }
+        return propertySource.getOrdinal();
+    }
+
+    /**
+     * Overrides/adds the key to evaluate/override a property sources ordinal.
+     * @param ordinalKey sets the alternative ordinal key, if null default
+     *                   behaviour will be active.
+     * @return the instance for chaining.
+     */
+    public PropertySourceComparator setOrdinalKey(String ordinalKey) {
+        this.alternativeOrdinalKey = ordinalKey;
+        return this;
+    }
+
+    @Override
+    public int compare(PropertySource source1, PropertySource source2) {
+        return comparePropertySources(source1, source2);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/RegexPropertyFilter.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/RegexPropertyFilter.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/RegexPropertyFilter.java
new file mode 100644
index 0000000..9be444f
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/RegexPropertyFilter.java
@@ -0,0 +1,84 @@
+/*
+ * 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.spisupport;
+
+import org.apache.tamaya.spi.FilterContext;
+import org.apache.tamaya.spi.PropertyFilter;
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Predicate filtering using a regex expression operating on the key. It allows either
+ * to define the target keys to be selected (includes), or to be excluded (excludes).
+ */
+public final class RegexPropertyFilter implements PropertyFilter {
+    /** The expression used to include entries that match. */
+    private List<String> includes;
+    /** The expression used to exclude entries that match. */
+    private List<String> excludes;
+
+    /**
+     * Sets the regex expression to be applied on the key to filter the corresponding entry
+     * if matching.
+     * @param expressions the regular expression for inclusion, not null.
+     */
+    public void setIncludes(String... expressions){
+        this.includes = Arrays.asList(expressions);
+    }
+
+    /**
+     * Sets the regex expression to be applied on the key to remove the corresponding entries
+     * if matching.
+     * @param expressions the regular expressions for exclusion, not null.
+     */
+    public void setExcludes(String... expressions){
+        this.excludes= Arrays.asList(expressions);
+    }
+
+    @Override
+    public PropertyValue filterProperty(PropertyValue valueToBeFiltered, FilterContext context) {
+        if(includes!=null){
+            for(String expression:includes){
+                if(context.getProperty().getKey().matches(expression)){
+                    return valueToBeFiltered;
+                }
+            }
+            return null;
+        }
+        if(excludes!=null){
+            for(String expression:excludes){
+                if(context.getProperty().getKey().matches(expression)){
+                    return null;
+                }
+            }
+        }
+        return valueToBeFiltered;
+    }
+
+    @Override
+    public String toString() {
+        return "RegexPropertyFilter{" +
+                "includes='" + includes + '\'' +
+                "excludes='" + excludes + '\'' +
+                '}';
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BasePropertySource.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BasePropertySource.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BasePropertySource.java
new file mode 100644
index 0000000..6126b68
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BasePropertySource.java
@@ -0,0 +1,172 @@
+/*
+ * 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.spisupport.propertysource;
+
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Abstract {@link org.apache.tamaya.spi.PropertySource} that allows to set a default ordinal that will be used, if no
+ * ordinal is provided with the config.
+ */
+public abstract class BasePropertySource implements PropertySource{
+    /** default ordinal that will be used, if no ordinal is provided with the config. */
+    private int defaultOrdinal;
+    /** Used if the ordinal has been set explicitly. */
+    private volatile Integer ordinal;
+    /** The name of the property source. */
+    private String name;
+
+    /**
+     * Constructor.
+     * @param name the (unique) property source name, not {@code null}.
+     */
+    protected BasePropertySource(String name){
+        this.name = Objects.requireNonNull(name);
+        this.defaultOrdinal = 0;
+    }
+
+    /**
+     * Constructor.
+     * @param defaultOrdinal default ordinal that will be used, if no ordinal is provided with the config.
+     */
+    protected BasePropertySource(int defaultOrdinal){
+        this.name = getClass().getSimpleName();
+        this.defaultOrdinal = defaultOrdinal;
+    }
+
+    /**
+     * Constructor.
+     * @param name the (unique) property source name, not {@code null}.
+     * @param defaultOrdinal default ordinal that will be used, if no ordinal is provided with the config.
+     */
+    protected BasePropertySource(String name, int defaultOrdinal){
+        this.name = Objects.requireNonNull(name);
+        this.defaultOrdinal = defaultOrdinal;
+    }
+
+
+    /**
+     * Constructor, using a default ordinal of 0.
+     */
+    protected BasePropertySource(){
+        this(0);
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the property source's (unique) name.
+     * @param name the name, not {@code null}.
+     */
+    public void setName(String name){
+        this.name = Objects.requireNonNull(name);
+    }
+
+    /**
+     * Allows to set the ordinal of this property source explcitly. This will override any evaluated
+     * ordinal, or default ordinal. To reset an explcit ordinal call {@code setOrdinal(null);}.
+     * @param ordinal the explicit ordinal, or {@code null}.
+     */
+    public void setOrdinal(Integer ordinal){
+        this.ordinal = ordinal;
+    }
+
+    /**
+     * Allows to set the ordinal of this property source explcitly. This will override any evaluated
+     * ordinal, or default ordinal. To reset an explcit ordinal call {@code setOrdinal(null);}.
+     * @param defaultOrdinal the default ordinal, or {@code null}.
+     */
+    public void setDefaultOrdinal(Integer defaultOrdinal){
+        this.defaultOrdinal = defaultOrdinal;
+    }
+
+    public int getOrdinal() {
+        Integer ordinal = this.ordinal;
+        if(ordinal!=null){
+            Logger.getLogger(getClass().getName()).finest(
+                    "Using explicit ordinal '"+ordinal+"' for property source: " + getName());
+            return ordinal;
+        }
+        PropertyValue configuredOrdinal = get(TAMAYA_ORDINAL);
+        if(configuredOrdinal!=null){
+            try {
+                return Integer.parseInt(configuredOrdinal.getValue());
+            } catch (Exception e) {
+                Logger.getLogger(getClass().getName()).log(Level.WARNING,
+                        "Configured ordinal is not an int number: " + configuredOrdinal, e);
+            }
+        }
+        return getDefaultOrdinal();
+    }
+
+    /**
+     * Returns the  default ordinal used, when no ordinal is set, or the ordinal was not parseable to an int value.
+     * @return the  default ordinal used, by default 0.
+     */
+    public int getDefaultOrdinal(){
+        return defaultOrdinal;
+    }
+
+    @Override
+    public PropertyValue get(String key) {
+        Map<String,PropertyValue> properties = getProperties();
+        PropertyValue val = properties.get(key);
+        if(val==null){
+            return null;
+        }
+        return val;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        BasePropertySource that = (BasePropertySource) o;
+
+        return name.equals(that.name);
+    }
+
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "{" +
+                toStringValues() +
+                '}';
+    }
+
+    protected String toStringValues() {
+        return  "  defaultOrdinal=" + defaultOrdinal + '\n' +
+                "  ordinal=" + ordinal  + '\n' +
+                "  name='" + name + '\''  + '\n';
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d0e14ed7/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySource.java
----------------------------------------------------------------------
diff --git a/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySource.java b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySource.java
new file mode 100644
index 0000000..fbea188
--- /dev/null
+++ b/code/compat/src/main/java/org/apache/tamaya/spisupport/propertysource/BuildablePropertySource.java
@@ -0,0 +1,231 @@
+/*
+ * 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.spisupport.propertysource;
+
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+
+import java.util.*;
+
+/**
+ * A Buildable property source.
+ */
+public class BuildablePropertySource implements PropertySource{
+
+    private int ordinal;
+    private String name = "PropertySource-"+UUID.randomUUID().toString();
+    private Map<String,PropertyValue> properties = new HashMap<>();
+
+    @Override
+    public int getOrdinal() {
+        return ordinal;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public PropertyValue get(String key) {
+        return properties.get(key);
+    }
+
+    @Override
+    public Map<String, PropertyValue> getProperties() {
+        return Collections.unmodifiableMap(properties);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        BuildablePropertySource that = (BuildablePropertySource) o;
+
+        return name.equals(that.name);
+    }
+
+    @Override
+    public boolean isScannable() {
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "BuildablePropertySource{" +
+                "ordinal=" + ordinal +
+                ", name='" + name + '\'' +
+                ", properties=" + properties +
+                '}';
+    }
+
+    /**
+     * Builder builder.
+     *
+     * @return the builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+
+    /**
+     * The type Builder.
+     */
+    public static final class Builder {
+        private int ordinal;
+        private String source = "<on-the-fly-build>";
+        private String name = "PropertySource-"+ UUID.randomUUID().toString();
+        private Map<String,PropertyValue> properties = new HashMap<>();
+
+        private Builder() {
+        }
+
+        /**
+         * With ordinal builder.
+         *
+         * @param ordinal the ordinal
+         * @return the builder
+         */
+        public Builder withOrdinal(int ordinal) {
+            this.ordinal = ordinal;
+            return this;
+        }
+
+        /**
+         * With source builder.
+         *
+         * @param source the source
+         * @return the builder
+         */
+        public Builder withSource(String source) {
+            this.source = Objects.requireNonNull(source);
+            return this;
+        }
+
+        /**
+         * With name builder.
+         *
+         * @param name the name
+         * @return the builder
+         */
+        public Builder withName(String name) {
+            this.name = Objects.requireNonNull(name);
+            return this;
+        }
+
+        /**
+         * With simple property builder.
+         *
+         * @param key   the key
+         * @param value the value
+         * @return the builder
+         */
+        public Builder withSimpleProperty(String key, String value) {
+            return withProperties(PropertyValue.of(key, value, this.source));
+        }
+
+        /**
+         * With simple property builder.
+         *
+         * @param key    the key
+         * @param value  the value
+         * @param source the source
+         * @return the builder
+         */
+        public Builder withSimpleProperty(String key, String value, String source) {
+            return withProperties(PropertyValue.of(key, value, source));
+        }
+
+        /**
+         * With properties builder.
+         *
+         * @param values the values
+         * @return the builder
+         */
+        public Builder withProperties(PropertyValue... values) {
+            for(PropertyValue val:values){
+                this.properties.put(val.getKey(), val);
+            }
+            return this;
+        }
+
+        /**
+         * With properties builder.
+         *
+         * @param properties the properties
+         * @return the builder
+         */
+        public Builder withProperties(Map<String, PropertyValue> properties) {
+            this.properties =  Objects.requireNonNull(properties);
+            return this;
+        }
+
+        /**
+         * With properties builder.
+         *
+         * @param properties the properties
+         * @param source     the source
+         * @return the builder
+         */
+        public Builder withProperties(Map<String, String> properties, String source) {
+            this.properties.putAll(PropertyValue.map(properties, source));
+            return this;
+        }
+
+        /**
+         * With simple properties builder.
+         *
+         * @param properties the properties
+         * @return the builder
+         */
+        public Builder withSimpleProperties(Map<String, String> properties) {
+            this.properties.putAll(PropertyValue.map(properties, this.source));
+            return this;
+        }
+
+        /**
+         * But builder.
+         *
+         * @return the builder
+         */
+        public Builder but() {
+            return builder().withOrdinal(ordinal).withName(name).withProperties(properties);
+        }
+
+        /**
+         * Build buildable property source.
+         *
+         * @return the buildable property source
+         */
+        public BuildablePropertySource build() {
+            BuildablePropertySource buildablePropertySource = new BuildablePropertySource();
+            buildablePropertySource.name = this.name;
+            buildablePropertySource.properties = this.properties;
+            buildablePropertySource.ordinal = this.ordinal;
+            return buildablePropertySource;
+        }
+    }
+}


Mime
View raw message