/*
* Created on Oct 11, 2011
* Copyright 2010 by Eduard Weissmann (edi.weissmann@gmail.com).
*
* This file is part of the Sejda source code
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sejda.cli;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.sejda.cli.command.TestableTask;
import org.sejda.model.exception.SejdaRuntimeException;
import com.lexicalscope.jewel.cli.Option;
/**
*
* Test verifying that short names are not repeated for each task cli interface
*
* @author Eduard Weissmann
*
*/
public class OptionDecriptionAndShortNameTest extends AcrossAllTasksTraitTest {
public OptionDecriptionAndShortNameTest(TestableTask testableTask) {
super(testableTask);
}
@Test
public void descriptionsHaveOptionalityInformation() {
for (MethodAndOption eachMethod : extractOptionAnnotations()) {
String description = eachMethod.getOption().description();
boolean hasOptionalityInfo = StringUtils.endsWith(description, "(optional)")
|| StringUtils.endsWith(description, "(required)");
if (!hasOptionalityInfo) {
throw new SejdaRuntimeException(
getTaskName() + " is missing optionality information [(optional) or (required)] on "
+ eachMethod.getMethodName());
}
}
}
@Test
public void shortNamesAreMandatory() {
for (MethodAndOption eachMethod : extractOptionAnnotations()) {
if (eachMethod.getNonBlankShortNames().isEmpty() && eachMethod.isNotBooleanFlag()) {
throw new SejdaRuntimeException(
getTaskName() + " has missing short name on " + eachMethod.getMethodName());
}
}
}
@Test
public void shortNamesAreUnique() {
Map<String, Method> shortNamesMapping = new HashMap<String, Method>();
for (MethodAndOption eachMethod : extractOptionAnnotations()) {
for (String eachShortName : eachMethod.getNonBlankShortNames()) {
if (shortNamesMapping.containsKey(eachShortName)) {
throw new SejdaRuntimeException(getTaskName() + " has duplicate short names: '" + eachShortName
+ "' defined on " + eachMethod.getMethodName() + "() and on "
+ shortNamesMapping.get(eachShortName).getName() + "()");
}
shortNamesMapping.put(eachShortName, eachMethod.getMethod());
}
}
}
private Collection<MethodAndOption> extractOptionAnnotations() {
Collection<MethodAndOption> result = new ArrayList<OptionDecriptionAndShortNameTest.MethodAndOption>();
Class<?> cliCommandClass = testableTask.getCommand().getCliArgumentsClass();
for (Method eachMethod : cliCommandClass.getMethods()) {
final Option optionAnnotation = eachMethod.getAnnotation(Option.class);
if (optionAnnotation == null) {
continue;
}
result.add(new MethodAndOption(eachMethod, optionAnnotation));
}
return result;
}
class MethodAndOption {
private final Method method;
private final Option option;
/**
* @param method
* @param option
*/
MethodAndOption(Method method, Option option) {
super();
this.method = method;
this.option = option;
}
/**
* @return true if the Option defined by the method is not a flag that has only true/false values (these are known to always be optional options)
*/
public boolean isNotBooleanFlag() {
return !method.getReturnType().equals(boolean.class);
}
/**
* @return name of the method
*/
public String getMethodName() {
return getMethod().getName();
}
public Collection<String> getNonBlankShortNames() {
Collection<String> result = new ArrayList<String>(Arrays.asList(getOption().shortName()));
result.remove("");
return result;
}
Method getMethod() {
return method;
}
Option getOption() {
return option;
}
}
}