public void startElement()

in languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleHandler.java [124:486]


  public void startElement(String namespaceURI, String lName,
                           String qName, Attributes attrs) throws SAXException {
    switch (qName) {
      case "category":
        String catName = attrs.getValue(NAME);
        premiumCategoryAttribute = attrs.getValue(PREMIUM); //check if all rules should be premium by default in this category
        String catId = attrs.getValue(ID);
        Category.Location location = YES.equals(attrs.getValue(EXTERNAL)) ?
          Category.Location.EXTERNAL : Category.Location.INTERNAL;
        boolean onByDefault = !OFF.equals(attrs.getValue(DEFAULT));
        String tabName = attrs.getValue(TABNAME);
        category = new Category(new CategoryId(catId), catName, location, onByDefault, tabName);
        if (attrs.getValue(TYPE) != null) {
          categoryIssueType = attrs.getValue(TYPE);
        }
        if (attrs.getValue("tags") != null) {
          categoryTags.addAll(Arrays.asList(attrs.getValue("tags").split(" ")));
        }
        if (attrs.getValue("tone_tags") != null) {
          categoryToneTags.addAll(Arrays.asList(attrs.getValue("tone_tags").split(" ")));
        }
        isGoalSpecificCategoryAttribute = attrs.getValue(GOAL_SPECIFIC);
        String prioCategoryAttributeValue = attrs.getValue(PRIO);
        if (prioCategoryAttributeValue != null) {
          prioCategoryAttribute = Integer.parseInt(prioCategoryAttributeValue);
        }
        break;
      case "rules":
        String languageStr = attrs.getValue("lang");
        premiumFileAttribute = attrs.getValue(PREMIUM); //check if all rules should be premium by default in this file
        idPrefix = attrs.getValue("idprefix");
        if (language == null) {
          language = Languages.getLanguageForShortCode(languageStr);
        }
        messages = ResourceBundleTools.getMessageBundle(language);
        break;
      case "regexp":
        inRegex = true;
        regexMode = "exact".equals(attrs.getValue("type")) ? RegexpMode.EXACT : RegexpMode.SMART;
        regexCaseSensitive = attrs.getValue(CASE_SENSITIVE) != null && YES.equals(attrs.getValue(CASE_SENSITIVE));
        regexpMark = attrs.getValue(MARK) != null ? Integer.parseInt(attrs.getValue(MARK)) : 0;
        break;
      case RULE:
        xmlLineNumber = pLocator.getLineNumber();
        regex = new StringBuilder();
        inRule = true;
        shortMessage = new StringBuilder();
        message = new StringBuilder();
        suggestionsOutMsg = new StringBuilder();
        url = new StringBuilder();
        id = attrs.getValue(ID);
        name = attrs.getValue(NAME);
        String minPrevMatchesStr = attrs.getValue(MINPREVMATCHES);
        if (minPrevMatchesStr != null) {
          if (inRuleGroup && ruleGroupMinPrevMatches > 0) {
            throw new RuntimeException("Rule group " + ruleGroupId + " has " + MINPREVMATCHES + "=" + ruleGroupMinPrevMatches
                + ", thus rule " + id + " cannot specify " + MINPREVMATCHES);
          }
          minPrevMatches = Integer.parseInt(minPrevMatchesStr);  
        } else {
          minPrevMatches = ruleGroupMinPrevMatches;
        }
        String distanceTokensStr = attrs.getValue(DISTANCETOKENS);
        if (distanceTokensStr != null) {
          if (inRuleGroup && ruleGroupDistanceTokens > 0) {
            throw new RuntimeException("Rule group " + ruleGroupId + " has " + DISTANCETOKENS + "=" + ruleGroupDistanceTokens
                + ", thus rule " + id + " cannot specify " + DISTANCETOKENS);
          }
          distanceTokens = Integer.parseInt(distanceTokensStr);  
        } else {
          distanceTokens = ruleGroupDistanceTokens;
        }
        String premiumRule = attrs.getValue(PREMIUM);
        //check if this rule is premium
        if (premiumRule != null) {
          if (YES.equals(premiumRule)) {
            isPremiumRule = true;
          } else if (NO.equals(premiumRule)) {
            isPremiumRule = false;
          }
        } else if (premiumRuleGroupAttribute != null){
          if (YES.equals(premiumRuleGroupAttribute)) {
            isPremiumRule = true;
          } else if (NO.equals(premiumRuleGroupAttribute)) {
            isPremiumRule = false;
          }
        } else if (premiumCategoryAttribute != null) {
          if (YES.equals(premiumCategoryAttribute)) {
            isPremiumRule = true;
          } else if (NO.equals(premiumCategoryAttribute)) {
            isPremiumRule = false;
          }
        } else if (premiumFileAttribute != null){
          if (YES.equals(premiumFileAttribute)) {
            isPremiumRule = true;
          } else if (NO.equals(premiumFileAttribute)) {
            isPremiumRule = false;
          }
        } else {
          isPremiumRule = false;
        }
        if (inRuleGroup) {
          subId++;
          if (id == null) {
            id = ruleGroupId;
          }
          if (name == null) {
            name = ruleGroupDescription;
          }
        }
        if (id == null && !relaxedMode) {
          throw new RuntimeException("id is null for rule with name '" + name + "'");
        }
        id = idPrefix != null ? idPrefix + id : id;
        if (inRuleGroup && ruleGroupDefaultOff && attrs.getValue(DEFAULT) != null) {
          throw new RuntimeException("Rule group " + ruleGroupId + " is off by default, thus a subrule of " + id + " cannot specify 'default=...'. \033[1m Remove 'default=...' from rule group or subrule level in " + ruleGroupId + "!\033[0m");
        }
        if (inRuleGroup && ruleGroupDefaultTempOff && attrs.getValue(DEFAULT) != null) {
          throw new RuntimeException("Rule group " + ruleGroupId + " is off by default, thus a subrule of " + id + " cannot specify 'default=...'. \033[1m Remove 'default=...' from rule group or subrule level in " + ruleGroupId + "!\033[0m");
        }
        if (inRuleGroup && ruleGroupDefaultOff) {
          defaultOff = true;
        } else if (inRuleGroup && ruleGroupDefaultTempOff) {
          defaultTempOff = true;
        } else {
          defaultOff = OFF.equals(attrs.getValue(DEFAULT));
          defaultTempOff = TEMP_OFF.equals(attrs.getValue(DEFAULT));
        }
        correctExamples = new ArrayList<>();
        antipatternExamples = new ArrayList<>();
        incorrectExamples = new ArrayList<>();
        errorTriggeringExamples = new ArrayList<>();
        suggestionMatches.clear();
        suggestionMatchesOutMsg.clear();
        if (attrs.getValue(TYPE) != null) {
          ruleIssueType = attrs.getValue(TYPE);
        }
        isRuleSuppressMisspelled = false;
        if (attrs.getValue("tags") != null) {
          ruleTags.addAll(Arrays.asList(attrs.getValue("tags").split(" ")));
        }
        if (attrs.getValue("tone_tags") != null) {
          ruleToneTags.addAll(Arrays.asList(attrs.getValue("tone_tags").split(" ")));
        }
        String isGoalSpecificRule = attrs.getValue(GOAL_SPECIFIC);
        //check if this rule is goal specific
        if (isGoalSpecificRule != null) {
          if (TRUE.equals(isGoalSpecificRule)) {
            isGoalSpecific = true;
          } else if (FALSE.equals(isGoalSpecificRule)) {
            isGoalSpecific = false;
          }
        } else if (isGoalSpecificRuleGroupAttribute != null) {
          if (TRUE.equals(isGoalSpecificRuleGroupAttribute)) {
            isGoalSpecific = true;
          } else if (FALSE.equals(isGoalSpecificRuleGroupAttribute)) {
            isGoalSpecific = false;
          }
        } else if (isGoalSpecificCategoryAttribute != null) {
          if (TRUE.equals(isGoalSpecificCategoryAttribute)) {
            isGoalSpecific = true;
          } else if (FALSE.equals(isGoalSpecificCategoryAttribute)) {
            isGoalSpecific = false;
          }
        } else {
          isGoalSpecific = false;
        }
        String prioRuleAttributeValue = attrs.getValue(PRIO);
        if (prioRuleAttributeValue != null) {
          prioRuleAttribute = Integer.parseInt(prioRuleAttributeValue);
        }
        break;
      case PATTERN:
        startPattern(attrs);
        tokenCountForMarker = 0;
        interpretPosTagsPreDisambiguation = YES.equals(attrs.getValue(RAW_TAG));
        break;
      case ANTIPATTERN:
        xmlLineNumberAntiPattern = pLocator.getLineNumber();
        inAntiPattern = true;
        antiPatternCounter++;
        caseSensitive = YES.equals(attrs.getValue(CASE_SENSITIVE));
        tokenCounter = 0;
        tokenCountForMarker = 0;
        break;
      case AND:
        inAndGroup = true;
        tokenCountForMarker++;
        break;
      case OR:
        inOrGroup = true;
        tokenCountForMarker++;
        break;
      case UNIFY:
        inUnification = true;
        uniNegation = YES.equals(attrs.getValue(NEGATE));
        break;
      case UNIFY_IGNORE:
        inUnificationNeutral = true;
        break;
      case FEATURE:
        uFeature = attrs.getValue(ID);
        break;
      case TYPE:
        uType = attrs.getValue(ID);
        uTypeList.add(uType);
        break;
      case TOKEN:
        setToken(attrs);
        if (!inAndGroup && !inOrGroup) {
          tokenCountForMarker++;
        }
        break;
      case EXCEPTION:
        setExceptions(attrs);
        break;
      case EXAMPLE:
        String typeVal = attrs.getValue(TYPE);
        if (inAntiPattern) {
          if (inRuleGroup && !inRule) {
            inAntiPatternForRuleGroupExample = true;
            antiPatternForRuleGroupExample = new StringBuilder();
          } else {
            inAntiPatternExample = true;
            antiPatternExample = new StringBuilder();
          }
        } else if ("incorrect".equals(typeVal) || attrs.getValue("correction") != null) {
          inIncorrectExample = true;
          incorrectExample = new StringBuilder();
          if (attrs.getValue("correction") != null) {
            exampleCorrection = new StringBuilder();
            exampleCorrection.append(attrs.getValue("correction"));
          }
        } else if ("triggers_error".equals(typeVal)) {
          inErrorTriggerExample = true;
          errorTriggerExample = new StringBuilder();
        } else {
          // no attribute implies the sentence is a correct example
          inCorrectExample = true;
          correctExample = new StringBuilder();
        }
        break;
      case "filter":
        filterClassName = attrs.getValue("class");
        filterArgs = attrs.getValue("args");
        break;
      case MESSAGE:
        inMessage = true;
        inSuggestion = false;
        message = new StringBuilder();
        isRuleSuppressMisspelled = YES.equals(attrs.getValue("suppress_misspelled"));
        if (isRuleSuppressMisspelled) {
          message.append(PLEASE_SPELL_ME);
        }
        break;
      case SUGGESTION:
        String strToAppend = "<suggestion>";
        isSuggestionSuppressMisspelled = YES.equals(attrs.getValue("suppress_misspelled"));
        if (isSuggestionSuppressMisspelled || isRuleSuppressMisspelled) {
          strToAppend = strToAppend + PLEASE_SPELL_ME;
        }
        if (inMessage) {
          message.append(strToAppend);
        } else { // suggestions outside message
          suggestionsOutMsg.append(strToAppend);
        }
        inSuggestion = true;
        break;
      case "short":
        if (inRule) {
          inShortMessage = true;
          shortMessage = new StringBuilder();
        } else {
          inShortMessageForRuleGroup = true;
          shortMessageForRuleGroup = new StringBuilder();
        }
        break;
      case "url":
        if (inRule) {
          inUrl = true;
          url = new StringBuilder();
        } else {
          inUrlForRuleGroup = true;
          urlForRuleGroup = new StringBuilder();
        }
        break;
      case RULEGROUP:
        ruleGroupId = attrs.getValue(ID);
        premiumRuleGroupAttribute = attrs.getValue(PREMIUM);
        ruleGroupDescription = attrs.getValue(NAME);
        ruleGroupDefaultOff = OFF.equals(attrs.getValue(DEFAULT));
        ruleGroupDefaultTempOff = TEMP_OFF.equals(attrs.getValue(DEFAULT));
        urlForRuleGroup = new StringBuilder();
        shortMessageForRuleGroup = new StringBuilder();
        inRuleGroup = true;
        subId = 0;
        if (attrs.getValue(TYPE) != null) {
          ruleGroupIssueType = attrs.getValue(TYPE);
        }
        if (attrs.getValue("tags") != null) {
          ruleGroupTags.addAll(Arrays.asList(attrs.getValue("tags").split(" ")));
        }
        if (attrs.getValue("tone_tags") != null) {
          ruleGroupToneTags.addAll(Arrays.asList(attrs.getValue("tone_tags").split(" ")));
        }
        isGoalSpecificRuleGroupAttribute = attrs.getValue(GOAL_SPECIFIC);
        String minPrevMatchesStr2 = attrs.getValue(MINPREVMATCHES);
        if (minPrevMatchesStr2 != null) {
          ruleGroupMinPrevMatches = Integer.parseInt(minPrevMatchesStr2);  
        }
        String distanceTokensStr2 = attrs.getValue(DISTANCETOKENS);
        if (distanceTokensStr2 != null) {
          ruleGroupDistanceTokens = Integer.parseInt(distanceTokensStr2);  
        }
        antipatternForRuleGroupsExamples = new ArrayList<>();
        String prioRuleGroupAttributeValue = attrs.getValue(PRIO);
        if (prioRuleGroupAttributeValue != null) {
          prioRuleGroupAttribute = Integer.parseInt(prioRuleGroupAttributeValue);
        }
        break;
      case MATCH:
        setMatchElement(attrs, inSuggestion && (isSuggestionSuppressMisspelled || isRuleSuppressMisspelled));
        break;
      case MARKER:
        if (inMarker) {
          throw new IllegalStateException("'<marker>' may not be nested in rule '" + id + "'");
        }
        if (inIncorrectExample) {
          incorrectExample.append(MARKER_TAG);
        } else if (inCorrectExample) {
          correctExample.append(MARKER_TAG);
        } else if (inErrorTriggerExample) {
          errorTriggerExample.append(MARKER_TAG);
        } else if (inPattern || inAntiPattern) {
          startPos = tokenCounter;
          inMarker = true;
        }
        break;
      case UNIFICATION:
        uFeature = attrs.getValue("feature");
        inUnificationDef = true;
        break;
      case "equivalence":
        uType = attrs.getValue(TYPE);
        break;
      case PHRASES:
        inPhrases = true;
        break;
      case "includephrases":
        break;
      case "phrase":
        if (inPhrases) {
          phraseId = attrs.getValue(ID);
        }
        break;
      case "phraseref":
        if (attrs.getValue("idref") != null) {
          preparePhrase(attrs);
          tokenCountForMarker++;
        }
        break;
    }
  }