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

io.scalecube.config.PropertyCallback Maven / Gradle / Ivy

There is a newer version: 0.4.21.RC1
Show newest version
package io.scalecube.config;

import io.scalecube.config.audit.ConfigEvent;
import io.scalecube.config.source.LoadedConfigProperty;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Property controller class for config property instances of type {@link T}. Config property
 * instances of the same type are managed by exactly one property controller.
 *
 * @param  type of the property value
 */
class PropertyCallback {
  private static final Logger LOGGER = LoggerFactory.getLogger(PropertyCallback.class);

  private static final String ERROR_EXCEPTION_ON_VALUE_PARSER =
      "Exception occurred at valueParser on input: %s, cause: %s";
  private static final String ERROR_EXCEPTION_AT_ACCEPT_VALUE =
      "Exception occurred at acceptValue on input: %s, on value: %s, cause: %s";

  /**
   * Value parser function. Converts list of string name-value pairs (input list can be null or
   * empty, in this case function would simply return null) to concrete object, i.e. a config
   * property value.
   */
  private final Function, T> valueParser;

  /**
   * Collection of ConfigProperty objects of the same type assigned to this {@link
   * PropertyCallback}.
   */
  private final Collection> configProperties =
      new CopyOnWriteArraySet<>();

  /**
   * Creates property callback.
   *
   * @param valueParser value parser for config property object of certain type.
   */
  PropertyCallback(Function, T> valueParser) {
    this.valueParser = list -> list == null || list.isEmpty() ? null : valueParser.apply(list);
  }

  /** Just adds config property instance to internal collection. */
  void addConfigProperty(AbstractConfigProperty configProperty) {
    configProperties.add(configProperty);
  }

  /**
   * Computes new value for config property instances (of type {@link T}) from the list of {@link
   * ConfigEvent}-s. This method is being called from config registry reload process.
   *
   * @param events config events computed during config registry reload.
   * @see ConfigRegistryImpl#loadAndNotify()
   */
  void computeValue(List events) {
    List inputList =
        events
            .stream()
            .filter(
                event ->
                    event.getType()
                        != ConfigEvent.Type.REMOVED) // we only interested in ADDED or UPDATED
            .map(
                event ->
                    LoadedConfigProperty.withNameAndValue(event.getName(), event.getNewValue())
                        .source(event.getNewSource())
                        .origin(event.getNewOrigin())
                        .build())
            .collect(Collectors.toList());

    T value;
    try {
      value = applyValueParser(inputList);
    } catch (Exception e) {
      LOGGER.error(e.getMessage(), e.getCause());
      return; // return right away if parser failed
    }

    T value1 = value; // new value
    configProperties.forEach(
        configProperty -> {
          try {
            configProperty.acceptValue(value1, inputList, true /* invokeCallbacks */);
          } catch (Exception e) {
            LOGGER.error(String.format(ERROR_EXCEPTION_AT_ACCEPT_VALUE, inputList, value1, e));
          }
        });
  }

  /**
   * Computes new value for config property instance (passed as second parameter) from the list of
   * {@link LoadedConfigProperty}-s.
   *
   * @param inputList an input for {@link #valueParser}.
   * @param configProperty an instance where attempt to set a new value has to be made.
   * @throws IllegalArgumentException in case value can't be parsed from the inputList or validation
   *     doesn't pass.
   */
  void computeValue(
      List inputList, AbstractConfigProperty configProperty) {
    T value = applyValueParser(inputList);
    try {
      configProperty.acceptValue(value, inputList, false /* invokeCallbacks */);
    } catch (Exception e) {
      throw new IllegalArgumentException(
          String.format(ERROR_EXCEPTION_AT_ACCEPT_VALUE, inputList, value, e));
    }
  }

  private T applyValueParser(List inputList) {
    try {
      return valueParser.apply(inputList);
    } catch (Exception e) {
      throw new IllegalArgumentException(
          String.format(ERROR_EXCEPTION_ON_VALUE_PARSER, inputList, e));
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy