/*******************************************************************************
* GenPlay, Einstein Genome Analyzer
* Copyright (C) 2009, 2014 Albert Einstein College of Medicine
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* Authors: Julien Lajugie <julien.lajugie@einstein.yu.edu>
* Nicolas Fourel <nicolas.fourel@einstein.yu.edu>
* Eric Bouhassira <eric.bouhassira@einstein.yu.edu>
*
* Website: <http://genplay.einstein.yu.edu>
******************************************************************************/
package edu.yu.einstein.genplay.gui.projectFrame.newProject;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.filechooser.FileFilter;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
import edu.yu.einstein.genplay.core.multiGenome.VCF.VCFFile.VCFFile;
import edu.yu.einstein.genplay.core.multiGenome.utils.FormattedMultiGenomeName;
import edu.yu.einstein.genplay.exception.ExceptionManager;
import edu.yu.einstein.genplay.gui.dialog.multiGenomeDialog.vcfLoader.SettingsHandler;
import edu.yu.einstein.genplay.gui.dialog.multiGenomeDialog.vcfLoader.VCFData;
import edu.yu.einstein.genplay.gui.dialog.multiGenomeDialog.vcfLoader.VCFLoaderDialog;
import edu.yu.einstein.genplay.gui.fileFilter.XMLFilter;
import edu.yu.einstein.genplay.gui.projectFrame.ProjectFrame;
import edu.yu.einstein.genplay.util.FileChooser;
/**
* This class shows information and buttons about the multi genome
* @author Nicolas Fourel
*/
class MultiGenomePanel extends JPanel {
private static final long serialVersionUID = -1295541774864815129L;
private final MultiGenomeInformationPanel informationPanel; // multi genome information panel
private final JButton exportXML; // button to export the multi-genome settings as data
private VCFLoaderDialog vcfLoaderDialog; // the VCF loader
private List<VCFData> data; // data
private Map<String, List<VCFFile>> genomeFileAssociation;
/**
* Constructor of {@link MultiGenomePanel}
*/
protected MultiGenomePanel () {
informationPanel = new MultiGenomeInformationPanel();
vcfLoaderDialog = new VCFLoaderDialog();
data = new ArrayList<VCFData>();
//Edit button
JButton editVCFFile = new JButton("Select VCF");
editVCFFile.setToolTipText("Edit multi-genome information");
editVCFFile.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (vcfLoaderDialog == null) {
vcfLoaderDialog = new VCFLoaderDialog();
}
vcfLoaderDialog.setData(getData());
if (vcfLoaderDialog.showDialog(ProjectFrame.getInstance().getRootPane()) == VCFLoaderDialog.APPROVE_OPTION) {
setData(vcfLoaderDialog.getData());
if (vcfLoaderDialog.areValidSettings()) {
initializesGenomeFileAssociation();
updatesStatistics();
}
}
}
});
//Import button
JButton importXML = new JButton("Import Config");
importXML.setToolTipText("Import information from xml");
importXML.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
importXML();
}
});
//Export button
exportXML = new JButton("Export Config");
exportXML.setToolTipText("Export information to xml");
exportXML.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
exportXML();
}
});
exportXML.setEnabled(false);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = 2;
add(informationPanel, gbc);
gbc.insets = new Insets(10, 0, 0, 0);
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridy = 1;
add(editVCFFile, gbc);
gbc.gridy = 2;
gbc.gridwidth = 1;
add(importXML, gbc);
gbc.gridx = 1;
add(exportXML, gbc);
setOpaque(false);
setVarTableVisible(false);
}
/**
* Adds data to the current list.
* Case of importing data.
* (importing do not erase current settings but add new ones!)
* If the VCF file is not found we look into the directory containing xml
* config to check if the vcf is not there.
* @param newData
* @param xmlPath path to xml config file
*/
private void addData (List<VCFData> newData, File xmlPath) {
if (data == null) {
data = new ArrayList<VCFData>();
}
for (VCFData vcfData: newData) {
data.add(vcfData);
if (!vcfData.getFile().exists() && (xmlPath != null)) {
File newVcf = new File(xmlPath, vcfData.getFile().getName());
if (newVcf.exists()) {
vcfData.setFile(newVcf);
}
}
}
}
/**
* Closes the XML stream
* @param xml
*/
private void closeXML (FileInputStream xml) {
if (xml != null) {
try {
xml.close();
} catch (IOException e) {
ExceptionManager.getInstance().caughtException(e);
}
}
}
/**
* Exports a XML file settings
*/
private void exportXML () {
if (data.size() > 0) {
File file = FileChooser.chooseFile(getRootPane(), FileChooser.SAVE_FILE_MODE, "Export Configuration", new FileFilter[] {new XMLFilter()}, false);
if (file != null) {
SettingsHandler xmlParser = new SettingsHandler(file);
xmlParser.setData(data);
xmlParser.write();
}
} else {
JOptionPane.showMessageDialog(getRootPane(), "No setting has been found", "Settings export process", JOptionPane.WARNING_MESSAGE);
}
}
/**
* @return the data object
*/
private List<VCFData> getData () {
List<VCFData> newData = new ArrayList<VCFData>();
if (data == null) {
data = new ArrayList<VCFData>();
}
for (VCFData vcfData: data) {
newData.add(vcfData);
}
return newData;
}
/**
* @return the mapping between genome full names and their readers.
*/
protected Map<String, List<VCFFile>> getGenomeFileAssociation () {
return genomeFileAssociation;
}
/**
* Imports a XML file settings
*/
private void importXML () {
// XML File
File xmlFile = null;
// XML Chooser
File file = FileChooser.chooseFile(getRootPane(), FileChooser.OPEN_FILE_MODE, "Export Configuration", new FileFilter[] {new XMLFilter()}, false);
if(file != null) {
String xmlPath = file.getPath();
xmlFile = new File(xmlPath);
// Stream & Parsers
FileInputStream xml = null;
SAXParser parser;
SAXParserFactory parserFactory = SAXParserFactory.newInstance();
parserFactory.setValidating(true);
SettingsHandler xmlParser = new SettingsHandler(xmlFile);
try {
xml = new FileInputStream(xmlFile);
parser = parserFactory.newSAXParser();
parser.parse(xml, xmlParser);
closeXML(xml);
} catch (ParserConfigurationException e1) {
closeXML(xml);
ExceptionManager.getInstance().caughtException(e1);
} catch (SAXException e1) {
closeXML(xml);
ExceptionManager.getInstance().caughtException(e1);
} catch (FileNotFoundException e) {
closeXML(xml);
ExceptionManager.getInstance().caughtException(e);
} catch (IOException e) {
closeXML(xml);
ExceptionManager.getInstance().caughtException(e);
}
closeXML(xml);
// Manager initialization
addData(xmlParser.getData(), file.getParentFile());
vcfLoaderDialog.setData(data);
initializesGenomeFileAssociation();
updatesStatistics();
}
}
/**
* Initializes the genome/file map association.
* Updates also the statistical information and refreshes the panel.
*/
private void initializesGenomeFileAssociation () {
genomeFileAssociation = new HashMap<String, List<VCFFile>>();
for (VCFData vcfData: data) {
String fullName = FormattedMultiGenomeName.getFullFormattedGenomeName(vcfData.getGroup(), vcfData.getNickname(), vcfData.getRaw());
if (!genomeFileAssociation.containsKey(fullName)) {
genomeFileAssociation.put(fullName, new ArrayList<VCFFile>());
}
VCFFile vcfFile = vcfLoaderDialog.getVCFFile(vcfData.getFile());
genomeFileAssociation.get(fullName).add(vcfFile);
}
}
/**
* @return true if the multi genome project is valid
*/
protected boolean isValidMultigenomeProject () {
return vcfLoaderDialog.areValidSettings();
}
/**
* Sets the data object.
* After VCF loader dialog validation.
* @param newData new data
*/
private void setData (List<VCFData> newData) {
data = new ArrayList<VCFData>();
for (VCFData vcfData: newData) {
data.add(vcfData);
}
}
/**
* Displays or hides the var panel
* @param visible set to true to show the var table
*/
void setVarTableVisible(boolean visible) {
if (visible) {
setBorder(BorderFactory.createTitledBorder("Genomes Selection"));
} else {
setBorder(null);
}
for (Component c: getComponents()) {
c.setVisible(visible);
}
}
/**
* Generates statistics about:
* - group #
* - genome #
* - VCF file #
* Updates the information panel to display them
*/
private void updatesStatistics () {
List<String> groupList = new ArrayList<String>();
List<String> genomeList = new ArrayList<String>();
Map<String, Integer> fileGenome = new HashMap<String, Integer>();
if (genomeFileAssociation.keySet().isEmpty()) {
exportXML.setEnabled(false);
} else {
exportXML.setEnabled(true);
for (String fullGenomeName: genomeFileAssociation.keySet()) {
String groupName = FormattedMultiGenomeName.getGroupName(fullGenomeName);
if (!groupList.contains(groupName)) {
groupList.add(groupName);
}
String rawName = FormattedMultiGenomeName.getRawName(fullGenomeName);
if (!genomeList.contains(rawName)) {
genomeList.add(rawName);
}
for (VCFFile reader: genomeFileAssociation.get(fullGenomeName)) {
String path = reader.getFile().getPath();
if (!fileGenome.containsKey(path)) {
fileGenome.put(path, 0);
}
Integer cpt = fileGenome.get(path) + 1;
fileGenome.put(path, cpt);
}
}
MultiGenomeInformationPanel.GROUP_NUMBER = groupList.size();
MultiGenomeInformationPanel.GENOME_NUMBER = genomeList.size();
MultiGenomeInformationPanel.FILE_NUMBER = fileGenome.size();
MultiGenomeInformationPanel.refreshInformation();
}
}
}