YamlConfig.java
package org.egothor.methodatlas;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
/**
* Loads a YAML configuration file that provides default values for
* command-line options.
*
* <p>
* When a {@code -config <file>} argument is present, {@link CliArgs} calls
* {@link #load(Path)} before processing the remaining arguments. The returned
* {@link YamlConfigFile} seeds the initial values; any matching command-line
* flag then overrides the YAML value.
* </p>
*
* <h2>Supported fields</h2>
*
* <pre>
* outputMode: csv # csv | plain | sarif (default: csv)
* emitMetadata: false # (default: false)
* contentHash: false # (default: false)
* fileSuffixes:
* - Test.java
* testAnnotations:
* - Test
* - ParameterizedTest
* ai:
* enabled: true
* provider: ollama # auto | ollama | openai | openrouter | anthropic
* model: qwen2.5-coder:7b
* baseUrl: http://localhost:11434
* apiKey: sk-...
* apiKeyEnv: MY_KEY_ENV
* taxonomyFile: /path/to/taxonomy.txt
* taxonomyMode: default # default | optimized
* maxClassChars: 100000
* timeoutSec: 30
* maxRetries: 3
* confidence: false
* </pre>
*
* <p>
* Unknown fields in the YAML file are silently ignored.
* </p>
*
* @see CliArgs
*/
final class YamlConfig {
/**
* Prevents instantiation of this utility class.
*/
private YamlConfig() {
}
/**
* Loads a YAML configuration file.
*
* @param configFile path to the YAML file
* @return parsed configuration; never {@code null}
* @throws IOException if the file cannot be read
* @throws IllegalArgumentException if the file cannot be parsed as valid YAML
*/
/* default */ static YamlConfigFile load(Path configFile) throws IOException {
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return mapper.readValue(configFile.toFile(), YamlConfigFile.class);
}
// -------------------------------------------------------------------------
// POJO classes
// -------------------------------------------------------------------------
/**
* Top-level YAML configuration structure.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
/* default */ static final class YamlConfigFile {
/** Output mode: {@code csv}, {@code plain}, or {@code sarif}. */
@JsonProperty("outputMode")
/* default */ String outputMode;
/** Whether to emit {@code # key: value} metadata comment lines. */
@JsonProperty("emitMetadata")
/* default */ boolean emitMetadata;
/** File name suffixes used to select test source files. */
@JsonProperty("fileSuffixes")
/* default */ List<String> fileSuffixes;
/** Annotation simple names that identify test methods. */
@JsonProperty("testAnnotations")
/* default */ List<String> testAnnotations;
/**
* Whether to include a SHA-256 content-hash fingerprint of each class
* source as a {@code content_hash} column.
*/
@JsonProperty("contentHash")
/* default */ boolean contentHash;
/** AI enrichment settings. */
@JsonProperty("ai")
/* default */ YamlAiConfig ai;
}
/**
* AI subsystem configuration within the YAML file.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
/* default */ static final class YamlAiConfig {
/** Whether AI enrichment is enabled. */
@JsonProperty("enabled")
/* default */ Boolean enabled;
/**
* AI provider: {@code auto}, {@code ollama}, {@code openai},
* {@code openrouter}, or {@code anthropic}.
*/
@JsonProperty("provider")
/* default */ String provider;
/** Provider-specific model name. */
@JsonProperty("model")
/* default */ String model;
/** Provider base URL override. */
@JsonProperty("baseUrl")
/* default */ String baseUrl;
/** API key supplied directly. */
@JsonProperty("apiKey")
/* default */ String apiKey;
/** Name of the environment variable that holds the API key. */
@JsonProperty("apiKeyEnv")
/* default */ String apiKeyEnv;
/** Path to an external taxonomy file. */
@JsonProperty("taxonomyFile")
/* default */ String taxonomyFile;
/** Built-in taxonomy variant: {@code default} or {@code optimized}. */
@JsonProperty("taxonomyMode")
/* default */ String taxonomyMode;
/** Maximum number of characters of class source sent to the AI. */
@JsonProperty("maxClassChars")
/* default */ Integer maxClassChars;
/** AI request timeout in seconds. */
@JsonProperty("timeoutSec")
/* default */ Long timeoutSec;
/** Maximum number of retries for AI requests. */
@JsonProperty("maxRetries")
/* default */ Integer maxRetries;
/** Whether to request a confidence score for each classification. */
@JsonProperty("confidence")
/* default */ Boolean confidence;
}
}