code: /* LanguageTool, a natural language style checker
   * Copyright (C) 2023 Jaume Ortolà
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
   * License along with this library; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
   * USA
   */
  package org.languagetool.rules.ca;
  
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  import org.languagetool.AnalyzedTokenReadings;
  import org.languagetool.AnalyzedToken;
  import org.languagetool.chunking.ChunkTag;
  import org.languagetool.rules.RuleMatch;
  import org.languagetool.rules.patterns.RuleFilter;
  import org.languagetool.rules.patterns.PatternRule;
  import org.languagetool.synthesis.ca.CatalanSynthesizer;
  import org.languagetool.tools.StringTools;
  
  /*
   * Suggestions for rule PORTA_UNA_HORA: porta una hora -> fa una hora que
   */
  
  public class PortarTempsSuggestionsFilter extends RuleFilter {
  
    static private CatalanSynthesizer synth = CatalanSynthesizer.INSTANCE;
  
    @Override
    public RuleMatch acceptRuleMatch(RuleMatch match, Map<String, String> arguments, int patternTokenPos,
                                     AnalyzedTokenReadings[] patternTokens) throws IOException {
      int posWord = 0;
      AnalyzedTokenReadings[] tokens = match.getSentence().getTokensWithoutWhitespace();
      while (posWord < tokens.length
        && (tokens[posWord].getStartPos() < match.getFromPos() || tokens[posWord].isSentenceStart())) {
        posWord++;
      }
      StringBuilder suggestion = new StringBuilder();
      String verbPostag = tokens[posWord].readingWithTagRegex("V.*").getPOSTag();
      AnalyzedToken at = new AnalyzedToken("", "", "fer");
      String newPostag = verbPostag.substring(0, 4) + "[30][S0]." + verbPostag.substring(7, 8);
      String[] synthForms = synth.synthesize(at, newPostag, true,
        getLanguageVariantCode(match));
      if (synthForms.length == 0) {
        return null;
      }
      suggestion.append(synthForms[0]);
      int i = posWord + 1;
      while (tokens[i].getChunkTags().contains(new ChunkTag("PTime"))) {
        if (tokens[i].isWhitespaceBefore()) {
          suggestion.append(" ");
        }
        suggestion.append(tokens[i].getToken());
        i++;
      }
      int lastTokenPos = i;
      if (lastTokenPos + 1 >= tokens.length) {
        return null;
      }
      int adjustEndPos = 0;
      AnalyzedTokenReadings lastToken = tokens[lastTokenPos];
      if (lastToken.getToken().equals("que")) {
        suggestion.append(" que");
      } else if (lastToken.hasPosTagStartingWith("VMG") || lastToken.hasPosTagStartingWith("VSG")) {
        suggestion.append(" que ");
        String[] result = getTwoNextPronouns(tokens,lastTokenPos + 1);
        String pronoms = result[0];
        adjustEndPos += Integer.valueOf(result[1]);
        AnalyzedToken at2 = new AnalyzedToken("", "", lastToken.readingWithTagRegex("V.G.*").getLemma());
        String[] synthForms2 = synth.synthesize(at2, "V.I" + verbPostag.substring(3,8), true, getLanguageVariantCode(match));
        if (synthForms2.length == 0) {
          return null;
        }
        if (!pronoms.isEmpty()) {
          suggestion.append(PronomsFeblesHelper.transformDavant(pronoms, synthForms2[0]));
        }
        suggestion.append(synthForms2[0]);
      } else if (lastToken.getToken().equals("sense")
        && (tokens[lastTokenPos + 1].hasPosTagStartingWith("VSN")
        || tokens[lastTokenPos + 1].hasPosTagStartingWith("VMN"))) {
        suggestion.append(" que no ");
        adjustEndPos++;
        String[] result = getTwoNextPronouns(tokens,lastTokenPos + 2);
        String pronoms = result[0];
        adjustEndPos += Integer.valueOf(result[1]);
        AnalyzedToken at2 = new AnalyzedToken("", "", tokens[lastTokenPos + 1].readingWithTagRegex("V.N.*").getLemma());
        String[] synthForms2 = synth.synthesize(at2, "V.I" + verbPostag.substring(3,8), true, getLanguageVariantCode(match));
        if (synthForms2.length == 0) {
          return null;
        }
        if (!pronoms.isEmpty()) {
          suggestion.append(PronomsFeblesHelper.transformDavant(pronoms, synthForms2[0]));
        }
        suggestion.append(synthForms2[0]);
      } else if (lastToken.getToken().equals("així") || lastToken.getToken().equals("a") || lastToken.getToken().equals("en")
        || lastToken.getToken().equals("de")
        || lastToken.hasPosTagStartingWith("AQ")
        || lastToken.hasPosTagStartingWith("VMP")) {
        AnalyzedToken at2 = new AnalyzedToken("", "", "estar");
        String[] synthForms2 = synth.synthesize(at2, "V.I" + verbPostag.substring(3,8), true, getLanguageVariantCode(match));
        if (synthForms2.length == 0) {
          return null;
        }
        suggestion.append(" que " + synthForms2[0]);
        adjustEndPos--;
      }else {
        return null;
      }
      String replacement = suggestion.toString();
      replacement = StringTools.preserveCase(replacement, tokens[posWord].getToken());
      if (replacement.isEmpty()) {
        return null;
      }
      RuleMatch ruleMatch = new RuleMatch(match.getRule(), match.getSentence(), tokens[posWord].getStartPos(),
        tokens[lastTokenPos + adjustEndPos].getEndPos(), match.getMessage(), match.getShortMessage());
      ruleMatch.setType(match.getType());
      ruleMatch.setSuggestedReplacement(replacement);
      return ruleMatch;
    }
  
    private String[] getTwoNextPronouns(AnalyzedTokenReadings[] tokens, int from) {
      String[] result = new String[2];
      int adjustEndPos = 0;
      String pronoms = "";
      if (from < tokens.length && !tokens[from].isWhitespaceBefore()) {
        AnalyzedToken pronom = tokens[from].readingWithTagRegex("P[P0].*");
        if (pronom != null) {
          pronoms = pronom.getToken();
          adjustEndPos++;
        }
        if (from + 1 < tokens.length && !tokens[from + 1].isWhitespaceBefore()) {
          AnalyzedToken pronom2 = tokens[from + 1].readingWithTagRegex("P[P0].*");
          if (pronom2 != null) {
            pronoms = pronoms + pronom2.getToken();
            adjustEndPos++;
          }
        }
      }
      result[0] = pronoms;
      result[1] = String.valueOf(adjustEndPos);
      return result;
    }
    private String getLanguageVariantCode(RuleMatch match) {
      PatternRule pr = (PatternRule) match.getRule();
      return pr.getLanguage().getShortCodeWithCountryAndVariant();
    }
  }