001package arez;
002
003import javax.annotation.Nonnull;
004import javax.annotation.Nullable;
005import static org.realityforge.braincheck.Guards.*;
006
007/**
008 * Interface that allows caller to release any resources associated with element.
009 * It is safe to invoke {@link #dispose()} multiple times on a element. Once an
010 * element is disposed, no methods should be invoked on element.
011 */
012public interface Disposable
013{
014  /**
015   * Dispose the element. See {@link Disposable} for a description of the implications.
016   */
017  void dispose();
018
019  /**
020   * Return true if dispose() has been called on object.
021   *
022   * @return true if dispose has been called.
023   */
024  boolean isDisposed();
025
026  /**
027   * Return true if {@link #isDisposed()} returns false.
028   *
029   * @return true if {@link #isDisposed()} returns false.
030   */
031  default boolean isNotDisposed()
032  {
033    return !isDisposed();
034  }
035
036  /**
037   * Dispose the supplied object if it is Disposable, else do nothing.
038   *
039   * @param object the object to dispose.
040   */
041  static void dispose( @Nullable final Object object )
042  {
043    if ( object instanceof Disposable )
044    {
045      ( (Disposable) object ).dispose();
046    }
047  }
048
049  /**
050   * Return true if the parameter is Disposable and has been disposed, else return false.
051   *
052   * @param object the object to check disposed state.
053   * @return true if the parameter is Disposable and has been disposed, else return false.
054   */
055  static boolean isDisposed( @Nullable final Object object )
056  {
057    return object instanceof Disposable && ( (Disposable) object ).isDisposed();
058  }
059
060  /**
061   * Return true if {@link #isDisposed(Object)} returns false for the same parameter.
062   *
063   * @param object the object to check state.
064   * @return true if the parameter is not Disposable or has not been disposed, else return false.
065   */
066  static boolean isNotDisposed( @Nullable final Object object )
067  {
068    return !isDisposed( object );
069  }
070
071  /**
072   * Cast specified object to instance of Disposable.
073   * Invariant checks will verify that the cast is valid before proceeding.
074   *
075   * @param object the object to cast to Disposable.
076   * @return the object cast to Disposable.
077   */
078  @Nonnull
079  static Disposable asDisposable( @Nonnull final Object object )
080  {
081    if ( Arez.shouldCheckApiInvariants() )
082    {
083      apiInvariant( () -> object instanceof Disposable,
084                    () -> "Object passed to asDisposable does not implement Disposable. Object: " + object );
085    }
086    return (Disposable) object;
087  }
088}