package org.codefx.libfx.nesting.listener; import java.util.Objects; import javafx.beans.InvalidationListener; import org.codefx.libfx.nesting.Nesting; /** * A builder for a {@link NestedInvalidationListenerHandle}. */ public class NestedInvalidationListenerBuilder { // #begin PROPERTIES /** * The {@link Nesting} to which the listener will be added. */ private final Nesting<?> nesting; /** * The {@link InvalidationListener} which will be added to the nesting's inner observable. */ private InvalidationListener listener; //#end PROPERTIES // #begin CONSTRUCTION /** * Creates a new builder for the specified nesting. * * @param nesting * the {@link Nesting} to which the listener will be added */ private NestedInvalidationListenerBuilder(Nesting<?> nesting) { Objects.requireNonNull(nesting, "The argument 'nesting' must not be null."); this.nesting = nesting; } /** * Copy constructor. * * @param other * the other {@link NestedInvalidationListenerBuilder} from which this builder will be copied */ private NestedInvalidationListenerBuilder(NestedInvalidationListenerBuilder other) { Objects.requireNonNull(other, "The argument 'other' must not be null."); this.nesting = other.nesting; } /** * Creates a new builder for the specified nesting. * * @param nesting * the {@link Nesting} to which the listener will be added * @return the new builder */ public static NestedInvalidationListenerBuilder forNesting(Nesting<?> nesting) { return new NestedInvalidationListenerBuilder(nesting); } //#end CONSTRUCTION // #begin METHODS /** * Specified the listener which will be added to the nesting. * * @param listener * the {@link InvalidationListener} which will be added to the nesting's inner observable * @return a {@link NestedInvalidationListenerBuilder} which provides a {@link Buildable#buildAttached() build}-method */ public Buildable withListener(InvalidationListener listener) { Objects.requireNonNull(listener, "The argument 'listener' must not be null."); this.listener = listener; return new Buildable(this); } //#end METHODS // #begin PRIVATE CLASSES /** * A subtype of {@link NestedInvalidationListenerBuilder} which can actually build a listener with {@link #buildAttached()}. */ public class Buildable extends NestedInvalidationListenerBuilder { /** * Indicates whether the nested listener was already built. */ private boolean built; /** * Creates a buildable {@link NestedInvalidationListenerBuilder}. * * @param builder * the builder from which this builder is copied */ private Buildable(NestedInvalidationListenerBuilder builder) { super(builder); } /** * Builds and {@link NestedInvalidationListenerHandle#attach() attaches} a nested invalidation listener and * returns the handle for it. * <p> * This method can only be called once as the same {@link InvalidationListener} should not be added more than * once to the same {@link Nesting}. * * @return a new instance of {@link NestedInvalidationListenerHandle}; initially attached * @see #buildDetached() */ public NestedInvalidationListenerHandle buildAttached() { NestedInvalidationListenerHandle listenerHandle = buildDetached(); listenerHandle.attach(); return listenerHandle; } /** * Builds a nested invalidation listener and returns the handle for it. * <p> * Note that the listener is not yet {@link NestedInvalidationListenerHandle#attach() attached}! * <p> * This method can only be called once as the same {@link InvalidationListener} should not be added more than * once to the same {@link Nesting}. * * @return a new instance of {@link NestedInvalidationListenerHandle}; initially detached * @see #buildAttached() */ public NestedInvalidationListenerHandle buildDetached() { if (built) throw new IllegalStateException("This builder can only build one 'NestedInvalidationListenerHandle'."); built = true; return new NestedInvalidationListenerHandle(nesting, listener); } } //#end region }