private LoggingEvent convertToEvent(Map fieldMap, String[] exception, DateFormat dateFormat) {
    if (fieldMap == null) {
      return null;
    }

    // a logger must exist at a minimum for the event to be processed
    if (!fieldMap.containsKey(LOGGER)) {
      fieldMap.put(LOGGER, "Unknown");
    }
    if (exception == null) {
      exception = emptyException;
    }

    String logger = "";
    long timeStamp = 0L;
    String level = null;
    String threadName = null;
    Object message = null;
    String ndc = null;
    String className = null;
    String methodName = null;
    String eventFileName = null;
    String lineNumber = null;
    Hashtable properties = new Hashtable();

    logger = StringUtils.trim((String) fieldMap.remove(LOGGER));

    if ((dateFormat != null) && fieldMap.containsKey(TIMESTAMP)) {
      String dateString = (String) fieldMap.remove(TIMESTAMP);
      try {
        timeStamp = dateFormat.parse(dateString).getTime();
      } catch (Exception e) {
        LOG.log(java.util.logging.Level.WARNING, "Error parsing date with format \"" + dateFormat + "\" with String \"" + dateString + "\"", e);
      }
    }
    // use current time if timestamp not parseable
    if (timeStamp == 0L) {
      timeStamp = System.currentTimeMillis();
    }

    message = fieldMap.remove(MESSAGE);
    if (message == null) {
      message = "";
    }

    level = StringUtils.trim((String) fieldMap.remove(LEVEL));
    Level levelImpl;
    if (level == null) {
      levelImpl = Level.DEBUG;
    } else {
      // first try to resolve against custom level definition map, then
      // fall back to regular levels
      level = level.trim();
      final Optional<Level> levelOptional = customLevelsParser.parse(level);
      if (levelOptional.isPresent()) {
        levelImpl = levelOptional.get();
      } else {
        levelImpl = Level.toLevel(level.trim());
        if (!level.equals(levelImpl.toString())) {
          // check custom level map
          levelImpl = Level.DEBUG;
          LOG.fine("found unexpected level: " + level + ", logger: " + logger + ", msg: " + message);
          // make sure the text that couldn't match a level is
          // added to the message
          message = level + " " + message;
        }
      }
    }

    threadName = StringUtils.trim((String) fieldMap.remove(THREAD));
    if (threadName == null) {
      threadName = "";
    }

    ndc = (String) fieldMap.remove(NDC);

    className = StringUtils.trim((String) fieldMap.remove(CLASS));

    methodName = (String) fieldMap.remove(METHOD);

    eventFileName = (String) fieldMap.remove(FILE);

    lineNumber = (String) fieldMap.remove(LINE);

    // properties.put(Constants.HOSTNAME_KEY, host);
    // properties.put(Constants.APPLICATION_KEY, path);
    // properties.put(Constants.RECEIVER_NAME_KEY, getName());

    // all remaining entries in fieldmap are properties
    properties.putAll(fieldMap);

    LocationInfo info = null;

    if ((eventFileName != null) || (className != null) || (methodName != null) || (lineNumber != null)) {
      info = new LocationInfo(eventFileName, className, methodName, lineNumber);
    } else {
      info = LocationInfo.NA_LOCATION_INFO;
    }
    LoggingEvent event = new LoggingEvent(null, logger, timeStamp, levelImpl, message, threadName, exception, ndc, info, properties);
    return event;
  }
Convert a keyword-to-values map to a LoggingEvent

@param fieldMap
@param exception

@return logging event
olv-core/src/main/java/pl/otros/logview/parser/log4j/Log4jPatternMultilineLogParser.java