// Path: src/main/java/uk/ac/ic/wlgitbridge/application/exception/ConfigFileException.java
// public class ConfigFileException extends Exception {
// 
//     private final String missingMember;
// 
//     public ConfigFileException(String missingMember) {
//         this.missingMember = missingMember;
//     }
// 
//     public String getMissingMember() {
//         return missingMember;
//     }
// 
// }
// 
// Path: src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStoreConfig.java
// public class RepoStoreConfig {
// 
//     @Nullable
//     private final Long maxFileSize;
// 
//     public RepoStoreConfig(Long maxFileSize) {
//         this.maxFileSize = maxFileSize;
//     }
// 
//     public Optional<Long> getMaxFileSize() {
//         return Optional.ofNullable(maxFileSize);
//     }
// }
// 
// Path: src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobConfig.java
// public class SwapJobConfig {
// 
//     private final int minProjects;
//     private final int lowGiB;
//     private final int highGiB;
//     private final long intervalMillis;
// 
//     public SwapJobConfig(
//             int minProjects,
//             int lowGiB,
//             int highGiB,
//             long intervalMillis
//     ) {
//         this.minProjects = minProjects;
//         this.lowGiB = lowGiB;
//         this.highGiB = highGiB;
//         this.intervalMillis = intervalMillis;
//     }
// 
//     public int getMinProjects() {
//         return minProjects;
//     }
// 
//     public int getLowGiB() {
//         return lowGiB;
//     }
// 
//     public int getHighGiB() {
//         return highGiB;
//     }
// 
//     public long getIntervalMillis() {
//         return intervalMillis;
//     }
// 
// }
// 
// Path: src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStoreConfig.java
// public class SwapStoreConfig {
// 
//     public static final SwapStoreConfig NOOP = new SwapStoreConfig(
//             "noop",
//             null,
//             null,
//             null
//     );
// 
//     private String type;
//     private String awsAccessKey;
//     private String awsSecret;
//     private String s3BucketName;
// 
//     public SwapStoreConfig() {}
// 
//     public SwapStoreConfig(
//             String awsAccessKey,
//             String awsSecret,
//             String s3BucketName
//     ) {
//         this(
//                 "s3",
//                 awsAccessKey,
//                 awsSecret,
//                 s3BucketName
//         );
//     }
// 
//     SwapStoreConfig(
//             String type,
//             String awsAccessKey,
//             String awsSecret,
//             String s3BucketName
//     ) {
//         this.type = type;
//         this.awsAccessKey = awsAccessKey;
//         this.awsSecret = awsSecret;
//         this.s3BucketName = s3BucketName;
//     }
// 
//     public String getType() {
//         return type;
//     }
// 
//     public String getAwsAccessKey() {
//         return awsAccessKey;
//     }
// 
//     public String getAwsSecret() {
//         return awsSecret;
//     }
// 
//     public String getS3BucketName() {
//         return s3BucketName;
//     }
// 
//     public SwapStoreConfig sanitisedCopy() {
//         return new SwapStoreConfig(
//                 type,
//                 awsAccessKey == null ? null : "<awsAccessKey>",
//                 awsSecret == null ? null : "<awsSecret>",
//                 s3BucketName
//         );
//     }
// 
//     public static SwapStoreConfig sanitisedCopy(SwapStoreConfig swapStore) {
//         return swapStore == null ? null : swapStore.sanitisedCopy();
//     }
//     
// }


