PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
kcenon::pacs::samples::config_loader Class Reference

#include <config_loader.h>

Collaboration diagram for kcenon::pacs::samples::config_loader:
Collaboration graph

Static Public Member Functions

static auto load (const std::filesystem::path &path) -> kcenon::common::Result< production_config >
 Load configuration from a YAML file.
 
static auto load_from_string (std::string_view yaml_content) -> kcenon::common::Result< production_config >
 Load configuration from a YAML string.
 
static auto create_default () -> production_config
 Create a default configuration.
 
static auto validate (const production_config &config) -> kcenon::common::VoidResult
 Validate a configuration.
 

Static Private Member Functions

static auto parse_value (std::string_view value) -> std::string
 Parse a YAML value (simple types)
 
static auto parse_bool (std::string_view value) -> bool
 Parse a boolean value.
 
static auto parse_int (std::string_view value) -> int
 Parse an integer value.
 
static auto parse_anonymization_profile (std::string_view value) -> security::anonymization_profile
 Parse anonymization profile.
 
static auto trim (std::string_view str) -> std::string
 Trim whitespace from string.
 

Detailed Description

Definition at line 248 of file config_loader.h.

Member Function Documentation

◆ create_default()

auto kcenon::pacs::samples::config_loader::create_default ( ) -> production_config
staticnodiscard

Create a default configuration.

Returns
Default production configuration
Examples
/home/runner/work/pacs_system/pacs_system/examples/tutorials/05_production_pacs/config_loader.h.

Definition at line 263 of file config_loader.cpp.

263 {
264 production_config config;
265
266 // Server defaults
267 config.server.ae_title = "PROD_PACS";
268 config.server.port = 11112;
269 config.server.max_associations = 100;
270 config.server.idle_timeout = std::chrono::seconds{300};
271 config.server.tls.enabled = false;
272
273 // Storage defaults
274 config.storage.root_path = "./pacs_data";
275 config.storage.naming_scheme = "uid_hierarchical";
276 config.storage.duplicate_policy = "replace";
277 config.storage.database.path = "./pacs_data/index.db";
278
279 // Security defaults
280 config.security.access_control.enabled = true;
281 config.security.access_control.default_role = "viewer";
282 config.security.anonymization.auto_anonymize = false;
283 config.security.anonymization.profile = security::anonymization_profile::basic;
284
285 // REST API defaults
286 config.rest_api.enabled = true;
287 config.rest_api.port = 8080;
288 config.rest_api.cors_enabled = true;
289
290 // Monitoring defaults
291 config.monitoring.health_check_interval = std::chrono::seconds{30};
292 config.monitoring.metrics_enabled = true;
293
294 // Logging defaults
295 config.logging.level = "info";
296
297 return config;
298}
@ basic
Basic Profile - Remove direct identifiers.

References kcenon::pacs::samples::security_config::access_control, kcenon::pacs::samples::server_config::ae_title, kcenon::pacs::samples::security_config::anonymization, kcenon::pacs::samples::anonymization_config::auto_anonymize, kcenon::pacs::security::basic, kcenon::pacs::samples::rest_api_config::cors_enabled, kcenon::pacs::samples::storage_config::database, kcenon::pacs::samples::access_control_config::default_role, kcenon::pacs::samples::storage_config::duplicate_policy, kcenon::pacs::samples::access_control_config::enabled, kcenon::pacs::samples::rest_api_config::enabled, kcenon::pacs::samples::tls_config::enabled, kcenon::pacs::samples::monitoring_config::health_check_interval, kcenon::pacs::samples::server_config::idle_timeout, kcenon::pacs::samples::logging_config::level, kcenon::pacs::samples::production_config::logging, kcenon::pacs::samples::server_config::max_associations, kcenon::pacs::samples::monitoring_config::metrics_enabled, kcenon::pacs::samples::production_config::monitoring, kcenon::pacs::samples::storage_config::naming_scheme, kcenon::pacs::samples::database_config::path, kcenon::pacs::samples::rest_api_config::port, kcenon::pacs::samples::server_config::port, kcenon::pacs::samples::anonymization_config::profile, kcenon::pacs::samples::production_config::rest_api, kcenon::pacs::samples::storage_config::root_path, kcenon::pacs::samples::production_config::security, kcenon::pacs::samples::production_config::server, kcenon::pacs::samples::production_config::storage, and kcenon::pacs::samples::server_config::tls.

Referenced by main().

Here is the caller graph for this function:

◆ load()

