diff --git a/build.xml b/build.xml index 437a267..98e705b 100644 --- a/build.xml +++ b/build.xml @@ -17,7 +17,7 @@ - + diff --git a/src/beast/app/beauti/FileInputEditor.java b/src/beast/app/beauti/FileInputEditor.java new file mode 100644 index 0000000..70c7e85 --- /dev/null +++ b/src/beast/app/beauti/FileInputEditor.java @@ -0,0 +1,84 @@ +package beast.app.beauti; + + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; + +import javax.swing.JButton; + +import beast.app.draw.InputEditor; +import beast.app.util.Utils; +import beast.core.BEASTInterface; +import beast.core.Input; + + +/** for opening files for reading + * use OutFile when you need a file for writing + */ +public class FileInputEditor extends InputEditor.Base { + + private static final long serialVersionUID = 1L; + + @Override + public Class type() { + return File.class; + } + + public FileInputEditor(BeautiDoc doc) { + super(doc); + } + + @Override + public void init(Input input, BEASTInterface plugin, int itemNr, ExpandOption bExpandOption, boolean bAddButtons) { + super.init(input, plugin, itemNr, bExpandOption, bAddButtons); + if (input.get() == null) { + m_entry.setText("[[none]]"); + } else { + m_entry.setText(((File) m_input.get()).getName()); + } + + JButton button = new JButton("browse"); + button.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent arg0) { + File defaultFile; + if (m_input.get() != null && ((File) m_input.get()).exists()) { + defaultFile = (File) m_input.get(); + } else { + defaultFile = new File(Beauti.g_sDir); + } + File file = Utils.getLoadFile(m_input.getTipText(), defaultFile, "All files", ""); + try { + m_entry.setText(file.getName()); + m_input.setValue(file, m_beastObject); + String path = file.getPath(); + Beauti.g_sDir = path; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + }); + add(button); + } + + @Override + protected void setValue(Object o) { + String file = o.toString(); + if (file.equals("")) { + return; + } + String fileSep = System.getProperty("file.separator"); + String origFile = ((File) m_input.get()).getAbsolutePath(); + if (origFile.indexOf(fileSep) >= 0 && file.indexOf(fileSep) < 0) { + if (origFile.contains(origFile)) { + file = origFile.substring(0, origFile.lastIndexOf(fileSep) + 1) + file; + } + } + m_input.setValue(file, m_beastObject); + } + + +} diff --git a/src/beast/app/beauti/LogFileInputEditor.java b/src/beast/app/beauti/LogFileInputEditor.java new file mode 100644 index 0000000..0913205 --- /dev/null +++ b/src/beast/app/beauti/LogFileInputEditor.java @@ -0,0 +1,78 @@ +package beast.app.beauti; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; + +import javax.swing.JButton; + +import beast.app.draw.InputEditor; +import beast.app.util.LogFile; +import beast.app.util.Utils; +import beast.core.BEASTInterface; +import beast.core.Input; + +public class LogFileInputEditor extends InputEditor.Base { + + private static final long serialVersionUID = 1L; + + @Override + public Class type() { + return LogFile.class; + } + + public LogFileInputEditor(BeautiDoc doc) { + super(doc); + } + + @Override + public void init(Input input, BEASTInterface plugin, int itemNr, ExpandOption bExpandOption, boolean bAddButtons) { + super.init(input, plugin, itemNr, bExpandOption, bAddButtons); + m_entry.setText(((File) m_input.get()).getName()); + + JButton button = new JButton("browse"); + button.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent arg0) { + File defaultFile; + if (((File) m_input.get()).exists()) { + defaultFile = (File) m_input.get(); + } else { + defaultFile = new File(Beauti.g_sDir); + } + File file = Utils.getLoadFile(m_input.getTipText(), defaultFile, "trace files", "log"); + if (file != null) + file = new LogFile(file.getPath()); + try { + m_entry.setText(file.getName()); + m_input.setValue(file, m_beastObject); + String path = file.getPath(); + Beauti.g_sDir = path; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + }); + add(button); + } + + @Override + protected void setValue(Object o) { + String file = o.toString(); + if (file.equals("")) { + return; + } + String fileSep = System.getProperty("file.separator"); + String origFile = ((File) m_input.get()).getAbsolutePath(); + if (origFile.indexOf(fileSep) >= 0 && file.indexOf(fileSep) < 0) { + if (origFile.contains(origFile)) { + file = origFile.substring(0, origFile.lastIndexOf(fileSep) + 1) + file; + } + } + m_input.setValue(file, m_beastObject); + } + + +} diff --git a/src/beast/app/beauti/OutFileInputEditor.java b/src/beast/app/beauti/OutFileInputEditor.java new file mode 100644 index 0000000..b869335 --- /dev/null +++ b/src/beast/app/beauti/OutFileInputEditor.java @@ -0,0 +1,82 @@ +package beast.app.beauti; + + + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; + +import javax.swing.JButton; + +import beast.app.util.OutFile; +import beast.app.util.Utils; +import beast.core.BEASTInterface; +import beast.core.Input; +import beast.app.draw.InputEditor; + +public class OutFileInputEditor extends InputEditor.Base { + + private static final long serialVersionUID = 1L; + + @Override + public Class type() { + return OutFile.class; + } + + public OutFileInputEditor(BeautiDoc doc) { + super(doc); + } + + @Override + public void init(Input input, BEASTInterface plugin, int itemNr, ExpandOption bExpandOption, boolean bAddButtons) { + super.init(input, plugin, itemNr, bExpandOption, bAddButtons); + m_entry.setText(((File) m_input.get()).getName()); + + JButton button = new JButton("browse"); + button.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent arg0) { + File defaultFile; + if (((File) m_input.get()).exists()) { + defaultFile = (File) m_input.get(); + } else { + defaultFile = new File(Beauti.g_sDir); + } + File file = Utils.getSaveFile(m_input.getTipText(), defaultFile, "All files", ""); + if (file != null) + file = new OutFile(file.getPath()); + try { + m_entry.setText(file.getName()); + m_input.setValue(file, m_beastObject); + String path = file.getPath(); + Beauti.g_sDir = path; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + }); + add(button); + } + + + @Override + protected void setValue(Object o) { + String file = o.toString(); + if (file.equals("")) { + return; + } + String fileSep = System.getProperty("file.separator"); + String origFile = ((File) m_input.get()).getAbsolutePath(); + if (origFile.indexOf(fileSep) >= 0 && file.indexOf(fileSep) < 0) { + if (origFile.contains(origFile)) { + file = origFile.substring(0, origFile.lastIndexOf(fileSep) + 1) + file; + } + } + m_input.setValue(file, m_beastObject); + } + + + +} diff --git a/src/beast/app/beauti/TreeFileInputEditor.java b/src/beast/app/beauti/TreeFileInputEditor.java new file mode 100644 index 0000000..66dcaeb --- /dev/null +++ b/src/beast/app/beauti/TreeFileInputEditor.java @@ -0,0 +1,79 @@ +package beast.app.beauti; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; + +import javax.swing.JButton; + +import beast.app.draw.InputEditor; +import beast.app.util.XMLFile; +import beast.app.util.Utils; +import beast.core.BEASTInterface; +import beast.core.Input; + +public class TreeFileInputEditor extends InputEditor.Base { + + private static final long serialVersionUID = 1L; + + @Override + public Class type() { + return XMLFile.class; + } + + public TreeFileInputEditor(BeautiDoc doc) { + super(doc); + } + + @Override + public void init(Input input, BEASTInterface plugin, int itemNr, ExpandOption bExpandOption, boolean bAddButtons) { + super.init(input, plugin, itemNr, bExpandOption, bAddButtons); + m_entry.setText(((File) m_input.get()).getName()); + + JButton button = new JButton("browse"); + button.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent arg0) { + File defaultFile; + if (((File) m_input.get()).exists()) { + defaultFile = (File) m_input.get(); + } else { + defaultFile = new File(Beauti.g_sDir); + } + File file = Utils.getLoadFile(m_input.getTipText(), defaultFile, "tree files", "trees"); + if (file != null) { + file = new XMLFile(file.getPath()); + } + try { + m_entry.setText(file.getName()); + m_input.setValue(file, m_beastObject); + String path = file.getPath(); + Beauti.g_sDir = path; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + }); + add(button); + } + + @Override + protected void setValue(Object o) { + String file = o.toString(); + if (file.equals("")) { + return; + } + String fileSep = System.getProperty("file.separator"); + String origFile = ((File) m_input.get()).getAbsolutePath(); + if (origFile.indexOf(fileSep) >= 0 && file.indexOf(fileSep) < 0) { + if (origFile.contains(origFile)) { + file = origFile.substring(0, origFile.lastIndexOf(fileSep) + 1) + file; + } + } + m_input.setValue(file, m_beastObject); + } + + +} diff --git a/src/beast/app/beauti/XMLFileInputEditor.java b/src/beast/app/beauti/XMLFileInputEditor.java new file mode 100644 index 0000000..129f7bf --- /dev/null +++ b/src/beast/app/beauti/XMLFileInputEditor.java @@ -0,0 +1,79 @@ +package beast.app.beauti; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; + +import javax.swing.JButton; + +import beast.app.draw.InputEditor; +import beast.app.util.XMLFile; +import beast.app.util.Utils; +import beast.core.BEASTInterface; +import beast.core.Input; + +public class XMLFileInputEditor extends InputEditor.Base { + + private static final long serialVersionUID = 1L; + + @Override + public Class type() { + return XMLFile.class; + } + + public XMLFileInputEditor(BeautiDoc doc) { + super(doc); + } + + @Override + public void init(Input input, BEASTInterface plugin, int itemNr, ExpandOption bExpandOption, boolean bAddButtons) { + super.init(input, plugin, itemNr, bExpandOption, bAddButtons); + m_entry.setText(((File) m_input.get()).getName()); + + JButton button = new JButton("browse"); + button.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent arg0) { + File defaultFile; + if (((File) m_input.get()).exists()) { + defaultFile = (File) m_input.get(); + } else { + defaultFile = new File(Beauti.g_sDir); + } + File file = Utils.getLoadFile(m_input.getTipText(), defaultFile, "BEAST XML files", "xml"); + if (file != null) { + file = new XMLFile(file.getPath()); + } + try { + m_entry.setText(file.getName()); + m_input.setValue(file, m_beastObject); + String path = file.getPath(); + Beauti.g_sDir = path; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + }); + add(button); + } + + @Override + protected void setValue(Object o) { + String file = o.toString(); + if (file.equals("")) { + return; + } + String fileSep = System.getProperty("file.separator"); + String origFile = ((File) m_input.get()).getAbsolutePath(); + if (origFile.indexOf(fileSep) >= 0 && file.indexOf(fileSep) < 0) { + if (origFile.contains(origFile)) { + file = origFile.substring(0, origFile.lastIndexOf(fileSep) + 1) + file; + } + } + m_input.setValue(file, m_beastObject); + } + + +} diff --git a/src/beast/app/util/Application.java b/src/beast/app/util/Application.java new file mode 100644 index 0000000..1f7d6fe --- /dev/null +++ b/src/beast/app/util/Application.java @@ -0,0 +1,154 @@ +package beast.app.util; + + +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONObject; + +import beast.core.BEASTObject; +import beast.core.Description; +import beast.core.Input; +import beast.core.util.Log; + +@Description("BEAST application that handles argument parsing by introspection " + + "using Inputs declared in the class.") +public class Application { + + BEASTObject myBeastObject; + + public Application(BEASTObject myBeastObject) { + this.myBeastObject = myBeastObject; + } + + /** default input used for argument parsing **/ + protected Input defaultInput = null; + + /** + * Arguments of the form -name value are processed by finding Inputs with + * matching name and setting their value. + * + * If the input is a boolean that needs to be set to true, the 'value' a + * argument can be omitted. + * + * The last argument is assigned to the defaultInput. + * **/ + public void parseArgs(String[] args, boolean sloppy) throws Exception { + List> inputs = myBeastObject.listInputs(); + for (Input input : inputs) { + input.determineClass(this); + } + + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + boolean done = false; + if (arg.startsWith("-")) { + String name = arg.substring(1); + String value = (i < args.length - 1 ? args[i + 1] : null); + for (Input input : inputs) { + if (input.getName().equals(name)) { + try { + if (input.getType() == Boolean.class) { + if (value != null + && (value.toLowerCase().equals("true") || value + .toLowerCase().equals("false"))) { + input.setValue(value, null); + i++; + } else { + input.setValue(Boolean.TRUE, null); + } + } else { + input.setValue(value, myBeastObject); + i++; + } + } catch (Exception e) { + throw new Exception("Problem parsing arguments:\n" + + e.getMessage()); + } + done = true; + break; + } + } + if (name.equals("help")) { + throw new Exception(""); // calling app should call getUsage() + } + } else { + if (i == args.length - 1) { + defaultInput.setValue(arg, null); + done = true; + } + } + if (!done) { + if (sloppy) { + Log.info.println("Unknown argument: " + args[i] + + " ignored."); + i++; + } else { + throw new Exception("Unknown argument: " + args[i] + "\n"); + //+ getUsage()); + } + } + } + + } + + protected void parseArgs(JSONObject args) throws Exception { + List argList = new ArrayList<>(); + for (String key : args.keySet()) { + argList.add("-" + key.trim()); + argList.add(args.get(key).toString().trim()); + } + parseArgs(argList.toArray(new String[] {}), true); + } + + public String getUsage() { + StringBuffer buf = new StringBuffer(); + try { + List> inputs = myBeastObject.listInputs(); + buf.append("Usage: " + myBeastObject.getClass().getName() + "\n"); + for (Input input : inputs) { + buf.append("-" + input.getName() + " "); + try { + Class typeClass = input.getType(); + if (typeClass == null) { + input.determineClass(myBeastObject); + } + buf.append(input.getValueTipText()); + } catch (Exception e) { + // ignore + } + buf.append("\t" + input.getTipText() + "\n"); + } + } catch (Exception e) { + e.printStackTrace(); + } + buf.append("-help\t show arguments"); + return buf.toString(); + } + + // placeholder, so that the main method compiles + public void run() throws Exception { + myBeastObject.initAndValidate(); + }; + + // template for implementing a main for an application + // the first argument is interpreted as class name of a BEASTObject + public static void main(final String[] args) throws Exception { + Application main = null; + try { + BEASTObject myBeastObject = (BEASTObject) Class.forName(args[0]) + .newInstance(); + main = new Application(myBeastObject); + String[] args2 = new String[args.length - 1]; + System.arraycopy(args, 1, args2, 0, args2.length); + main.parseArgs(args2, false); + main.run(); + } catch (Exception e) { + System.out.println("Error:" + e.getMessage()); + if (main != null) { + System.out.println(main.getUsage()); + } + } + } + +} diff --git a/src/beast/app/util/ConsoleApp.java b/src/beast/app/util/ConsoleApp.java new file mode 100644 index 0000000..a733402 --- /dev/null +++ b/src/beast/app/util/ConsoleApp.java @@ -0,0 +1,76 @@ +package beast.app.util; + +import java.io.IOException; +import java.util.logging.Filter; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +import javax.swing.Icon; +import javax.swing.WindowConstants; + +import beast.app.BEASTVersion; + +public class ConsoleApp { + PathSampleConsoleApp consoleApp = null; + + + public ConsoleApp(String nameString, String title, Icon icon) throws IOException { + Utils.loadUIManager(); + System.setProperty("com.apple.macos.useScreenMenuBar", "true"); + System.setProperty("apple.laf.useScreenMenuBar", "true"); + System.setProperty("apple.awt.showGrowBox", "true"); + System.setProperty("beast.useWindow", "true"); + + int maxErrorCount = 100; + + BEASTVersion version = new BEASTVersion(); + + final String aboutString = "
" + + "

Bayesian Evolutionary Analysis Sampling Trees
" + + "Version " + version.getVersionString() + ", " + version.getDateString() + "

" + + version.getHTMLCredits() + + "
"; + + consoleApp = new PathSampleConsoleApp(nameString, aboutString, icon); + + consoleApp.setTitle(title); + + // Add a handler to handle warnings and errors. This is a ConsoleHandler + // so the messages will go to StdOut.. + final Logger logger = Logger.getLogger("beast"); + + Handler handler = new MessageLogHandler(); + handler.setFilter(new Filter() { + @Override + public boolean isLoggable(final LogRecord record) { + return record.getLevel().intValue() < Level.SEVERE.intValue(); + } + }); + logger.addHandler(handler); + logger.setUseParentHandlers(false); + + handler = new ErrorLogHandler(maxErrorCount); + handler.setLevel(Level.ALL);//INFO); + logger.addHandler(handler); + } + + + static class PathSampleConsoleApp extends jam.console.ConsoleApplication { + + public PathSampleConsoleApp(final String nameString, final String aboutString, final javax.swing.Icon icon) throws IOException { + super(nameString, aboutString, icon, false); + getDefaultFrame().setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + } + + @Override + public void doStop() { + // thread.stop is deprecated so need to send a message to running threads... + } + + public void setTitle(final String title) { + getDefaultFrame().setTitle(title); + } + } +} diff --git a/src/beast/app/util/LogFile.java b/src/beast/app/util/LogFile.java new file mode 100644 index 0000000..04fe7fa --- /dev/null +++ b/src/beast/app/util/LogFile.java @@ -0,0 +1,15 @@ +package beast.app.util; + +import java.io.File; + +public class LogFile extends File { + + public LogFile(File parent, String child) { + super(parent, child); + } + + public LogFile(String pathname) { + super(pathname); + } + +} diff --git a/src/beast/app/util/OutFile.java b/src/beast/app/util/OutFile.java new file mode 100644 index 0000000..b71ec53 --- /dev/null +++ b/src/beast/app/util/OutFile.java @@ -0,0 +1,15 @@ +package beast.app.util; + +import java.io.File; + +public class OutFile extends File { + + public OutFile(File parent, String child) { + super(parent, child); + } + + public OutFile(String string) { + super(string); + } + +} diff --git a/src/beast/app/util/TreeFile.java b/src/beast/app/util/TreeFile.java new file mode 100644 index 0000000..5b4394d --- /dev/null +++ b/src/beast/app/util/TreeFile.java @@ -0,0 +1,15 @@ +package beast.app.util; + +import java.io.File; + +public class TreeFile extends File { + + public TreeFile(File parent, String child) { + super(parent, child); + } + + public TreeFile(String string) { + super(string); + } + +} diff --git a/src/beast/app/util/XMLFile.java b/src/beast/app/util/XMLFile.java new file mode 100644 index 0000000..fbc88cf --- /dev/null +++ b/src/beast/app/util/XMLFile.java @@ -0,0 +1,15 @@ +package beast.app.util; + +import java.io.File; + +public class XMLFile extends File { + + public XMLFile(File parent, String child) { + super(parent, child); + } + + public XMLFile(String pathname) { + super(pathname); + } + +} diff --git a/version.xml b/version.xml index 35874f6..512331b 100644 --- a/version.xml +++ b/version.xml @@ -1,4 +1,4 @@ - +