001package arez.component;
002
003import arez.Arez;
004import arez.Disposable;
005import javax.annotation.Nonnull;
006import javax.annotation.Nullable;
007import static org.realityforge.braincheck.Guards.*;
008
009/**
010 * Interface implemented by components so that the underlying identifier can be exposed.
011 * The <code>ArezId</code> is used by Arez classes when manipulating the component. As long as
012 * {@link Disposable#dispose()} has not been invoked on the component then the <code>ArezId</code>
013 * value should be unique within the scope of the {@link arez.ArezContext}.
014 *
015 * @param <K> the type of the id.
016 */
017@SuppressWarnings( "unchecked" )
018public interface Identifiable<K>
019{
020  /**
021   * Return the unique id of the component.
022   * As long as {@link Disposable#dispose()} has not been invoked on the component,
023   * the return value should be unique within the scope of the {@link arez.ArezContext}.
024   *
025   * @return the unique id of the component.
026   */
027  @Nonnull
028  K getArezId();
029
030  /**
031   * Return the unique id of the object if it is Identifiable, else return null.
032   *
033   * @param <K>    the type of the id.
034   * @param object the object to dispose.
035   * @return the arez id if the object is Identifiable, otherwise null.
036   */
037  @Nullable
038  static <K> K getArezId( @Nullable final Object object )
039  {
040    if ( object instanceof Identifiable )
041    {
042      return ( (Identifiable<K>) object ).getArezId();
043    }
044    else
045    {
046      return null;
047    }
048  }
049
050  /**
051   * Cast specified object to instance of Identifiable.
052   * Invariant checks will verify that the cast is valid before proceeding.
053   *
054   * @param <K>    the type parameter for Identifiable.
055   * @param object the object.
056   * @return the object cast to Identifiable.
057   */
058  @Nonnull
059  static <K> Identifiable<K> asIdentifiable( @Nonnull final Object object )
060  {
061    if ( Arez.shouldCheckApiInvariants() )
062    {
063      apiInvariant( () -> object instanceof Identifiable,
064                    () -> "Arez-0158: Object passed to asIdentifiable does not implement " +
065                          "Identifiable. Object: " + object );
066    }
067    return (Identifiable<K>) object;
068  }
069}