# Copyright 2025, Battelle Energy Alliance, LLC ALL RIGHTS RESERVED
import jsonschema
import jsonpointer
import logging
[docs]
logger = logging.getLogger('BAHAMAS.validate')
# schema is generated by AI and validated by wangc
[docs]
bbn_schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"description": "Schema to validate a TOML input configuration for BAHAMAS input",
"properties": {
"BBN":{
"type": "object",
"description": "BBN configuration settings",
"properties":{
"params": {
"type": "object",
"description": "Parameters for the analysis process.",
"properties": {
"samples": {
"type": "integer",
"minimum": 1,
"description": "The number of samples to be used in the analysis."
},
"seed": {
"type": "integer",
"minimum": 0,
"description": "The seed value for random number generation to ensure reproducibility."
}
},
"required": ["samples"]
},
"files": {
"type": "object",
"description": "File paths for required data inputs.",
"properties": {
"task": {
"type": "string",
"format": "uri-reference",
"description": "Path to the task list file."
},
"defect": {
"type": "string",
"format": "uri-reference",
"description": "Path to the defect data file."
},
"approx": {
"type": "string",
"format": "uri-reference",
"description": "Path to the SDLC macro data file."
}
},
"required": ["defect"]
},
"analysis": {
"type": "object",
"description": "Configuration for the type of analysis to be performed.",
"properties": {
"type": {
"type": "string",
"enum": ["precise", "approx"],
"description": "The type of analysis: 'precise' for task level assessment, 'approx' for stage level assessment."
}
},
"required": ["type"]
}
},
"required": ["params", "files", "analysis"],
"allOf": [
{
"if": {
"properties": { "analysis": { "properties": { "type": { "const": "precise" } } } }
},
"then": {
"properties": {
"files": {
"required": ["task"]
}
}
}
},
{
"if": {
"properties": { "analysis": { "properties": { "type": { "const": "approx" } } } }
},
"then": {
"properties": {
"files": {
"required": ["approx"]
}
}
}
}
],
"additionalProperties": False
}
}
}
[docs]
ccf_schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "CCF Configuration",
"description": "Schema for validating CCF TOML configuration files",
"type": "object",
"properties": {
"CCF": {
"type": "object",
"description": "CCF configuration section",
"properties": {
"files": {
"type": "object",
"description": "File configurations for CCF",
"properties": {
"structure": {
"type": "string",
"description": "Path to the structure file"
}
},
"required": ["structure"]
},
"generate": {
"type": "object",
"description": "Generate CCCGs configurations for CCF",
"properties": {
"output_file_base": {
"type": "string",
"description": "Base name for the output files"
},
"output_type": {
"type": "string",
"enum": ["csv"],
"description": "Type of the output file"
},
"final": {
"type": "boolean",
"description": "Flag indicating if the final CCCGs output is required"
},
"single": {
"type": "boolean",
"description": "Flag indicating if single CCCGs output is required"
},
"double": {
"type": "boolean",
"description": "Flag indicating if double CCCGs output is required"
},
"triple": {
"type": "boolean",
"description": "Flag indicating if triple output CCCGs is required"
},
"function_all": {
"type": "boolean",
"description": "Flag indicating if all function related CCCGs output is required"
},
"input_all": {
"type": "boolean",
"description": "Flag indicating if all input related CCCGs output is required"
},
"design_all": {
"type": "boolean",
"description": "Flag indicating if all design related CCCGs output is required"
}
},
}
},
"required": ["files"]
}
},
# "required": ["CCF"]
}
schema.update(bbn_schema)
schema['properties'].update(ccf_schema['properties'])
[docs]
def validate_toml(config):
"""Validate TOML input file
Args:
config (dict): Loaded TOML input
Returns:
bool: True if valid
"""
try:
jsonschema.validate(instance=config, schema=schema)
logger.info("TOML input file is valid.")
return True
except jsonschema.exceptions.ValidationError as e:
logger.info("TOML input file is invalid.")
logger.info(e.message)
# Use jsonpointer to get the path to the error
path = e.absolute_path
pointer = jsonpointer.JsonPointer.from_parts(path)
logger.info("Path to error: %s", pointer)
# Optionally, print the part of the data causing the issue
try:
problematicData = pointer.resolve(config)
logger.info("Problematic data: %s", problematicData)
except jsonpointer.JsonPointerException:
logger.info("Could not resolve the path to the problematic data.")
return False