001package arez.component;
002
003import arez.Arez;
004import javax.annotation.Nonnull;
005import javax.annotation.Nullable;
006import static org.realityforge.braincheck.Guards.*;
007
008/**
009 * Interface implemented by components so that observers can observe the component without
010 * observing a particular property.
011 */
012public interface ComponentObservable
013{
014  /**
015   * Return true if the component is "alive" a.k.a. not disposing or disposed.
016   * This method MUST be invoked within a non-DISPOSE transaction and will add
017   * the component as a dependency if the transaction is tracking, unless
018   * this component is disposing or disposed.
019   *
020   * @return true if the component is "alive" a.k.a. not disposing or disposed.
021   */
022  boolean observe();
023
024  /**
025   * Invoke {@link #observe()} on the supplied object.
026   *
027   * @param object the object to observe.
028   * @return true if the component is not disposing or disposed, false otherwise.
029   */
030  static boolean observe( @Nonnull final Object object )
031  {
032    return asComponentObservable( object ).observe();
033  }
034
035  /**
036   * Invoke {@link #observe()} on the supplied object if not null.
037   *
038   * @param object the object to observe if not null.
039   * @return true if the component is null or not disposing or disposed, false otherwise.
040   */
041  static boolean maybeObserve( @Nullable final Object object )
042  {
043    return null == object || asComponentObservable( object ).observe();
044  }
045
046  /**
047   * Return true if {@link #observe(Object)} returns false for the same parameter.
048   *
049   * @param object the object to observe if any.
050   * @return true if {@link #observe(Object)} returns false for the same parameter, false otherwise.
051   */
052  static boolean notObserved( @Nonnull final Object object )
053  {
054    return !observe( object );
055  }
056
057  /**
058   * Cast specified object to an instance of ComponentObservable.
059   * Invariant checks will verify that the cast is valid before proceeding.
060   *
061   * @param object the object.
062   * @return the object cast to ComponentObservable.
063   */
064  @Nonnull
065  static ComponentObservable asComponentObservable( @Nonnull final Object object )
066  {
067    if ( Arez.shouldCheckApiInvariants() )
068    {
069      apiInvariant( () -> object instanceof ComponentObservable,
070                    () -> "Arez-0179: Object passed to asComponentObservable does not implement " +
071                          "ComponentObservable. Object: " + object );
072    }
073    return (ComponentObservable) object;
074  }
075}