package com.netflix.fabricator.supplier; import com.google.common.base.Function; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.netflix.fabricator.supplier.ListenableSupplier; /** * Implementation of a ListenableSupplier that gets it's value from an optional * ListenableSupplier but returns a default value if the source returns {$code null}. * * <pre> {@code public class Service { public class Builder { // Define a SupplierWithDefault in your code. private final SupplierWithDefault<String> param1 = SupplierWithDefault.from("DefaultValue"); // Assign an optional 'source'. This will be called by a Mapper that supports dynamic // values (@see ArchaiusConfigurationProviderMapper). public Builder withParam1(ListenableSupplier<String> source) { param1.setSource(source); return this; } public Service build() { return new Service(this); } } // The service's reference to the supplier private final ListenableSupplier<String> param1; protected Service(Builder builder) { this.param1 = builder.param1; // Set an optional callback notification for when the value changes param1.onChange(new Function<String, Void>() { public Void apply(String newValue) { System.out.println("Got a new value for newValue"); } }); } }} </pre> * @author elandau * * @param <T> */ public class SupplierWithDefault<T> implements ListenableSupplier<T> { private final T defaultValue; private ListenableSupplier<T> source; public SupplierWithDefault(T defaultValue) { this.defaultValue = defaultValue; this.source = new ListenableSupplier<T>() { @Override public T get() { return SupplierWithDefault.this.defaultValue; } @Override public void onChange(Function<T, Void> func) { // throw new RuntimeException("Change notification not supported"); } }; } public static <T> SupplierWithDefault<T> from(T defaultValue) { return new SupplierWithDefault<T>(defaultValue); } @Override public T get() { T value = source.get(); if (value == null) { return defaultValue; } return value; } /** * Set the ListenableSupplier from which the value will be read and a notification * can be subscribed to. * @param supplier */ public void setSource(ListenableSupplier<T> supplier) { source = supplier; } /** * Set a 'fixed' value to be returned. * @param value */ public void setValue(T value) { addOverride(Suppliers.ofInstance(value)); } /** * Set the onChange callback on the source. Note that the function reference is lost * if source is changed */ public void onChange(Function<T, Void> func) { source.onChange(func); } /** * Assign a simple Supplier that does not provide change notification * This will result in an exception being thrown if the client code tries to listen * for changes * @param supplier */ public void addOverride(final Supplier<T> supplier) { source = new ListenableSupplier<T>() { @Override public T get() { return supplier.get(); } @Override public void onChange(Function<T, Void> func) { throw new RuntimeException("Change notification not supported"); } }; } }