All Downloads are FREE. Search and download functionalities are using the official Maven repository.

weka.gui.GenericPropertiesCreator Maven / Gradle / Ivy

Go to download

The Waikato Environment for Knowledge Analysis (WEKA), a machine learning workbench. This version represents the developer version, the "bleeding edge" of development, you could say. New functionality gets added to this version.

There is a newer version: 3.9.6
Show newest version
/*
 *   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 3 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, see .
 */

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

import weka.core.ClassDiscovery;
import weka.core.ClassDiscovery.StringCompare;
import weka.core.InheritanceUtils;
import weka.core.Utils;
import weka.core.WekaPackageClassLoaderManager;
import weka.core.WekaPackageManager;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;

/**
 * This class can generate the properties object that is normally loaded from
 * the GenericObjectEditor.props file (= PROPERTY_FILE). It takes
 * the GenericPropertiesCreator.props 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). 
* E.g. if we want to have all the subclasses of the Classifier * class then we specify the superclass ("weka.classifiers.Classifier") and the * packages where to look for ("weka.classifiers.bayes" etc.): * *
 * 
 *   weka.classifiers.Classifier=\
 *     weka.classifiers.bayes,\
 *     weka.classifiers.functions,\
 *     weka.classifiers.lazy,\
 *     weka.classifiers.meta,\
 *     weka.classifiers.trees,\
 *     weka.classifiers.rules
 * 
 * 
* * This creates the same list as stored in the * GenericObjectEditor.props 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.
*
* 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).
*
* The dynamic discovery can be turned off via the UseDyanmic * property in the props file (values: true|false). * * @see #CREATOR_FILE * @see #PROPERTY_FILE * @see #USE_DYNAMIC * @see GenericObjectEditor * @see weka.core.ClassDiscovery * @author FracPete (fracpete at waikato dot ac dot nz) * @version $Revision: 14293 $ */ public class GenericPropertiesCreator { /** whether to output some debug information */ public final static boolean VERBOSE = false; /** * name of property whether to use the dynamic approach or the old * GenericObjectEditor.props file */ public final static String USE_DYNAMIC = "UseDynamic"; /** * The name of the properties file to use as a template. Contains the packages * in which to look for derived classes. It has the same structure as the * PROPERTY_FILE * * @see #PROPERTY_FILE */ protected static String CREATOR_FILE = "weka/gui/GenericPropertiesCreator.props"; /** * The name of the properties file that lists classes/interfaces/superclasses * to exclude from being shown in the GUI. See the file for more information. */ protected static String EXCLUDE_FILE = "weka/gui/GenericPropertiesCreator.excludes"; /** the prefix for an interface exclusion */ protected static String EXCLUDE_INTERFACE = "I"; /** the prefix for an (exact) class exclusion */ protected static String EXCLUDE_CLASS = "C"; /** the prefix for a superclass exclusion */ protected static String EXCLUDE_SUPERCLASS = "S"; /** * The name of the properties file for the static GenericObjectEditor ( * USE_DYNAMIC = false) * * @see GenericObjectEditor * @see #USE_DYNAMIC */ protected static String PROPERTY_FILE = "weka/gui/GenericObjectEditor.props"; /** the input file with the packages */ protected String m_InputFilename; /** the output props file for the GenericObjectEditor */ protected String m_OutputFilename; /** the "template" properties file with the layout and the packages */ protected Properties m_InputProperties; /** the output properties file with the filled in classes */ protected Properties m_OutputProperties; /** Globally available properties */ protected static GenericPropertiesCreator GLOBAL_CREATOR; protected static Properties GLOBAL_INPUT_PROPERTIES; protected static Properties GLOBAL_OUTPUT_PROPERTIES; /** * whether an explicit input file was given - if false, the Utils class is * used to locate the props-file */ protected boolean m_ExplicitPropsFile; /** * the hashtable that stores the excludes: key -> Hashtable(prefix -> * Vector of classnames) */ protected Hashtable>> m_Excludes; static { try { GenericPropertiesCreator creator = new GenericPropertiesCreator(); GLOBAL_CREATOR = creator; if (creator.useDynamic() && !WekaPackageManager.m_initialPackageLoadingInProcess) { creator.execute(false, true); GLOBAL_INPUT_PROPERTIES = creator.getInputProperties(); GLOBAL_OUTPUT_PROPERTIES = creator.getOutputProperties(); } else { // Read the static information from the GenericObjectEditor.props GLOBAL_OUTPUT_PROPERTIES = Utils .readProperties("weka/gui/GenericObjectEditor.props"); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * Get the global output properties * * @return the global output properties */ public static Properties getGlobalOutputProperties() { return GLOBAL_OUTPUT_PROPERTIES; } /** * Get the global input properties * * @return the global input properties */ public static Properties getGlobalInputProperties() { return GLOBAL_INPUT_PROPERTIES; } /** * Regenerate the global output properties. Does not load the input * properties, instead uses the GLOBAL_INPUT_PROPERTIES */ public static void regenerateGlobalOutputProperties() { if (GLOBAL_CREATOR != null) { try { GLOBAL_CREATOR.execute(false, false); GLOBAL_INPUT_PROPERTIES = GLOBAL_CREATOR.getInputProperties(); GLOBAL_OUTPUT_PROPERTIES = GLOBAL_CREATOR.getOutputProperties(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 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); m_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(); m_InputFilename = filename; m_OutputFilename = PROPERTY_FILE; m_InputProperties = null; m_OutputProperties = null; m_ExplicitPropsFile = true; m_Excludes = new Hashtable>>(); } /** * if FALSE, the locating of a props-file of the Utils-class is used, * otherwise it's tried to load the specified file * * @param value if true the specified file will be loaded not via the * Utils-class * @see Utils#readProperties(String) * @see #loadInputProperties() */ public void setExplicitPropsFile(boolean value) { m_ExplicitPropsFile = value; } /** * returns TRUE, if a file is loaded and not the Utils class used for locating * the props file. * * @return true if the specified file is used and not the one found by the * Utils class * @see Utils#readProperties(String) * @see #loadInputProperties() */ public boolean getExplicitPropsFile() { return m_ExplicitPropsFile; } /** * returns the name of the output file * * @return the name of the output file */ public String getOutputFilename() { return m_OutputFilename; } /** * sets the file to output the properties for the GEO to * * @param filename the filename for the output */ public void setOutputFilename(String filename) { m_OutputFilename = filename; } /** * returns the name of the input file * * @return the name of the input file */ public String getInputFilename() { return m_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) { m_InputFilename = filename; setExplicitPropsFile(true); } /** * returns the input properties object (template containing the packages) * * @return the input properties (the template) */ public Properties getInputProperties() { return m_InputProperties; } /** * returns the output properties object (structure like the template, but * filled with classes instead of packages) * * @return the output properties (filled with classes) */ public Properties getOutputProperties() { return m_OutputProperties; } /** * loads the property file containing the layout and the packages of the * output-property-file. The exlcude property file is also read here. * * @see #m_InputProperties * @see #m_InputFilename */ protected void loadInputProperties() { if (VERBOSE) { System.out.println("Loading '" + getInputFilename() + "'..."); } m_InputProperties = new Properties(); try { File f = new File(getInputFilename()); if (getExplicitPropsFile() && f.exists()) { m_InputProperties.load(new FileInputStream(getInputFilename())); } else { m_InputProperties = Utils.readProperties(getInputFilename()); } // excludes m_Excludes.clear(); Properties p = Utils.readProperties(EXCLUDE_FILE); Enumeration enm = p.propertyNames(); while (enm.hasMoreElements()) { String name = enm.nextElement().toString(); // new Hashtable for key Hashtable> t = new Hashtable>(); m_Excludes.put(name, t); t.put(EXCLUDE_INTERFACE, new Vector()); t.put(EXCLUDE_CLASS, new Vector()); t.put(EXCLUDE_SUPERCLASS, new Vector()); // process entries StringTokenizer tok = new StringTokenizer(p.getProperty(name), ","); while (tok.hasMoreTokens()) { String item = tok.nextToken(); // get list Vector list = new Vector(); if (item.startsWith(EXCLUDE_INTERFACE + ":")) { list = t.get(EXCLUDE_INTERFACE); } else if (item.startsWith(EXCLUDE_CLASS + ":")) { list = t.get(EXCLUDE_CLASS); } else if (item.startsWith(EXCLUDE_SUPERCLASS)) { list = t.get(EXCLUDE_SUPERCLASS); } // add to list list.add(item.substring(item.indexOf(":") + 1)); } } } catch (Exception e) { e.printStackTrace(); } } /** * gets whether the dynamic approach should be used or not * * @return true if the dynamic approach is to be used */ public boolean useDynamic() { if (getInputProperties() == null) { loadInputProperties(); } // check our classloader against the system one - if different then // return false (as dynamic classloading only works for classes discoverable // in the system classpath /* * if * (!ClassLoader.getSystemClassLoader().equals(this.getClass().getClassLoader * ())) { if * (Boolean.parseBoolean(getInputProperties().getProperty(USE_DYNAMIC, * "true")) == true) { System.out.println( * "[GenericPropertiesCreator] classloader in use is not the system " + * "classloader: using static entries in weka/gui/GenericObjectEditor.props rather " * + "than dynamic class discovery."); } return false; } */ return Boolean.parseBoolean(getInputProperties().getProperty(USE_DYNAMIC, "true")); } /** * 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. This is * based on the settings in the Exclude file. * * @param key the property key * @param classname the classname to check * @return whether the classname is a valid one * @see #EXCLUDE_FILE */ protected boolean isValidClassname(String key, String classname) { boolean result; Class cls; Class clsCurrent; Vector list; int i; result = true; try { clsCurrent = WekaPackageClassLoaderManager.forName(classname); // check for GPCIgnore for (Annotation a : clsCurrent.getAnnotations()) { if (a instanceof GPCIgnore) { return false; } } } catch (Exception ex) { clsCurrent = null; } // are there excludes for this key? if (m_Excludes.containsKey(key)) { // interface if ((clsCurrent != null) && result) { list = m_Excludes.get(key).get(EXCLUDE_INTERFACE); for (i = 0; i < list.size(); i++) { try { cls = WekaPackageClassLoaderManager.forName(list.get(i).toString()); if (InheritanceUtils.hasInterface(cls, clsCurrent)) { result = false; break; } } catch (Exception e) { // we ignore this Exception } } } // superclass if ((clsCurrent != null) && result) { list = m_Excludes.get(key).get(EXCLUDE_SUPERCLASS); for (i = 0; i < list.size(); i++) { try { cls = WekaPackageClassLoaderManager.forName(list.get(i).toString()); if (InheritanceUtils.isSubclass(cls, clsCurrent)) { result = false; break; } } catch (Exception e) { // we ignore this Exception } } } // class if ((clsCurrent != null) && result) { list = m_Excludes.get(key).get(EXCLUDE_CLASS); for (i = 0; i < list.size(); i++) { try { cls = WekaPackageClassLoaderManager.forName(list.get(i).toString()); if (cls.getName().equals(clsCurrent.getName())) { result = false; } } catch (Exception e) { // we ignore this Exception } } } } return result; } /** * fills in all the classes (based on the packages in the input properties * file) into the output properties file * * @throws Exception if something goes wrong * @see #m_OutputProperties */ protected void generateOutputProperties() throws Exception { Enumeration keys; String key; String value; String pkg; StringTokenizer tok; Vector classes; HashSet names; int i; m_OutputProperties = new Properties(); keys = m_InputProperties.propertyNames(); while (keys.hasMoreElements()) { key = keys.nextElement().toString(); if (key.equals(USE_DYNAMIC)) { continue; } tok = new StringTokenizer(m_InputProperties.getProperty(key), ","); names = new HashSet(); // get classes for all packages while (tok.hasMoreTokens()) { pkg = tok.nextToken().trim(); try { classes = ClassDiscovery.find(WekaPackageClassLoaderManager.forName(key), pkg); } 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; } names.add(classes.get(i)); } } // generate list value = ""; classes = new Vector(); classes.addAll(names); Collections.sort(classes, new StringCompare()); for (i = 0; i < classes.size(); i++) { if (!value.equals("")) { value += ","; } value += classes.get(i).toString(); } if (VERBOSE) { System.out.println(pkg + " -> " + value); } // set value m_OutputProperties.setProperty(key, value); } } /** * stores the generated output properties file * * @throws Exception if the saving fails * @see #m_OutputProperties * @see #m_OutputFilename */ protected void storeOutputProperties() throws Exception { if (VERBOSE) { System.out.println("Saving '" + getOutputFilename() + "'..."); } m_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 * * @throws Exception if something goes wrong * @see #execute(boolean) */ public void execute() throws Exception { execute(true, true); } /** * generates the props-file for the GenericObjectEditor * * @param store true if the generated props should be stored * @throws Exception */ public void execute(boolean store) throws Exception { execute(store, true); } /** * generates the props-file for the GenericObjectEditor and stores it only if * the the param store is TRUE. If it is FALSE then the generated * properties file can be retrieved via the getOutputProperties * method. * * @param store if TRUE then the properties file is stored to the stored * filename * @param loadInputProps true if the input properties should be loaded * @throws Exception if something goes wrong * @see #getOutputFilename() * @see #setOutputFilename(String) * @see #getOutputProperties() */ public void execute(boolean store, boolean loadInputProps) throws Exception { // read properties file if (loadInputProps) { loadInputProperties(); } // generate the props file generateOutputProperties(); // write properties file if (store) { storeOutputProperties(); } } /** * for generating props file: *
    *
  • * no parameter: see default constructor
  • *
  • * 1 parameter (i.e., filename): see default constructor + * setOutputFilename(String)
  • *
  • * 2 parameters (i.e, filenames): see constructor with String argument + * setOutputFilename(String)
  • *
* * @param args the commandline arguments * @throws Exception if something goes wrong * @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() + " [] []"); System.exit(1); } c.execute(true); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy