// 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;
     * @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;
                }
            }
        }
    }

    private LogEntry createLogEntry(String source, Matcher matcher, String line) {
        BiMap<String, Integer> map = options.getPatternGroups();

// 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;

     * @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;
                }
            }
        }
    }

    private LogEntry createLogEntry(String source, Matcher matcher, String line) {
        BiMap<String, Integer> map = options.getPatternGroups();

        String timestamp = getGroup(matcher, map.get(TIMESTAMP));