protected void initializePatterns() {

    // if custom level definitions exist, parse them
    customLevelsParser = new CustomLevelsParser(customLevelDefinitions);

    List<String> buildingKeywords = new ArrayList<>();

    String newPattern = logFormat;

    int index = 0;
    String current = newPattern;
    // build a list of property names and temporarily replace the property
    // with an empty string,
    // we'll rebuild the pattern later
    // ?  The propertyNames list is never used.
    List<String> propertyNames = new ArrayList<>();
    while (index > -1) {
      if (current.contains(PROP_START) && current.indexOf(PROP_END) > -1) {
        index = current.indexOf(PROP_START);
        String longPropertyName = current.substring(current.indexOf(PROP_START), current.indexOf(PROP_END) + 1);
        String shortProp = getShortPropertyName(longPropertyName);
        buildingKeywords.add(shortProp);
        propertyNames.add(longPropertyName);
        current = current.substring(longPropertyName.length() + 1 + index);
        newPattern = singleReplace(newPattern, longPropertyName, Integer.toString(buildingKeywords.size() - 1));
      } else {
        // no properties
        index = -1;
      }
    }

    /*
     * we're using a treemap, so the index will be used as the key to ensure keywords are ordered correctly
     * 
     * examine pattern, adding keywords to an index-based map patterns can contain only one of these per entry...properties are the only 'keyword' that can
     * occur multiple times in an entry
     */
    Iterator iter = keywords.iterator();
    while (iter.hasNext()) {
      String keyword = (String) iter.next();
      int index2 = newPattern.indexOf(keyword);
      if (index2 > -1) {
        buildingKeywords.add(keyword);
        newPattern = singleReplace(newPattern, keyword, Integer.toString(buildingKeywords.size() - 1));
      }
    }

    String buildingInt = "";

    for (int i = 0; i < newPattern.length(); i++) {
      String thisValue = String.valueOf(newPattern.substring(i, i + 1));
      if (isInteger(thisValue)) {
        buildingInt = buildingInt + thisValue;
      } else {
        if (isInteger(buildingInt)) {
          matchingKeywords.add(buildingKeywords.get(Integer.parseInt(buildingInt)));
        }
        // reset
        buildingInt = "";
      }
    }

    // if the very last value is an int, make sure to add it
    if (isInteger(buildingInt)) {
      matchingKeywords.add(buildingKeywords.get(Integer.parseInt(buildingInt)));
    }

    newPattern = replaceMetaChars(newPattern);

    // compress one or more spaces in the pattern into the [ ]+ regexp
    // (supports padding of level in log files)
    newPattern = newPattern.replaceAll(MULTIPLE_SPACES_REGEXP, MULTIPLE_SPACES_REGEXP);
    newPattern = newPattern.replaceAll(Pattern.quote(PATTERN_WILDCARD), REGEXP_DEFAULT_WILDCARD);
    // use buildingKeywords here to ensure correct order
    for (int i = 0; i < buildingKeywords.size(); i++) {
      String keyword = buildingKeywords.get(i);
      // make the final keyword greedy (we're assuming it's the message)
      if (i == (buildingKeywords.size() - 1)) {
        newPattern = singleReplace(newPattern, String.valueOf(i), GREEDY_GROUP);
      } else if (TIMESTAMP.equals(keyword)) {
        newPattern = singleReplace(newPattern, String.valueOf(i), "(" + timestampPatternText.replaceAll("'", "") + ")");
      } else if (LOGGER.equals(keyword) || LEVEL.equals(keyword)) {
        newPattern = singleReplace(newPattern, String.valueOf(i), IN_SPACE_GROUP);
      } else {
        newPattern = singleReplace(newPattern, String.valueOf(i), DEFAULT_GROUP);
      }
    }

    regexp = newPattern;
    LOG.fine("regexp is " + regexp);
  }
Build the regular expression needed to parse log entries
olv-core/src/main/java/pl/otros/logview/parser/log4j/Log4jPatternMultilineLogParser.java