Add attribute config via cli

This commit is contained in:
2023-02-20 23:48:49 +01:00
parent 5f72f4545f
commit 156e327943
8 changed files with 46 additions and 42 deletions

View File

@@ -1,15 +1,16 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.config; package at.pcgamingfreaks.mkvaudiosubtitlechanger.config;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.validator.*; import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.validator.*;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.ConfigProperty;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.util.VersionUtil; import at.pcgamingfreaks.mkvaudiosubtitlechanger.util.VersionUtil;
import at.pcgamingfreaks.yaml.YAML; import at.pcgamingfreaks.yaml.YAML;
import at.pcgamingfreaks.yaml.YamlInvalidContentException; import at.pcgamingfreaks.yaml.YamlInvalidContentException;
import org.apache.commons.cli.*; import org.apache.commons.cli.*;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -18,7 +19,7 @@ import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.CommandLineOptionsU
public class ConfigLoader { public class ConfigLoader {
private static final List<ConfigValidator<?>> VALIDATORS = List.of( private static final List<ConfigValidator<?>> VALIDATORS = List.of(
new ConfigPathValidator(CONFIG_PATH, true, Path.of("./config.yaml").toFile()), new ConfigPathValidator(CONFIG_PATH, false),
new PathValidator(LIBRARY, true, null), new PathValidator(LIBRARY, true, null),
new ThreadValidator(THREADS, false, 2), new ThreadValidator(THREADS, false, 2),
new MkvToolNixPathValidator(MKV_TOOL_NIX, true, Path.of("C:\\Program Files\\MKVToolNix").toFile()), new MkvToolNixPathValidator(MKV_TOOL_NIX, true, Path.of("C:\\Program Files\\MKVToolNix").toFile()),
@@ -32,6 +33,7 @@ public class ConfigLoader {
public static void initConfig(String[] args) { public static void initConfig(String[] args) {
HelpFormatter formatter = new HelpFormatter(); HelpFormatter formatter = new HelpFormatter();
formatter.setOptionComparator(null);
YAML yamlConfig = null; YAML yamlConfig = null;
Options options = initOptions(); Options options = initOptions();
@@ -44,7 +46,7 @@ public class ConfigLoader {
for (ConfigValidator<?> validator: VALIDATORS) { for (ConfigValidator<?> validator: VALIDATORS) {
results.add(validator.validate(yamlConfig, cmd)); results.add(validator.validate(yamlConfig, cmd));
if (yamlConfig == null && Config.getInstance().getConfigPath() != null) { if (yamlConfig == null) {
try { try {
yamlConfig = Config.getInstance().getConfigPath() != null yamlConfig = Config.getInstance().getConfigPath() != null
? new YAML(Config.getInstance().getConfigPath()) ? new YAML(Config.getInstance().getConfigPath())
@@ -59,16 +61,10 @@ public class ConfigLoader {
private static Options initOptions() { private static Options initOptions() {
Options options = new Options(); Options options = new Options();
options.addOption(optionOf(HELP, HELP.abrv(), HELP.args())); Arrays.stream(ConfigProperty.values())
options.addOption(optionOf(VERSION, VERSION.abrv(), VERSION.args())); .filter(prop -> prop.abrv() != null)
options.addOption(optionOf(LIBRARY, LIBRARY.abrv(), LIBRARY.args() )); .map(prop -> optionOf(prop, prop.abrv(), prop.args()))
options.addOption(optionOf(MKV_TOOL_NIX, MKV_TOOL_NIX.abrv(), MKV_TOOL_NIX.args() )); .forEach(options::addOption);
options.addOption(optionOf(CONFIG_PATH, CONFIG_PATH.abrv(), CONFIG_PATH.args() ));
options.addOption(optionOf(THREADS, THREADS.abrv(), THREADS.args()));
options.addOption(optionOf(SAFE_MODE, SAFE_MODE.abrv(), SAFE_MODE.args() ));
options.addOption(optionOf(FORCED_KEYWORDS, FORCED_KEYWORDS.abrv(), FORCED_KEYWORDS.args()));
options.addOption(optionOf(EXCLUDE_DIRECTORY, FORCED_KEYWORDS.abrv(), FORCED_KEYWORDS.args()));
options.addOption(optionOf(INCLUDE_PATTERN, INCLUDE_PATTERN.abrv(), INCLUDE_PATTERN.args()));
return options; return options;
} }

View File

@@ -13,6 +13,7 @@ import java.util.stream.Collectors;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.LanguageValidatorUtil.isLanguageValid; import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.LanguageValidatorUtil.isLanguageValid;
public class AttributeConfigValidator extends ConfigValidator<List<AttributeConfig>> { public class AttributeConfigValidator extends ConfigValidator<List<AttributeConfig>> {
private static final String SEPARATOR = ":";
public AttributeConfigValidator() { public AttributeConfigValidator() {
super(ConfigProperty.ATTRIBUTE_CONFIG, true, null); super(ConfigProperty.ATTRIBUTE_CONFIG, true, null);
@@ -25,10 +26,18 @@ public class AttributeConfigValidator extends ConfigValidator<List<AttributeConf
System.out.printf("%s: ", property.prop()); System.out.printf("%s: ", property.prop());
List<AttributeConfig> result; List<AttributeConfig> result;
Function<String, String> audio = key -> yaml.getString(key + ".audio", null);
Function<String, String> subtitle = key -> yaml.getString(key + ".subtitle", null);
if (yaml.getKeysFiltered(property.prop() + ".*").size() > 0) { if (cmd.hasOption(property.prop())) {
List<String> values = List.of(cmd.getOptionValues(property.prop()));
result = values.stream().anyMatch(pair -> !pair.contains(SEPARATOR))
? List.of()
: values.stream().map(pair -> pair.split(SEPARATOR))
.map(split -> new AttributeConfig(split[0], split[1]))
.collect(Collectors.toList());
} else if(yaml.getKeysFiltered(property.prop() + ".*").size() > 0) {
Function<String, String> audio = key -> yaml.getString(key + ".audio", null);
Function<String, String> subtitle = key -> yaml.getString(key + ".subtitle", null);
result = yaml.getKeysFiltered(".*audio.*").stream() result = yaml.getKeysFiltered(".*audio.*").stream()
.sorted() .sorted()
.map(key -> key.replace(".audio", "")) .map(key -> key.replace(".audio", ""))
@@ -67,7 +76,7 @@ public class AttributeConfigValidator extends ConfigValidator<List<AttributeConf
if (result.isEmpty()) { if (result.isEmpty()) {
return false; return false;
} }
boolean isValid = true; boolean isValid;
for (AttributeConfig attributeConfig : result) { for (AttributeConfig attributeConfig : result) {
isValid = isLanguageValid(attributeConfig.getAudioLanguage()) isValid = isLanguageValid(attributeConfig.getAudioLanguage())
&& isLanguageValid(attributeConfig.getSubtitleLanguage()); && isLanguageValid(attributeConfig.getSubtitleLanguage());

View File

@@ -8,8 +8,8 @@ import java.util.Optional;
import java.util.function.BiFunction; import java.util.function.BiFunction;
public class ConfigPathValidator extends PathValidator { public class ConfigPathValidator extends PathValidator {
public ConfigPathValidator(ConfigProperty property, boolean required, File defaultValue) { public ConfigPathValidator(ConfigProperty property, boolean required) {
super(property, required, defaultValue); super(property, required, null);
} }
/** /**

View File

@@ -10,21 +10,21 @@ import java.util.stream.Collectors;
@AllArgsConstructor @AllArgsConstructor
public enum ConfigProperty { public enum ConfigProperty {
CONFIG_PATH("config-path", "Path to config file", "p", 1),
LIBRARY("library", "Path to library", "l", 1), LIBRARY("library", "Path to library", "l", 1),
SAFE_MODE("safe-mode", "Test run (no files will be changes)", "s", 0), ATTRIBUTE_CONFIG("attribute-config", "Attribute config to decide which tracks to choose when", "a", Option.UNLIMITED_VALUES),
WINDOWS("windows", "Is operating system windows", null, 0), CONFIG_PATH("config-path", "Path to config file", "p", 1),
THREADS("threads", "thread count (default: 2)", "t", 1),
INCLUDE_PATTERN("include-pattern", "Include files matching pattern", "i", 1),
MKV_TOOL_NIX("mkvtoolnix", "Path to mkv tool nix installation", "m", 1), MKV_TOOL_NIX("mkvtoolnix", "Path to mkv tool nix installation", "m", 1),
SAFE_MODE("safe-mode", "Test run (no files will be changes)", "s", 0),
COHERENT("coherent", "Try to match whole series with same config", "c", 0),
WINDOWS("windows", "Is operating system windows", null, 0),
THREADS("threads", "Thread count (default: 2)", "t", 1),
INCLUDE_PATTERN("include-pattern", "Include files matching pattern (default: \".*\")", "i", 1),
EXCLUDE_DIRECTORY("exclude-directories", "Directories to be excluded, combines with config file", "e", 1),
FORCED_KEYWORDS("forcedKeywords", "Additional keywords to identify forced tracks", "fk", Option.UNLIMITED_VALUES), FORCED_KEYWORDS("forcedKeywords", "Additional keywords to identify forced tracks", "fk", Option.UNLIMITED_VALUES),
COMMENTARY_KEYWORDS("commentary-keywords", "Additional keywords to identify commentary tracks", "ck", Option.UNLIMITED_VALUES), COMMENTARY_KEYWORDS("commentary-keywords", "Additional keywords to identify commentary tracks", "ck", Option.UNLIMITED_VALUES),
EXCLUDE_DIRECTORY("exclude-directories", "Directories to be excluded, combines with config file", "e", 1),
COHERENT("coherent", "Try to match whole series with same config", "c", 0),
HELP("help", "\"for help this is\" - Yoda", "h", 0),
VERSION("version", "Display version", "v", 0),
ARGUMENTS("arguments", "List of arguments", null, 0), ARGUMENTS("arguments", "List of arguments", null, 0),
ATTRIBUTE_CONFIG("attribute-config", "Attribute config to decide which tracks to choose when", "a", 1); VERSION("version", "Display version", "v", 0),
HELP("help", "\"For help this is\" - Yoda", "h", 0);
private final String property; private final String property;
private final String description; private final String description;

View File

@@ -43,8 +43,11 @@ class AttributeConfigValidatorTest {
private static Stream<Arguments> provideTestCases() { private static Stream<Arguments> provideTestCases() {
return Stream.of( return Stream.of(
Arguments.of(attrConfYaml("jpn", "ger"), new String[]{}, VALID, attrConf("jpn", "ger")), Arguments.of(attrConfYaml("jpn", "ger"), new String[]{}, VALID, attrConf("jpn", "ger")),
Arguments.of("", new String[]{"-a", "jpn:ger"}, VALID, attrConf("jpn", "ger")),
Arguments.of(attrConfYaml("jpn", "ger", "jpn", "eng"), new String[]{}, VALID, attrConf("jpn", "ger", "jpn", "eng")), Arguments.of(attrConfYaml("jpn", "ger", "jpn", "eng"), new String[]{}, VALID, attrConf("jpn", "ger", "jpn", "eng")),
Arguments.of("", new String[]{"-a", "jpn:ger", "jpn:eng"}, VALID, attrConf("jpn", "ger", "jpn", "eng")),
Arguments.of(attrConfYaml("jpn", "ger", "jpn", "OFF"), new String[]{}, VALID, attrConf("jpn", "ger", "jpn", "OFF")), Arguments.of(attrConfYaml("jpn", "ger", "jpn", "OFF"), new String[]{}, VALID, attrConf("jpn", "ger", "jpn", "OFF")),
Arguments.of("", new String[]{"-a", "jpn:ger", "jpn:OFF"}, VALID, attrConf("jpn", "ger", "jpn", "OFF")),
Arguments.of(attrConfYaml("jpn", "invalid"), new String[]{}, INVALID, null), Arguments.of(attrConfYaml("jpn", "invalid"), new String[]{}, INVALID, null),
Arguments.of("", new String[]{}, MISSING, null) Arguments.of("", new String[]{}, MISSING, null)
); );
@@ -67,7 +70,7 @@ class AttributeConfigValidatorTest {
int counter = 0; int counter = 0;
for (int i = 0; i < languages.length; i += 2) { for (int i = 0; i < languages.length; i += 2) {
counter++; counter++;
yaml.append(String.format("\n %s:\n audio: %s\n subtitle: %s", counter, languages[0], languages[1])); yaml.append(String.format("\n %s:\n audio: %s\n subtitle: %s", counter, languages[i], languages[i+1]));
} }
return yaml.toString(); return yaml.toString();
} }
@@ -75,7 +78,7 @@ class AttributeConfigValidatorTest {
private static List<AttributeConfig> attrConf(String... languages) { private static List<AttributeConfig> attrConf(String... languages) {
List<AttributeConfig> conf = new ArrayList<>(); List<AttributeConfig> conf = new ArrayList<>();
for (int i = 0; i < languages.length; i += 2) { for (int i = 0; i < languages.length; i += 2) {
conf.add(new AttributeConfig(languages[0], languages[1])); conf.add(new AttributeConfig(languages[i], languages[i+1]));
} }
return conf; return conf;
} }

View File

@@ -13,20 +13,17 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import java.io.File;
import java.nio.file.Path;
import java.util.stream.Stream; import java.util.stream.Stream;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.config.ValidationResult.*; import static at.pcgamingfreaks.mkvaudiosubtitlechanger.config.ValidationResult.*;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.config.ValidationResult.INVALID; import static at.pcgamingfreaks.mkvaudiosubtitlechanger.config.ValidationResult.INVALID;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.model.ConfigProperty.CONFIG_PATH; import static at.pcgamingfreaks.mkvaudiosubtitlechanger.model.ConfigProperty.CONFIG_PATH;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.CommandLineOptionsUtil.optionOf; import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.CommandLineOptionsUtil.optionOf;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.TestUtil.argumentsOf;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
class ConfigPathValidatorTest { class ConfigPathValidatorTest {
private static final String TEST_FILE = "src/test/resources/test-dir/test-file.mkv"; private static final String TEST_FILE = "src/test/resources/test-dir/test-file.mkv";
private static final String TEST_CONFIG = "src/test/resources/test-dir/test-config.yml"; private static final String TEST_CONFIG = "src/test/resources/test-dir/test-config.yaml";
private static CommandLineParser parser; private static CommandLineParser parser;
private static Options options; private static Options options;
@@ -40,19 +37,18 @@ class ConfigPathValidatorTest {
private static Stream<Arguments> provideTestCases() { private static Stream<Arguments> provideTestCases() {
return Stream.of( return Stream.of(
argumentsOf(CONFIG_PATH, true, null, "", new String[]{"-p", TEST_CONFIG}, VALID), Arguments.of(CONFIG_PATH, true, "", new String[]{"-p", TEST_CONFIG}, VALID),
argumentsOf(CONFIG_PATH, true, null, "config-path: " + TEST_CONFIG, new String[]{}, MISSING), Arguments.of(CONFIG_PATH, true, "config-path: " + TEST_CONFIG, new String[]{}, MISSING),
argumentsOf(CONFIG_PATH, false, null, "config-path: " + TEST_CONFIG, new String[]{}, NOT_PRESENT), Arguments.of(CONFIG_PATH, false, "config-path: " + TEST_CONFIG, new String[]{}, NOT_PRESENT),
argumentsOf(CONFIG_PATH, false, Path.of(TEST_CONFIG).toFile(), "", new String[]{}, DEFAULT), Arguments.of(CONFIG_PATH, true, "", new String[]{"-p", TEST_FILE}, INVALID)
argumentsOf(CONFIG_PATH, true, null, "", new String[]{"-p", TEST_FILE}, INVALID)
); );
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("provideTestCases") @MethodSource("provideTestCases")
void validate(ConfigProperty property, boolean required, File defaultValue, String yamlArgs, String[] cmdArgs, void validate(ConfigProperty property, boolean required, String yamlArgs, String[] cmdArgs,
ValidationResult expectedResult) throws ParseException, YamlInvalidContentException { ValidationResult expectedResult) throws ParseException, YamlInvalidContentException {
ConfigPathValidator underTest = new ConfigPathValidator(property, required, defaultValue); ConfigPathValidator underTest = new ConfigPathValidator(property, required);
ValidationResult result = underTest.validate(new YAML(yamlArgs), parser.parse(options, cmdArgs)); ValidationResult result = underTest.validate(new YAML(yamlArgs), parser.parse(options, cmdArgs));