auto kcenon::pacs::samples::config_loader::load ( const std::filesystem::path & path) -> kcenon::common::Result<production_config>
staticnodiscard

Load configuration from a YAML file.

Parameters
pathPath to the YAML configuration file
Returns
Result containing configuration or error message
Examples
/home/runner/work/pacs_system/pacs_system/examples/tutorials/05_production_pacs/config_loader.h.

Definition at line 170 of file config_loader.cpp.

171 {
172 std::ifstream file(path);
173 if (!file.is_open()) {
175 kcenon::common::error_info("Failed to open configuration file: " + path.string()));
176 }
177
178 std::stringstream buffer;
179 buffer << file.rdbuf();
180 return load_from_string(buffer.str());
181}
static auto load_from_string(std::string_view yaml_content) -> kcenon::common::Result< production_config >
Load configuration from a YAML string.
std::string buffer

References buffer.

Referenced by main().

Here is the caller graph for this function:

◆ load_from_string()

auto kcenon::pacs::samples::config_loader::load_from_string ( std::string_view yaml_content) -> kcenon::common::Result<production_config>
staticnodiscard

Load configuration from a YAML string.

Parameters
yaml_contentYAML content as a string
Returns
Result containing configuration or error message
Examples
/home/runner/work/pacs_system/pacs_system/examples/tutorials/05_production_pacs/config_loader.h.

Definition at line 183 of file config_loader.cpp.

184 {
185 try {
186 simple_yaml_parser parser(yaml_content);
187 production_config config = create_default();
188
189 // Server configuration
190 config.server.ae_title = parser.get_string("server.ae_title", config.server.ae_title);
191 config.server.port = static_cast<std::uint16_t>(
192 parser.get_int("server.port", config.server.port));
193 config.server.max_associations = static_cast<std::size_t>(
194 parser.get_int("server.max_associations",
195 static_cast<int>(config.server.max_associations)));
196 config.server.idle_timeout = std::chrono::seconds(
197 parser.get_int("server.idle_timeout_seconds",
198 static_cast<int>(config.server.idle_timeout.count())));
199
200 // TLS configuration
201 config.server.tls.enabled = parser.get_bool("server.tls.enabled",
202 config.server.tls.enabled);
203 config.server.tls.certificate = parser.get_string("server.tls.certificate");
204 config.server.tls.private_key = parser.get_string("server.tls.private_key");
205 config.server.tls.ca_certificate = parser.get_string("server.tls.ca_certificate");
206 config.server.tls.require_client_cert =
207 parser.get_bool("server.tls.require_client_cert", false);
208 config.server.tls.min_version = parser.get_string("server.tls.min_version", "1.2");
209
210 // Storage configuration
211 config.storage.root_path = parser.get_string("storage.root_path",
212 config.storage.root_path.string());
213 config.storage.naming_scheme = parser.get_string("storage.naming_scheme",
214 config.storage.naming_scheme);
215 config.storage.duplicate_policy = parser.get_string("storage.duplicate_policy",
216 config.storage.duplicate_policy);
217 config.storage.database.path = parser.get_string("storage.database.path",
218 config.storage.database.path.string());
219
220 // Security configuration
221 config.security.access_control.enabled =
222 parser.get_bool("security.access_control.enabled", true);
223 config.security.access_control.default_role =
224 parser.get_string("security.access_control.default_role", "viewer");
225 config.security.allowed_ae_titles =
226 parser.get_list("security.allowed_ae_titles");
227 config.security.anonymization.auto_anonymize =
228 parser.get_bool("security.anonymization.auto_anonymize", false);
229
230 auto profile_str = parser.get_string("security.anonymization.profile", "basic");
231 config.security.anonymization.profile = parse_anonymization_profile(profile_str);
232
233 // REST API configuration
234 config.rest_api.enabled = parser.get_bool("rest_api.enabled", true);
235 config.rest_api.port = static_cast<std::uint16_t>(
236 parser.get_int("rest_api.port", config.rest_api.port));
237 config.rest_api.cors_enabled = parser.get_bool("rest_api.cors_enabled", true);
238
239 // Monitoring configuration
240 config.monitoring.health_check_interval = std::chrono::seconds(
241 parser.get_int("monitoring.health_check_interval_seconds", 30));
242 config.monitoring.metrics_enabled = parser.get_bool("monitoring.metrics_enabled", true);
243
244 // Logging configuration
245 config.logging.level = parser.get_string("logging.level", "info");
246 config.logging.audit_log_path = parser.get_string("logging.audit_log_path");
247
248 // Validate configuration
249 auto validation = validate(config);
250 if (!validation.is_ok()) {
252 kcenon::common::error_info(validation.error().message));
253 }
254
255 return kcenon::common::Result<production_config>::ok(std::move(config));
256
257 } catch (const std::exception& e) {
259 kcenon::common::error_info(std::string("Configuration parsing error: ") + e.what()));
260 }
261}
static auto create_default() -> production_config
Create a default configuration.
static auto parse_anonymization_profile(std::string_view value) -> security::anonymization_profile
Parse anonymization profile.
static auto validate(const production_config &config) -> kcenon::common::VoidResult
Validate a configuration.