import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import uk.ac.ic.wlgitbridge.application.exception.ConfigFileException;
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStoreConfig;
import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJobConfig;
import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStoreConfig;
import uk.ac.ic.wlgitbridge.snapshot.base.JSONSource;
import uk.ac.ic.wlgitbridge.util.Instance;
import javax.annotation.Nullable;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Optional;
        this.port = port;
        this.rootGitDirectory = rootGitDirectory;
        this.username = username;
        this.password = password;
        this.apiBaseURL = apiBaseURL;
        this.postbackURL = postbackURL;
        this.serviceName = serviceName;
        this.oauth2 = oauth2;
        this.repoStore = repoStore;
        this.swapStore = swapStore;
        this.swapJob = swapJob;
    }

    @Override
    public void fromJSON(JsonElement json) {
        JsonObject configObject = json.getAsJsonObject();
        port = getElement(configObject, "port").getAsInt();
        rootGitDirectory = getElement(
                configObject,
                "rootGitDirectory"
        ).getAsString();
        username = getOptionalString(configObject, "username");
        password = getOptionalString(configObject, "password");
        String apiBaseURL = getElement(
                configObject,
                "apiBaseUrl"
        ).getAsString();
        if (!apiBaseURL.endsWith("/")) {
            apiBaseURL += "/";
        }
// Path: src/main/java/uk/ac/ic/wlgitbridge/application/exception/ConfigFileException.java
// public class ConfigFileException extends Exception {
// 
//     private final String missingMember;
// 
//     public ConfigFileException(String missingMember) {
//         this.missingMember = missingMember;
//     }
// 
//     public String getMissingMember() {
//         return missingMember;
//     }
// 
// }
// 
// Path: src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStoreConfig.java
// public class RepoStoreConfig {
// 
//     @Nullable
//     private final Long maxFileSize;
// 
//     public RepoStoreConfig(Long maxFileSize) {
//         this.maxFileSize = maxFileSize;
//     }
// 
//     public Optional<Long> getMaxFileSize() {
//         return Optional.ofNullable(maxFileSize);
//     }
// }
// 
// Path: src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobConfig.java
// public class SwapJobConfig {
// 
//     private final int minProjects;
//     private final int lowGiB;
//     private final int highGiB;
//     private final long intervalMillis;
// 
//     public SwapJobConfig(
//             int minProjects,
//             int lowGiB,
//             int highGiB,
//             long intervalMillis
//     ) {
//         this.minProjects = minProjects;
//         this.lowGiB = lowGiB;
//         this.highGiB = highGiB;
//         this.intervalMillis = intervalMillis;
//     }
// 
//     public int getMinProjects() {
//         return minProjects;
//     }
// 
//     public int getLowGiB() {
//         return lowGiB;
//     }
// 
//     public int getHighGiB() {
//         return highGiB;
//     }
// 
//     public long getIntervalMillis() {
//         return intervalMillis;
//     }
// 
// }
// 
// Path: src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStoreConfig.java
// public class SwapStoreConfig {
// 
//     public static final SwapStoreConfig NOOP = new SwapStoreConfig(
//             "noop",
//             null,
//             null,
//             null
//     );
// 
//     private String type;
//     private String awsAccessKey;
//     private String awsSecret;
//     private String s3BucketName;
// 
//     public SwapStoreConfig() {}
// 
//     public SwapStoreConfig(
//             String awsAccessKey,
//             String awsSecret,
//             String s3BucketName
//     ) {
//         this(
//                 "s3",
//                 awsAccessKey,
//                 awsSecret,
//                 s3BucketName
//         );
//     }
// 
//     SwapStoreConfig(
//             String type,
//             String awsAccessKey,
//             String awsSecret,
//             String s3BucketName
//     ) {
//         this.type = type;
//         this.awsAccessKey = awsAccessKey;
//         this.awsSecret = awsSecret;
//         this.s3BucketName = s3BucketName;
//     }
// 
//     public String getType() {
//         return type;
//     }
// 
//     public String getAwsAccessKey() {
//         return awsAccessKey;
//     }
// 
//     public String getAwsSecret() {
//         return awsSecret;
//     }
// 
//     public String getS3BucketName() {
//         return s3BucketName;
//     }
// 
//     public SwapStoreConfig sanitisedCopy() {
//         return new SwapStoreConfig(
//                 type,
//                 awsAccessKey == null ? null : "<awsAccessKey>",
//                 awsSecret == null ? null : "<awsSecret>",
//                 s3BucketName
//         );
//     }
// 
//     public static SwapStoreConfig sanitisedCopy(SwapStoreConfig swapStore) {
//         return swapStore == null ? null : swapStore.sanitisedCopy();
//     }
//     
// }


// Path: src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import uk.ac.ic.wlgitbridge.application.exception.ConfigFileException;
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStoreConfig;
import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJobConfig;
import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStoreConfig;
import uk.ac.ic.wlgitbridge.snapshot.base.JSONSource;
import uk.ac.ic.wlgitbridge.util.Instance;
import javax.annotation.Nullable;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Optional;

        this.port = port;
        this.rootGitDirectory = rootGitDirectory;
        this.username = username;
        this.password = password;
        this.apiBaseURL = apiBaseURL;
        this.postbackURL = postbackURL;
        this.serviceName = serviceName;
        this.oauth2 = oauth2;
        this.repoStore = repoStore;
        this.swapStore = swapStore;
        this.swapJob = swapJob;
    }

    @Override
    public void fromJSON(JsonElement json) {
        JsonObject configObject = json.getAsJsonObject();
        port = getElement(configObject, "port").getAsInt();
        rootGitDirectory = getElement(
                configObject,
                "rootGitDirectory"
        ).getAsString();
        username = getOptionalString(configObject, "username");
        password = getOptionalString(configObject, "password");
        String apiBaseURL = getElement(
                configObject,
                "apiBaseUrl"
        ).getAsString();
        if (!apiBaseURL.endsWith("/")) {
            apiBaseURL += "/";
        }
        this.apiBaseURL = apiBaseURL;