Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
weka.core.Option 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.
/*
* 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 .
*/
/*
* Option.java
* Copyright (C) 1999-2012 University of Waikato, Hamilton, New Zealand
*
*/
package weka.core;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
/**
* Class to store information about an option.
*
*
* Typical usage:
*
*
* Option myOption = new Option("Uses extended mode.", "E", 0, "-E"));
*
*
* @author Eibe Frank ([email protected] )
* @version $Revision: 15700 $
*/
public class Option implements RevisionHandler {
/** A cache of property descriptors */
private static final Map, PropertyDescriptor[]> s_descriptorCache =
new HashMap, PropertyDescriptor[]>();
/** What does this option do? */
private String m_Description;
/** The synopsis. */
private String m_Synopsis;
/** What's the option's name? */
private String m_Name;
/** How many arguments does it take? */
private int m_NumArguments;
/**
* Creates new option with the given parameters.
*
* @param description the option's description
* @param name the option's name
* @param numArguments the number of arguments
* @param synopsis the option's synopsis
*/
public Option(String description, String name, int numArguments,
String synopsis) {
m_Description = description;
m_Name = name;
m_NumArguments = numArguments;
m_Synopsis = synopsis;
}
/**
* Get a list of options for a class. Options identified by this method are
* bean properties (with get/set methods) annotated using the OptionMetadata
* annotation. All options from the class up to, but not including, the
* supplied oldest superclass are returned.
*
*
* @param childClazz the class to get options for
* @param oldestAncestorClazz the oldest superclass (inclusive) at which to
* stop getting options from
* @return a list of options
*/
public static Vector listOptionsForClassHierarchy(
Class> childClazz, Class> oldestAncestorClazz) {
Vector results = listOptionsForClass(childClazz);
Class> parent = childClazz;
do {
parent = parent.getSuperclass();
if (parent == null) {
break;
}
results.addAll(listOptionsForClass(parent));
} while (!parent.equals(oldestAncestorClazz));
return results;
}
/**
* Adds all methods from the supplied class to the supplied list of methods.
*
* @param clazz the class to get methods from
* @param methList the list to add them to
*/
protected static void addMethodsToList(Class> clazz, List methList) {
Method[] methods = clazz.getDeclaredMethods();
for (Method m : methods) {
methList.add(m);
}
}
/**
* Gets a list of options for the supplied class. Only examines immediate
* methods in the class (does not consider superclasses). Options identified
* by this method are bean properties (with get/set methods) annotated using
* the OptionMetadata annotation.
*
* @param clazz the class to examine for options
* @return a list of options
*/
public static Vector listOptionsForClass(Class> clazz) {
Vector results = new Vector ();
List allMethods = new ArrayList();
addMethodsToList(clazz, allMethods);
Class>[] interfaces = clazz.getInterfaces();
for (Class c : interfaces) {
addMethodsToList(c, allMethods);
}
Option[] unsorted = new Option[allMethods.size()];
int[] opOrder = new int[allMethods.size()];
for (int i = 0; i < opOrder.length; i++) {
opOrder[i] = Integer.MAX_VALUE;
}
int index = 0;
for (Method m : allMethods) {
OptionMetadata o = m.getAnnotation(OptionMetadata.class);
if (o != null) {
if (o.commandLineParamName().length() > 0) {
opOrder[index] = o.displayOrder();
String description = o.description();
if (!description.startsWith("\t")) {
description = "\t" + description;
}
description = description.replace("\n", "\n\t");
String name = o.commandLineParamName();
if (name.startsWith("-")) {
name = name.substring(1, name.length());
}
String synopsis = o.commandLineParamSynopsis();
if (!synopsis.startsWith("-")) {
synopsis = "-" + synopsis;
}
int numParams = o.commandLineParamIsFlag() ? 0 : 1;
Option option = new Option(description, name, numParams, synopsis);
unsorted[index] = option;
index++;
}
}
}
int[] sortedOpts = Utils.sort(opOrder);
for (int i = 0; i < opOrder.length; i++) {
if (opOrder[i] < Integer.MAX_VALUE) {
results.add(unsorted[sortedOpts[i]]);
}
}
return results;
}
/**
* Get the settings of the supplied object. Settings identified by this method
* are bean properties (with get/set methods) annotated using the
* OptionMetadata annotation. All options from the class up to, but not
* including, the supplied oldest superclass are returned.
*
* @param target the target object to get settings for
* @param oldestAncestorClazz the oldest superclass at which to stop getting
* options from
* @return
*/
public static String[] getOptionsForHierarchy(Object target,
Class> oldestAncestorClazz) {
ArrayList options = new ArrayList();
for (String s : getOptions(target, target.getClass())) {
options.add(s);
}
Class> parent = target.getClass();
do {
parent = parent.getSuperclass();
if (parent == null) {
break;
}
for (String s : getOptions(target, parent)) {
options.add(s);
}
} while (!parent.equals(oldestAncestorClazz));
return options.toArray(new String[options.size()]);
}
/**
* Get the settings of the supplied object. Settings identified by this method
* are bean properties (with get/set methods) annotated using the
* OptionMetadata annotation. Options belonging to the targetClazz (either the
* class of the target or one of its superclasses) are returned.
*
* @param target the target to extract settings from
* @param targetClazz the class to consider for obtaining settings - i.e.
* annotated methods from this class will have their values
* extracted. This class is expected to be either the class of the
* target or one of its superclasses
* @return an array of settings
*/
public static String[] getOptions(Object target, Class> targetClazz) {
ArrayList options = new ArrayList();
try {
Object[] args = {};
Class> parent = targetClazz.getSuperclass();
PropertyDescriptor[] properties =
getPropertyDescriptors(targetClazz, parent);
for (PropertyDescriptor p : properties) {
Method getter = p.getReadMethod();
Method setter = p.getWriteMethod();
if (getter == null || setter == null) {
continue;
}
OptionMetadata parameterDescription = null;
parameterDescription = getter.getAnnotation(OptionMetadata.class);
if (parameterDescription == null) {
parameterDescription = setter.getAnnotation(OptionMetadata.class);
}
if (parameterDescription != null
&& parameterDescription.commandLineParamName().length() > 0) {
Object value = getter.invoke(target, args);
if (value != null) {
if (!parameterDescription.commandLineParamIsFlag()) {
options.add("-" + parameterDescription.commandLineParamName());
}
if (value.getClass().isArray()) {
if (parameterDescription.commandLineParamIsFlag()) {
throw new IllegalArgumentException(
"Getter method for a command "
+ "line flag should return a boolean value");
}
if (((Object[]) value).length == 0) {
// remove the initial option identifier (added above)
// as the array is empty
options.remove(options.size() - 1);
}
int index = 0;
for (Object element : (Object[]) value) {
if (index > 0) {
options
.add("-" + parameterDescription.commandLineParamName());
}
if (element instanceof OptionHandler) {
options
.add(getOptionStringForOptionHandler((OptionHandler) element));
} else {
options.add(element.toString());
}
index++;
}
} else if (value instanceof OptionHandler) {
if (parameterDescription.commandLineParamIsFlag()) {
throw new IllegalArgumentException(
"Getter method for a command "
+ "line flag should return a boolean value");
}
options
.add(getOptionStringForOptionHandler((OptionHandler) value));
} else if (value instanceof SelectedTag) {
options.add(""
+ ((SelectedTag) value).getSelectedTag().getReadable());
} else {
// check for boolean/flag
if (parameterDescription.commandLineParamIsFlag()) {
if (!(value instanceof Boolean)) {
throw new IllegalArgumentException(
"Getter method for a command "
+ "line flag should return a boolean value");
}
if (((Boolean) value).booleanValue()) {
options
.add("-" + parameterDescription.commandLineParamName());
}
} else {
if (value.toString().length() > 0) {
options.add(value.toString());
} else {
// don't allow empty strings
options.remove(options.size() - 1);
}
}
}
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return options.toArray(new String[options.size()]);
}
/**
* Construct a String containing the class name of an OptionHandler and its
* option settings
*
* @param handler the OptionHandler to construct an option string for
* @return a String containing the name of the handler class and its options
*/
protected static String
getOptionStringForOptionHandler(OptionHandler handler) {
String optHandlerClassName = handler.getClass().getCanonicalName();
String optsVal = Utils.joinOptions(handler.getOptions());
String totalOptVal = optHandlerClassName + " " + optsVal;
return totalOptVal;
}
/**
* Sets options on the target object. Settings identified by this method are
* bean properties (with get/set methods) annotated using the OptionMetadata
* annotation. All options from the class up to, but not including, the
* supplied oldest superclass are processed in order.
*
* @param options the options to set
* @param target the target on which to set options
* @param oldestAncestorClazz the oldest superclass at which to stop setting
* options
*/
public static void setOptionsForHierarchy(String[] options, Object target,
Class> oldestAncestorClazz) {
setOptions(options, target, target.getClass());
Class> parent = target.getClass();
do {
parent = parent.getSuperclass();
if (parent == null) {
break;
}
setOptions(options, target, parent);
} while (!parent.equals(oldestAncestorClazz));
}
/**
* Get property descriptors for a target class. Checks a cache first before
* using introspection.
*
* @param targetClazz the target to get the descriptors for
* @param parent the parent class at which to stop getting descriptors
* @return an array of property descriptors
* @throws IntrospectionException if a problem occurs
*/
private static PropertyDescriptor[] getPropertyDescriptors(
Class> targetClazz, Class> parent) throws IntrospectionException {
PropertyDescriptor[] result = s_descriptorCache.get(targetClazz);
if (result == null) {
BeanInfo bi = Introspector.getBeanInfo(targetClazz, parent);
result = bi.getPropertyDescriptors();
s_descriptorCache.put(targetClazz, result);
}
return result;
}
/**
* Sets options on the target object. Settings identified by this method are
* bean properties (with get/set methods) annotated using the OptionMetadata
* annotation. Options from just the supplied targetClazz (which is expected
* to be either the class of the target or one of its superclasses) are set.
*
* @param options the options to set
* @param target the target on which to set options
* @param targetClazz the class containing options to be be set - i.e.
* annotated option methods in this class will have their values set.
* This class is expected to be either the class of the target or one
* of its superclasses
*/
public static void setOptions(String[] options, Object target,
Class> targetClazz) {
if (options != null && options.length > 0) {
// Set the options just for this class
try {
Object[] getterArgs = {};
Class> parent = targetClazz.getSuperclass();
PropertyDescriptor[] properties =
getPropertyDescriptors(targetClazz, parent);
for (PropertyDescriptor p : properties) {
Method getter = p.getReadMethod();
Method setter = p.getWriteMethod();
if (getter == null || setter == null) {
continue;
}
OptionMetadata parameterDescription = null;
parameterDescription = getter.getAnnotation(OptionMetadata.class);
if (parameterDescription == null) {
parameterDescription = setter.getAnnotation(OptionMetadata.class);
}
if (parameterDescription != null
&& parameterDescription.commandLineParamName().length() > 0) {
boolean processOpt = false;
String optionValue = "";
Object valueToSet = null;
if (parameterDescription.commandLineParamIsFlag()) {
processOpt = true;
valueToSet =
(Utils.getFlag(parameterDescription.commandLineParamName(),
options));
} else {
optionValue =
Utils.getOption(parameterDescription.commandLineParamName(),
options);
processOpt = optionValue.length() > 0;
}
// grab the default/current return value so that we can determine
// the type
Object value = getter.invoke(target, getterArgs);
if (value != null && processOpt) {
if (value.getClass().isArray() && ((Object[]) value).length >= 0) {
// We're interested in the actual element type...
Class> elementType =
getter.getReturnType().getComponentType();
// handle arrays by looking for the option multiple times
List optionValues = new ArrayList();
optionValues.add(optionValue);
while (true) {
optionValue =
Utils.getOption(
parameterDescription.commandLineParamName(), options);
if (optionValue.length() == 0) {
break;
}
optionValues.add(optionValue);
}
valueToSet =
Array.newInstance(elementType, optionValues.size());
for (int i = 0; i < optionValues.size(); i++) {
Object elementObject = null;
if (elementType.isAssignableFrom(File.class)) {
elementObject = new File(optionValues.get(i));
} else if (elementType.isAssignableFrom(Enum.class)) {
elementObject = EnumHelper.valueFromString(elementType, optionValues.get(i));
} else if (elementType.isAssignableFrom(Number.class)) {
try {
if (elementType.isAssignableFrom(Integer.class)) {
elementObject = new Integer(optionValues.get(i));
} else if (elementType.isAssignableFrom(Long.class)) {
elementObject = new Long(optionValues.get(i));
} else if (elementType.isAssignableFrom(Double.class)) {
elementObject = new Double(optionValues.get(i));
} else if (elementType.isAssignableFrom(Float.class)) {
elementObject = new Float(optionValues.get(i));
}
} catch (NumberFormatException e) {
throw new Exception("Option: '"
+ parameterDescription.commandLineParamName()
+ "' requires elements of " + value.getClass().getCanonicalName());
}
} else if (elementType.isAssignableFrom(SelectedTag.class)) {
SelectedTag reference = (SelectedTag)((Object[]) value)[0];
Tag[] legalTags = reference.getTags();
int tagIndex = Integer.MAX_VALUE;
// first try and parse as an integer
try {
int specifiedID = Integer.parseInt(optionValues.get(i));
for (int z = 0; z < legalTags.length; z++) {
if (legalTags[z].getID() == specifiedID) {
tagIndex = z;
break;
}
}
} catch (NumberFormatException e) {
// try to match tag strings
for (int z = 0; z < legalTags.length; z++) {
if (legalTags[z].getReadable().equals(optionValues.get(i).trim())) {
tagIndex = z;
break;
}
}
}
if (tagIndex != Integer.MAX_VALUE) {
elementObject = new SelectedTag(tagIndex, legalTags);
} else {
throw new Exception("Unable to set option: '"
+ parameterDescription.commandLineParamName()
+ "'. This option takes a SelectedTag argument, and "
+ "the supplied value of '" + optionValues.get(i) + "' "
+ "does not match any of the legal IDs or strings "
+ "for it.");
}
} else if (elementType.isAssignableFrom(String.class)) {
elementObject = optionValues.get(i);
} else {
// assume option handler spec
elementObject =
constructOptionHandlerValue(optionValues.get(i));
}
Array.set(valueToSet, i, elementObject);
}
} else if (value instanceof SelectedTag) {
Tag[] legalTags = ((SelectedTag) value).getTags();
int tagIndex = Integer.MAX_VALUE;
// first try and parse as an integer
try {
int specifiedID = Integer.parseInt(optionValue);
for (int z = 0; z < legalTags.length; z++) {
if (legalTags[z].getID() == specifiedID) {
tagIndex = z;
break;
}
}
} catch (NumberFormatException e) {
// try to match tag strings
for (int z = 0; z < legalTags.length; z++) {
if (legalTags[z].getReadable().equals(optionValue.trim())) {
tagIndex = z;
break;
}
}
}
if (tagIndex != Integer.MAX_VALUE) {
valueToSet = new SelectedTag(tagIndex, legalTags);
} else {
throw new Exception("Unable to set option: '"
+ parameterDescription.commandLineParamName()
+ "'. This option takes a SelectedTag argument, and "
+ "the supplied value of '" + optionValue + "' "
+ "does not match any of the legal IDs or strings "
+ "for it.");
}
} else if (value instanceof Enum) {
Class> eClazz = value.getClass();
valueToSet = EnumHelper.valueFromString(eClazz, optionValue);
} else if (value instanceof OptionHandler) {
valueToSet = constructOptionHandlerValue(optionValue);
} else if (value instanceof Number) {
try {
if (value instanceof Integer) {
valueToSet = new Integer(optionValue);
} else if (value instanceof Long) {
valueToSet = new Long(optionValue);
} else if (value instanceof Double) {
valueToSet = new Double(optionValue);
} else if (value instanceof Float) {
valueToSet = new Float(optionValue);
}
} catch (NumberFormatException e) {
throw new Exception("Option: '"
+ parameterDescription.commandLineParamName()
+ "' requires a " + value.getClass().getCanonicalName()
+ " argument");
}
} else if (value instanceof String) {
valueToSet = optionValue;
} else if (value instanceof File) {
valueToSet = new File(optionValue);
}
if (valueToSet != null) {
// set it!
// System.err.println("Setter: " + setter.getName());
// System.err.println("Argument: " +
// valueToSet.getClass().getCanonicalName());
setOption(setter, target, valueToSet);
}
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
/**
* Construct an instance of an option handler from a String specifying its
* class name and option values
*
* @param optionValue a String containing the class of the option handler
* followed by its options
* @return an instantiated option handling object
* @throws Exception if a problem occurs
*/
protected static Object constructOptionHandlerValue(String optionValue)
throws Exception {
String[] optHandlerSpec = Utils.splitOptions(optionValue);
if (optHandlerSpec.length == 0) {
throw new Exception("Invalid option handler specification " + "string '"
+ optionValue);
}
String optionHandler = optHandlerSpec[0];
optHandlerSpec[0] = "";
Object handler = Utils.forName(null, optionHandler, optHandlerSpec);
return handler;
}
/**
* Removes an option from a given list of options.
*
* @param list the list to reduce
* @param name the name of the option
*/
public static void deleteOption(List list, String name) {
for (Iterator iter = list.listIterator(); iter.hasNext();) {
Option a = iter.next();
if (a.name().equals(name)) {
iter.remove();
}
}
}
/**
* Removes an option from a given list of strings that specifies options. This
* method is for an option that has a parameter value.
*
* @param list the list to reduce
* @param name the name of the option (including hyphen)
*/
public static void deleteOptionString(List list, String name) {
for (Iterator iter = list.listIterator(); iter.hasNext();) {
String a = iter.next();
if (a.equals(name)) {
iter.remove();
iter.next();
iter.remove();
}
}
}
/**
* Removes an option from a given list of strings that specifies options. This
* method is for an option without a parameter value (i.e., a flag).
*
* @param list the list to reduce
* @param name the name of the option (including hyphen)
*/
public static void deleteFlagString(List list, String name) {
for (Iterator iter = list.listIterator(); iter.hasNext();) {
String a = iter.next();
if (a.equals(name)) {
iter.remove();
}
}
}
/**
* Set an option value on a target object
*
* @param setter the Method object for the setter method of the option to set
* @param target the target object on which to set the option
* @param valueToSet the value of the option to set
* @throws InvocationTargetException if a problem occurs
* @throws IllegalAccessException if a problem occurs
*/
protected static void setOption(Method setter, Object target,
Object valueToSet) throws InvocationTargetException, IllegalAccessException {
Object[] setterArgs = { valueToSet };
setter.invoke(target, setterArgs);
}
/**
* Returns the option's description.
*
* @return the option's description
*/
public String description() {
return m_Description;
}
/**
* Returns the option's name.
*
* @return the option's name
*/
public String name() {
return m_Name;
}
/**
* Returns the option's number of arguments.
*
* @return the option's number of arguments
*/
public int numArguments() {
return m_NumArguments;
}
/**
* Returns the option's synopsis.
*
* @return the option's synopsis
*/
public String synopsis() {
return m_Synopsis;
}
/**
* Returns the revision string.
*
* @return the revision
*/
public String getRevision() {
return RevisionUtils.extract("$Revision: 15700 $");
}
}