Package weka.gui.scripting

Source Code of weka.gui.scripting.Script

/*
*    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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
* Script.java
* Copyright (C) 2009 University of Waikato, Hamilton, New Zealand
*/

package weka.gui.scripting;

import weka.core.Option;
import weka.core.OptionHandler;
import weka.core.SerializedObject;
import weka.core.Utils;
import weka.core.WekaException;
import weka.gui.ExtensionFileFilter;
import weka.gui.scripting.event.ScriptExecutionEvent;
import weka.gui.scripting.event.ScriptExecutionListener;
import weka.gui.scripting.event.ScriptExecutionEvent.Type;

import java.io.File;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;

/**
* A simple helper class for loading, saving scripts.
*
* @author  fracpete (fracpete at waikato dot ac dot nz)
* @version $Revision: 5142 $
*/
public abstract class Script
  implements OptionHandler, Serializable {

  /** for serialization. */
  private static final long serialVersionUID = 5053328052680586401L;

  /**
   * The Thread for running a script.
   *
   * @author  fracpete (fracpete at waikato dot ac dot nz)
   * @version $Revision: 5142 $
   */
  public abstract static class ScriptThread
    extends Thread {
   
    /** the owning script. */
    protected Script m_Owner;
   
    /** commandline arguments. */
    protected String[] m_Args;
   
    /** whether the thread was stopped. */
    protected boolean m_Stopped;
   
    /**
     * Initializes the thread.
     *
     * @param owner  the owning script
     * @param args  the commandline arguments
     */
    public ScriptThread(Script owner, String[] args) {
      super();
     
      m_Owner = owner;
      m_Args  = args.clone();
    }

    /**
     * Returns the owner.
     *
     * @return    the owning script
     */
    public Script getOwner() {
      return m_Owner;
    }
   
    /**
     * Returns the commandline args.
     *
     * @return    the arguments
     */
    public String[] getArgs() {
      return m_Args;
    }
   
    /**
     * Performs the actual run.
     */
    protected abstract void doRun();
   
    /**
     * Executes the script.
     */
    public void run() {
      m_Stopped = false;
     
      getOwner().notifyScriptFinishedListeners(new ScriptExecutionEvent(m_Owner, Type.STARTED));
      try {
  doRun();
  if (!m_Stopped)
    getOwner().notifyScriptFinishedListeners(new ScriptExecutionEvent(m_Owner, Type.FINISHED));
      }
      catch (Exception e) {
  e.printStackTrace();
  getOwner().notifyScriptFinishedListeners(new ScriptExecutionEvent(m_Owner, Type.ERROR, e));
      }
      getOwner().m_ScriptThread = null;
    }
   
    /**
     * Stops the script execution.
     */
    public void stopScript() {
      if (isAlive()) {
  m_Stopped = true;
  try {
    stop();
  }
  catch (Exception e) {
    // ignored
  }
      }
    }
  }

  /** the backup extension. */
  public final static String BACKUP_EXTENSION = ".bak";
 
  /** the document this script is a wrapper around. */
  protected Document m_Document;
 
  /** the filename of the script. */
  protected File m_Filename;
 
  /** the newline used on this platform. */
  protected String m_NewLine;
 
  /** whether the script is modified. */
  protected boolean m_Modified;
 
  /** the current script thread. */
  protected transient ScriptThread m_ScriptThread;
 
  /** optional listeners when the script finishes. */
  protected HashSet<ScriptExecutionListener> m_FinishedListeners;
 
  /**
   * Initializes the script.
   */
  public Script() {
    this(null);
  }
 
  /**
   * Initializes the script.
   *
   * @param doc    the document to use as basis
   */
  public Script(Document doc) {
    this(doc, null);
  }
 
  /**
   * Initializes the script. Automatically loads the specified file, if not
   * null.
   *
   * @param doc    the document to use as basis
   * @param file  the file to load (if not null)
   */
  public Script(Document doc, File file) {
    initialize();
   
    m_Document = doc;
   
    if (m_Document != null) {
      m_Document.addDocumentListener(new DocumentListener() {
  public void changedUpdate(DocumentEvent e) {
    m_Modified = true;
  }
  public void insertUpdate(DocumentEvent e) {
    m_Modified = true;
  }
  public void removeUpdate(DocumentEvent e) {
    m_Modified = true;
  }
      });
    }
   
    if (file != null)
      open(file);
  }
 
  /**
   * Initializes the script.
   */
  protected void initialize() {
    m_Filename          = null;
    m_NewLine           = System.getProperty("line.separator");
    m_Modified          = false;
    m_ScriptThread      = null;
    m_FinishedListeners = new HashSet<ScriptExecutionListener>();
  }

  /**
   * Returns an enumeration describing the available options.
   *
   * @return an enumeration of all the available options
   */
  public Enumeration listOptions() {
    return new Vector().elements();
  }

  /**
   * Parses a given list of options.
   *
   * @param options   the list of options as an array of strings
   * @throws Exception   if an option is not supported
   */
  public void setOptions(String[] options) throws Exception {
  }

  /**
   * Gets the current settings of the script.
   *
   * @return     an array of strings suitable for passing to setOptions
   */
  public String[] getOptions() {
    return new String[0];
  }
 
  /**
   * Returns the extension filters for this type of script.
   *
   * @return    the filters
   */
  public abstract ExtensionFileFilter[] getFilters();
 
  /**
   * Returns the default extension. Gets automatically added to files if
   * their name doesn't end with this.
   *
   * @return    the default extension (incl. the dot)
   * @see    #saveAs(File)
   */
  public abstract String getDefaultExtension();
 
  /**
   * Returns the current filename.
   *
   * @return    the filename, null if no file loaded/saved
   */
  public File getFilename() {
    return m_Filename;
  }
 
  /**
   * Returns the new line string in use.
   *
   * @return    the new line string
   */
  public String getNewLine() {
    return m_NewLine;
  }
 
  /**
   * Returns whether the script is modified.
   *
   * @return    true if the script is modified
   */
  public boolean isModified() {
    return m_Modified;
  }
 
  /**
   * Returns the content.
   *
   * @return    the content or null in case of an error
   */
  public String getContent() {
    String  result;
   
    if (m_Document == null)
      return "";
   
    try {
      synchronized(m_Document) {
  result = m_Document.getText(0, m_Document.getLength());
      }
    }
    catch (Exception e) {
      e.printStackTrace();
      result = null;
    }
   
    return result;
  }
 
  /**
   * Sets the content.
   *
   * @param value  the new content
   */
  public void setContent(String value) {
    if (m_Document == null)
      return;
   
    try {
      m_Document.insertString(0, value, null);
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * Checks whether the extension of the file is a known one.
   *
   * @param file  the file to check
   * @return    true if the exetnsion is known
   */
  protected boolean checkExtension(File file) {
    boolean      result;
    int        i;
    int        n;
    ExtensionFileFilter[]  filters;
    String[]      exts;

    result = false;
    filters  = getFilters();
    for (i = 0; i < filters.length; i++) {
      exts = filters[i].getExtensions();
      for (n = 0; n < exts.length; n++) {
  if (file.getName().endsWith(exts[n])) {
    result = true;
    break;
  }
      }
      if (result)
  break;
    }
   
    return result;
  }
 
  /**
   * Empties the document.
   */
  public void empty() {
    if (m_Document != null) {
      try {
  m_Document.remove(0, m_Document.getLength());
      }
      catch (Exception e) {
  // ignored
      }
    }
   
    m_Modified = false;
    m_Filename = null;
  }
 
  /**
   * Tries to open the file.
   *
   * @param file  the file to open
   * @return    true if successfully read
   */
  public boolean open(File file) {
    boolean  result;
    String  content;

    if (m_Document == null)
      return true;
   
    // Warn if extension unwknown
    if (!checkExtension(file))
      System.err.println("Extension of file '" + file + "' is unknown!");
   
    try {
      // clear old content
      m_Document.remove(0, m_Document.getLength());
     
      // add new content
      content = ScriptUtils.load(file);
      if (content == null)
  throw new WekaException("Error reading content of file '" + file + "'!");
      m_Document.insertString(0, content, null);
     
      m_Modified = false;
      m_Filename = file;
      result     = true;
    }
    catch (Exception e) {
      e.printStackTrace();
      try {
  m_Document.remove(0, m_Document.getLength());
      }
      catch (Exception ex) {
  // ignored
      }
      result     = false;
      m_Filename = null;
    }
   
    return result;
  }
 
  /**
   * Saves the file under with the current filename.
   *
   * @return    true if successfully written
   */
  public boolean save() {
    if (m_Filename == null)
      return false;
    else
      return saveAs(m_Filename);
  }
 
  /**
   * Saves the file under with the given filename (and updates the internal
   * filename).
   *
   * @param file  the filename to write the content to
   * @return    true if successfully written
   */
  public boolean saveAs(File file) {
    boolean  result;
    File  backupFile;
   
    if (m_Document == null)
      return true;
   
    // correct extension?
    if (!checkExtension(file))
      file = new File(file.getPath() + getDefaultExtension());

    // backup previous file
    if (file.exists()) {
      backupFile = new File(file.getPath() + BACKUP_EXTENSION);
      try {
  ScriptUtils.copy(file, backupFile);
      }
      catch (Exception e) {
  e.printStackTrace();
      }
    }
   
    // save current content
    try {
      result     = ScriptUtils.save(file, m_Document.getText(0, m_Document.getLength()));
      m_Filename = file;
      m_Modified = false;
    }
    catch (Exception e) {
      e.printStackTrace();
      result = false;
    }
   
    return result;
  }

  /**
   * Returns whether scripts can be executed.
   *
   * @return    true if scripts can be executed
   */
  protected abstract boolean canExecuteScripts();

  /**
   * Returns a new thread to execute.
   *
   * @param args  optional commandline arguments
   * @return    the new thread object
   */
  public abstract ScriptThread newThread(String[] args);
 
  /**
   * Performs pre-execution checks:
   * <ul>
   *   <li>whether a script is currently running.</li>
   *   <li>whether script has changed and needs saving</li>
   *   <li>whether a filename is set (= empty content)</li>
   * </ul>
   * Throws exceptions if checks not met.
   *
   * @param args  optional commandline arguments
   * @throws Exception  if checks fail
   */
  protected void preCheck(String[] args) throws Exception {
    if (m_ScriptThread != null)
      throw new Exception("A script is currently running!");
    if (m_Modified)
      throw new Exception("The Script has been modified!");
    if (m_Filename == null)
      throw new Exception("The Script contains no content?");
  }
 
  /**
   * Executes the script.
   *
   * @param args  optional commandline arguments
   */
  protected void execute(String[] args) {
    m_ScriptThread = newThread(args);
    try {
      m_ScriptThread.start();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
 
  /**
   * Executes the script.
   *
   * @param args  optional commandline arguments, can be null
   * @throws Exception  if checks or execution fail
   */
  public void start(String[] args) throws Exception {
    if (args == null)
      args = new String[0];
   
    preCheck(args);
   
    execute(args);
  }
 
  /**
   * Stops the execution of the script.
   */
  public void stop() {
    if (isRunning()) {
      m_ScriptThread.stopScript();
      m_ScriptThread = null;
      notifyScriptFinishedListeners(new ScriptExecutionEvent(this, Type.STOPPED));
    }
  }
 
  /**
   * Executes the script without loading it first.
   *
   * @param file  the script to execute
   * @param args  the commandline parameters for the script
   */
  public void run(File file, String[] args) {
    Script  script;
   
    try {
      script = (Script) new SerializedObject(this).getObject();
      script.m_Filename = file;
      script.m_Modified = false;
      script.start(args);
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
 
  /**
   * Returns whether the script is still running.
   *
   * @return    true if the script is still running
   */
  public boolean isRunning() {
    return (m_ScriptThread != null);
  }
 
  /**
   * Adds the given listener to its internal list.
   *
   * @param l    the listener to add
   */
  public void addScriptFinishedListener(ScriptExecutionListener l) {
    m_FinishedListeners.add(l);
  }
 
  /**
   * Removes the given listener from its internal list.
   *
   * @param l    the listener to remove
   */
  public void removeScriptFinishedListener(ScriptExecutionListener l) {
    m_FinishedListeners.remove(l);
  }
 
  /**
   * Notifies all listeners.
   *
   * @param e    the event to send to all listeners
   */
  protected void notifyScriptFinishedListeners(ScriptExecutionEvent e) {
    Iterator<ScriptExecutionListener>  iter;
   
    iter = m_FinishedListeners.iterator();
    while (iter.hasNext())
      iter.next().scriptFinished(e);
  }
 
  /**
   * Returns the content as string.
   *
   * @return    the current content
   */
  public String toString() {
    String  result;
   
    try {
      if (m_Document == null)
  result = "";
      else
  result = m_Document.getText(0, m_Document.getLength());
    }
    catch (Exception e) {
      result = "";
    }
   
    return result.toString();
  }

  /**
   * Make up the help string giving all the command line options.
   *
   * @param script   the script to include options for
   * @return     a string detailing the valid command line options
   */
  protected static String makeOptionString(Script script) {
    StringBuffer   result;
    Enumeration   enm;
    Option     option;
   
    result = new StringBuffer("");

    result.append("\nHelp requested:\n\n");
    result.append("-h or -help\n");
    result.append("\tDisplays this help screen.\n");
    result.append("-s <file>\n");
    result.append("\tThe script to execute.\n");

    enm = script.listOptions();
    while (enm.hasMoreElements()) {
      option = (Option) enm.nextElement();
      result.append(option.synopsis() + '\n');
      result.append(option.description() + "\n");
    }

    result.append("\n");
    result.append("Any additional options are passed on to the script as\n");
    result.append("command-line parameters.\n");
    result.append("\n");
   
    return result.toString();
  }
 
  /**
   * Runs the specified script. All options that weren't "consumed" (like
   * "-s" for the script filename), will be used as commandline arguments for
   * the actual script.
   *
   * @param script  the script object to use
   * @param args  the commandline arguments
   * @throws Exception  if execution fails
   */
  public static void runScript(Script script, String[] args) throws Exception {
    String    tmpStr;
    File    scriptFile;
    Vector<String>  options;
    int      i;
   
    if (Utils.getFlag('h', args) || Utils.getFlag("help", args)) {
      System.out.println(makeOptionString(script));
    }
    else {
      // process options
      tmpStr = Utils.getOption('s', args);
      if (tmpStr.length() == 0)
        throw new WekaException("No script supplied!");
      else
  scriptFile = new File(tmpStr);
      script.setOptions(args);
     
      // remove empty elements from array
      options = new Vector<String>();
      for (i = 0; i < args.length; i++) {
  if (args[i].length() > 0)
    options.add(args[i]);
      }
     
      // run script
      script.run(scriptFile, options.toArray(new String[options.size()]));
    }
  }
}
TOP

Related Classes of weka.gui.scripting.Script

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.