All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.avanza.astrix.config.DynamicPropertyChain Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2014 Avanza Bank AB
 *
 * Licensed 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 com.avanza.astrix.config;

import java.util.LinkedList;
import java.util.Objects;
import java.util.Optional;

/**
 * A DynamicPropertyChain is a hierarchical set of properties. A property
 * is resolved to the first {@link DynamicConfigProperty} in the chain
 * that have a value set. If no property in the chain has a value then
 * the default value is used.
 * 
 * The {@link DynamicPropertyChainListener} will be notified synchronously
 * when it is registered by calling {@link #bindTo(DynamicPropertyChainListener)}.
 * After the initial notification with the current value, the listener is notified 
 * every time the resolved property changes, for instance when:
 * 
 * 
    *
  • A property with higher precedence than the current resolved property is set
  • *
  • The current resolved property is changed. In that case * the listener will be notified with the new value
  • *
  • The current resolved property is cleared. In that case * the listener will be notified with the new (possibly default) resolved value
  • *
* * * @author Elias Lindholm (elilin) * * @param */ final class DynamicPropertyChain implements DynamicPropertyListener> { private final LinkedList> chain = new LinkedList<>(); private volatile Optional propertyChainListener; private final PropertyParser parser; private final T defaultValue; private DynamicPropertyChain(T defaultValue, PropertyParser parser) { this.defaultValue = defaultValue; this.parser = parser; this.propertyChainListener = Optional.empty(); } /** * Binds the resolved value of this chain to a given listener. The listener will be * notified synchronously with the current resolved value of this property chain, and * will later receive a notification each time the resolved of this chain changes. * */ void bindTo(DynamicPropertyChainListener l) { this.propertyChainListener = Optional.of(new PropertyChangeEventDispatcher(l)); this.propertyChainListener.ifPresent(PropertyChangeEventDispatcher::init); } static DynamicPropertyChain createWithDefaultValue(T defaultValue, PropertyParser parser) { return new DynamicPropertyChain<>(defaultValue, parser); } private T get() { return chain.stream() .filter(DynamicConfigProperty::isSet) .findFirst() .map(DynamicConfigProperty::get) .orElse(defaultValue); } @Override public void propertyChanged(DynamicConfigProperty updatedProperty) { this.propertyChainListener.ifPresent(PropertyChangeEventDispatcher::propertyChanged); } DynamicConfigProperty appendValue() { DynamicConfigProperty property = DynamicConfigProperty.create(this, parser); chain.addLast(property); return property; } private class PropertyChangeEventDispatcher { private DynamicPropertyChainListener listener; private T lastNotifiedState; public PropertyChangeEventDispatcher(DynamicPropertyChainListener listener) { this.listener = listener; } private void init() { propertyChanged(); } private void propertyChanged() { T currentResolvedValue = get(); if (!Objects.equals(currentResolvedValue, lastNotifiedState)) { listener.propertyChanged(currentResolvedValue); lastNotifiedState = currentResolvedValue; } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy