mdmodels 0.2.10

A tool to generate models, code and schemas from markdown files
Documentation
{# Helper macros for Julia type generation #}

{# 
  get_type: Determines the appropriate Julia type based on attribute properties
  Parameters:
    - attr: Attribute object containing dtypes and other properties
    - parent_name: Name of the parent struct
    - object_names: List of available object type names
  Returns: The appropriate Julia type as a string
#}
{% macro get_type(attr, parent_name, object_names) -%}
{%- if attr.dtypes | length > 1 -%}
{{ parent_name }}{{ attr.name | to_identifier | capitalize }}Type
{%- elif attr.dtypes[0] in object_names -%}
{{ attr.dtypes[0] }}
{%- elif attr.dtypes[0] == "string" or attr.dtypes[0] in enum_names -%}
String
{%- elif attr.dtypes[0] == "float" -%}
Float64
{%- elif attr.dtypes[0] == "integer" -%}
Int64
{%- elif attr.dtypes[0] == "boolean" -%}
Bool
{%- else -%}
{{ attr.dtypes[0] }}
{%- endif -%}
{%- endmacro %}

{# 
  wrap_type: Wraps types in appropriate containers based on multiplicity and optionality
  Parameters:
    - attr: Attribute object containing multiple and required flags
    - parent_name: Name of the parent struct
    - object_names: List of available object type names
  Returns: The wrapped Julia type as a string
#}
{% macro wrap_type(attr, parent_name, object_names) -%}
{%- if attr.multiple -%}
Union{Vector{ {{ get_type(attr, parent_name, object_names) }} }, Nothing}
{%- else -%}
{%- if attr.required is false -%}
Union{ {{ get_type(attr, parent_name, object_names) }}, Nothing}
{%- else -%}
{{ get_type(attr, parent_name, object_names) }}
{%- endif -%}
{%- endif -%}
{%- endmacro %}

{# 
  generate_union_struct: Generates a union type struct for a specific dtype
  Parameters:
    - object_name: Name of the parent object
    - attr_name: Name of the attribute
    - dtype: The specific data type for this union variant
    - object_names: List of available object type names
  Returns: The appropriate struct definition
#}
{% macro generate_union_struct(object_name, attr_name, dtype, object_names) -%}
{%- if dtype in object_names or dtype in enum_names %}
struct {{ object_name }}{{ attr_name | to_identifier | capitalize }}{{ dtype }} <: {{ object_name }}{{ attr_name | to_identifier | capitalize }}Type
    value::{{ dtype }}
end
{%- elif dtype == "string" %}
struct {{ object_name }}{{ attr_name | to_identifier | capitalize }}String <: {{ object_name }}{{ attr_name | to_identifier | capitalize }}Type
    value::String
end
{%- elif dtype == "float" %}
struct {{ object_name }}{{ attr_name | to_identifier | capitalize }}Float <: {{ object_name }}{{ attr_name | to_identifier | capitalize }}Type
    value::Float64
end
{%- elif dtype == "integer" %}
struct {{ object_name }}{{ attr_name | to_identifier | capitalize }}Integer <: {{ object_name }}{{ attr_name | to_identifier | capitalize }}Type
    value::Int64
end
{%- elif dtype == "boolean" %}
struct {{ object_name }}{{ attr_name | to_identifier | capitalize }}Boolean <: {{ object_name }}{{ attr_name | to_identifier | capitalize }}Type
    value::Bool
end
{%- else %}
struct {{ object_name }}{{ attr_name | to_identifier | capitalize }}{{ dtype | capitalize }} <: {{ object_name }}{{ attr_name | to_identifier | capitalize }}Type
    value::{{ dtype }}
end
{%- endif -%}
{%- endmacro %}

# This file contains Julia type definitions with JSON serialization.
# 
# WARNING: This is an auto-generated file.
# Do not edit directly - any changes will be overwritten.

module {% if title -%}{{ title | replace_lower(" ", "_") | pascal_case }}{% else %}Model{% endif %}

using JSON3
using StructTypes

#=
  Type Definitions
  ---------------
  Main struct definitions with their fields and JSON serialization support.
=#
{%- for object in objects %}

{# Generate union types for this object if any exist #}
{%- for attr in object.attributes %}
{%- if attr.dtypes | length > 1 %}
#=
  Union Type Definitions for {{ object.name }}.{{ attr.name }}
  ---------------------
  Custom union types for fields that can accept multiple types.
=#

"""
Union type for {{ object.name }}.{{ attr.name }}
"""
abstract type {{ object.name }}{{ attr.name | to_identifier | capitalize }}Type end

{%- for dtype in attr.dtypes %}
{{ generate_union_struct(object.name, attr.name, dtype, object_names) }}
{%- endfor %}

export {{ object.name }}{{ attr.name | to_identifier | capitalize }}Type
{%- for dtype in attr.dtypes %}
{%- if dtype in object_names or dtype in enum_names %}
export {{ object.name }}{{ attr.name | to_identifier | capitalize }}{{ dtype }}
{%- elif dtype == "string" %}
export {{ object.name }}{{ attr.name | to_identifier | capitalize }}String
{%- elif dtype == "float" %}
export {{ object.name }}{{ attr.name | to_identifier | capitalize }}Float
{%- elif dtype == "integer" %}
export {{ object.name }}{{ attr.name | to_identifier | capitalize }}Integer
{%- elif dtype == "boolean" %}
export {{ object.name }}{{ attr.name | to_identifier | capitalize }}Boolean
{%- else %}
export {{ object.name }}{{ attr.name | to_identifier | capitalize }}{{ dtype | capitalize }}
{%- endif %}
{%- endfor %}

{%- endif %}
{%- endfor %}

{# Generate the main struct definition #}
{%- if object.docstring %}
"""
{{ wrap(object.docstring, 70, "", "", None) }}
"""
{%- endif %}
Base.@kwdef mutable struct {{ object.name }}
    {%- for attr in object.attributes %}
    {%- if attr.docstring %}
    """
    {{ wrap(attr.docstring, 70, "", "    ", None) }}
    """
    {%- endif %}
    {{ attr.name | to_identifier }}::{{ wrap_type(attr, object.name, object_names) }}{% if attr.required is false %} = nothing{% endif %}
    {% endfor %}
end

export {{ object.name }}
{% endfor %}

end # module {{ title | replace_lower(" ", "_") }}