private static String getAllEntries(final ArrayList<ConfigurationParserObject> list) {
    String entries = "";

    for (final ConfigurationParserObject cpo : list) entries += cpo.getEntry() + "\n";

    return entries;
  }
  private static int findEntry(
      final ArrayList<ConfigurationParserObject> list, final String entry) {
    int pos = -1;

    for (int i = 0; i < list.size() && pos == -1; i++) {
      final ConfigurationParserObject cpo = list.get(i);

      if (cpo.getEntry().toLowerCase().compareTo(entry.toLowerCase()) == 0) pos = i;
    }

    return pos;
  }
  public static SPIMConfiguration parseFile(String confFileName)
      throws ConfigurationParserException {
    SPIMConfiguration conf = new SPIMConfiguration();

    String knownDatatypes[] = {
      "int",
      "double",
      "String",
      "boolean",
      "float",
      "float[]",
      "ContainerFactory",
      "InterpolatorFactory",
      "OutsideStrategyFactory"
    };

    // convert to unix-style
    confFileName = confFileName.replace('\\', '/');
    confFileName = confFileName.replaceAll("//", "/");

    // get path
    String confFilePath;

    try {
      if (confFileName.indexOf("/") != -1)
        confFilePath = confFileName.substring(0, confFileName.lastIndexOf("/") + 1);
      else confFilePath = "";

    } catch (Exception e) {
      throw new ConfigurationParserException(
          "Error parsing confFileName-String: '" + e.getMessage() + "'");
    }

    // open configfile
    BufferedReader assignFile = null;
    BufferedReader confFile;

    try {
      confFile = TextFileAccess.openFileReadEx(confFileName);
    } catch (IOException e) {
      throw new ConfigurationParserException(
          "Configuration file not found: '" + confFileName + "'");
    }

    // open assignment file
    try {
      while (confFile.ready() && assignFile == null) {
        String line = confFile.readLine().trim();

        if (line.startsWith("<") && line.endsWith(">")) {
          assignFile =
              TextFileAccess.openFileRead(confFilePath + line.substring(1, line.length() - 1));
          if (assignFile == null)
            throw new ConfigurationParserException(
                "Variables Assignment file not found: '"
                    + confFilePath
                    + (line.substring(1, line.length() - 1))
                    + "'");
        }
      }
    } catch (Exception e) {
      throw new ConfigurationParserException(
          "Error finding assignment file entry: '" + e.getMessage() + "'");
    }

    // load assignments
    final ArrayList<ConfigurationParserObject> assignments =
        new ArrayList<ConfigurationParserObject>();
    Field[] fields = conf.getClass().getDeclaredFields();

    int lineCount = 0;
    try {
      while (assignFile.ready()) {
        lineCount++;
        String line = assignFile.readLine().trim();

        if (!line.startsWith("#") && line.length() > 0) {
          String words[] = line.split("=");

          if (words.length != 2)
            throw new ConfigurationParserException(
                "Wrong format in assignment file, should be 'entry = datatype name'");

          // entry name
          final ConfigurationParserObject cpo = new ConfigurationParserObject();
          cpo.setEntry(words[0].trim());

          words = words[1].trim().split(" ");
          if (words.length != 2)
            throw new ConfigurationParserException(
                "Wrong format in assignment file, datatype and name on right side MUST have no spaces");

          words[0] = words[0].trim();
          words[1] = words[1].trim();

          // datatype
          boolean positiveMatch = false;

          for (int i = 0; i < knownDatatypes.length; i++) {
            if (words[0].compareTo(knownDatatypes[i]) == 0) positiveMatch = true;
          }

          if (!positiveMatch) {
            String datatypes = "";
            for (int i = 0; i < knownDatatypes.length; i++) datatypes += knownDatatypes[i] + " ";

            throw new ConfigurationParserException(
                "Unknown datatype '" + words[0] + "', available datatypes are: " + datatypes);
          }

          cpo.setDataType(words[0]);

          // variable name
          int variablesPosition = -1;

          for (int i = 0; i < fields.length; i++) {
            if (words[1].compareTo(fields[i].getName()) == 0) variablesPosition = i;
          }

          if (variablesPosition == -1) {
            String variables = "";
            for (int i = 0; i < fields.length; i++) variables += fields[i].getName() + "\n";

            throw new ConfigurationParserException(
                "Unknown variable '" + words[1] + "', available variables are:\n" + variables);
          }

          cpo.setVariableName(words[1]);
          cpo.setVariableFieldPosition(variablesPosition);

          assignments.add(cpo);
        }
      }
    } catch (Exception e) {
      throw new ConfigurationParserException(
          "Error reading/parsing assignment file at line " + lineCount + ":\n" + e.getMessage());
    }

    // read configuration file and assign entry values to assigned variables
    lineCount = 0;

    try {
      while (confFile.ready()) {
        lineCount++;
        String line = confFile.readLine().trim();

        if (!line.startsWith("#") && line.length() > 0) {
          String words[] = line.split("=");

          if (words.length != 2)
            throw new ConfigurationParserException(
                "Wrong format in configuration file, should be 'entry = value'");

          words[0] = words[0].trim();
          words[1] = words[1].trim();

          int entryPos = findEntry(assignments, words[0]);

          if (entryPos == -1)
            throw new ConfigurationParserException(
                "Entry '"
                    + words[0]
                    + "' does not exist!\nFollowing entries are available:\n"
                    + getAllEntries(assignments));

          final ConfigurationParserObject cpo = assignments.get(entryPos);
          final int varFieldPos = cpo.getVariableFieldPosition();

          if (cpo.getDataType().compareTo("byte") == 0) {
            fields[varFieldPos].setByte(conf, Byte.parseByte(words[1]));
          } else if (cpo.getDataType().compareTo("short") == 0) {
            fields[varFieldPos].setShort(conf, Short.parseShort(words[1]));
          } else if (cpo.getDataType().compareTo("int") == 0) {
            fields[varFieldPos].setInt(conf, Integer.parseInt(words[1]));
          } else if (cpo.getDataType().compareTo("long") == 0) {
            fields[varFieldPos].setLong(conf, Long.parseLong(words[1]));
          } else if (cpo.getDataType().compareTo("boolean") == 0) {
            fields[varFieldPos].setBoolean(conf, Boolean.parseBoolean(words[1]));
          } else if (cpo.getDataType().compareTo("float[]") == 0) {
            final String[] entries = words[1].split(",");

            if (entries.length < 1)
              throw new ConfigurationParserException(
                  "Cannot parse array, should be 3, 4.3, 2, ... - but is '" + words[1] + "'");

            final float[] values = new float[entries.length];

            for (int i = 0; i < entries.length; ++i) values[i] = Float.parseFloat(entries[i]);

            fields[varFieldPos].set(conf, values);
          } else if (cpo.getDataType().compareTo("float") == 0) {
            if (words[1].toLowerCase().compareTo("nan") == 0)
              fields[varFieldPos].setFloat(conf, Float.NaN);
            else fields[varFieldPos].setFloat(conf, Float.parseFloat(words[1]));
          } else if (cpo.getDataType().compareTo("double") == 0) {
            if (words[1].toLowerCase().compareTo("nan") == 0)
              fields[varFieldPos].setDouble(conf, Double.NaN);
            else fields[varFieldPos].setDouble(conf, Double.parseDouble(words[1]));
          } else if (cpo.getDataType().compareTo("String") == 0) {
            if (words[1].equals("null")) fields[varFieldPos].set(conf, null);
            else {
              if (words[1].startsWith("\"") && words[1].endsWith("\""))
                fields[varFieldPos].set(conf, words[1].substring(1, words[1].length() - 1));
              else
                throw new ConfigurationParserException(
                    "Strings have to be surrounded by  \"\" or be null");
            }
          } else if (cpo.getDataType().compareTo("ContainerFactory") == 0) {
            if (words[1].startsWith("ArrayContainerFactory")) {
              ArrayContainerFactory factory = new ArrayContainerFactory();
              factory.setParameters(words[1].substring(words[1].indexOf("("), words[1].length()));
              fields[varFieldPos].set(conf, factory);
            } else if (words[1].startsWith("CellContainerFactory")) {
              CellContainerFactory factory = new CellContainerFactory();
              factory.setParameters(words[1].substring(words[1].indexOf("("), words[1].length()));
              fields[varFieldPos].set(conf, factory);
            } else {
              throw new ConfigurationParserException(
                  "Unknown implementation of ContainerFactory '" + words[1] + "'");
            }
          } else if (cpo.getDataType().compareTo("InterpolatorFactory") == 0) {
            if (words[1].startsWith("LinearInterpolatorFactory")) {
              LinearInterpolatorFactory<FloatType> factory =
                  new LinearInterpolatorFactory<FloatType>(null);
              factory.setParameters(words[1].substring(words[1].indexOf("("), words[1].length()));
              fields[varFieldPos].set(conf, factory);
            } else if (words[1].startsWith("NearestNeighborInterpolatorFactory")) {
              NearestNeighborInterpolatorFactory<FloatType> factory =
                  new NearestNeighborInterpolatorFactory<FloatType>(null);
              factory.setParameters(words[1].substring(words[1].indexOf("("), words[1].length()));
              fields[varFieldPos].set(conf, factory);
            } else {
              throw new ConfigurationParserException(
                  "Unknown implementation of FloatInterpolatorFactory '" + words[1] + "'");
            }
          } else if (cpo.getDataType().compareTo("OutsideStrategyFactory") == 0) {
            if (words[1].startsWith("OutsideStrategyMirrorFactory")) {
              OutOfBoundsStrategyFactory<FloatType> factory =
                  new OutOfBoundsStrategyMirrorFactory<FloatType>();
              factory.setParameters(words[1].substring(words[1].indexOf("("), words[1].length()));
              fields[varFieldPos].set(conf, factory);
            } else if (words[1].startsWith("OutsideStrategyValueFactory")) {
              OutOfBoundsStrategyFactory<FloatType> factory =
                  new OutOfBoundsStrategyValueFactory<FloatType>();
              factory.setParameters(words[1].substring(words[1].indexOf("("), words[1].length()));
              fields[varFieldPos].set(conf, factory);
            } else {
              throw new ConfigurationParserException(
                  "Unknown implementation of OutsideStrategyFactory '" + words[1] + "'");
            }
          } else {
            throw new ConfigurationParserException("Unknown datatype '" + cpo.getDataType() + "'");
          }
        }
      }
    } catch (Exception e) {
      throw new ConfigurationParserException(
          "Error reading/parsing configuration file at line " + lineCount + ":\n" + e.getMessage());
    }

    // variable specific verification
    if (conf.numberOfThreads < 1) conf.numberOfThreads = Runtime.getRuntime().availableProcessors();

    if (conf.scaleSpaceNumberOfThreads < 1)
      conf.scaleSpaceNumberOfThreads = Runtime.getRuntime().availableProcessors();

    // check the directory string
    conf.inputdirectory = conf.inputdirectory.replace('\\', '/');
    conf.inputdirectory = conf.inputdirectory.trim();
    if (conf.inputdirectory.length() > 0 && !conf.inputdirectory.endsWith("/"))
      conf.inputdirectory = conf.inputdirectory + "/";

    if (conf.outputdirectory == null || conf.outputdirectory.length() == 0) {
      conf.outputdirectory = conf.inputdirectory;
    } else {
      conf.outputdirectory = conf.outputdirectory.replace('\\', '/');
      conf.outputdirectory = conf.outputdirectory.trim();
      if (conf.outputdirectory.length() > 0 && !conf.outputdirectory.endsWith("/"))
        conf.outputdirectory = conf.outputdirectory + "/";
    }

    if (conf.registrationFiledirectory == null || conf.registrationFiledirectory.length() == 0) {
      conf.registrationFiledirectory = conf.inputdirectory;
    } else {
      conf.registrationFiledirectory = conf.registrationFiledirectory.replace('\\', '/');
      conf.registrationFiledirectory = conf.registrationFiledirectory.trim();
      if (conf.registrationFiledirectory.length() > 0
          && !conf.registrationFiledirectory.endsWith("/"))
        conf.registrationFiledirectory = conf.registrationFiledirectory + "/";
    }

    // check if directories exist
    File dir = new File(conf.outputdirectory, "");
    if (!dir.exists()) {
      IOFunctions.println(
          "("
              + new Date(System.currentTimeMillis())
              + "): Creating directory '"
              + conf.outputdirectory
              + "'.");
      boolean success = dir.mkdirs();
      if (!success) {
        if (!dir.exists()) {
          throw new ConfigurationParserException(
              "("
                  + new Date(System.currentTimeMillis())
                  + "): Cannot create directory '"
                  + conf.outputdirectory
                  + "', quitting.");
        }
      }
    }

    dir = new File(conf.registrationFiledirectory, "");
    if (!dir.exists()) {
      IOFunctions.println(
          "("
              + new Date(System.currentTimeMillis())
              + "): Creating directory '"
              + conf.registrationFiledirectory
              + "'.");
      boolean success = dir.mkdirs();
      if (!success) {
        if (!dir.exists()) {
          throw new ConfigurationParserException(
              "("
                  + new Date(System.currentTimeMillis())
                  + "): Cannot create directory '"
                  + conf.registrationFiledirectory
                  + "', quitting.");
        }
      }
    }

    int countTrue = 0;
    if (conf.paralellFusion) countTrue++;
    if (conf.sequentialFusion) countTrue++;
    if (conf.multipleImageFusion) countTrue++;

    if (countTrue != 1)
      throw new ConfigurationParserException(
          "Error reading/parsing configuration file: Only one fusion method must be true!");

    if (conf.debugLevel.toUpperCase().equals("DEBUG_ERRORONLY"))
      conf.debugLevelInt = ViewStructure.DEBUG_ERRORONLY;

    if (conf.debugLevel.toUpperCase().equals("DEBUG_MAIN"))
      conf.debugLevelInt = ViewStructure.DEBUG_MAIN;

    if (conf.debugLevel.toUpperCase().equals("DEBUG_ALL"))
      conf.debugLevelInt = ViewStructure.DEBUG_ALL;

    // here all angles, timepoints and channels are parsed from the input strings
    conf.getFileNames();

    // set interpolator stuff
    conf.interpolatorFactorOutput.setOutOfBoundsStrategyFactory(conf.strategyFactoryOutput);

    // close files
    try {
      assignFile.close();
      confFile.close();
    } catch (Exception e) {
    }
    ;

    return conf;
  }