package org.caudexorigo.cli;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
class ArgumentPresenterImpl<O> implements ArgumentPresenter<O>
{
private final OptionsSpecification<O> m_specification;
private final Class<O> m_klass;
public ArgumentPresenterImpl(final Class<O> klass, final OptionsSpecification<O> specification)
{
m_specification = specification;
m_klass = klass;
}
/**
* @inheritdoc
*/
@SuppressWarnings("unchecked")
public O presentArguments(final TypedArguments arguments)
{
final O result = (O) Proxy.newProxyInstance(m_klass.getClassLoader(), new Class[] { m_klass }, new InvocationHandler()
{
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable
{
if (args != null && args.length != 0)
{
throw new UnsupportedOperationException(String.format("Method (%s) with arguments not supported for reading argument values", method.toGenericString()));
}
else if (method.isAnnotationPresent(Unparsed.class))
{
return arguments.getUnparsedValue();
}
else if (!m_specification.isSpecified(method))
{
throw new UnsupportedOperationException(String.format("Method (%s) is not annotated for option specification", method.toGenericString()));
}
final OptionSpecification specification = m_specification.getSpecification(method);
if (m_specification.isExistenceChecker(method) || !specification.hasValue())
{
return optionPresent(arguments, specification);
}
return getValue(arguments, method, specification);
}
private Object optionPresent(final TypedArguments arguments, final ArgumentSpecification specification)
{
return arguments.contains(specification);
}
private Object getValue(final TypedArguments arguments, final Method method, final ArgumentSpecification specification) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException
{
final Object value = arguments.getValue(specification);
if (value == null)
{
throw new OptionNotPresentException(specification);
}
return value;
}
});
return result;
}
}