Auto-Generation of Component Structs
InfrastructureSystems.jl
provides a mechanism to auto-generate Julia files containing structs and field accessor functions from JSON descriptors. Here are reasons to consider using this approach:
- Auto-generation allows for easy refactoring of code. Adding fields to many structs can be tedious because you might have to edit many constructors. This process eliminates boiler-plate edits.
- The JSON descriptor format includes a mechanism to define range validation on component fields. Validation can be enabled when adding components to a system.
- Provides consistent formatting of structs, fields, and constructors.
- Provides consistent documentation of structs and fields.
Instructions
Refer to the docstrings for generate_struct
and generate_structs
and generate the files from the REPL.
Or
- Create or modify the JSON descriptor file. Follow the PowerSystems.jl example.
- Run the generation script, passing your descriptor file and an output directory.
InfrastructureSystems.generate_structs(
"./src/descriptors/power_system_structs.json",
"./src/models/generated",
)
Struct Descriptor Rules
Each struct descriptor must define the following fields:
struct_name
: Name of structdocstring
: The docstring of the structfields
: Array of struct members. See below for requirements.supertype
: Declare the struct with this parent type.
Required fields for each struct member:
name
: Name of fielddata_type
: Type of field
Optional fields for each struct member:
accessor_module
: Set this if the getter/setter functions are reimplementing a method defined in a different module.comment
: Field commentdefault
: The constructors will define this as a default value.exclude_setter
: Do not generate a setter function for this field.internal_default
: Set to true for non-user-facing fields likeInfrastructureSystemsInternal
that have default values.needs_conversion
: Set to true if the getter and setter function needs to apply unit conversion. The type must implementget_value(::InfrastructureSystemsComponent, ::Type)
andset_value(::InfrastructureSystemsComponent, ::Type)
for this combination of component type and member type.
null_value
: Value to indicate the value is null, such as 0.0 for floating point numbers. If all members in the struct define this field then a "demo" constructor will be generated. This allows you to enterval = MyType(nothing)
in the REPL and see the layout of a struct without worrying about valid values.valid_range
: Define this as a Dict withmin
andmax
andInfrastructureSystems.jl
will validate any value against that range when you add the component to the system. Usenull
if one doesn't apply, such as if there is no max limit.validation_action
: Define this aserror
orwarn
. If it iserror
thenInfrastructureSystems.jl
will raise an exception if the validation code detects a problem. Otherwise, it will log a warning.
Notes:
- You will need to decide how to manage the generated files. The Sienna packages keep the generated code in the git repository. This is not required. You could choose to generate them at startup.
- You may need to create custom constructors and this approach will not allow you to put them in the same file as the struct definition.