/**
  * Converts a String back to connection parameters.
  *
  * @param input String from configuration
  * @return JDBC connection parameters
  */
 protected static Properties propertiesFromString(String input) {
   if (input != null && !input.isEmpty()) {
     Properties result = new Properties();
     StrTokenizer propertyTokenizer = StrTokenizer.getCSVInstance(input);
     StrTokenizer valueTokenizer = StrTokenizer.getCSVInstance();
     valueTokenizer.setDelimiterChar('=');
     while (propertyTokenizer.hasNext()) {
       valueTokenizer.reset(propertyTokenizer.nextToken());
       String[] values = valueTokenizer.getTokenArray();
       if (values.length == 2) {
         result.put(values[0], values[1]);
       }
     }
     return result;
   } else {
     return null;
   }
 }
  static List<double[]> readDataBodyAsDouble(
      BufferedReader br, int[] remappedColumns, int mappedColumnCount)
      throws NumberFormatException, IOException {
    List<double[]> rows = new ArrayList<double[]>(500);
    int colCount = 0; // Number of columns (minus one) - must match in each row
    int curRow = 0; // Current row number - 0 based;
    String s = null; // Single line from file

    while ((s = br.readLine()) != null) {
      StrTokenizer strTk = new StrTokenizer(s);
      strTk.setIgnoreEmptyTokens(false);
      strTk.setDelimiterChar('\t');
      String src[] = strTk.getTokenArray();
      // String src[] = s.split("\t");

      if (isNonEmptyLine(src)) {

        if (colCount == 0) {
          colCount = src.length; // initialize column count
          if (remappedColumns == null) {
            // assign default mapping now
            remappedColumns = new int[colCount];
            for (int i = 0; i < colCount; i++) {
              remappedColumns[i] = i;
            }

            mappedColumnCount = colCount;
          }
        } else {
          if (src.length != colCount) {
            for (int i = 0; i < src.length; i++) {
              System.out.println(i + ": " + src[i]);
            }

            throw new IllegalStateException(
                "Parse Error: Row "
                    + curRow
                    + " has "
                    + src.length
                    + " columns, previous columns had "
                    + colCount
                    + " columns.");
          }
        }

        double[] row = new double[mappedColumnCount];

        for (int i = 0; i < src.length; i++) {
          if (remappedColumns[i] != -1) {
            if (src[i].length() > 0) {

              // Simple hack to ignore text columns in the predict.txt file

              try {
                row[remappedColumns[i]] = Double.parseDouble(src[i]);
              } catch (Exception e) {
                row[remappedColumns[i]] = Double.NaN;
              }
            } else {
              row[remappedColumns[i]] = 0;
            }
          }
        }

        rows.add(row);
      } else {
        // ignore empty lines
      }

      curRow++;
    }

    log.debug("Found " + curRow + " rows in predict.txt file.");
    return rows;
  }