package org.realityforge.replicant.client.aoi;

import arez.annotations.ArezComponent;
import arez.component.AbstractContainer;
import arez.component.RepositoryUtil;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Singleton;
import org.realityforge.replicant.client.Channel;
import org.realityforge.replicant.client.ChannelAddress;
import org.realityforge.replicant.client.FilterUtil;

/**
 * The AreaOfInterestService is responsible for managing the expected subscriptions
 * that the client is interested in. The subscriptions may cross different replicant
 * systems, and may exist before the data sources have been connected. The AreaOfInterestService
 * intends to represent the desired state that the DataSources converge towards.
 */
@Singleton
@ArezComponent
public abstract class AreaOfInterestService
  extends AbstractContainer<ChannelAddress, AreaOfInterest>
{
  @Nonnull
  public static AreaOfInterestService create()
  {
    return new Arez_AreaOfInterestService();
  }

  @Nonnull
  public List<AreaOfInterest> getAreasOfInterest()
  {
    return RepositoryUtil.asList( entities() );
  }

  @Nullable
  public AreaOfInterest findAreaOfInterestByAddress( @Nonnull final ChannelAddress address )
  {
    return super.findByArezId( address );
  }

  @Nonnull
  public AreaOfInterest findOrCreateAreaOfInterest( @Nonnull final ChannelAddress address,
                                                    @Nullable final Object filter )
  {
    final AreaOfInterest areaOfInterest = findAreaOfInterestByAddress( address );
    if ( null != areaOfInterest )
    {
      if ( !FilterUtil.filtersEqual( areaOfInterest.getChannel().getFilter(), filter ) )
      {
        areaOfInterest.getChannel().setFilter( filter );
      }
      return areaOfInterest;
    }
    else
    {
      final Channel channel = Channel.create( address, filter );
      final AreaOfInterest newAreaOfInterest = AreaOfInterest.create( channel );
      registerEntity( newAreaOfInterest );
      return newAreaOfInterest;
    }
  }
}

@@ -506,820 +506,1796 @@
 ing 
-the expected subscriptions%0A * that the client is interested in. The subscriptions may cross different replicant%0A * systems, and may exist before the data sources have been connected. The AreaOfInterestService%0A * intends to represent the desired state that the DataSources converge towards.%0A */%0A@Singleton%0A@ArezComponent%0Apublic abstract class AreaOfInterestService%0A  extends AbstractContainer%3CChannelAddress, AreaOfInterest%3E%0A%7B%0A  @Nonnull%0A  public static AreaOfInterestService create()%0A  %7B%0A    return new Arez_AreaOfInterestService();%0A  %7D%0A%0A  @Nonnull%0A  public List%3CAreaOfInterest%3E getAreasOfInterest()%0A  %7B%0A    return RepositoryUtil.asList( entities() );%0A  %7D%0A%0A  @Nullable%0A  public AreaOfInterest findAreaOfInterestByAddress( @Nonnull final ChannelAddress address )%0A  %7B%0A    return super.findByArezId( address );%0A  %7D%0A
+AreaOfInterest instance.%0A * An %7B@link AreaOfInterest%7D represents a delcaration of a desire for a%0A * %7B@link org.realityforge.replicant.client.subscription.Subscription%7D. The intention%0A * is that user code defines the desired state as instances of %7B@link AreaOfInterest%7D%0A * and the %7B@link org.realityforge.replicant.client.converger.ContextConverger%7D converges%0A * the actual state towards the desired state.%0A */%0A@Singleton%0A@ArezComponent%0Apublic abstract class AreaOfInterestService%0A  extends AbstractContainer%3CChannelAddress, AreaOfInterest%3E%0A%7B%0A  /**%0A   * Create an instance of the AreaOfInterestService.%0A   *%0A   * @return an instance of the AreaOfInterestService.%0A   */%0A  @Nonnull%0A  public static AreaOfInterestService create()%0A  %7B%0A    return new Arez_AreaOfInterestService();%0A  %7D%0A%0A  /**%0A   * Return the collection of AreaOfInterest that have been declared.%0A   *%0A   * @return the collection of AreaOfInterest that have been declared.%0A   */%0A  @Nonnull%0A  public List%3CAreaOfInterest%3E getAreasOfInterest()%0A  %7B%0A    return RepositoryUtil.asList( entities() );%0A  %7D%0A%0A  /**%0A   * Return a specific AreaOfInterest that has specified address.%0A   *%0A   * @param address the address of the channel that AreaOfInterest is about.%0A   * @return the AreaOfInterest that matches if any.%0A   */%0A  @Nullable%0A  public AreaOfInterest findAreaOfInterestByAddress( @Nonnull final ChannelAddress address )%0A  %7B%0A    return super.findByArezId( address );%0A  %7D%0A%0A  /**%0A   * Locate an existing AreaOfInterest with specified address or create a new AreaOfInterest.%0A   * The filter is updated, if required, to match the specified parameter.%0A   *%0A   * @param address the address of the channel that AreaOfInterest is about.%0A   * @param filter  the filter that is used to define the channel.%0A   * @return the AreaOfInterest.%0A   */
 %0A  @

Add some javadocs