⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 genericpropertiescreator.java

📁 MacroWeka扩展了著名数据挖掘工具weka
💻 JAVA
字号:
/*
 *    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.
 */

/*
 * GenericPropertiesCreator.java
 * Copyright (C) 2005 University of Waikato, Hamilton, New Zealand
 *
 */
package weka.gui;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Enumeration;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;

import weka.core.RTSI;
import weka.core.Utils;

/**
 * This class can generate the properties object that is normally loaded from
 * the <code>GenericObjectEditor.props</code> file (= PROPERTY_FILE). It takes
 * the <code>GenericPropertiesCreator.props</code> file as a template to
 * determine all the derived classes by checking the classes in the given
 * packages (a file with the same name in your home directory overrides the
 * the one in the weka/gui directory/package). <br>
 * E.g. if we want to have all the subclasses of the <code>Classifier</code>
 * class then we specify the superclass ("weka.classifiers.Classifier") and the
 * packages where to look for ("weka.classifiers.bayes" etc.):
 * 
 * <pre>
 * 
 *   weka.classifiers.Classifier=\
 *     weka.classifiers.bayes,\
 *     weka.classifiers.functions,\
 *     weka.classifiers.lazy,\
 *     weka.classifiers.meta,\
 *     weka.classifiers.trees,\
 *     weka.classifiers.rules
 *  
 * </pre>
 * 
 * This creates the same list as stored in the
 * <code>GenericObjectEditor.props</code> file, but it will also add
 * additional classes, that are not listed in the static list (e.g. a newly
 * developed Classifier), but still in the classpath. <br>
 * <br>
 * For discovering the subclasses the whole classpath is inspected, which means
 * that you can have several parallel directories with the same package
 * structure (e.g. a release directory and a developer directory with additional
 * classes). <br>
 * <br>
 * Code used and adapted from the following JavaWorld Tips:
 * <ul>
 *    <li><a href="http://www.javaworld.com/javaworld/javatips/jw-javatip113.html" target="_blank">Tip 113 </a>: Identify subclasses at runtime</li>
 *    <li><a href="http://www.javaworld.com/javaworld/javatips/jw-javatip105.html" target="_blank">Tip 105 </a>: Mastering the classpath with JWhich</li>
 * </ul>
 * 
 * @see #CREATOR_FILE
 * @see #PROPERTY_FILE
 * @see GenericObjectEditor
 * @see weka.core.RTSI
 * @author FracPete (fracpete at waikato dot ac dot nz)
 * @version $Revision: 1.1 $
 */
public class GenericPropertiesCreator {
  /** whether to output some debug information */
  public final static boolean VERBOSE = false;
  
  /** The name of the properties file to use as a template. Ccontains the 
   * packages in which to look for derived classes. It has the same structure
   * as the <code>PROPERTY_FILE</code>
   * @see #PROPERTY_FILE
   */
  protected static String CREATOR_FILE = "weka/gui/GenericPropertiesCreator.props";
  
  /** The name of the properties file for the static GenericObjectEditor 
   * (<code>USE_DYNAMIC</code> = <code>false</code>) 
   * @see GenericObjectEditor 
   * @see GenericObjectEditor#USE_DYNAMIC 
   */
  protected static String PROPERTY_FILE = "weka/gui/GenericObjectEditor.props";
  
  /** the input file with the packages */
  protected String inputFilename;
  
  /** the output props file for the GenericObjectEditor */
  protected String outputFilename;
  
  /** the "template" properties file with the layout and the packages */
  protected Properties inputProperties;
  
  /** the output properties file with the filled in classes */
  protected Properties outputProperties;
  
  /** whether an explicit input file was given - if false, the Utils class
   * is used to locate the props-file */
  protected boolean explicitPropsFile;
  
  /**
   * initializes the creator, locates the props file with the Utils class.
   * 
   * @throws Exception if loading of CREATOR_FILE fails
   * @see #CREATOR_FILE
   * @see Utils#readProperties(String)
   * @see #loadInputProperties()
   */
  public GenericPropertiesCreator() throws Exception {
    this(CREATOR_FILE);
    explicitPropsFile = false;
  }

