package org.caudexorigo.cli; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.logging.Logger; class ArgumentSpecificationImpl { private static final Logger g_logger = Logger.getLogger(ArgumentSpecificationImpl.class.getName()); private final Class<?> m_type; private final Method m_method; private final boolean m_multiValued; private final String m_baseName; private final Method m_optionalityMethod; public ArgumentSpecificationImpl(final Method method, final Class<?> klass) { m_method = method; final Type returnType = method.getGenericReturnType(); m_type = (Class<?>) (isList(method.getReturnType()) ? getListType(returnType) : returnType); m_multiValued = isList(method.getReturnType()); m_baseName = extractBaseMethodName(method); m_optionalityMethod = findCorrespondingOptionalityMethod(m_baseName, klass); } /** * @inheritdoc */ public final String getName() { return m_baseName; } /** * {@inheritDoc} */ public final Class<?> getType() { return m_type; } /** * {@inheritDoc} */ public final boolean isMultiValued() { return m_multiValued; } /** * {@inheritDoc} */ public final Method getMethod() { return m_method; } /** * @inheritdoc */ public boolean isOptional() { return m_optionalityMethod != null || !hasValue(); } public Method getOptionalityMethod() { return m_optionalityMethod; } /** * @inheritdoc */ public boolean hasValue() { return !isBoolean(getType()); } private final boolean isList(final Class<?> klass) { return klass.isAssignableFrom(List.class); } private final Class<?> getListType(final Type genericReturnType) { if (genericReturnType instanceof ParameterizedType) { return (Class<?>) ((ParameterizedType) genericReturnType).getActualTypeArguments()[0]; } else { g_logger.finer("Found raw List type; assuming List<String>."); return String.class; } } private final Method findCorrespondingOptionalityMethod(final String name, Class<?> klass) { try { final Method method = klass.getMethod(addPrefix("is", name), new Class[] {}); if (isBoolean(method.getReturnType())) { return method; } return null; } catch (final NoSuchMethodException e) { return null; } } private final boolean isBoolean(final Class<?> type) { return (type.isAssignableFrom(Boolean.class) || type.isAssignableFrom(boolean.class)); } private final String stripPrefix(final String methodName, final String prefix) { if (methodName.length() > prefix.length() && methodName.startsWith(prefix)) { return methodName.substring(prefix.length(), prefix.length() + 1).toLowerCase() + ((methodName.length() > prefix.length() + 1) ? methodName.substring(prefix.length() + 1) : ""); } return methodName; } private String addPrefix(final String prefix, final String name) { return prefix + name.substring(0, 1).toUpperCase() + name.substring(1); } private String extractBaseMethodName(final Method method) { final String methodName = method.getName(); final String isPrefix = "is"; if (isBoolean(method.getReturnType()) && methodName.startsWith(isPrefix)) { return stripPrefix(methodName, isPrefix); } return stripPrefix(methodName, "get"); } }