private void createRules(List<PatternToken> elemList,
    List<PatternToken> tmpPatternTokens, int numElement) {
    String shortMessage = "";
    if (this.shortMessage != null && this.shortMessage.length() > 0) {
      shortMessage = this.shortMessage.toString();
    } else if (shortMessageForRuleGroup != null && shortMessageForRuleGroup.length() > 0) {
      shortMessage = this.shortMessageForRuleGroup.toString();
    }
    if (numElement >= elemList.size()) {
      AbstractPatternRule rule;
      if (tmpPatternTokens.size() > 0) {
        rule = new PatternRule(id, language, tmpPatternTokens, name,
                message.toString(), shortMessage,
                suggestionsOutMsg.toString(), phrasePatternTokens.size() > 1, interpretPosTagsPreDisambiguation);
        rule.setSourceFile(sourceFile);
      } else if (regex.length() > 0) {
        int flags = regexCaseSensitive ? 0 : Pattern.CASE_INSENSITIVE|Pattern.UNICODE_CASE;
        String regexStr = regex.toString();
        if (regexMode == RegexpMode.SMART) {
          // Note: it's not that easy to add \b because the regex might look like '(foo)' or '\d' so we cannot just look at the last character
          regexStr = replaceSpacesInRegex(regexStr);
        }
        if (ruleAntiPatterns.size() > 0 || rulegroupAntiPatterns.size() > 0) {
          throw new RuntimeException("<regexp> rules currently cannot be used together with <antipattern>. Rule id: " + id + "[" + subId + "]");
        }
        rule = new RegexPatternRule(id, name, message.toString(), shortMessage, suggestionsOutMsg.toString(), language, Pattern.compile(regexStr, flags), regexpMark);
      } else {
        throw new IllegalStateException("Neither '<pattern>' tokens nor '<regex>' is set in rule '" + id + "'");
      }
      setRuleFilter(filterClassName, filterArgs, rule);
      prepareRule(rule);
      rules.add(rule);
    } else {
      PatternToken patternToken = elemList.get(numElement);
      if (patternToken.hasOrGroup()) {
        // When creating a new rule, we finally clear the backed-up variables. All the elements in
        // the OR group should share the values of backed-up variables. That's why these variables
        // are backed-up.
        List<Match> suggestionMatchesBackup = new ArrayList<>(suggestionMatches);
        List<Match> suggestionMatchesOutMsgBackup =  new ArrayList<>(suggestionMatchesOutMsg);
        int startPosBackup = startPos;
        int endPosBackup = endPos;
        List<DisambiguationPatternRule> ruleAntiPatternsBackup = new ArrayList<>(ruleAntiPatterns);
        for (PatternToken patternTokenOfOrGroup : patternToken.getOrGroup()) {
          List<PatternToken> tmpElements2 = new ArrayList<>();
          tmpElements2.addAll(tmpPatternTokens);
          tmpElements2.add(ObjectUtils.clone(patternTokenOfOrGroup));
          createRules(elemList, tmpElements2, numElement + 1);
          startPos = startPosBackup;
          endPos = endPosBackup;
          suggestionMatches = suggestionMatchesBackup;
          suggestionMatchesOutMsg = suggestionMatchesOutMsgBackup;
          ruleAntiPatterns.addAll(ruleAntiPatternsBackup);
        }
      }
      tmpPatternTokens.add(ObjectUtils.clone(patternToken));
      createRules(elemList, tmpPatternTokens, numElement + 1);
    }
  }
private void createRules ( List < PatternToken > elemList , List < PatternToken > tmpPatternTokens , int numElement ) { String shortMessage = "" ; if ( this . shortMessage != null && this . shortMessage . length ( ) > 0 ) { shortMessage = this . shortMessage . toString ( ) ; } else if ( shortMessageForRuleGroup != null && shortMessageForRuleGroup . length ( ) > 0 ) { shortMessage = this . shortMessageForRuleGroup . toString ( ) ; } if ( numElement >= elemList . size ( ) ) { AbstractPatternRule rule ; if ( tmpPatternTokens . size ( ) > 0 ) { rule = new PatternRule ( id , language , tmpPatternTokens , name , message . toString ( ) , shortMessage , suggestionsOutMsg . toString ( ) , phrasePatternTokens . size ( ) > 1 , interpretPosTagsPreDisambiguation ) ; rule . setSourceFile ( sourceFile ) ; } else if ( regex . length ( ) > 0 ) { int flags = regexCaseSensitive ? 0 : Pattern . CASE_INSENSITIVE | Pattern . UNICODE_CASE ; String regexStr = regex . toString ( ) ; if ( regexMode == RegexpMode . SMART ) { regexStr = replaceSpacesInRegex ( regexStr ) ; } if ( ruleAntiPatterns . size ( ) > 0 || rulegroupAntiPatterns . size ( ) > 0 ) { throw new RuntimeException ( "<regexp> rules currently cannot be used together with <antipattern>. Rule id: " + id + "[" + subId + "]" ) ; } rule = new RegexPatternRule ( id , name , message . toString ( ) , shortMessage , suggestionsOutMsg . toString ( ) , language , Pattern . compile ( regexStr , flags ) , regexpMark ) ; } else { throw new IllegalStateException ( "Neither '<pattern>' tokens nor '<regex>' is set in rule '" + id + "'" ) ; } setRuleFilter ( filterClassName , filterArgs , rule ) ; prepareRule ( rule ) ; rules . add ( rule ) ; } else { PatternToken patternToken = elemList . get ( numElement ) ; if ( patternToken . hasOrGroup ( ) ) { List < Match > suggestionMatchesBackup = new ArrayList < > ( suggestionMatches ) ; List < Match > suggestionMatchesOutMsgBackup = new ArrayList < > ( suggestionMatchesOutMsg ) ; int startPosBackup = startPos ; int endPosBackup = endPos ; List < DisambiguationPatternRule > ruleAntiPatternsBackup = new ArrayList < > ( ruleAntiPatterns ) ; for ( PatternToken patternTokenOfOrGroup : patternToken . getOrGroup ( ) ) { List < PatternToken > tmpElements2 = new ArrayList < > ( ) ; tmpElements2 . addAll ( tmpPatternTokens ) ; tmpElements2 . add ( ObjectUtils . clone ( patternTokenOfOrGroup ) ) ; createRules ( elemList , tmpElements2 , numElement + 1 ) ; startPos = startPosBackup ; endPos = endPosBackup ; suggestionMatches = suggestionMatchesBackup ; suggestionMatchesOutMsg = suggestionMatchesOutMsgBackup ; ruleAntiPatterns . addAll ( ruleAntiPatternsBackup ) ; } } tmpPatternTokens . add ( ObjectUtils . clone ( patternToken ) ) ; createRules ( elemList , tmpPatternTokens , numElement + 1 ) ; } }
Create rule from an Element list.
In case of OR groups, several rules are created recursively.
@since 2.3

@param elemList The complete original Element list
@param tmpPatternTokens Temporary list being created
@param numElement Index of elemList being analyzed