// Path: Java/statsdb-api/src/main/java/uk/ac/tgac/statsdb/analysis/DefaultQCAnalysis.java
// public class DefaultQCAnalysis extends AbstractQCAnalysis {
//   public DefaultQCAnalysis() {
//     properties = new HashMap<>();
//     valueTypes = new HashMap<>();
//     valueDescriptions = new HashMap<>();
//     generalValues = new HashMap<>();
//     partitionValues = new ArrayList<>();
//     positionValues = new ArrayList<>();
//   }
// }
// 
// Path: Java/statsdb-api/src/main/java/uk/ac/tgac/statsdb/analysis/QCAnalysis.java
// public interface QCAnalysis {
//   /**
//    * Get the QCAnalysis ID
//    * @return the QCAnalysis object ID
//    */
//   public long getId();
// 
//   /**
//    * Sets the ID of this QCAnalysis object
//    * @param id
//    */
//   public void setId(long id);
// 
//   /**
//    * Retrieve an analysis property value associated with a given key
//    *
//    * @param key
//    * @return
//    * @throws QCAnalysisException
//    */
//   public String getProperty(String key) throws QCAnalysisException;
// 
//   /**
//    * Add an analysis property
//    *
//    * @param key
//    * @param value
//    * @throws QCAnalysisException
//    */
//   public void addProperty(String key, String value) throws QCAnalysisException;
// 
//   /**
//    * Add a partition value
//    *
//    * @param range
//    * @param key
//    * @param value
//    * @throws QCAnalysisException
//    */
//   public void addPartitionValue(String range, String key, String value) throws QCAnalysisException;
// 
//   /**
//    * Add a position value
//    *
//    * @param position
//    * @param key
//    * @param value
//    * @throws QCAnalysisException
//    */
//   public void addPositionValue(String position, String key, String value) throws QCAnalysisException;
// 
//   /**
//    * Add a general value
//    *
//    * @param valueType
//    * @param valueScope
//    * @param descriptor
//    * @throws QCAnalysisException
//    */
//   public void addGeneralValue(String valueType, String valueScope, String descriptor) throws QCAnalysisException;
// 
//   /**
//    * Add a value type scope
//    *
//    * @param valueTypeKey
//    * @param valueScope
//    * @throws QCAnalysisException
//    */
//   public void addValueType(String valueTypeKey, String valueScope) throws QCAnalysisException;
// 
//   /**
//    * Add a value type description
//    *
//    * @param valueTypeKey
//    * @param valueDescription
//    * @throws QCAnalysisException
//    */
//   public void addValueDescription(String valueTypeKey, String valueDescription) throws QCAnalysisException;
// 
//   /**
//    * Retrieve all analysis properties
//    *
//    * @return a map of key:value pairs
//    */
//   public Map<String, String> getProperties();
// 
//   /**
//    * Retrieve all analysis general values
//    *
//    * @return a map of key:value pairs
//    */
//   public Map<String,String> getGeneralValues();
// 
//   /**
//    * Retrieve all analysis partition values
//    *
//    * @return a list of PartitionValues
//    */
//   public List<PartitionValue> getPartitionValues();
// 
//   /**
//    * Retrieve all analysis position values
//    *
//    * @return a list of PositionValues
//    */
//   public List<PositionValue> getPositionValues();
// 
//   /**
//    * Retrieve all analysis value descriptions
//    *
//    * @return a map of key:value pairs
//    */
//   public Map<String, String> getValueDescriptions();
// 
//   /**
//    * Retrieve all analysis value type scopes
//    *
//    * @return a map of key:value pairs
//    */
//   public Map<String, String> getValueScopes();
// }
// 
// Path: Java/statsdb-api/src/main/java/uk/ac/tgac/statsdb/exception/QCAnalysisException.java
// public class QCAnalysisException extends Exception {
//   public QCAnalysisException(String s) {
//     super(s);
//   }
// 
//   public QCAnalysisException(String s, Throwable cause) {
//     super(s);
//     if (cause != null) {
//         initCause(cause);
//     }
//   }
// }


