package jp.vmi.selenium.selenese.config;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* OptionEntry accessor.
*/
public class OptionEntry {
@SuppressWarnings("javadoc")
public final String optionName;
@SuppressWarnings("javadoc")
public final Class<?> type;
private final Method getter;
private final Method setter;
private final Method adder;
/**
* Convert option name to capitalized property name.
*
* @param name option name such as "word-word-word".
* @return capitalized property name such as "WordWordWord".
*/
private static String propName(String name) {
StringBuilder methodName = new StringBuilder(name.length());
for (String word : name.split("-"))
methodName.append(Character.toUpperCase(word.charAt(0))).append(word.substring(1));
return methodName.toString();
}
/**
* Create OptionEntry object from bean class.
*
* @param beanClass bean class.
* @param optionName option name.
* @return OptionEntry object.
*/
public static OptionEntry newInstance(Class<?> beanClass, String optionName) {
if (optionName.toLowerCase().equals("class"))
throw new IllegalArgumentException("Invalid option name: " + optionName);
String propName = propName(optionName);
try {
Method getter;
try {
getter = beanClass.getMethod("get" + propName);
} catch (NoSuchMethodException e) {
getter = beanClass.getMethod("is" + propName);
}
Class<?> type = getter.getReturnType();
Method setter = null;
try {
setter = beanClass.getMethod("set" + propName, type);
} catch (NoSuchMethodException e) {
// no operation.
}
Method adder = null;
if (type.isArray()) {
try {
adder = beanClass.getMethod("add" + propName, type.getComponentType());
} catch (NoSuchMethodException e) {
// no operation.
}
}
return new OptionEntry(optionName, type, getter, setter, adder);
} catch (SecurityException | NoSuchMethodException e) {
throw new IllegalArgumentException("Invalid option name: " + optionName);
}
}
private OptionEntry(String optionName, Class<?> type, Method getter, Method setter, Method adder) {
this.optionName = optionName;
this.type = type;
this.getter = getter;
this.setter = setter;
this.adder = adder;
}
/**
* Get option value.
*
* @param <T> type of option value.
* @param obj object.
* @return option value.
*/
@SuppressWarnings("unchecked")
public <T> T get(Object obj) {
try {
return (T) getter.invoke(obj);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new IllegalArgumentException("Invalid option value", e);
}
}
/**
* Set option value.
*
* @param obj object.
* @param value option value.
*/
public void set(Object obj, Object value) {
if (setter == null)
throw new UnsupportedOperationException("set " + optionName);
try {
setter.invoke(obj, value);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new IllegalArgumentException(String.format("Cannot assign: (%s) %s <- (%s) %s", type, optionName, value.getClass(), value), e);
}
}
/**
* Add option value.
*
* @param obj object.
* @param value option value item.
*/
public void add(Object obj, Object value) {
if (adder == null)
throw new UnsupportedOperationException("add " + optionName);
try {
adder.invoke(obj, value);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new IllegalArgumentException(String.format("Cannot assign: %s", value), e);
}
}
}