  /**
   * initializes the creator, the given file overrides the props-file search
   * of the Utils class
   * 
   * @param filename the file containing the packages to create a props file from
   * @throws Exception if loading of the file fails
   * @see #CREATOR_FILE
   * @see Utils#readProperties(String)
   * @see #loadInputProperties()
   */
  public GenericPropertiesCreator(String filename) throws Exception {
    super();
    inputFilename    = filename;
    outputFilename   = PROPERTY_FILE;
    inputProperties  = null;
    outputProperties = null;
    explicitPropsFile = true;
  }

  /**
   * if FALSE, the locating of a props-file of the Utils-class is used, 
   * otherwise it's tried to load the specified file
   * @see Utils#readProperties(String)
   * @see #loadInputProperties()
   */
  public void setExplicitPropsFile(boolean value) {
    explicitPropsFile = value;
  }
  
  /**
   * returns TRUE, if a file is loaded and not the Utils class used for 
   * locating the props file.
   * @see Utils#readProperties(String)
   * @see #loadInputProperties()
   */
  public boolean getExplicitPropsFile() {
    return explicitPropsFile;
  }
  
  /**
   * returns the name of the output file
   * 
   * @return the name of the output file 
   */
  public String getOutputFilename() {
    return outputFilename;
  }
  
  /**
   * sets the file to output the properties for the GEO to
   * 
   * @param filename the filename for the output 
   */
  public void setOutputFilename(String filename) {
    outputFilename = filename;
  }

  /**
   * returns the name of the input file
   * 
   * @return the name of the input file 
   */
  public String getInputFilename() {
    return inputFilename;
  }
  
  /**
   * sets the file to get the information about the packages from. 
   * automatically sets explicitPropsFile to TRUE.
   * 
   * @param filename the filename for the input 
   * @see #setExplicitPropsFile(boolean)
   */
  public void setInputFilename(String filename) {
    inputFilename = filename;
    setExplicitPropsFile(true);
  }
  
  /**
   * returns the input properties object (template containing the packages)
   */
  public Properties getInputProperties() {
    return inputProperties;
  }
  
  /**
   * returns the output properties object (structure like the template, but
   * filled with classes instead of packages)
   */
  public Properties getOutputProperties() {
    return outputProperties;
  }
  