import uk.ac.tgac.statsdb.analysis.DefaultQCAnalysis;
import uk.ac.tgac.statsdb.analysis.QCAnalysis;
import uk.ac.tgac.statsdb.exception.QCAnalysisException;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

  private void processMetadataFile(Reader r, List<QCAnalysis> qcas) throws QCAnalysisException {
    BufferedReader br = null;
    try {
      br = new BufferedReader(r);
      String line;
      boolean first = true;
      String[] headers = null;
      while ((line = br.readLine()) != null) {
        if (first) {
          headers = line.toLowerCase().split("[\\s|,]+");
          first = false;
        }
        else {
          String[] values = line.split("[\\s|,]+");
          if (headers == null || headers.length != values.length) {
            throw new QCAnalysisException("Invalid headers found");
          }
          QCAnalysis qa = new DefaultQCAnalysis();
          for (int i = 0; i < headers.length; i++) {
            qa.addProperty(headers[i], values[i]);
          }
          qcas.add(qa);
        }
      }
    }
    catch (IOException e) {
      System.err.println("Error parsing run metadata headers: " + e.getMessage());
    }
    finally {
// Path: Java/statsdb-api/src/main/java/uk/ac/tgac/statsdb/analysis/DefaultQCAnalysis.java
// public class DefaultQCAnalysis extends AbstractQCAnalysis {
//   public DefaultQCAnalysis() {
//     properties = new HashMap<>();
//     valueTypes = new HashMap<>();
//     valueDescriptions = new HashMap<>();
//     generalValues = new HashMap<>();
//     partitionValues = new ArrayList<>();
//     positionValues = new ArrayList<>();
//   }
// }
// 
// Path: Java/statsdb-api/src/main/java/uk/ac/tgac/statsdb/analysis/QCAnalysis.java
// public interface QCAnalysis {
//   /**
//    * Get the QCAnalysis ID
//    * @return the QCAnalysis object ID
//    */
//   public long getId();
// 
//   /**
//    * Sets the ID of this QCAnalysis object
//    * @param id
//    */
//   public void setId(long id);
// 
//   /**
//    * Retrieve an analysis property value associated with a given key
//    *
//    * @param key
//    * @return
//    * @throws QCAnalysisException
//    */
//   public String getProperty(String key) throws QCAnalysisException;
// 
//   /**
//    * Add an analysis property
//    *
//    * @param key
//    * @param value
//    * @throws QCAnalysisException
//    */
//   public void addProperty(String key, String value) throws QCAnalysisException;
// 
//   /**
//    * Add a partition value
//    *
//    * @param range
//    * @param key
//    * @param value
//    * @throws QCAnalysisException
//    */
//   public void addPartitionValue(String range, String key, String value) throws QCAnalysisException;
// 
//   /**
//    * Add a position value
//    *
//    * @param position
//    * @param key
//    * @param value
//    * @throws QCAnalysisException
//    */
//   public void addPositionValue(String position, String key, String value) throws QCAnalysisException;
// 
//   /**
//    * Add a general value
//    *
//    * @param valueType
//    * @param valueScope
//    * @param descriptor
//    * @throws QCAnalysisException
//    */
//   public void addGeneralValue(String valueType, String valueScope, String descriptor) throws QCAnalysisException;
// 
//   /**
//    * Add a value type scope
//    *
//    * @param valueTypeKey
//    * @param valueScope
//    * @throws QCAnalysisException
//    */
//   public void addValueType(String valueTypeKey, String valueScope) throws QCAnalysisException;
// 
//   /**
//    * Add a value type description
//    *
//    * @param valueTypeKey
//    * @param valueDescription
//    * @throws QCAnalysisException
//    */
//   public void addValueDescription(String valueTypeKey, String valueDescription) throws QCAnalysisException;
// 
//   /**
//    * Retrieve all analysis properties
//    *
//    * @return a map of key:value pairs
//    */
//   public Map<String, String> getProperties();
// 
//   /**
//    * Retrieve all analysis general values
//    *
//    * @return a map of key:value pairs
//    */
//   public Map<String,String> getGeneralValues();
// 
//   /**
//    * Retrieve all analysis partition values
//    *
//    * @return a list of PartitionValues
//    */
//   public List<PartitionValue> getPartitionValues();
// 
//   /**
//    * Retrieve all analysis position values
//    *
//    * @return a list of PositionValues
//    */
//   public List<PositionValue> getPositionValues();
// 
//   /**
//    * Retrieve all analysis value descriptions
//    *
//    * @return a map of key:value pairs
//    */
//   public Map<String, String> getValueDescriptions();
// 
//   /**
//    * Retrieve all analysis value type scopes
//    *
//    * @return a map of key:value pairs
//    */
//   public Map<String, String> getValueScopes();
// }
// 
// Path: Java/statsdb-api/src/main/java/uk/ac/tgac/statsdb/exception/QCAnalysisException.java
// public class QCAnalysisException extends Exception {
//   public QCAnalysisException(String s) {
//     super(s);
//   }
// 
//   public QCAnalysisException(String s, Throwable cause) {
//     super(s);
//     if (cause != null) {
//         initCause(cause);
//     }
//   }
// }


// Path: Java/statsdb-api/src/main/java/uk/ac/tgac/statsdb/run/parser/AnalysisMetadataParser.java
import uk.ac.tgac.statsdb.analysis.DefaultQCAnalysis;
import uk.ac.tgac.statsdb.analysis.QCAnalysis;
import uk.ac.tgac.statsdb.exception.QCAnalysisException;
import java.io.*;
import java.util.ArrayList;
import java.util.List;


  private void processMetadataFile(Reader r, List<QCAnalysis> qcas) throws QCAnalysisException {
    BufferedReader br = null;
    try {
      br = new BufferedReader(r);
      String line;
      boolean first = true;
      String[] headers = null;
      while ((line = br.readLine()) != null) {
        if (first) {
          headers = line.toLowerCase().split("[\\s|,]+");
          first = false;
        }
        else {
          String[] values = line.split("[\\s|,]+");
          if (headers == null || headers.length != values.length) {
            throw new QCAnalysisException("Invalid headers found");
          }
          QCAnalysis qa = new DefaultQCAnalysis();
          for (int i = 0; i < headers.length; i++) {
            qa.addProperty(headers[i], values[i]);
          }
          qcas.add(qa);
        }
      }
    }
    catch (IOException e) {
      System.err.println("Error parsing run metadata headers: " + e.getMessage());
    }
    finally {
      if (br != null) {