Repository: incubator-tamaya-extensions Updated Branches: refs/heads/master 1aa999966 -> 45d8afdea
TAMAYA-300 Added tests to improver coverage. Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/commit/45d8afde Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/tree/45d8afde Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/diff/45d8afde Branch: refs/heads/master Commit: 45d8afdea32f6d1fc4d955e484db44d56651ce9d Parents: 1aa9999 Author: Anatole Tresch <[email protected]> Authored: Wed Nov 15 19:14:02 2017 +0100 Committer: Anatole Tresch <[email protected]> Committed: Wed Nov 15 19:14:02 2017 +0100 ---------------------------------------------------------------------- modules/injection/injection-api/pom.xml | 6 + .../tamaya/inject/spi/BaseDynamicValue.java | 166 +++++++++++++++++++ .../tamaya/inject/spi/BaseDynamicValueTest.java | 101 +++++++++++ 3 files changed, 273 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/45d8afde/modules/injection/injection-api/pom.xml ---------------------------------------------------------------------- diff --git a/modules/injection/injection-api/pom.xml b/modules/injection/injection-api/pom.xml index 57972d8..82c89c3 100644 --- a/modules/injection/injection-api/pom.xml +++ b/modules/injection/injection-api/pom.xml @@ -45,6 +45,12 @@ under the License. <scope>provided</scope> </dependency> <dependency> + <groupId>org.apache.tamaya</groupId> + <artifactId>tamaya-core</artifactId> + <version>${tamaya-apicore.version}</version> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.apache.geronimo.specs</groupId> <artifactId>geronimo-atinject_1.0_spec</artifactId> <version>${geronimo-atinject-1.0-spec.version}</version> http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/45d8afde/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/spi/BaseDynamicValue.java ---------------------------------------------------------------------- diff --git a/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/spi/BaseDynamicValue.java b/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/spi/BaseDynamicValue.java index 1d0e75e..59e7683 100644 --- a/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/spi/BaseDynamicValue.java +++ b/modules/injection/injection-api/src/main/java/org/apache/tamaya/inject/spi/BaseDynamicValue.java @@ -18,10 +18,23 @@ */ package org.apache.tamaya.inject.spi; +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.Configuration; +import org.apache.tamaya.TypeLiteral; import org.apache.tamaya.inject.api.DynamicValue; +import org.apache.tamaya.inject.api.UpdatePolicy; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.Serializable; +import java.lang.reflect.Member; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; import java.util.function.Supplier; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Basic abstract implementation skeleton for a {@link DynamicValue}. This can be used to support values that may @@ -44,6 +57,159 @@ public abstract class BaseDynamicValue<T> implements DynamicValue<T>, Serializab private static final long serialVersionUID = 1L; + private static final Logger LOG = Logger.getLogger(DynamicValue.class.getName()); + + private UpdatePolicy updatePolicy = UpdatePolicy.NEVER; + private TypeLiteral<T> targetType; + private T currentValue; + private T newValue; + private List<String> keys = new ArrayList<>(); + private List<PropertyChangeListener> listeners = Collections.synchronizedList(new ArrayList<>()); + + + public BaseDynamicValue(TypeLiteral targetType, List<String> keys){ + if(keys == null || keys.isEmpty()){ + throw new ConfigException("At least one key is required."); + } + this.targetType = Objects.requireNonNull(targetType); + this.keys.addAll(keys); + this.currentValue = evaluateValue(); + } + + /** + * Get the configuration to evaluate. + * @return the configuration, never null. + */ + protected abstract Configuration getConfiguration(); + + /** + * Get the owner of this dynamic value instance. + * @return the owner, never null. + */ + protected abstract Object getOwner(); + + /** + * Get the corresponding property name. + * @return + */ + protected abstract String getPropertyName(); + + /** + * Get the targeted keys, in evaluation order. + * @return the keys evaluated. + */ + public List<String> getKeys(){ + return Collections.unmodifiableList(keys); + } + + /** + * Get the target type. + * @return the target type, not null. + */ + public TypeLiteral<T> getTargetType(){ + return targetType; + } + + @Override + public void commit() { + if(!Objects.equals(newValue, currentValue)) { + T oldValue = this.currentValue; + currentValue = newValue; + publishChangeEvent(this.currentValue, newValue); + } + } + + @Override + public UpdatePolicy getUpdatePolicy() { + return updatePolicy; + } + + @Override + public void addListener(PropertyChangeListener l) { + synchronized(listeners){ + if(!listeners.contains(l)){ + listeners.add(l); + } + } + } + + @Override + public void removeListener(PropertyChangeListener l) { + synchronized(listeners){ + listeners.remove(l); + } + } + + @Override + public T get() { + return currentValue; + } + + @Override + public boolean updateValue() { + Configuration config = getConfiguration(); + T val = evaluateValue(); + if(!Objects.equals(val, currentValue)){ + switch (updatePolicy){ + case EXPLICIT: + newValue = val; + break; + case IMMEDIATE: + this.currentValue = val; + publishChangeEvent(this.currentValue, val); + break; + case LOG_ONLY: + LOG.info("New config value for keys " + keys + " detected, but not yet applied."); + break; + case NEVER: + LOG.finest("New config value for keys " + keys + " detected, but ignored."); + break; + } + return true; + } + return false; + } + + /** + * Publishes a change event to all listeners. + * @param newValue the new value + * @param oldValue the new old value + */ + protected void publishChangeEvent(T oldValue, T newValue) { + PropertyChangeEvent evt = new PropertyChangeEvent(getOwner(), getPropertyName(),oldValue, newValue); + synchronized (listeners){ + listeners.parallelStream().forEach(l -> { + try{ + l.propertyChange(evt); + }catch(Exception e){ + LOG.log(Level.SEVERE, "Error in config change listener: " + l, e); + } + }); + } + } + + @Override + public T evaluateValue() { + Configuration config = getConfiguration(); + for(String key:getKeys()){ + T val = config.getOrDefault(key, targetType, null); + if(val!=null){ + return val; + } + } + return null; + } + + @Override + public void setUpdatePolicy(UpdatePolicy updatePolicy) { + this.updatePolicy = Objects.requireNonNull(updatePolicy); + } + + @Override + public T getNewValue() { + return newValue; + } + /** * Performs a commit, if necessary, and returns the current value. * http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/45d8afde/modules/injection/injection-api/src/test/java/org/apache/tamaya/inject/spi/BaseDynamicValueTest.java ---------------------------------------------------------------------- diff --git a/modules/injection/injection-api/src/test/java/org/apache/tamaya/inject/spi/BaseDynamicValueTest.java b/modules/injection/injection-api/src/test/java/org/apache/tamaya/inject/spi/BaseDynamicValueTest.java new file mode 100644 index 0000000..3f8720e --- /dev/null +++ b/modules/injection/injection-api/src/test/java/org/apache/tamaya/inject/spi/BaseDynamicValueTest.java @@ -0,0 +1,101 @@ +/* + * 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.inject.spi; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.Configuration; +import org.apache.tamaya.ConfigurationProvider; +import org.apache.tamaya.TypeLiteral; +import org.apache.tamaya.inject.api.UpdatePolicy; +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.*; + +public class BaseDynamicValueTest { + + @Test + public void create(){ + new MyDynamicValue("a", "b"); + } + + @Test(expected = ConfigException.class) + public void create_nokeys(){ + new MyDynamicValue(); + } + + @Test + public void commitAndGet() throws Exception { + System.setProperty("commitAndGet", "yes"); + MyDynamicValue dv = new MyDynamicValue("commitAndGet"); + System.setProperty("commitAndGet", "no"); + dv.setUpdatePolicy(UpdatePolicy.EXPLICIT); + assertTrue(dv.updateValue()); + assertEquals(dv.commitAndGet(), "no"); + dv.setUpdatePolicy(UpdatePolicy.IMMEDIATE); + System.setProperty("commitAndGet", "yes2"); + assertTrue(dv.updateValue()); + assertEquals(dv.get(), "yes2"); + } + + @Test + public void isPresent() throws Exception { + assertFalse(new MyDynamicValue("a", "b").isPresent()); + assertTrue(new MyDynamicValue("java.version").isPresent()); + } + + @Test + public void orElse() throws Exception { + assertEquals(new MyDynamicValue("a", "b").orElse("foo"), "foo"); + } + + @Test + public void orElseGet() throws Exception { + assertEquals(new MyDynamicValue("a", "b").orElseGet(() -> "foo"), "foo"); + } + + @Test(expected = NoSuchFieldException.class) + public void orElseThrow() throws Throwable { + new MyDynamicValue("foo").orElseThrow(() -> new NoSuchFieldException("Test")); + } + + private static final class MyDynamicValue extends BaseDynamicValue{ + + public MyDynamicValue(String... keys){ + super(TypeLiteral.of(String.class), Arrays.asList(keys)); + } + + @Override + protected Configuration getConfiguration() { + return ConfigurationProvider.getConfiguration(); + } + + @Override + protected Object getOwner() { + return this; + } + + @Override + protected String getPropertyName() { + return "this"; + } + } + +} \ No newline at end of file
