jcommander
jcommander copied to clipboard
JCommander value validator checks only the default value of the list of arguments
If an instance of IParameterValidator is used with an arguments list, then only non-default values are validated. It makes sense in most cases, because the defaults are supplied by the app developer.
If an instance of IValueValidator is used with it, then only the default contents of the list is validated. The list of arguments from the command line is never validated.
In the following example both are used. DirectoryNameValidator will be called only with the default value, which is ["./"]. If a user passes a list of arguments from the command line, DirectoryNameValidator won't validate them.
import com.beust.jcommander.IParameterValidator;
import com.beust.jcommander.IValueValidator;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import static java.util.Collections.singletonList;
public class Main {
private static class CommandLineOptions {
@Parameter(description = "A path", validateWith = DirectoryNameValidator.class,
validateValueWith = DirectoryListValidator.class)
List<String> files = new ArrayList<>(singletonList("./"));
}
public static class DirectoryNameValidator implements IParameterValidator {
@Override
public void validate(String name, String value) throws ParameterException {
System.out.println("Validating directory: " + value);
checkIsExistingDirectory(value);
}
}
public static class DirectoryListValidator implements IValueValidator<List<String>> {
@Override
public void validate(String name, List<String> value) throws ParameterException {
System.out.println("Validating parameters list: " + value);
for (String directoryName : value) {
checkIsExistingDirectory(directoryName);
}
}
}
public static void main(String[] args) {
CommandLineOptions options = new CommandLineOptions();
JCommander jCommander = new JCommander(options, args);
System.out.println("Path(s): " + options.files);
}
private static void checkIsExistingDirectory(String directoryName) {
if (!Paths.get(directoryName).toFile().isDirectory()) {
throw new ParameterException(directoryName + " is not a directory");
}
}
}
@cbeust started work to fix this. Hope that's ok.
Hi @dmitry-timofeev,
looking closely at the source of JCommander.java execution of IValueValidtor for "Main parameters" is not implemented at all right now.
It should be implemented in the else part of parseValues.
For default values it is executed in public static void validateValueParameter(Class<? extends IValueValidator> validator, String name, Object value) in ParameterDescription.java line 283, called from validateDefaultValues line 159.
This change looks more complicated. Might come back with a PR in a couple of days.
This is still an issue. But too busy to work on this for now.