class SpanishSynthesizer extends BaseSynthesizer {

  private static final String RESOURCE_FILENAME = "/es/es-ES_synth.dict";
  private static final String TAGS_FILE_NAME = "/es/es-ES_tags.txt";

  private static final Pattern pLemmaSpace = Pattern.compile("([^ ]+) (.+)");

  public static final SpanishSynthesizer INSTANCE = new SpanishSynthesizer();

  /** @deprecated use {@link #INSTANCE} */
  public SpanishSynthesizer(Language lang) {
    this();
  }
  private SpanishSynthesizer() {
    super("/es/es.sor", RESOURCE_FILENAME, TAGS_FILE_NAME, "es");
  }

  @Override
  public String[] synthesize(AnalyzedToken token, String posTag) throws IOException {<FILL_FUNCTION_BODY>}
  
  @Override
  public String[] synthesize(AnalyzedToken token, String posTag, boolean posTagRegExp) throws IOException {
    if (posTag.startsWith(SPELLNUMBER_TAG)) {
      return synthesize(token, posTag);
    }
    if (posTagRegExp) {
      String lemma = token.getLemma();
      String toAddAfter = "";
      // verbs with noun
      if (posTag.startsWith("V")) {
        Matcher mLemmaSpace = pLemmaSpace.matcher(lemma);
        if (mLemmaSpace.matches()) {
          lemma = mLemmaSpace.group(1);
          toAddAfter = mLemmaSpace.group(2);
        }
      }
      initPossibleTags();
      Pattern p;
      try {
        p = Pattern.compile(posTag);
      } catch (PatternSyntaxException e) {
        System.err.println("WARNING: Error trying to synthesize POS tag " + posTag + " from token " + token.getToken()
            + ": " + e.getMessage());
        return null;
      }
      List<String> results = new ArrayList<>();
      for (String tag : possibleTags) {
        Matcher m = p.matcher(tag);
        if (m.matches()) {
          results.addAll(lookup(lemma, tag));
        }
      }
      return addWordsAfter(results, toAddAfter).toArray(new String[0]);
    }
    return synthesize(token, posTag);
  }

  private List<String> addWordsAfter(List<String> results, String toAddAfter) {
    if (!toAddAfter.isEmpty()) {
      List<String> output = new ArrayList<>();
      for (String result : results) {
        output.add(result + " " + toAddAfter);
      }
      return output;
    }
    return results;
  }

  @Override
  public String getTargetPosTag(List<String> posTags, String targetPosTag) {
    if (posTags.isEmpty()) {
      return targetPosTag;
    }
    PostagComparator postagComparator = new PostagComparator();
    posTags.sort(postagComparator);
    // return the last one to keep the previous results
    return posTags.get(posTags.size() - 1);
  }


  private static class PostagComparator implements Comparator<String> {
    @Override
    public int compare(String arg0, String arg1) {
      // Indicative > Imperative
      int len0 = arg0.length();
      int len1 = arg1.length();
      if (len0 > 4 && len1 > 4) {
        if (arg0.equals("VMIP3S0") && arg1.equals("VMM02S0")) {
          return 150;
        }
        if (arg0.equals("VMM02S0") && arg1.equals("VMIP3S0")) {
          return -150;
        }
      }
      return 0;
    }
  }
}

    if (posTag.startsWith(SPELLNUMBER_TAG)) {
      return super.synthesize(token, posTag);
    }
    String lemma = token.getLemma();
    String toAddAfter = "";
    // verbs with noun
    if (posTag.startsWith("V")) {
      Matcher mLemmaSpace = pLemmaSpace.matcher(lemma);
      if (mLemmaSpace.matches()) {
        lemma = mLemmaSpace.group(1);
        toAddAfter = mLemmaSpace.group(2);
      }
    }
    List<String> results = new ArrayList<>();
    results.addAll(lookup(lemma, posTag));
    return addWordsAfter(results, toAddAfter).toArray(new String[0]);
  
<methods>public void <init>(java.lang.String, java.lang.String, java.lang.String, org.languagetool.Language) ,public void <init>(java.lang.String, java.lang.String, java.lang.String, java.lang.String) ,public void <init>(java.lang.String, java.lang.String, org.languagetool.Language) ,public void <init>(java.lang.String, java.lang.String, java.lang.String) ,public java.lang.String getPosTagCorrection(java.lang.String) ,public java.lang.String getRomanNumber(java.lang.String) ,public java.lang.String getSpelledNumber(java.lang.String) ,public IStemmer getStemmer() ,public java.lang.String getTargetPosTag(List<java.lang.String>, java.lang.String) ,public java.lang.String[] synthesize(org.languagetool.AnalyzedToken, java.lang.String) throws java.io.IOException,public java.lang.String[] synthesize(org.languagetool.AnalyzedToken, java.lang.String, boolean) throws java.io.IOException,public java.lang.String[] synthesizeForPosTags(java.lang.String, Predicate<java.lang.String>) throws java.io.IOException<variables>public final java.lang.String SPELLNUMBER_FEMININE_TAG,public final java.lang.String SPELLNUMBER_ROMAN_TAG,public final java.lang.String SPELLNUMBER_TAG,private volatile Dictionary dictionary,private final non-sealed org.languagetool.synthesis.ManualSynthesizer manualSynthesizer,private final non-sealed org.languagetool.synthesis.Soros numberSpeller,protected volatile List<java.lang.String> possibleTags,private final non-sealed org.languagetool.synthesis.ManualSynthesizer removalSynthesizer,private final non-sealed org.languagetool.synthesis.ManualSynthesizer removalSynthesizer2,private final non-sealed java.lang.String resourceFileName,private final non-sealed org.languagetool.synthesis.Soros romanNumberer,private final non-sealed java.lang.String sorosFileName,private final non-sealed IStemmer stemmer,private final non-sealed java.lang.String tagFileName