/*
Copyright (C) 2009 Diego Darriba
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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package es.uvigo.darwin.prottest.exe.util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import pal.alignment.Alignment;
import pal.alignment.AlignmentUtils;
import pal.tree.Tree;
import pal.tree.TreeUtils;
import es.uvigo.darwin.prottest.facade.thread.ThreadPoolSynchronizer;
import es.uvigo.darwin.prottest.util.exception.ProtTestInternalException;
/**
* A singleton class to manage the temporary files usage in the
* application. It should be accessible for every thread that gets
* part in the execution.
*/
public class TemporaryFileManager {
/** The Constant BASE_ALIGNMENT_FILE_NAME. */
private static final String BASE_ALIGNMENT_FILE_NAME = "prottest_alignment_";
/** The Constant BASE_TREE_FILE_NAME. */
private static final String BASE_TREE_FILE_NAME = "prottest_tree_";
/** The Constant BASE_LOG_FILE_NAME. */
private static final String BASE_LOG_FILE_NAME = "prottest_";
/** The unique instance. */
private static TemporaryFileManager instance;
/** The alignment temporary files. */
private File[] alignmentTempFile;
/** The log temporary files. */
private File[] logTempFile;
/** The tree temporary file. */
private File treeTempFile;
/** The thread pool synchronizer. */
private ThreadPoolSynchronizer synchronizer;
/** The alignment. */
private Alignment alignment;
/** The tree. */
private Tree tree;
/**
* Gets the alignment filename.
*
* @param thread the thread
*
* @return the alignment filename
*/
public String getAlignmentFilename(Thread thread) {
int threadId = synchronizer.getThreadId(thread);
return alignmentTempFile[threadId].getAbsolutePath();
}
/**
* Gets the log filename.
*
* @param thread the thread
*
* @return the log filename
*/
public String getLogFilename(Thread thread) {
int threadId = synchronizer.getThreadId(thread);
return logTempFile[threadId].getAbsolutePath();
}
/**
* Gets the tree filename for a thread.
*
* @param thread the thread
*
* @return the tree filename
*/
public String getTreeFilename(Thread thread) {
if (tree == null)
return null;
return treeTempFile.getAbsolutePath();
}
/**
* Checks if is synchronized.
*
* @return true, if is synchronized
*/
public static boolean isSynchronized() {
return instance != null;
}
/**
* Sets the input tree. For each manager sync, the input tree should be set just
* once, or all the trees must be the same (i.e., this method can be used to
* check consistency between processes)
*
* @param tree the new tree
*
* @throws ProtTestInternalException when attempting to set different trees
*/
public void setTree(Tree tree) {
if (this.tree == null) {
convertTree(tree, treeTempFile);
this.tree = tree;
} else {
if (!tree.equals(this.tree)) {
throw new ProtTestInternalException("Attempting to set different trees");
}
}
}
/**
* Gets the input tree.
*
* @return the tree
*/
public Tree getTree() {
return tree;
}
/**
* Gets the input alignment.
*
* @return the alignment
*/
public Alignment getAlignment() {
return alignment;
}
/**
* Instantiates a new temporary file manager.
*
* @param path the path
* @param alignment the alignment
* @param tree the tree
* @param poolSize the pool size
*/
private TemporaryFileManager(Alignment alignment, Tree tree, int poolSize) {
alignmentTempFile = new File[poolSize];
logTempFile = new File[poolSize];
this.alignment = alignment;
this.tree = tree;
try {
for (int i = 0; i < poolSize; i++) {
alignmentTempFile[i] = File.createTempFile(BASE_ALIGNMENT_FILE_NAME, null);
alignmentTempFile[i].deleteOnExit();
logTempFile[i] = File.createTempFile(BASE_LOG_FILE_NAME, null);
logTempFile[i].deleteOnExit();
convertAlignment(alignment, alignmentTempFile[i]);
}
treeTempFile = File.createTempFile(BASE_TREE_FILE_NAME, null);
treeTempFile.deleteOnExit();
if (tree != null)
convertTree(tree, treeTempFile);
} catch (IOException e) {
throw new ProtTestInternalException("Cannot create temporary files");
}
ThreadPoolSynchronizer.synchronize(poolSize);
synchronizer = ThreadPoolSynchronizer.getInstance();
}
/**
* Gets the single instance of TemporaryFileManager.
*
* @return single instance of TemporaryFileManager
*/
public static TemporaryFileManager getInstance() {
if (instance == null) {
throw new ProtTestInternalException("TemporaryFileManager out of sync");
}
return instance;
}
/**
* Synchronizes this manager.
*
* @param alignment the input alignment
* @param tree the input tree
* @param poolSize the pool size
*/
public static void synchronize(Alignment alignment, Tree tree, int poolSize) {
instance = new TemporaryFileManager(alignment, tree, poolSize);
}
/**
* Converts an alignment into a file.
*
* @param alignment the input alignment
* @param outputFile the output file
*
* @return true, if successful
*/
private boolean convertAlignment(Alignment alignment, File outputFile) {
try {
FileOutputStream fo = new FileOutputStream(outputFile);
PrintWriter output = new PrintWriter(fo);
//AlignmentUtils.printSequential(alignment, output);
AlignmentUtils.printInterleaved(alignment, output);
output.flush();
output.close();
} catch (IOException e) {
throw new ProtTestInternalException();
}
return true;
}
/**
* Converts a tree into a file.
*
* @param tree the input tree
* @param outputFile the output file
*
* @return true, if successful
*/
private boolean convertTree(Tree tree, File outputFile) {
if (tree != null) {
try {
FileOutputStream fo = new FileOutputStream(outputFile);
PrintWriter output = new PrintWriter(fo);
TreeUtils.printNH(tree, output);
output.flush();
output.close();
} catch (IOException e) {
throw new ProtTestInternalException();
}
}
return true;
}
}