Make picocli fully handle config validation

This commit is contained in:
RatzzFatzz
2025-12-04 23:20:49 +01:00
parent 5eca28ecb9
commit 181c718e7a
13 changed files with 116 additions and 46 deletions

View File

@@ -1,6 +1,7 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.InputConfig;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.validation.ValidationExecutionStrategy;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.CachedMkvFileProcessor;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.kernel.AttributeUpdaterKernel;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.kernel.CoherentAttributeUpdaterKernel;
@@ -35,7 +36,10 @@ public class Main implements Runnable {
if (args.length == 0) {
args = new String[] { "--help" };
}
new CommandLine(Main.class).execute(args);
new CommandLine(Main.class)
.setExecutionStrategy(new ValidationExecutionStrategy())
.execute(args);
}
@Override

View File

@@ -4,6 +4,7 @@ import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.validation.ValidFile;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.validation.ValidMkvToolNix;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.AttributeConfig;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.MkvToolNix;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.util.FileUtils;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.util.ValidationUtil;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validator;
@@ -108,20 +109,6 @@ public class InputConfig {
public static void setInstance(InputConfig c) {
config = c;
validate();
}
private static void validate() {
Validator validator = ValidationUtil.getValidator();
Set<ConstraintViolation<InputConfig>> violations = validator.validate(config);
if (!violations.isEmpty()) {
StringBuilder errors = new StringBuilder();
for (ConstraintViolation<InputConfig> violation : violations) {
errors.append(violation.getPropertyPath()).append(" ").append(violation.getMessage()).append("\n");
}
throw new CommandLine.ParameterException(config.getSpec().commandLine(), errors.toString());
}
}
/**
@@ -129,13 +116,7 @@ public class InputConfig {
* @return absolute path to desired application.
*/
public String getPathFor(MkvToolNix application) {
return mkvToolNix.getAbsolutePath().endsWith("/")
? mkvToolNix.getAbsolutePath() + application
: mkvToolNix.getAbsolutePath() + "/" + application;
}
public String getPathFor(MkvToolNix application, boolean isWindows) {
return getPathFor(application) + (isWindows ? ".exe" : "");
return FileUtils.getPathFor(mkvToolNix, application).getAbsolutePath();
}
public String getNormalizedLibraryPath() {

View File

@@ -1,14 +1,12 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.config.validation;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.InputConfig;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.MkvToolNix;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.apache.commons.lang3.SystemUtils;
import java.io.File;
import java.nio.file.Path;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.FileUtils.getPathFor;
public class ValidMkvToolNixValidator implements ConstraintValidator<ValidMkvToolNix, File> {
@Override
@@ -18,7 +16,9 @@ public class ValidMkvToolNixValidator implements ConstraintValidator<ValidMkvToo
@Override
public boolean isValid(File file, ConstraintValidatorContext context) {
return file != null && file.exists()
&& Path.of(InputConfig.getInstance().getPathFor(MkvToolNix.MKV_MERGE, SystemUtils.IS_OS_WINDOWS)).toFile().exists()
&& Path.of(InputConfig.getInstance().getPathFor(MkvToolNix.MKV_PROP_EDIT, SystemUtils.IS_OS_WINDOWS)).toFile().exists();
&& getPathFor(file, MkvToolNix.MKV_MERGE).exists()
&& getPathFor(file, MkvToolNix.MKV_PROP_EDIT).exists();
}
}

View File

@@ -0,0 +1,31 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.config.validation;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.Main;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.InputConfig;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.util.ValidationUtil;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validator;
import picocli.CommandLine;
import java.util.Set;
public class ValidationExecutionStrategy implements CommandLine.IExecutionStrategy {
public int execute(CommandLine.ParseResult parseResult) {
validate(parseResult.commandSpec());
return new CommandLine.RunLast().execute(parseResult); // default execution strategy
}
private static void validate(CommandLine.Model.CommandSpec spec) {
Validator validator = ValidationUtil.getValidator();
Set<ConstraintViolation<InputConfig>> violations = validator.validate(((Main)spec.userObject()).getConfig());
if (!violations.isEmpty()) {
StringBuilder errors = new StringBuilder();
for (ConstraintViolation<InputConfig> violation : violations) {
errors.append(violation.getPropertyPath()).append(" ").append(violation.getMessage()).append("\n");
}
throw new CommandLine.ParameterException(spec.commandLine(), errors.toString());
}
}
}

View File

@@ -0,0 +1,21 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.util;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.MkvToolNix;
import org.apache.commons.lang3.SystemUtils;
import java.io.File;
import java.nio.file.Path;
public class FileUtils {
private static final boolean isWindows = SystemUtils.IS_OS_WINDOWS;
private static String expandPath(File dir, MkvToolNix application) {
return dir.getAbsolutePath().endsWith("/")
? dir.getAbsolutePath() + application
: dir.getAbsolutePath() + "/" + application;
}
public static File getPathFor(File dir, MkvToolNix application) {
return Path.of(expandPath(dir, application) + (isWindows ? ".exe" : "")).toFile();
}
}