// Path: src/main/java/io/aif/language/common/ISearchable.java
// public interface ISearchable<T, R> {
// 
//   public Optional<R> search(final T subject);
// 
// }
// 
// Path: src/main/java/io/aif/language/word/IWord.java
// public interface IWord {
// 
//   public String getRootToken();
// 
//   public Set<String> getAllTokens();
// 
//   public Long getCount();
// 
//   public int getTokenCount(String token);
// 
//   public static interface IWordPlaceholder {
// 
//     public IWord getWord();
// 
//     public String getToken();
// 
//   }
// 
// }


import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import io.aif.language.common.IDict;
import io.aif.language.common.ISearchable;
import io.aif.language.word.IWord;
    final Map<String, IWord> reverseIndex = new HashMap<>();
    for (IWord word : words) {
      word.getAllTokens().forEach(token -> reverseIndex.put(token, word));
    }
    return reverseIndex;
  }

  public static Dict create(final Set<IWord> words) {
    final Dict d = new Dict(words, generateReverseIndex(words));
    return d;
  }

  @Override
  public Set<IWord> getWords() {
    return words;
  }

  @Override
  public String toString() {
    final StringBuilder stringBuilder = new StringBuilder();
    getWords()
        .stream()
        .sorted((w1, w2) -> w1.getRootToken().compareTo(w2.getRootToken()))
        .forEach(word -> stringBuilder.append(String.format("%s\n", word.toString())));
    return stringBuilder.toString();
  }

  @Override
  public Optional<IWord> search(final String token) {
    return reverseIndex.containsKey(token) ?
// Path: src/main/java/io/aif/language/common/ISearchable.java
// public interface ISearchable<T, R> {
// 
//   public Optional<R> search(final T subject);
// 
// }
// 
// Path: src/main/java/io/aif/language/word/IWord.java
// public interface IWord {
// 
//   public String getRootToken();
// 
//   public Set<String> getAllTokens();
// 
//   public Long getCount();
// 
//   public int getTokenCount(String token);
// 
//   public static interface IWordPlaceholder {
// 
//     public IWord getWord();
// 
//     public String getToken();
// 
//   }
// 
// }


// Path: src/main/java/io/aif/language/word/dict/Dict.java
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import io.aif.language.common.IDict;
import io.aif.language.common.ISearchable;
import io.aif.language.word.IWord;

    final Map<String, IWord> reverseIndex = new HashMap<>();
    for (IWord word : words) {
      word.getAllTokens().forEach(token -> reverseIndex.put(token, word));
    }
    return reverseIndex;
  }

  public static Dict create(final Set<IWord> words) {
    final Dict d = new Dict(words, generateReverseIndex(words));
    return d;
  }

  @Override
  public Set<IWord> getWords() {
    return words;
  }

  @Override
  public String toString() {
    final StringBuilder stringBuilder = new StringBuilder();
    getWords()
        .stream()
        .sorted((w1, w2) -> w1.getRootToken().compareTo(w2.getRootToken()))
        .forEach(word -> stringBuilder.append(String.format("%s\n", word.toString())));
    return stringBuilder.toString();
  }

  @Override
  public Optional<IWord> search(final String token) {
    return reverseIndex.containsKey(token) ?
        Optional.of(reverseIndex.get(token)) : Optional.empty();