/* LanguageTool, a natural language style checker * Copyright (C) 2013 Daniel Naber (http://www.danielnaber.de) * * 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.de; import org.languagetool.AnalyzedToken; import org.languagetool.AnalyzedTokenReadings; import org.languagetool.synthesis.Synthesizer; import org.languagetool.tools.StringTools; import java.io.IOException; import java.util.*; /** * Create suggestions for German noun phrases that lack agreement. * @since 2.4 */ class AgreementSuggestor { private final Synthesizer synthesizer; private final AnalyzedTokenReadings determinerToken; private final AnalyzedTokenReadings nounToken; AgreementSuggestor(Synthesizer synthesizer, AnalyzedTokenReadings determinerToken, AnalyzedTokenReadings nounToken) { this.synthesizer = synthesizer; this.determinerToken = determinerToken; this.nounToken = nounToken; } List<String> getSuggestions() { Set<String> suggestionSet = new HashSet<>(); try { for (AnalyzedToken token2Reading : nounToken.getReadings()) { String nounCase = GermanHelper.getNounCase(token2Reading.getPOSTag()); String nounNumber = GermanHelper.getNounNumber(token2Reading.getPOSTag()); String nounGender = GermanHelper.getNounGender(token2Reading.getPOSTag()); for (AnalyzedToken token1Reading : determinerToken.getReadings()) { List<String> articleSuggestions = getArticleSuggestions(nounCase, nounNumber, nounGender, token1Reading); suggestionSet.addAll(articleSuggestions); List<String> pronounSuggestions = getPronounSuggestions(nounCase, nounNumber, nounGender, token1Reading); suggestionSet.addAll(pronounSuggestions); List<String> nounSuggestions = getNounSuggestions(token2Reading, token1Reading); suggestionSet.addAll(nounSuggestions); } } } catch (IOException e) { throw new RuntimeException(e); } List<String> suggestions = new ArrayList<>(suggestionSet); Collections.sort(suggestions); return suggestions; } private List<String> getArticleSuggestions(String nounCase, String nounNumber, String nounGender, AnalyzedToken article) throws IOException { String determinerDefiniteness = GermanHelper.getDeterminerDefiniteness(article.getPOSTag()); if (StringTools.isEmpty(determinerDefiniteness)) { return Collections.emptyList(); } List<String> result = new ArrayList<>(); String correctPosTag1 = "ART:" + determinerDefiniteness + ":" + nounCase + ":" + nounNumber + ":" + nounGender; result.addAll(getDeterminerSuggestionsForPosTag(article, correctPosTag1, null)); String correctPosTag2 = "PRO:DEM:" + nounCase + ":" + nounNumber + ":" + nounGender + ":B/S"; result.addAll(getDeterminerSuggestionsForPosTag(article, correctPosTag2, null)); return result; } private List<String> getPronounSuggestions(String nounCase, String nounNumber, String nounGender, AnalyzedToken pronoun) throws IOException { String correctPosTag = "PRO:POS:" + nounCase + ":" + nounNumber + ":" + nounGender + ":BEG"; // BEG = begleitend return getDeterminerSuggestionsForPosTag(pronoun, correctPosTag, determinerToken.getToken().substring(0, 1)); } private List<String> getNounSuggestions(AnalyzedToken token2Reading, AnalyzedToken determiner) throws IOException { if (determiner.getPOSTag() != null && determiner.getPOSTag().endsWith(":STV")) { // STV = stellvertretend return Collections.emptyList(); } String determinerCase = GermanHelper.getDeterminerCase(determiner.getPOSTag()); String determinerNumber = GermanHelper.getDeterminerNumber(determiner.getPOSTag()); String determinerGender = GermanHelper.getDeterminerGender(determiner.getPOSTag()); String correctPosTag = "SUB:" + determinerCase + ":" + determinerNumber + ":" + determinerGender; return getNounSuggestionsForPosTag(determinerToken, token2Reading, correctPosTag); } private List<String> getDeterminerSuggestionsForPosTag(AnalyzedToken token1Reading, String correctPosTag, String startsWith) throws IOException { List<String> suggestions = new ArrayList<>(); String[] correctedDeterminer = synthesizer.synthesize(token1Reading, correctPosTag); for (String determiner : correctedDeterminer) { if (startsWith != null && !determiner.startsWith(startsWith)) { // ignore so we don't create suggestions like "unsere" for "mein": continue; } String correctDeterminer = StringTools.isCapitalizedWord(determinerToken.getToken()) ? StringTools.uppercaseFirstChar(determiner) : determiner; suggestions.add(correctDeterminer + " " + nounToken.getToken()); } return suggestions; } private List<String> getNounSuggestionsForPosTag(AnalyzedTokenReadings token1, AnalyzedToken token2Reading, String correctPosTag) throws IOException { List<String> suggestions = new ArrayList<>(); String[] correctedNouns = synthesizer.synthesize(token2Reading, correctPosTag); for (String correctedNoun : correctedNouns) { suggestions.add(token1.getToken() + " " + correctedNoun); } return suggestions; } }