in languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleHandler.java [489:744]
public void endElement(String namespaceURI, String sName,
String qName) throws SAXException {
switch (qName) {
case "category":
categoryIssueType = null;
categoryTags.clear();
categoryToneTags.clear();
isGoalSpecific = false;
premiumCategoryAttribute = null;
isGoalSpecificCategoryAttribute = null;
prioCategoryAttribute = 0;
break;
case "regexp":
inRegex = false;
break;
case RULE:
suggestionMatchesOutMsg = addLegacyMatches(suggestionMatchesOutMsg, suggestionsOutMsg.toString(), false);
if (relaxedMode && id == null) {
id = "";
}
if (relaxedMode && name == null) {
name = "";
}
if (phrasePatternTokens.isEmpty()) {
// Elements contain information whether they are inside a <marker>...</marker>,
// but for phraserefs this depends on the position where the phraseref is used
// not where it's defined. Thus we have to copy the elements so each use of
// the phraseref can carry their own information:
List<PatternToken> tmpPatternTokens = new ArrayList<>();
createRules(new ArrayList<>(patternTokens), tmpPatternTokens, 0);
} else {
if (!patternTokens.isEmpty()) {
for (List<PatternToken> ph : phrasePatternTokens) {
ph.addAll(new ArrayList<>(patternTokens));
}
}
for (List<PatternToken> phrasePatternToken : phrasePatternTokens) {
processElement(phrasePatternToken);
List<PatternToken> tmpPatternTokens = new ArrayList<>();
createRules(phrasePatternToken, tmpPatternTokens, 0);
}
}
patternTokens.clear();
if (phrasePatternTokens != null) {
phrasePatternTokens.clear();
}
ruleIssueType = null;
inRule = false;
filterClassName = null;
filterArgs = null;
minPrevMatches = 0;
distanceTokens = 0;
ruleTags.clear();
ruleToneTags.clear();
isPremiumRule = false;
isGoalSpecific = false;
prioRuleAttribute = 0;
break;
case EXCEPTION:
finalizeExceptions();
break;
case AND:
inAndGroup = false;
andGroupCounter = 0;
tokenCounter++;
break;
case OR:
inOrGroup = false;
orGroupCounter = 0;
tokenCounter++;
break;
case TOKEN:
finalizeTokens(language.getUnifierConfiguration());
break;
case PATTERN:
inPattern = false;
if (lastPhrase) {
patternTokens.clear();
}
tokenCounter = 0;
break;
case ANTIPATTERN:
String antiId = id;
if (inRuleGroup) {
if (subId > 0) {
antiId = ruleGroupId + "[" + subId + "]";
} else {
antiId = ruleGroupId;
}
}
DisambiguationPatternRule rule = new DisambiguationPatternRule(
antiId + "_antipattern:" + antiPatternCounter,
"antipattern", language, patternTokens, null, null,
DisambiguationPatternRule.DisambiguatorAction.IMMUNIZE);
rule.setXmlLineNumber(xmlLineNumberAntiPattern);
if (startPos != -1 && endPos != -1) {
rule.setStartPositionCorrection(startPos);
rule.setEndPositionCorrection(endPos - tokenCountForMarker);
} else {
// No '<marker>'? Then add artificial <marker>s around all tokens to work
// around issue https://github.com/languagetool-org/languagetool/issues/189:
for (PatternToken patternToken : patternTokens) {
patternToken.setInsideMarker(true);
}
}
patternTokens.clear();
if (inRule) {
ruleAntiPatterns.add(rule);
} else { // a rulegroup shares all antipatterns not included in a single rule
rulegroupAntiPatterns.add(rule);
}
tokenCounter = 0;
inAntiPattern = false;
endPos = -1;
startPos = -1;
inAntiPatternExample = false;
xmlLineNumberAntiPattern = -1;
break;
case EXAMPLE:
if (inAntiPatternExample) {
antipatternExamples.add(new CorrectExample(antiPatternExample.toString()));
} else if (inAntiPatternForRuleGroupExample) {
antipatternForRuleGroupsExamples.add(new CorrectExample(antiPatternForRuleGroupExample.toString()));
} else if (inCorrectExample) {
correctExamples.add(new CorrectExample(correctExample.toString()));
} else if (inIncorrectExample) {
if (inAntiPattern) {
throw new RuntimeException("<antipattern>s can only contain <example>s without errors (i.e. no 'correction=...'). " +
"Rule id: " + id + "[" + subId + "], antipattern no " + antiPatternCounter);
}
IncorrectExample example;
if (exampleCorrection == null) {
example = new IncorrectExample(incorrectExample.toString());
} else {
List<String> corrections = new ArrayList<>(Arrays.asList(exampleCorrection.toString().split("\\|")));
if (exampleCorrection.toString().endsWith("|")) { // suggestions plus an empty suggestion (split() will ignore trailing empty items)
corrections.add("");
}
example = new IncorrectExample(incorrectExample.toString(), corrections);
}
incorrectExamples.add(example);
} else if (inErrorTriggerExample) {
errorTriggeringExamples.add(new ErrorTriggeringExample(errorTriggerExample.toString()));
}
inCorrectExample = false;
inIncorrectExample = false;
inErrorTriggerExample = false;
correctExample = new StringBuilder();
incorrectExample = new StringBuilder();
errorTriggerExample = new StringBuilder();
exampleCorrection = null;
antiPatternExample = new StringBuilder();
antiPatternForRuleGroupExample = new StringBuilder();
inAntiPatternExample = false;
inAntiPatternForRuleGroupExample = false;
break;
case MESSAGE:
suggestionMatches = addLegacyMatches(suggestionMatches, message.toString(), true);
inMessage = false;
break;
case SUGGESTION:
if (inMessage) {
message.append("</suggestion>");
} else { //suggestion outside message
suggestionsOutMsg.append("</suggestion>");
}
inSuggestion = false;
break;
case "short":
inShortMessage = false;
inShortMessageForRuleGroup = false;
break;
case "url":
inUrl = false;
inUrlForRuleGroup = false;
break;
case MATCH:
if (inMessage) {
suggestionMatches.get(suggestionMatches.size() - 1).
setLemmaString(match.toString());
} else if (inSuggestion) {
suggestionMatchesOutMsg.get(suggestionMatchesOutMsg.size() - 1).
setLemmaString(match.toString());
} else if (inToken) {
tokenReference.setLemmaString(match.toString());
}
inMatch = false;
break;
case RULEGROUP:
urlForRuleGroup = new StringBuilder();
shortMessageForRuleGroup = new StringBuilder();
inRuleGroup = false;
ruleGroupIssueType = null;
rulegroupAntiPatterns.clear();
antiPatternCounter = 0;
ruleGroupDefaultOff = false;
ruleGroupDefaultTempOff = false;
defaultOff = false;
defaultTempOff = false;
ruleGroupMinPrevMatches = 0;
ruleGroupDistanceTokens = 0;
ruleGroupTags.clear();
ruleGroupToneTags.clear();
premiumRuleGroupAttribute = null;
isGoalSpecificRuleGroupAttribute = null;
antipatternForRuleGroupsExamples.clear();
prioRuleGroupAttribute = 0;
break;
case MARKER:
if (inCorrectExample) {
correctExample.append("</marker>");
} else if (inIncorrectExample) {
incorrectExample.append("</marker>");
} else if (inErrorTriggerExample) {
errorTriggerExample.append("</marker>");
} else if (inPattern || inAntiPattern) {
endPos = tokenCountForMarker;
inMarker = false;
}
break;
case "phrase":
if (inPhrases) {
finalizePhrase();
}
break;
case "includephrases":
patternTokens.clear();
break;
case PHRASES:
if (inPhrases) {
inPhrases = false;
}
break;
case UNIFICATION:
inUnificationDef = false;
break;
case FEATURE:
equivalenceFeatures.put(uFeature, uTypeList);
uTypeList = new ArrayList<>();
break;
case UNIFY:
inUnification = false;
//clear the features...
equivalenceFeatures = new HashMap<>();
//set negation on the last token only!
int lastElement = patternTokens.size() - 1;
patternTokens.get(lastElement).setLastInUnification();
if (uniNegation) {
patternTokens.get(lastElement).setUniNegation();
}
break;
case UNIFY_IGNORE:
inUnificationNeutral = false;
break;
}
}