001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
002 *
003 * Copyright © 2023–2024 microBean™.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
006 * the License.  You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
011 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
012 * specific language governing permissions and limitations under the License.
013 */
014package org.microbean.bean;
015
016/**
017 * A reigstry of {@link AutoCloseable} instances that itself is {@link AutoCloseable}.
018 *
019 * <p>{@linkplain #close() Closing} an {@link AutoCloseableRegistry} {@linkplain AutoCloseable#close() closes} its
020 * registrants.</p>
021 *
022 * @author <a href="https://about.me/lairdnelson/" target="_top">Laird Nelson</a>
023 *
024 * @see #register(AutoCloseable)
025 */
026public interface AutoCloseableRegistry extends AutoCloseable {
027
028  /**
029   * Returns a new {@link AutoCloseableRegistry} instance that is not {@linkplain #closed() closed}, has no {@linkplain
030   * #register(AutoCloseable) registrations} yet, and is {@linkplain #register(AutoCloseable) registered} with this
031   * {@link AutoCloseableRegistry}.
032   *
033   * <p>The new {@link AutoCloseableRegistry} child therefore functions as an intermediate or leaf node in a tree of
034   * {@link AutoCloseable} implementations, such that if any node of the tree is {@linkplain AutoCloseable#close()
035   * closed}, all of its descendants will be {@linkplain AutoCloseable#close() closed} as well.</p>
036   *
037   * @return a new, {@linkplain #closed() unclosed} {@link AutoCloseableRegistry} {@linkplain #register(AutoCloseable)
038   * registered} with this {@link AutoCloseableRegistry} that functions as an intermediate or leaf node in a tree of
039   * such nodes
040   *
041   * @exception IllegalStateException if this {@link AutoCloseableRegistry} is {@linkplain #closed() closed}
042   *
043   * @nullability Implementations of this method must not return {@code null}.
044   *
045   * @idempotency All successful invocations of implementations of this method must return new, distinct {@link
046   * AutoCloseableRegistry} instances.
047   *
048   * @threadsafety Implementations of this method must be safe for concurrent use by multiple threads.
049   *
050   * @see #register(AutoCloseable)
051   */
052  public AutoCloseableRegistry newChild();
053
054  /**
055   * Closes this {@link AutoCloseableRegistry} and {@linkplain AutoCloseable#close() closes} its {@linkplain
056   * #register(AutoCloseable) registrants}.
057   *
058   * <p>After any successful invocation of this method, an invocation of the {@link #closed()} method must forever after
059   * return {@code true}.</p>
060   *
061   * @idempotency Implementations of this method must be idempotent.
062   *
063   * @threadsafety Implementations of this method must be safe for concurrent use by multiple threads.
064   *
065   * @see #closed()
066   */
067  @Override // AutoCloseable
068  public void close();
069
070  /**
071   * Returns {@code true} if and only if this {@link AutoCloseableRegistry} is {@linkplain #close() closed}.
072   *
073   * <p>Once an invocation of this method has returned {@code true}, on any thread, subsequent invocations must also
074   * return {@code true}, on any thread.</p>
075   *
076   * <p>An implementation of this method must return {@code false} until an invocation of the {@link #close()} method
077   * has successfully completed, and must return {@code true} thereafter.</p>
078   *
079   * @return {@code true} if and only if this {@link AutoCloseableRegistry} is {@linkplain #close() closed}
080   *
081   * @idempotency Implementations of this method must be idempotent.
082   *
083   * @threadsafety Implementations of this method must be safe for concurrent use by multiple threads.
084   *
085   * @see #close()
086   */
087  public boolean closed();
088
089  /**
090   * If this {@link AutoCloseableRegistry} is not {@linkplain #closed() closed}, and if the supplied {@link
091   * AutoCloseable} has not yet been registered, registers it such that it will be {@linkplain AutoCloseable#close()
092   * closed} when this {@link AutoCloseableRegistry} is {@linkplain #close() closed}, and returns {@code true}.
093   *
094   * <p>This method takes no action and returns {@code false} in all other cases.</p>
095   *
096   * @param closeable the {@link AutoCloseable} to register; must not be {@code null}
097   *
098   * @return {@code true} if and only if this {@link AutoCloseableRegistry} is not {@linkplain #closed() closed} and the
099   * supplied {@link AutoCloseable} is not already registered and registration completed successfully; {@code false} in
100   * all other cases
101   *
102   * @exception NullPointerException if {@code closeable} is {@code null}
103   *
104   * @idempotency Implementations of this method must be idempotent.
105   *
106   * @threadsafety Implementations of this method must be safe for concurrent use by multiple threads.
107   */
108  public boolean register(final AutoCloseable closeable);
109
110}