private double extractRetentionTime(Spectrum spectrum) {

    ScanList scanListElement = spectrum.getScanList();
    if (scanListElement == null) return 0;
    List<Scan> scanElements = scanListElement.getScan();
    if (scanElements == null) return 0;

    for (Scan scan : scanElements) {
      List<CVParam> cvParams = scan.getCvParam();
      if (cvParams == null) continue;

      for (CVParam param : cvParams) {
        String accession = param.getAccession();
        String unitAccession = param.getUnitAccession();
        String value = param.getValue();
        if ((accession == null) || (value == null)) continue;

        // Retention time (actually "Scan start time") MS:100001
        if (accession.equals("MS:1000016")) {
          // MS:1000038 is used in mzML 1.0, while UO:0000031
          // is used in mzML 1.1.0 :-/
          double retentionTime;
          if ((unitAccession == null)
              || (unitAccession.equals("MS:1000038"))
              || unitAccession.equals("UO:0000031")) {
            retentionTime = Double.parseDouble(value);
          } else {
            retentionTime = Double.parseDouble(value) / 60d;
          }
          return retentionTime;
        }
      }
    }

    return 0;
  }
  public void testReadingOfreferenceableParamGroupWithoutSpectrumCaching() {
    URL url = this.getClass().getClassLoader().getResource("sample_small.mzML");
    assertNotNull(url);

    MzMLUnmarshaller um = new MzMLUnmarshaller(url, false);

    MzML mz = um.unmarshall();
    assertNotNull(mz);

    assertNotNull(mz.getRun());

    // First pass.
    List<Spectrum> spectra = mz.getRun().getSpectrumList().getSpectrum();
    for (Spectrum spectrum : spectra) {
      if (spectrum.getId().equalsIgnoreCase("scan=21")) {
        // skip this spectrum, since it does not contain scan data
      } else {
        if (spectrum.getScanList() != null) {
          Scan scan = spectrum.getScanList().getScan().get(0); // get first scan
          if (scan != null) {
            Assert.assertEquals(5, scan.getCvParam().size());
            Assert.assertEquals(2, scan.getUserParam().size());
          }
        }
      }
    }

    // Second pass. See if it keeps adding the referenceable ones.
    spectra = mz.getRun().getSpectrumList().getSpectrum();
    for (Spectrum spectrum : spectra) {
      if (spectrum.getId().equalsIgnoreCase("scan=21")) {
        // skip this spectrum, since it does not contain scan data
      } else {
        if (spectrum.getScanList() != null) {
          Scan scan = spectrum.getScanList().getScan().get(0); // get first scan
          if (scan != null) {
            Assert.assertEquals(5, scan.getCvParam().size());
            Assert.assertEquals(2, scan.getUserParam().size());
          }
        }
      }
    }
  }
  public void testReferenceableParamGroupMarshallingWithoutSpectrumCaching() {
    URL url = this.getClass().getClassLoader().getResource("sample_small.mzML");
    assertNotNull(url);

    MzMLUnmarshaller um = new MzMLUnmarshaller(url, false);

    MzML mz = um.unmarshall();

    MzMLMarshaller marshaller = new MzMLMarshaller();
    try {
      // Try a single pass.
      File output =
          File.createTempFile(
              "testReferenceableParamGroupMarshallingWithoutSpectrumCaching", ".mzML");
      output.deleteOnExit();
      BufferedWriter bw = new BufferedWriter(new FileWriter(output));
      marshaller.marshall(mz, bw);
      bw.flush();
      bw.close();
      um = new MzMLUnmarshaller(output, false, null);
      mz = um.unmarshall();
      // First pass.
      List<Spectrum> spectra = mz.getRun().getSpectrumList().getSpectrum();
      for (Spectrum spectrum : spectra) {
        if (spectrum.getId().equalsIgnoreCase("scan=21")) {
          // skip this spectrum, since it does not contain scan data
        } else {
          if (spectrum.getScanList() != null) {
            Scan scan = spectrum.getScanList().getScan().get(0); // get first scan
            if (scan != null) {
              Assert.assertEquals(5, scan.getCvParam().size());
              Assert.assertEquals(2, scan.getUserParam().size());
              Assert.assertEquals(
                  2,
                  scan.getReferenceableParamGroupRef()
                      .get(0)
                      .getReferenceableParamGroup()
                      .getCvParam()
                      .size());
              Assert.assertEquals(
                  1,
                  scan.getReferenceableParamGroupRef()
                      .get(0)
                      .getReferenceableParamGroup()
                      .getUserParam()
                      .size());
            }
          }
        }
      }

      // Second pass. See if it keeps adding the referenceable ones.
      spectra = mz.getRun().getSpectrumList().getSpectrum();
      for (Spectrum spectrum : spectra) {
        if (spectrum.getId().equalsIgnoreCase("scan=21")) {
          // skip this spectrum, since it does not contain scan data
        } else {
          if (spectrum.getScanList() != null) {
            Scan scan = spectrum.getScanList().getScan().get(0); // get first scan
            if (scan != null) {
              Assert.assertEquals(5, scan.getCvParam().size());
              Assert.assertEquals(2, scan.getUserParam().size());
              Assert.assertEquals(
                  2,
                  scan.getReferenceableParamGroupRef()
                      .get(0)
                      .getReferenceableParamGroup()
                      .getCvParam()
                      .size());
              Assert.assertEquals(
                  1,
                  scan.getReferenceableParamGroupRef()
                      .get(0)
                      .getReferenceableParamGroup()
                      .getUserParam()
                      .size());
            }
          }
        }
      }

      // Try a double pass.
      output = File.createTempFile("tempTestReferenceableParamGroupMarshalling", "mzML");
      output.deleteOnExit();
      bw = new BufferedWriter(new FileWriter(output));
      marshaller.marshall(mz, bw);
      bw.flush();
      bw.close();

      File output2 = File.createTempFile("tempTestReferenceableParamGroupMarshalling2", "mzML");
      output2.deleteOnExit();
      bw = new BufferedWriter(new FileWriter(output2));
      marshaller.marshall(mz, bw);
      bw.flush();
      bw.close();

      // Check wether this one still makes sense.
      um = new MzMLUnmarshaller(output2, false, null);
      mz = um.unmarshall();
      // First pass.
      spectra = mz.getRun().getSpectrumList().getSpectrum();
      for (Spectrum spectrum : spectra) {
        if (spectrum.getId().equalsIgnoreCase("scan=21")) {
          // skip this spectrum, since it does not contain scan data
        } else {
          if (spectrum.getScanList() != null) {
            Scan scan = spectrum.getScanList().getScan().get(0); // get first scan
            if (scan != null) {
              Assert.assertEquals(5, scan.getCvParam().size());
              Assert.assertEquals(2, scan.getUserParam().size());
              Assert.assertEquals(
                  2,
                  scan.getReferenceableParamGroupRef()
                      .get(0)
                      .getReferenceableParamGroup()
                      .getCvParam()
                      .size());
              Assert.assertEquals(
                  1,
                  scan.getReferenceableParamGroupRef()
                      .get(0)
                      .getReferenceableParamGroup()
                      .getUserParam()
                      .size());
            }
          }
        }
      }

      // Second pass. See if it keeps adding the referenceable ones.
      spectra = mz.getRun().getSpectrumList().getSpectrum();
      for (Spectrum spectrum : spectra) {
        if (spectrum.getId().equalsIgnoreCase("scan=21")) {
          // skip this spectrum, since it does not contain scan data
        } else {
          if (spectrum.getScanList() != null) {
            Scan scan = spectrum.getScanList().getScan().get(0); // get first scan
            if (scan != null) {
              Assert.assertEquals(5, scan.getCvParam().size());
              Assert.assertEquals(2, scan.getUserParam().size());
              Assert.assertEquals(
                  2,
                  scan.getReferenceableParamGroupRef()
                      .get(0)
                      .getReferenceableParamGroup()
                      .getCvParam()
                      .size());
              Assert.assertEquals(
                  1,
                  scan.getReferenceableParamGroupRef()
                      .get(0)
                      .getReferenceableParamGroup()
                      .getUserParam()
                      .size());
            }
          }
        }
      }
    } catch (IOException ioe) {
      ioe.printStackTrace();
      fail("IOException when creating a temproray file to marshall to!\n" + ioe.getMessage());
    }
  }