public SyslogMessage parse() throws SyslogParserException {
    final SyslogMessage syslogMessage = new SyslogMessage();

    String message = getText();

    int lbIdx = message.indexOf('<');
    int rbIdx = message.indexOf('>');

    if (lbIdx < 0 || rbIdx < 0 || lbIdx >= (rbIdx - 1)) {
      LogUtils.warnf(this, "Syslogd received an unparsable message!");
    }

    int priCode = 0;
    String priStr = message.substring(lbIdx + 1, rbIdx);

    try {
      priCode = Integer.parseInt(priStr);
    } catch (final NumberFormatException ex) {
      LogUtils.debugf(this, "ERROR Bad priority code '%s'", priStr);
    }

    LogUtils.tracef(this, "priority code = %d", priCode);

    syslogMessage.setFacility(SyslogFacility.getFacilityForCode(priCode));
    syslogMessage.setSeverity(SyslogSeverity.getSeverityForCode(priCode));

    message = message.substring(rbIdx + 1, message.length());

    final Matcher idMatcher = m_messageIdPattern.matcher(message);
    if (idMatcher.find()) {
      final String messageId = idMatcher.group(2);
      LogUtils.tracef(this, "found message ID '%s'", messageId);
      syslogMessage.setMessageID(messageId);
      message = message.substring(idMatcher.group(1).length() - 1);
    }

    LogUtils.tracef(this, "message = %s", message);

    Matcher oldDateMatcher = m_oldDatePattern.matcher(message);
    if (!oldDateMatcher.find()) {
      oldDateMatcher = null;
    }
    LogUtils.tracef(this, "stdMsg = %s", Boolean.toString(oldDateMatcher != null));

    if (!this.find()) {
      if (traceEnabled()) {
        LogUtils.tracef(
            this, "Lenient Syslog pattern '%s' did not match '%s'", getPattern(), getText());
      }
      return null;
    }

    String timestamp;

    if (oldDateMatcher == null) {
      final Matcher stampMatcher = m_datePattern.matcher(message);
      if (stampMatcher.find()) {
        timestamp = stampMatcher.group(2);
        LogUtils.tracef(this, "found timestamp '%s'", timestamp);
        //                message = message.substring(stampMatcher.group(1).length());
      } else {
        try {
          timestamp = SyslogTimeStamp.getInstance().format(new Date());
        } catch (final IllegalArgumentException ex) {
          LogUtils.debugf(this, "ERROR INTERNAL DATE ERROR!");
          timestamp = "";
        }
      }
    } else {
      timestamp = oldDateMatcher.group(1);
      message = oldDateMatcher.replaceFirst("");
    }

    LogUtils.tracef(this, "timestamp = %s", timestamp);
    syslogMessage.setDate(parseDate(timestamp));

    // These 2 debugs will aid in analyzing the regexes as syslog seems
    // to differ a lot depending on implementation or message structure.

    if (LogUtils.isTraceEnabled(this)) {
      LogUtils.tracef(this, "message = %s", message);
      LogUtils.tracef(this, "pattern = %s", m_forwardingPattern);
      LogUtils.tracef(this, "host group = %d", m_matchingGroupHost);
      LogUtils.tracef(this, "message group = %d", m_matchingGroupMessage);
    }

    // We will also here find out if, the host needs to
    // be replaced, the message matched to a UEI, and
    // last if we need to actually hide the message.
    // this being potentially helpful in avoiding showing
    // operator a password or other data that should be
    // confidential.

    final Pattern pattern = m_forwardingPattern;
    final Matcher m = pattern.matcher(message);

    /*
     * We matched on a regexp for host/message pair.
     * This can be a forwarded message as in BSD Style
     * or syslog-ng.
     */

    if (m.matches()) {

      final String matchedMessage = m.group(m_matchingGroupMessage);
      syslogMessage.setMatchedMessage(matchedMessage);

      if (LogUtils.isTraceEnabled(this)) {
        LogUtils.tracef(
            this, "Syslog message '%s' matched regexp '%s'", message, m_forwardingPattern);
        LogUtils.tracef(this, "Found host '%s'", m.group(m_matchingGroupHost));
        LogUtils.tracef(this, "Found message '%s'", matchedMessage);
      }

      syslogMessage.setHostName(m.group(m_matchingGroupHost));

      message = matchedMessage;
    } else {
      LogUtils.debugf(this, "Regexp not matched: %s", message);
      return null;
    }

    lbIdx = message.indexOf('[');
    rbIdx = message.indexOf(']');
    final int colonIdx = message.indexOf(':');
    final int spaceIdx = message.indexOf(' ');

    int processId = 0;
    String processName = "";
    String processIdStr = "";

    if (lbIdx < (rbIdx - 1) && colonIdx == (rbIdx + 1) && spaceIdx == (colonIdx + 1)) {
      processName = message.substring(0, lbIdx);
      processIdStr = message.substring(lbIdx + 1, rbIdx);
      message = message.substring(colonIdx + 2);

      try {
        processId = Integer.parseInt(processIdStr);
      } catch (final NumberFormatException ex) {
        LogUtils.debugf(this, "Bad process id '%s'", processIdStr);
        processId = 0;
      }
    } else if (lbIdx < 0 && rbIdx < 0 && colonIdx > 0 && spaceIdx == (colonIdx + 1)) {
      processName = message.substring(0, colonIdx);
      message = message.substring(colonIdx + 2);
    }

    syslogMessage.setProcessId(processId);
    syslogMessage.setProcessName(processName);
    syslogMessage.setMessage(message.trim());

    return syslogMessage;
  }