class SimpleReplaceAnglicism extends AbstractSimpleReplaceRule2 {

  private static final String FILE_NAME = "/ca/replace_anglicism.txt";
  private static final Locale CA_LOCALE = new Locale("ca");

  public SimpleReplaceAnglicism(final ResourceBundle messages) throws IOException {
    super(messages, new Catalan());
    setCategory(Categories.STYLE.getCategory(messages));
    setLocQualityIssueType(ITSIssueType.Style);
    useSubRuleSpecificIds();
  }

  @Override
  public final String getId() {
    return "CA_SIMPLE_REPLACE_ANGLICISM";
  }

  @Override
  public String getDescription() {
    return "Anglicismes innecessaris: $match";
  }

  @Override
  public String getShort() {
    return "Anglicisme innecessari";
  }

  @Override
  public Locale getLocale() {
    return CA_LOCALE;
  }

  @Override
  public List<String> getFileNames() {
    return Arrays.asList(FILE_NAME);
  }

  @Override
  public String getMessage() {
    return "Anglicisme innecessari. Considereu fer servir una altra paraula.";
  }

  //private List<String> possibleExceptions = Arrays.asList("link", "links", "event", "events");

  @Override
  protected boolean isRuleMatchException(RuleMatch ruleMatch) {
    // accept English words in English sentences
    int startIndex = 0;
    AnalyzedTokenReadings[] tokens = ruleMatch.getSentence().getTokensWithoutWhitespace();
    while (startIndex < tokens.length && tokens[startIndex].getStartPos() < ruleMatch.getFromPos()) {
      startIndex++;
    }
    int endIndex = startIndex;
    while (endIndex < tokens.length && tokens[endIndex].getEndPos() < ruleMatch.getToPos()) {
      endIndex++;
    }
    if (startIndex > 1 && tokens[startIndex].hasPosTag("_english_ignore_")
      && tokens[startIndex - 1].hasPosTag("_english_ignore_")) {
      return true;
    }
    if (endIndex + 1 < tokens.length && tokens[endIndex].hasPosTag("_english_ignore_")
      && tokens[endIndex + 1].hasPosTag("_english_ignore_")) {
      return true;
    }
    return false;
  }

  @Override
  protected boolean isTokenException(AnalyzedTokenReadings atr) {<FILL_FUNCTION_BODY>}

}

    // proper nouns tagged in multiwords are exceptions
    return (atr.hasPosTagStartingWith("NP") && atr.getToken().length()>1) || atr.isImmunized() || atr.isIgnoredBySpeller();
  
<methods>public void <init>(java.util.ResourceBundle, org.languagetool.Language) ,public boolean checkKeyWordsAreKnownToSpeller() ,public boolean checkKeyWordsAreUnknownToSpeller() ,public org.languagetool.rules.AbstractSimpleReplaceRule2.CaseSensitivy getCaseSensitivy() ,public abstract java.lang.String getDescription() ,public java.lang.String getDescription(java.lang.String) ,public abstract List<java.lang.String> getFileNames() ,public List<java.net.URL> getFilePaths() ,public abstract java.lang.String getId() ,public abstract java.util.Locale getLocale() ,public abstract java.lang.String getMessage() ,public abstract java.lang.String getShort() ,public java.lang.String getSuggestionsSeparator() ,public List<Map<java.lang.String,org.languagetool.rules.SuggestionWithMessage>> getWrongWords() ,public org.languagetool.rules.RuleMatch[] match(org.languagetool.AnalyzedSentence) ,public boolean separateKeyWordsBySpeller() ,public void useSubRuleSpecificIds() <variables>private int MAX_LENGTH_SHORT_WORDS,private static final int MAX_TOKENS_IN_MULTIWORD,private boolean ignoreShortUppercaseWords,private volatile boolean initialized,protected final non-sealed org.languagetool.Language language,private Map<java.lang.String,org.languagetool.rules.SuggestionWithMessage> mFullNoSpace,private Map<java.lang.String,org.languagetool.rules.SuggestionWithMessage> mFullSpace,private Map<java.lang.String,java.lang.Integer> mStartNoSpace,private Map<java.lang.String,java.lang.Integer> mStartSpace,private boolean ruleHasSuggestions,protected boolean subRuleSpecificIds