References kcenon::pacs::samples::security_config::access_control, kcenon::pacs::samples::server_config::ae_title, kcenon::pacs::samples::security_config::allowed_ae_titles, kcenon::pacs::samples::security_config::anonymization, kcenon::pacs::samples::logging_config::audit_log_path, kcenon::pacs::samples::anonymization_config::auto_anonymize, kcenon::pacs::samples::tls_config::ca_certificate, kcenon::pacs::samples::tls_config::certificate, kcenon::pacs::samples::rest_api_config::cors_enabled, kcenon::pacs::samples::storage_config::database, kcenon::pacs::samples::access_control_config::default_role, kcenon::pacs::samples::storage_config::duplicate_policy, kcenon::pacs::samples::access_control_config::enabled, kcenon::pacs::samples::rest_api_config::enabled, kcenon::pacs::samples::tls_config::enabled, kcenon::pacs::samples::monitoring_config::health_check_interval, kcenon::pacs::samples::server_config::idle_timeout, kcenon::pacs::samples::logging_config::level, kcenon::pacs::samples::production_config::logging, kcenon::pacs::samples::server_config::max_associations, kcenon::pacs::samples::monitoring_config::metrics_enabled, kcenon::pacs::samples::tls_config::min_version, kcenon::pacs::samples::production_config::monitoring, kcenon::pacs::samples::storage_config::naming_scheme, kcenon::pacs::samples::database_config::path, kcenon::pacs::samples::rest_api_config::port, kcenon::pacs::samples::server_config::port, kcenon::pacs::samples::tls_config::private_key, kcenon::pacs::samples::anonymization_config::profile, kcenon::pacs::samples::tls_config::require_client_cert, kcenon::pacs::samples::production_config::rest_api, kcenon::pacs::samples::storage_config::root_path, kcenon::pacs::samples::production_config::security, kcenon::pacs::samples::production_config::server, kcenon::pacs::samples::production_config::storage, and kcenon::pacs::samples::server_config::tls.

◆ parse_anonymization_profile()

auto kcenon::pacs::samples::config_loader::parse_anonymization_profile ( std::string_view value) -> security::anonymization_profile
staticprivate

Parse anonymization profile.

Examples
/home/runner/work/pacs_system/pacs_system/examples/tutorials/05_production_pacs/config_loader.h.

Definition at line 378 of file config_loader.cpp.

379 {
380 auto v = trim(value);
381 std::transform(v.begin(), v.end(), v.begin(), ::tolower);
382
383 if (v == "basic" || v == "basic_profile") {
385 }
386 if (v == "hipaa" || v == "hipaa_safe_harbor") {
388 }
389 if (v == "retain_longitudinal" || v == "retain_longitudinal_full_dates") {
391 }
392 if (v == "retain_device" || v == "retain_device_identity" ||
393 v == "retain_patient" || v == "retain_patient_characteristics") {
395 }
396 if (v == "gdpr") {
398 }
399
400 // Default to basic
402}
static auto trim(std::string_view str) -> std::string
Trim whitespace from string.
@ hipaa_safe_harbor
HIPAA Safe Harbor - 18 identifier removal.
@ gdpr_compliant
GDPR Compliant - European data protection.
@ retain_longitudinal
Retain Longitudinal - Preserve temporal relationships.
@ retain_patient_characteristics
Retain Patient Characteristics.

References kcenon::pacs::security::basic, kcenon::pacs::security::gdpr_compliant, kcenon::pacs::security::hipaa_safe_harbor, kcenon::pacs::security::retain_longitudinal, and kcenon::pacs::security::retain_patient_characteristics.

◆ parse_bool()

auto kcenon::pacs::samples::config_loader::parse_bool ( std::string_view value) -> bool
staticprivate

Parse a boolean value.

Examples
/home/runner/work/pacs_system/pacs_system/examples/tutorials/05_production_pacs/config_loader.h.

