001package edu.pdx.cs.joy.grader;
002
003import java.io.BufferedReader;
004import java.io.IOException;
005import java.io.Reader;
006import java.util.regex.Matcher;
007import java.util.regex.Pattern;
008
009public class GitConfigParser {
010  static final Pattern PROPERTY_PATTERN = Pattern.compile("\\s+(.*) = (.*)");
011  static final Pattern REMOTE_PATTERN = Pattern.compile("\\[remote \"(.*)\"]");
012  private final Reader reader;
013  private String currentSection;
014
015  public GitConfigParser(Reader reader) {
016    this.reader = reader;
017  }
018
019  public void parse(Callback callback) throws IOException {
020    try (BufferedReader br = new BufferedReader(this.reader)) {
021      for (String line = br.readLine(); line != null; line = br.readLine()) {
022        parseLine(line, callback);
023      }
024
025      endCurrentSection(callback);
026    }
027
028  }
029
030  private void endCurrentSection(Callback callback) {
031    callback.endSection(currentSection);
032  }
033
034  private void parseLine(String line, Callback callback) {
035    if (line.startsWith("[core]")) {
036      endCurrentSection(callback);
037      startCoreSection(callback);
038
039    } else if (line.startsWith("[remote ")) {
040      endCurrentSection(callback);
041      startRemoteSection(line, callback);
042
043    } else if (line.contains(" = ")) {
044      parseProperty(line, callback);
045    }
046
047  }
048
049  private void startCoreSection(Callback callback) {
050    this.currentSection = "core";
051    callback.startCoreSection();
052  }
053
054  private void startRemoteSection(String line, Callback callback) {
055    Matcher matcher = REMOTE_PATTERN.matcher(line);
056    if (!matcher.matches()) {
057      throw new IllegalStateException("Cannot parse line with remote: \"" + line + "\"");
058    }
059
060    String remoteName = matcher.group(1);
061    this.currentSection = remoteName;
062    callback.startRemoteSection(remoteName);
063  }
064
065  private void parseProperty(String line, Callback callback) {
066    Matcher matcher = PROPERTY_PATTERN.matcher(line);
067    if (!matcher.matches()) {
068      throw new IllegalStateException("Cannot parse line with property: \"" + line + "\"");
069    }
070
071    String propertyName = matcher.group(1);
072    String propertyValue = matcher.group(2);
073
074    callback.property(propertyName, propertyValue);
075  }
076
077  public interface Callback {
078    void startCoreSection();
079
080    void property(String name, String value);
081
082    void endSection(String name);
083
084    void startRemoteSection(String name);
085  }
086}