// Path: src/main/java/com/github/davidmoten/logan/Field.java
// public static final String LEVEL = "logLevel";
// 
// Path: src/main/java/com/github/davidmoten/logan/Field.java
// public static final String LOGGER = "logLogger";
// 
// Path: src/main/java/com/github/davidmoten/logan/Field.java
// public static final String METHOD = "logMethod";
// 
// Path: src/main/java/com/github/davidmoten/logan/Field.java
// public static final String MSG = "logMsg";
// 
// Path: src/main/java/com/github/davidmoten/logan/Field.java
// public static final String THREAD_NAME = "threadName";
// 
// Path: src/main/java/com/github/davidmoten/logan/Field.java
// public static final String TIMESTAMP = "logTimestamp";


import static com.github.davidmoten.logan.Field.LEVEL;
import static com.github.davidmoten.logan.Field.LOGGER;
import static com.github.davidmoten.logan.Field.METHOD;
import static com.github.davidmoten.logan.Field.MSG;
import static com.github.davidmoten.logan.Field.THREAD_NAME;
import static com.github.davidmoten.logan.Field.TIMESTAMP;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import com.google.common.collect.BiMap;
import com.google.common.collect.Maps;
     * Returns the parsed line as a {@link LogEntry}. Note that this method is
     * synchronized because the {@link DateFormat} object used by it is not
     * thread-safe. However, you can safely instantiate multiple {@link LogParser}
     * objects and use them concurrently.
     * 
     * @param source
     *            source
     * @param line
     *            line
     * @return parsed LogEntry
     */
    public synchronized LogEntry parse(String source, String line) {
        if (line == null)
            return null;
        else {
            if (options.isMultiline() && (previousLine == null)) {
                previousLine = line;
                return null;
            } else {
                StringBuilder candidate = new StringBuilder(line);
                if (options.isMultiline()) {
                    candidate.insert(0, "ZZZ");
                    candidate.insert(0, previousLine);
                }
                Matcher matcher = options.getPattern().matcher(candidate);
                if (matcher.find()) {
                    previousLine = null;
                    return createLogEntry(source, matcher, line);
                } else {
                    previousLine = line;
// Path: src/main/java/com/github/davidmoten/logan/Field.java
// public static final String LEVEL = "logLevel";
// 
// Path: src/main/java/com/github/davidmoten/logan/Field.java
// public static final String LOGGER = "logLogger";
// 
// Path: src/main/java/com/github/davidmoten/logan/Field.java
// public static final String METHOD = "logMethod";
// 
// Path: src/main/java/com/github/davidmoten/logan/Field.java
// public static final String MSG = "logMsg";
// 
// Path: src/main/java/com/github/davidmoten/logan/Field.java
// public static final String THREAD_NAME = "threadName";
// 
// Path: src/main/java/com/github/davidmoten/logan/Field.java
// public static final String TIMESTAMP = "logTimestamp";


// Path: src/main/java/com/github/davidmoten/logan/LogParser.java
import static com.github.davidmoten.logan.Field.LEVEL;
import static com.github.davidmoten.logan.Field.LOGGER;
import static com.github.davidmoten.logan.Field.METHOD;
import static com.github.davidmoten.logan.Field.MSG;
import static com.github.davidmoten.logan.Field.THREAD_NAME;
import static com.github.davidmoten.logan.Field.TIMESTAMP;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import com.google.common.collect.BiMap;
import com.google.common.collect.Maps;

     * Returns the parsed line as a {@link LogEntry}. Note that this method is
     * synchronized because the {@link DateFormat} object used by it is not
     * thread-safe. However, you can safely instantiate multiple {@link LogParser}
     * objects and use them concurrently.
     * 
     * @param source
     *            source
     * @param line
     *            line
     * @return parsed LogEntry
     */
    public synchronized LogEntry parse(String source, String line) {
        if (line == null)
            return null;
        else {
            if (options.isMultiline() && (previousLine == null)) {
                previousLine = line;
                return null;
            } else {
                StringBuilder candidate = new StringBuilder(line);
                if (options.isMultiline()) {
                    candidate.insert(0, "ZZZ");
                    candidate.insert(0, previousLine);
                }
                Matcher matcher = options.getPattern().matcher(candidate);
                if (matcher.find()) {
                    previousLine = null;
                    return createLogEntry(source, matcher, line);
                } else {
                    previousLine = line;
                    return null;