  /**
   * loads the property file containing the layout and the packages of 
   * the output-property-file
   * 
   * @see #inputProperties
   * @see #inputFilename
   */
  protected void loadInputProperties() throws Exception {
    if (VERBOSE)
      System.out.println("Loading '" + getInputFilename() + "'...");
    inputProperties = new Properties();
    try {
      File f = new File(getInputFilename());
      if (getExplicitPropsFile() && f.exists())
        inputProperties.load(new FileInputStream(getInputFilename()));
      else
        inputProperties = Utils.readProperties(getInputFilename());
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  /**
   * checks whether the classname is a valid one, i.e., from a public class
   *
   * @param classname   the classname to check
   * @return            whether the classname is a valid one
   */
  protected boolean isValidClassname(String classname) {
    return (classname.indexOf("$") == -1);
  }

  /**
   * Checks whether the classname is a valid one for the given key.
   * A hack that prevents, e.g., the ResultProducers to be listed in the
   * ResultListeners (even though they implement the ResultListener
   * interface, they're not supposed to be listed there).
   *
   * @param key         the property key
   * @param classname   the classname to check
   * @return            whether the classname is a valid one
   */
  protected boolean isValidClassname(String key, String classname) {
    boolean       result;
    Class         cls;

    result = true;

    // remove ResultProducers from ResultListener list
    if (key.equals(weka.experiment.ResultListener.class.getName())) {
      try {
        cls = Class.forName(classname);
        if (RTSI.hasInterface(weka.experiment.ResultProducer.class, cls))
          result = false;
      }
      catch (Exception e) {
        // we can ignore this exception
      }
    }

    return result;
  }
  
  /**
   * fills in all the classes (based on the packages in the input properties 
   * file) into the output properties file
   *     
   * @see #outputProperties
   */
  protected void generateOutputProperties() throws Exception {
    Enumeration       keys;
    String            key;
    String            value;
    String            pkg;
    StringTokenizer   tok;
    Vector            classes;
    int               i;
    
    outputProperties = new Properties();
    keys             = inputProperties.propertyNames();
    while (keys.hasMoreElements()) {
      key   = keys.nextElement().toString();
      tok   = new StringTokenizer(inputProperties.getProperty(key), ",");
      value = "";
      // get classes for all packages
      while (tok.hasMoreTokens()) {
        pkg = tok.nextToken().trim();
        
        try {
          classes = RTSI.find(pkg, Class.forName(key));
        }
        catch (Exception e) {
          System.out.println("Problem with '" + key + "': " + e);
          classes = new Vector();
        }
        
        for (i = 0; i < classes.size(); i++) {
          // skip non-public classes
          if (!isValidClassname(classes.get(i).toString()))
            continue;
          // some classes should not be listed for some keys
          if (!isValidClassname(key, classes.get(i).toString()))
            continue;
          if (!value.equals(""))
            value += ",";
          value += classes.get(i).toString();
        }
        if (VERBOSE)
          System.out.println(pkg + " -> " + value);
      }
      outputProperties.setProperty(key, value);
    }
  }
  
  /**
   * stores the generated output properties file
   * 
   * @see #outputProperties
   * @see #outputFilename 
   */
  protected void storeOutputProperties() throws Exception {
    if (VERBOSE)
      System.out.println("Saving '" + getOutputFilename() + "'...");
    outputProperties.store(
        new FileOutputStream(getOutputFilename()), 
        " Customises the list of options given by the GenericObjectEditor\n# for various superclasses.");
  }
  
  /**
   * generates the props-file for the GenericObjectEditor and stores it
   * 
   * @see #execute(boolean)
   */
  public void execute() throws Exception {
    execute(true);
  }
  
  /**
   * generates the props-file for the GenericObjectEditor and stores it only
   * if the the param <code>store</code> is TRUE. If it is FALSE then the
   * generated properties file can be retrieved via the <code>getOutputProperties</code>
   * method. 
   * 
   * @param store     if TRUE then the properties file is stored to the stored 
   *                  filename
   * @see #getOutputFilename()
   * @see #setOutputFilename(String)
   * @see #getOutputProperties()
   */
  public void execute(boolean store) throws Exception {
    // read properties file
    loadInputProperties();
    
    // generate the props file
    generateOutputProperties();
    
    // write properties file
    if (store)
      storeOutputProperties();
  }
  
  /**
   * for generating props file:
   * <ul>
   *   <li>
   *     no parameter: 
   *     see default constructor
   *   </li>
   *   <li>
   *     1 parameter (i.e., filename): 
   *     see default constructor + setOutputFilename(String)
   *   </li>
   *   <li>
   *     2 parameters (i.e, filenames): 
   *     see constructor with String argument + setOutputFilename(String)
   *   </li>
   * </ul>
   *
   * @see #GenericPropertiesCreator()
   * @see #GenericPropertiesCreator(String)
   * @see #setOutputFilename(String)
   */
  public static void main(String[] args) throws Exception {
    GenericPropertiesCreator   c = null;
    
    if (args.length == 0) {
      c = new GenericPropertiesCreator();
    }
    else if (args.length == 1) {
      c = new GenericPropertiesCreator();
      c.setOutputFilename(args[0]);
    }
    else if (args.length == 2) {
      c = new GenericPropertiesCreator(args[0]);
      c.setOutputFilename(args[1]);
    }
    else {
      System.out.println("usage: " + GenericPropertiesCreator.class.getName() + " [<input.props>] [<output.props>]");
      System.exit(1);
    }
    
    c.execute(true);
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -