package au.com.acpfg.misc.jemboss.local;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import org.emboss.jemboss.programs.RunEmbossApplication;
import org.knime.base.node.util.BufferedFileReader;
/**
* Implements a TreeModel interface for displaying the list of programs with categories and helpful
* text about each supported program by the EMBOSS installation.
*
* @author andrew.cassin
*
*/
public class MyProgTreeModel implements TreeModel {
private final ArrayList<TreeModelListener> m_listeners = new ArrayList<TreeModelListener>();
protected final Map<String,ProgsInCategory> m_categories = new TreeMap<String,ProgsInCategory>();
public MyProgTreeModel() throws IOException {
File outfile = File.createTempFile("wossname", "progs");
String prog = new String("wossname -search \"\" -outfile "+outfile.getAbsolutePath());
File proj_dir = new File("c:\\temp");
Pattern p = Pattern.compile("^(\\w+)\\s+(.*)$");
RunEmbossApplication rea = new RunEmbossApplication(prog, null, proj_dir);
try {
int status = rea.getProcess().waitFor();
//Logger.getAnonymousLogger().info("wossname result status "+status+" output size(bytes): "+outfile.length());
BufferedReader br = new BufferedReader(new FileReader(outfile));
String line;
String category = null;
while ((line = br.readLine()) != null) {
if (line.trim().length() < 1)
continue;
if (Character.isUpperCase(line.charAt(0))) {
category = line.trim();
ProgsInCategory pic = m_categories.get(category);
if (pic == null) {
pic = new ProgsInCategory(category);
m_categories.put(category, pic);
}
continue;
}
if (Character.isLowerCase(line.charAt(0)) && category != null) {
ProgsInCategory pic = m_categories.get(category);
Matcher m = p.matcher(line.trim());
if (m.matches())
pic.add(m.group(1), m.group(2));
}
}
br.close();
outfile.delete();
} catch (Exception e) {
e.printStackTrace();
outfile.deleteOnExit();
}
}
@Override
public void addTreeModelListener(TreeModelListener arg0) {
if (arg0 != null)
m_listeners.add(arg0);
}
@Override
public Object getChild(Object parent, int child_idx) {
int idx = 0;
if (parent.equals(getRoot())) {
Set<String> categories = m_categories.keySet();
for (String category : categories) {
if (child_idx == idx++)
return m_categories.get(category);
}
} else if (parent instanceof ProgsInCategory) {
ProgsInCategory pic = (ProgsInCategory) parent;
Set<String> categories = pic.keys();
for (String category : categories) {
if (child_idx == idx++) {
return pic.getProgram(category);
}
}
} // else { parent instanceof EmbossProgramDescription
return parent;
}
@Override
public int getChildCount(Object parent) {
if (parent.equals(getRoot())) {
return m_categories.size();
} else if (parent instanceof ProgsInCategory) {
ProgsInCategory pic = (ProgsInCategory) parent;
return pic.getNumPrograms();
} else {
return 0;
}
}
@Override
public int getIndexOfChild(Object parent, Object child) {
if (parent.equals(getRoot())) {
assert(child instanceof ProgsInCategory);
Iterator<String> it = m_categories.keySet().iterator();
ProgsInCategory pic = (ProgsInCategory) child;
for (int i=0; i<m_categories.size(); i++) {
if (pic.hasName(it.next()))
return i;
}
} else if (parent instanceof ProgsInCategory){
ProgsInCategory pic = (ProgsInCategory) parent;
return pic.getIndexOfChild(child);
}
return 0;
}
@Override
public Object getRoot() {
return "/";
}
@Override
public boolean isLeaf(Object node) {
if (node.equals(getRoot()))
return false;
else if (m_categories.containsValue(node)) {
// BUG: maybe should check to see if category has any programs
return false;
} else {
// BUG: maybe should check to see if node is in tree?
return true;
}
}
/**
* Returns the TreePath (for a MyProgTreeModel) which represents the given emboss program name
*
* @param program_name
* @return
*/
TreePath findProgramTreePath(String program_name) {
if (program_name != null && program_name.length() > 0) {
for (String c1 : m_categories.keySet()) {
ProgsInCategory pic = m_categories.get(c1);
for (EmbossProgramDescription c2 : pic) {
if (c2.isProgram(program_name)) {
return new TreePath(new Object[] {getRoot(), pic, c2});
}
}
}
}
// not found: return root
return new TreePath(getRoot());
}
@Override
public void removeTreeModelListener(TreeModelListener arg0) {
if (arg0 != null)
m_listeners.remove(arg0);
}
@Override
public void valueForPathChanged(TreePath arg0, Object arg1) {
// NO-OP this node model does nothing with this message
}
protected void fireTreeStructureChanged() {
TreeModelEvent ev = new TreeModelEvent(this, new TreePath(getRoot()));
for (TreeModelListener tml : m_listeners) {
tml.treeStructureChanged(ev);
}
}
}