Definition at line 363 of file config_loader.cpp.

363 {
364 auto v = trim(value);
365 std::transform(v.begin(), v.end(), v.begin(), ::tolower);
366 return v == "true" || v == "yes" || v == "on" || v == "1";
367}

◆ parse_int()

auto kcenon::pacs::samples::config_loader::parse_int ( std::string_view value) -> int
staticprivate

Parse an integer value.

Examples
/home/runner/work/pacs_system/pacs_system/examples/tutorials/05_production_pacs/config_loader.h.

Definition at line 369 of file config_loader.cpp.

369 {
370 auto v = trim(value);
371 try {
372 return std::stoi(v);
373 } catch (...) {
374 return 0;
375 }
376}

◆ parse_value()

auto kcenon::pacs::samples::config_loader::parse_value ( std::string_view value) -> std::string
staticprivate

Parse a YAML value (simple types)

Examples
/home/runner/work/pacs_system/pacs_system/examples/tutorials/05_production_pacs/config_loader.h.

Definition at line 359 of file config_loader.cpp.

359 {
360 return trim(value);
361}

◆ trim()

auto kcenon::pacs::samples::config_loader::trim ( std::string_view str) -> std::string
staticprivate

Trim whitespace from string.

Examples
/home/runner/work/pacs_system/pacs_system/examples/tutorials/05_production_pacs/config_loader.h.

Definition at line 404 of file config_loader.cpp.

404 {
405 auto start = str.find_first_not_of(" \t\r\n");
406 if (start == std::string::npos) return "";
407 auto end = str.find_last_not_of(" \t\r\n");
408 return std::string(str.substr(start, end - start + 1));
409}

◆ validate()

auto kcenon::pacs::samples::config_loader::validate ( const production_config & config) -> kcenon::common::VoidResult
staticnodiscard

Validate a configuration.

Parameters
configConfiguration to validate
Returns
Result indicating success or error
Examples
/home/runner/work/pacs_system/pacs_system/examples/tutorials/05_production_pacs/config_loader.h.

Definition at line 300 of file config_loader.cpp.

301 {
302 // Validate AE Title (max 16 characters, no leading/trailing spaces)
303 if (config.server.ae_title.empty()) {
304 return kcenon::common::VoidResult::err(
305 kcenon::common::error_info("AE Title cannot be empty"));
306 }
307 if (config.server.ae_title.length() > 16) {
308 return kcenon::common::VoidResult::err(
309 kcenon::common::error_info("AE Title exceeds maximum length of 16 characters"));
310 }
311
312 // Validate port
313 if (config.server.port == 0) {
314 return kcenon::common::VoidResult::err(
315 kcenon::common::error_info("Server port cannot be 0"));
316 }
317
318 // Validate REST API port
319 if (config.rest_api.enabled && config.rest_api.port == 0) {
320 return kcenon::common::VoidResult::err(
321 kcenon::common::error_info("REST API port cannot be 0"));
322 }
323
324 // Validate TLS configuration
325 if (config.server.tls.enabled) {
326 if (config.server.tls.certificate.empty()) {
327 return kcenon::common::VoidResult::err(
328 kcenon::common::error_info("TLS enabled but no certificate specified"));
329 }
330 if (config.server.tls.private_key.empty()) {
331 return kcenon::common::VoidResult::err(
332 kcenon::common::error_info("TLS enabled but no private key specified"));
333 }
334 }
335
336 // Validate naming scheme
337 const std::vector<std::string> valid_schemes = {
338 "uid_flat", "uid_hierarchical", "date_based"
339 };
340 auto scheme_it = std::find(valid_schemes.begin(), valid_schemes.end(),
341 config.storage.naming_scheme);
342 if (scheme_it == valid_schemes.end()) {
343 return kcenon::common::VoidResult::err(
344 kcenon::common::error_info("Invalid naming scheme: " + config.storage.naming_scheme));
345 }
346
347 // Validate duplicate policy
348 const std::vector<std::string> valid_policies = {"reject", "replace", "rename"};
349 auto policy_it = std::find(valid_policies.begin(), valid_policies.end(),
350 config.storage.duplicate_policy);
351 if (policy_it == valid_policies.end()) {
352 return kcenon::common::VoidResult::err(
353 kcenon::common::error_info("Invalid duplicate policy: " + config.storage.duplicate_policy));
354 }
355
356 return kcenon::common::VoidResult::ok(std::monostate{});
357}

The documentation for this class was generated from the following files: