/*
* Eoulsan development code
*
* This code may be freely distributed and modified under the
* terms of the GNU Lesser General Public License version 2.1 or
* later and CeCILL-C. This should be distributed with the code.
* If you do not have a copy, see:
*
* http://www.gnu.org/licenses/lgpl-2.1.txt
* http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.txt
*
* Copyright for this code is held jointly by the Genomic platform
* of the Institut de Biologie de l'École normale supérieure and
* the individual authors. These should be listed in @author doc
* comments.
*
* For more information on the Eoulsan project and its aims,
* or to join the Eoulsan Google group, visit the home page
* at:
*
* http://outils.genomique.biologie.ens.fr/eoulsan
*
*/
package fr.ens.biologie.genomique.eoulsan.design.io;
import static com.google.common.base.Preconditions.checkNotNull;
import static fr.ens.biologie.genomique.eoulsan.design.DesignUtils.getAllSamplesMetadataKeys;
import static fr.ens.biologie.genomique.eoulsan.design.DesignUtils.getExperimentSampleAllMetadataKeys;
import static fr.ens.biologie.genomique.eoulsan.design.SampleMetadata.UUID_KEY;
import static fr.ens.biologie.genomique.eoulsan.design.io.Eoulsan2DesignReader.DOT_SEPARATOR;
import static fr.ens.biologie.genomique.eoulsan.design.io.Eoulsan2DesignReader.EQUAL_SEPARATOR;
import static fr.ens.biologie.genomique.eoulsan.design.io.Eoulsan2DesignReader.EXPERIMENT_FIELD_PREFIX;
import static fr.ens.biologie.genomique.eoulsan.design.io.Eoulsan2DesignReader.EXPERIMENT_NAME_SUFFIX;
import static fr.ens.biologie.genomique.eoulsan.design.io.Eoulsan2DesignReader.SAMPLE_ID_FIELDNAME;
import static fr.ens.biologie.genomique.eoulsan.design.io.Eoulsan2DesignReader.SAMPLE_NAME_FIELDNAME;
import static fr.ens.biologie.genomique.eoulsan.design.io.Eoulsan2DesignReader.TAB_SEPARATOR;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.List;
import java.util.Map;
import fr.ens.biologie.genomique.eoulsan.Globals;
import fr.ens.biologie.genomique.eoulsan.data.DataFile;
import fr.ens.biologie.genomique.eoulsan.design.Design;
import fr.ens.biologie.genomique.eoulsan.design.Experiment;
import fr.ens.biologie.genomique.eoulsan.design.ExperimentSampleMetadata;
import fr.ens.biologie.genomique.eoulsan.design.Sample;
import fr.ens.biologie.genomique.eoulsan.design.SampleMetadata;
/**
* This class implements a writer for Eoulsan 2 design files.
* @since 2.0
* @author Xavier Bauquet
*/
public class Eoulsan2DesignWriter implements DesignWriter {
private final OutputStream out;
private static final String HEADER_SECTION = "[Header]";
private static final String EXPERIMENT_SECTION = "[Experiments]";
private static final String COLUMN_SECTION = "[Columns]";
private static final String NEWLINE = "\r\n";
@Override
public void write(final Design design) throws IOException {
checkNotNull(design, "Design argument cannot be null");
final BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(this.out, Globals.DEFAULT_CHARSET));
checkNotNull(design, "design argument cannot be null");
// Write design metadata
bw.append(HEADER_SECTION);
bw.append(NEWLINE);
bw.append(Eoulsan2DesignReader.DESIGN_FORMAT_VERSION_METADATA_KEY);
bw.append(EQUAL_SEPARATOR);
bw.append(Eoulsan2DesignReader.FORMAT_VERSION);
bw.append(NEWLINE);
for (Map.Entry<String, String> e : design.getMetadata().entrySet()) {
bw.append(e.getKey());
bw.append(EQUAL_SEPARATOR);
bw.append(e.getValue());
bw.append(NEWLINE);
}
bw.append(NEWLINE);
// Write experiment metadata
if (!design.getExperiments().isEmpty()) {
bw.append(EXPERIMENT_SECTION);
bw.append(NEWLINE);
}
for (Experiment e : design.getExperiments()) {
final String expId = e.getId();
bw.append(EXPERIMENT_FIELD_PREFIX);
bw.append(expId).append(DOT_SEPARATOR);
bw.append(EXPERIMENT_NAME_SUFFIX);
bw.append(EQUAL_SEPARATOR);
bw.append(e.getName());
bw.append(NEWLINE);
for (Map.Entry<String, String> m : e.getMetadata().entrySet()) {
bw.append(EXPERIMENT_FIELD_PREFIX);
bw.append(expId);
bw.append(DOT_SEPARATOR);
bw.append(m.getKey());
bw.append(EQUAL_SEPARATOR);
bw.append(m.getValue());
bw.append(NEWLINE);
}
bw.append(NEWLINE);
}
// Write column names
bw.append(COLUMN_SECTION);
bw.append(NEWLINE);
//
// Print column names
//
bw.append(SAMPLE_ID_FIELDNAME);
bw.append(TAB_SEPARATOR);
bw.append(SAMPLE_NAME_FIELDNAME);
final List<String> sampleMDKeys = getAllSamplesMetadataKeys(design);
// Print common column names
for (String key : sampleMDKeys) {
// The UUID must be the last field
if (SampleMetadata.UUID_KEY.equals(key)) {
continue;
}
bw.append(TAB_SEPARATOR);
bw.append(key);
}
// Print experiments column names
for (Experiment experiment : design.getExperiments()) {
final String prefix =
EXPERIMENT_FIELD_PREFIX + experiment.getId() + DOT_SEPARATOR;
final List<String> experimentMDKeys =
getExperimentSampleAllMetadataKeys(experiment);
for (String key : experimentMDKeys) {
bw.append(TAB_SEPARATOR);
bw.append(prefix);
bw.append(key);
}
}
// The UUID if exists, must be the last field
if (sampleMDKeys.contains(UUID_KEY)) {
bw.append(TAB_SEPARATOR);
bw.append(UUID_KEY);
}
bw.append(NEWLINE);
// Print samples metadata
for (Sample sample : design.getSamples()) {
bw.append(sample.getId());
bw.append(TAB_SEPARATOR);
bw.append(sample.getName());
final SampleMetadata smd = sample.getMetadata();
for (String key : sampleMDKeys) {
// The UUID must be the last field
if (UUID_KEY.equals(key)) {
continue;
}
bw.append(TAB_SEPARATOR);
if (smd.contains(key)) {
bw.append(smd.get(key));
}
}
for (Experiment experiment : design.getExperiments()) {
final ExperimentSampleMetadata expSampleMetadata =
experiment.getExperimentSample(sample).getMetadata();
final List<String> experimentMDKeys =
getExperimentSampleAllMetadataKeys(experiment);
for (String key : experimentMDKeys) {
bw.append(TAB_SEPARATOR);
if (expSampleMetadata.contains(key)) {
bw.append(expSampleMetadata.get(key));
}
}
}
// The UUID if exists, must be the last field
if (sampleMDKeys.contains(UUID_KEY)) {
bw.append(TAB_SEPARATOR);
bw.append(smd.get(UUID_KEY));
}
bw.append(NEWLINE);
}
bw.close();
}
//
// Constructors
//
/**
* Public constructor.
* @param file file to read
* @throws IOException if an error occurs while creating the file
*/
public Eoulsan2DesignWriter(final File file) throws IOException {
checkNotNull(file, "file argument cannot be null");
this.out = new FileOutputStream(file);
}
/**
* Public constructor.
* @param file file to read
* @throws IOException if an error occurs while creating the file
*/
public Eoulsan2DesignWriter(final DataFile file) throws IOException {
checkNotNull(file, "file argument cannot be null");
this.out = file.create();
}
/**
* Public constructor.
* @param out Output stream to read
* @throws IOException if the stream cannot be created
*/
public Eoulsan2DesignWriter(final OutputStream out) throws IOException {
checkNotNull(out, "out argument cannot be null");
this.out = out;
}
/**
* Public constructor.
* @param filename File to write
* @throws FileNotFoundException if the file doesn't exist
*/
public Eoulsan2DesignWriter(final String filename)
throws FileNotFoundException {
checkNotNull(filename, "filename argument cannot be null");
this.out = new FileOutputStream(filename);
}
}