package arez.downstream;

import java.io.IOException;
import java.nio.file.Path;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.intellij.lang.annotations.RegExp;
import static org.testng.Assert.*;

/**
 * Index into which symbolMap can be loadded and assertions invoked on contents of index.
 */
@SuppressWarnings( "WeakerAccess" )
final class SymbolEntryIndex
{
  private final HashMap<String, ArrayList<SymbolEntry>> _classNameToEntry = new HashMap<>();

  /**
   * Read and build an index from symbolMap file.
   *
   * @param symbolMapPath the path to load symbolMap from.
   * @return the new index.
   * @throws IOException    if there is an error reading file.
   * @throws ParseException if there is an error parsing file.
   */
  @Nonnull
  static SymbolEntryIndex readSymbolMapIntoIndex( @Nonnull final Path symbolMapPath )
    throws IOException, ParseException
  {
    final SymbolEntryIndex index = new SymbolEntryIndex();
    SymbolEntry.readSymbolMap( symbolMapPath, index::addEntry );
    return index;
  }

  private void addEntry( @Nonnull final SymbolEntry entry )
  {
    _classNameToEntry
      .computeIfAbsent( entry.getClassName(), e -> new ArrayList<>() )
      .add( entry );
  }

  /**
   * Verify no entry for ClassName exists in index.
   * If a match is found then fail assertion error.
   *
   * @param pattern the pattern
   */
  void assertNoClassNameMatches( @RegExp( prefix = "^", suffix = "$" ) @Nonnull final String pattern )
  {
    assertNoClassNameMatches( Pattern.compile( "^" + pattern + "$" ) );
  }

  /**
   * Verify no entry for ClassName exists in index.
   * If a match is found then fail assertion error.
   *
   * @param pattern the pattern
   */
  void assertNoClassNameMatches( @Nonnull final Pattern pattern )
  {
    final List<String> matches =
      _classNameToEntry.keySet().stream().filter( n -> pattern.matcher( n ).matches() ).collect( Collectors.toList() );
    if ( !matches.isEmpty() )
    {
      fail( "Expected that the SymbolMap would have no classNames that match pattern " + pattern +
            " but the following classNames match: " + matches );
    }
  }
}

@@ -2297,11 +2297,1650 @@
    %7D%0A  %7D
+%0A%0A  /**%0A   * Verify no entry for member exists in index.%0A   * If a match is found then fail assertion error.%0A   *%0A   * @param classNamePattern  the pattern to match className.%0A   * @param memberNamePattern the pattern to match member name.%0A   */%0A  void assertNoMemberMatches( @RegExp( prefix = %22%5E%22, suffix = %22$%22 ) @Nonnull final String classNamePattern,%0A                              @RegExp( prefix = %22%5E%22, suffix = %22$%22 ) @Nonnull final String memberNamePattern )%0A  %7B%0A    assertNoMemberMatches( Pattern.compile( %22%5E%22 + classNamePattern + %22$%22 ),%0A                           Pattern.compile( %22%5E%22 + memberNamePattern + %22$%22 ) );%0A  %7D%0A%0A  /**%0A   * Verify no entry for member exists in index.%0A   * If a match is found then fail assertion error.%0A   *%0A   * @param classNamePattern  the pattern to match className.%0A   * @param memberNamePattern the pattern to match member name.%0A   */%0A  void assertNoMemberMatches( @Nonnull final Pattern classNamePattern, @Nonnull final Pattern memberNamePattern )%0A  %7B%0A    final List%3CSymbolEntry%3E matches =%0A      _classNameToEntry%0A        .entrySet()%0A        .stream()%0A        .filter( e -%3E classNamePattern.matcher( e.getKey() ).matches() &&%0A                      e.getValue().stream().anyMatch( s -%3E memberNamePattern.matcher( s.getMemberName() ).matches() ) )%0A        .flatMap( e -%3E e.getValue().stream() )%0A        .collect( Collectors.toList() );%0A    if ( !matches.isEmpty() )%0A    %7B%0A      fail( %22Expected that the SymbolMap would have no members that match: classNamePattern '%22 + classNamePattern +%0A            %22', memberPattern '%22 + memberNamePattern + %22' but the following entries match: %22 + matches );%0A    %7D%0A  %7D
 %0A%7D%0A

Add assertions for members