import logging

from mhd_model.model.definitions import MHD_MODEL_V0_1_MS_PROFILE_NAME
from mhd_model.model.v0_1.dataset.validation.profile.base import (
    EmbeddedRefValidation,
    RelationshipValidation,
)
from mhd_model.model.v0_1.dataset.validation.profile.definition import (
    CvNodeValidation,
    CvTermValidation,
    FilterCondition,
    MhDatasetValidation,
    NodePropertyValidation,
    NodeValidation,
    PropertyConstraint,
)
from mhd_model.model.v0_1.rules.managed_cv_term_rules import (
    MANAGED_CHARACTERISTIC_VALUE_RULES,
    MANAGED_CHEMICAL_DATABASE_IDENTIFIER_RULE,
    MANAGED_FACTOR_VALUE_RULES,
    MANAGED_FILE_FORMAT_RULES,
    MANAGED_PARAMETER_VALUE_RULES,
)
from mhd_model.model.v0_1.rules.managed_cv_terms import (
    COMMON_ASSAY_TYPES,
    COMMON_CHARACTERISTIC_DEFINITION_ENFORCEMENT_LEVELS,
    COMMON_CHARACTERISTIC_DEFINITIONS,
    COMMON_MEASUREMENT_TYPES,
    COMMON_OMICS_TYPES,
    COMMON_PARAMETER_DEFINITIONS,
    COMMON_PARAMETER_ENFORCEMENT_LEVELS,
    COMMON_PROTOCOL_PARAMETER_MAPPINGS,
    COMMON_PROTOCOLS,
    COMMON_STUDY_FACTOR_DEFINITION_ENFORCEMENT_LEVELS,
    COMMON_STUDY_FACTOR_DEFINITIONS,
    COMMON_TECHNOLOGY_TYPES,
)
from mhd_model.shared.validation.definitions import (
    AllowAnyCvTerm,
    AllowedCvTerms,
    CvTermPlaceholder,
)

logger = logging.getLogger(__name__)

MHD_MS_PROFILE_V0_1 = MhDatasetValidation(schema=MHD_MODEL_V0_1_MS_PROFILE_NAME)

MHD_MS_PROFILE_V0_1.mhd_nodes = [
    NodeValidation(
        node_type="assay",
        min=1,
        validations=[
            NodePropertyValidation(
                identifier="assay-001-01",
                node_type="assay",
                node_property_name="repository_identifier",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            NodePropertyValidation(
                identifier="assay-001-02",
                node_type="assay",
                node_property_name="name",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            EmbeddedRefValidation(
                identifier="assay-002-01",
                node_type="assay",
                node_property_name="metadata_file_ref",
                required=True,
                target_ref_types=["metadata-file"],
            ),
            EmbeddedRefValidation(
                identifier="assay-002-02",
                node_type="assay",
                node_property_name="technology_type_ref",
                required=True,
                target_ref_types=["descriptor"],
            ),
            EmbeddedRefValidation(
                identifier="assay-002-03",
                node_type="assay",
                node_property_name="assay_type_ref",
                required=True,
                target_ref_types=["descriptor"],
            ),
            EmbeddedRefValidation(
                identifier="assay-002-04",
                node_type="assay",
                node_property_name="measurement_type_ref",
                required=True,
                target_ref_types=["descriptor"],
            ),
            EmbeddedRefValidation(
                identifier="assay-002-05",
                node_type="assay",
                node_property_name="omics_type_ref",
                required=True,
                target_ref_types=["descriptor"],
            ),
            EmbeddedRefValidation(
                identifier="assay-002-06",
                node_type="assay",
                node_property_name="protocol_refs",
                required=False,
                target_ref_types=["protocol"],
            ),
            EmbeddedRefValidation(
                identifier="assay-002-07",
                node_type="assay",
                node_property_name="sample_run_refs",
                required=True,
                target_ref_types=["sample-run"],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="assay-003-01",
                description="A link to a descriptor that describes the assay.",
                source="assay",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="assay-003-02",
                description="A link to a study that the assay was conducted as part of it "
                "to generate data addressing study objectives",
                source="assay",
                relationship_name="part-of",
                reverse_relationship_name="has-assay",
                target="study",
                min=1,
                min_for_each_source=1,
                max_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="assay-003-03",
                description="A link to a protocol conducted in assay.",
                source="assay",
                relationship_name="follows",
                reverse_relationship_name="used-in",
                target="protocol",
                min=0,
                min_for_each_source=1,
            ),
        ],
    ),
    NodeValidation(
        node_type="characteristic-definition",
        min=len(COMMON_CHARACTERISTIC_DEFINITION_ENFORCEMENT_LEVELS["required"]),
        validations=[
            NodePropertyValidation(
                identifier="characteristic-definition-001-01",
                node_type="characteristic-definition",
                node_property_name="name",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            EmbeddedRefValidation(
                identifier="characteristic-definition-002-01",
                node_type="characteristic-definition",
                node_property_name="characteristic_type_ref",
                required=True,
                target_ref_types=["characteristic-type"],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="characteristic-definition-003-01",
                source="characteristic-definition",
                relationship_name="has-instance",
                reverse_relationship_name="instance-of",
                target="characteristic-value",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="characteristic-definition-003-02",
                source="characteristic-definition",
                relationship_name="has-instance",
                reverse_relationship_name="instance-of",
                target="characteristic-value",
                min=0,
                min_for_each_source=1,
                condition=[
                    FilterCondition(
                        name="organism",
                        relationship_name="[embedded].characteristic_type_ref",
                        expression="characteristic_type_ref.name",
                        expression_value="organism",
                    )
                ],
            ),
            RelationshipValidation(
                identifier="characteristic-definition-003-03",
                source="characteristic-definition",
                relationship_name="has-instance",
                reverse_relationship_name="instance-of",
                target="characteristic-value",
                min=0,
                min_for_each_source=1,
                condition=[
                    FilterCondition(
                        name="organism part",
                        relationship_name="[embedded].characteristic_type_ref",
                        expression="characteristic_type_ref.name",
                        expression_value="organism part",
                    )
                ],
            ),
            RelationshipValidation(
                identifier="characteristic-definition-003-04",
                source="characteristic-definition",
                relationship_name="has-instance",
                reverse_relationship_name="instance-of",
                target="characteristic-value",
                min=0,
                min_for_each_source=1,
                condition=[
                    FilterCondition(
                        name="cell type",
                        relationship_name="[embedded].characteristic_type_ref",
                        expression="characteristic_type_ref.name",
                        expression_value="cell type",
                    )
                ],
            ),
            RelationshipValidation(
                identifier="characteristic-definition-003-05",
                source="characteristic-definition",
                relationship_name="has-instance",
                reverse_relationship_name="instance-of",
                target="characteristic-value",
                min=0,
                min_for_each_source=1,
                condition=[
                    FilterCondition(
                        name="disease",
                        relationship_name="[embedded].characteristic_type_ref",
                        expression="characteristic_type_ref.name",
                        expression_value="disease",
                    )
                ],
            ),
            RelationshipValidation(
                identifier="characteristic-definition-003-06",
                source="characteristic-definition",
                relationship_name="has-type",
                reverse_relationship_name="type-of",
                target="characteristic-type",
                min=0,
                min_for_each_source=1,
                max_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="characteristic-definition-003-07",
                source="characteristic-definition",
                relationship_name="used-in",
                reverse_relationship_name="has-characteristic-definition",
                target="study",
                min=1,
                min_for_each_source=1,
            ),
        ],
    ),
    NodeValidation(
        node_type="derived-data-file",
        min=0,
        validations=[
            NodePropertyValidation(
                identifier="derived-data-file-001-01",
                node_type="derived-data-file",
                node_property_name="url_list",
                constraints=PropertyConstraint(required=True, min_length=1),
            ),
            NodePropertyValidation(
                identifier="derived-data-file-001-02",
                node_type="derived-data-file",
                node_property_name="name",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            NodePropertyValidation(
                identifier="derived-data-file-001-03",
                node_type="derived-data-file",
                node_property_name="extension",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            EmbeddedRefValidation(
                identifier="derived-data-file-002-01",
                node_type="derived-data-file",
                node_property_name="format_ref",
                constraints=PropertyConstraint(required=False),
                target_ref_types=["descriptor"],
            ),
            EmbeddedRefValidation(
                identifier="derived-data-file-002-02",
                node_type="derived-data-file",
                node_property_name="compression_format_refs",
                constraints=PropertyConstraint(required=False),
                target_ref_types=["descriptor"],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="derived-data-file-003-01",
                source="derived-data-file",
                relationship_name="referenced-in",
                reverse_relationship_name="references",
                target="metadata-file",
                min=0,
                min_for_each_source=0,
                max_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="derived-data-file-003-02",
                source="derived-data-file",
                relationship_name="created-in",
                reverse_relationship_name="has-derived-data-file",
                target="study",
                min=0,
                min_for_each_source=1,
                max_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="derived-data-file-003-03",
                description="A link to a descriptor that describes the derived data file.",
                source="derived-data-file",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
                max_for_each_source=0,
            ),
        ],
    ),
    NodeValidation(
        node_type="factor-definition",
        min=0,
        validations=[
            NodePropertyValidation(
                identifier="factor-definition-001-01",
                node_type="factor-definition",
                node_property_name="name",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            EmbeddedRefValidation(
                identifier="factor-definition-002-01",
                node_type="factor-definition",
                node_property_name="factor_type_ref",
                required=True,
                target_ref_types=["factor-type"],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="factor-definition-003-01",
                source="factor-definition",
                relationship_name="has-type",
                reverse_relationship_name="type-of",
                target="factor-type",
                min=0,
                min_for_each_source=1,
                max_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="factor-definition-003-02",
                source="factor-definition",
                relationship_name="has-instance",
                reverse_relationship_name="instance-of",
                target="factor-value",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="factor-definition-003-03",
                source="factor-definition",
                relationship_name="used-in",
                reverse_relationship_name="has-factor-definition",
                target="study",
                min=0,
                min_for_each_source=1,
            ),
        ],
    ),
    NodeValidation(
        node_type="metadata-file",
        min=1,
        validations=[
            NodePropertyValidation(
                identifier="metadata-file-001-01",
                node_type="metadata-file",
                node_property_name="url_list",
                constraints=PropertyConstraint(required=True, min_length=1),
            ),
            NodePropertyValidation(
                identifier="metadata-file-001-02",
                node_type="metadata-file",
                node_property_name="name",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            NodePropertyValidation(
                identifier="metadata-file-001-03",
                node_type="metadata-file",
                node_property_name="extension",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            EmbeddedRefValidation(
                identifier="metadata-file-002-01",
                node_type="metadata-file",
                node_property_name="format_ref",
                constraints=PropertyConstraint(required=False),
                target_ref_types=["descriptor"],
            ),
            EmbeddedRefValidation(
                identifier="metadata-file-002-02",
                node_type="metadata-file",
                node_property_name="compression_format_refs",
                constraints=PropertyConstraint(required=False),
                target_ref_types=["descriptor"],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="metadata-file-003-01",
                source="metadata-file",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="metadata-file-003-02",
                source="metadata-file",
                relationship_name="referenced-in",
                reverse_relationship_name="references",
                target="metadata-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="metadata-file-003-03",
                source="metadata-file",
                relationship_name="describes",
                reverse_relationship_name="has-metadata-file",
                target="study",
                min=1,
                min_for_each_source=1,
                max_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="metadata-file-003-04",
                source="metadata-file",
                relationship_name="references",
                reverse_relationship_name="referenced-in",
                target="derived-data-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="metadata-file-003-05",
                source="metadata-file",
                relationship_name="references",
                reverse_relationship_name="referenced-in",
                target="raw-data-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="metadata-file-003-06",
                source="metadata-file",
                relationship_name="references",
                reverse_relationship_name="referenced-in",
                target="result-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="metadata-file-003-07",
                source="metadata-file",
                relationship_name="references",
                reverse_relationship_name="referenced-in",
                target="supplementary-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="metadata-file-003-08",
                source="metadata-file",
                relationship_name="reports",
                reverse_relationship_name="reported-in",
                target="metabolite",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    NodeValidation(
        node_type="metabolite",
        min=0,
        validations=[
            NodePropertyValidation(
                identifier="metabolite-001-01",
                node_type="metabolite",
                node_property_name="name",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="metabolite-003-01",
                source="metabolite",
                relationship_name="identified-as",
                reverse_relationship_name="reported-identifier-of",
                target="metabolite-identifier",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="metabolite-003-02",
                source="metabolite",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="metabolite-003-03",
                source="metabolite",
                relationship_name="reported-in",
                reverse_relationship_name="reports",
                target="study",
                min=0,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="metabolite-003-04",
                source="metabolite",
                relationship_name="reported-in",
                reverse_relationship_name="reports",
                target="metadata-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="metabolite-003-05",
                source="metabolite",
                relationship_name="reported-in",
                reverse_relationship_name="reports",
                target="result-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="metabolite-003-06",
                source="metabolite",
                relationship_name="measured-in",
                reverse_relationship_name="measures",
                target="raw-data-file",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    NodeValidation(
        node_type="organization",
        min=1,
        validations=[
            NodePropertyValidation(
                identifier="organization-001-01",
                node_type="organization",
                node_property_name="repository_identifier",
                constraints=PropertyConstraint(required=False),
            ),
            NodePropertyValidation(
                identifier="organization-001-02",
                node_type="organization",
                node_property_name="name",
                constraints=PropertyConstraint(required=True, min_length=10),
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="organization-003-01",
                source="organization",
                relationship_name="funds",
                reverse_relationship_name="funded-by",
                target="project",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="organization-003-02",
                source="organization",
                relationship_name="funds",
                reverse_relationship_name="funded-by",
                target="study",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="organization-003-03",
                source="organization",
                relationship_name="manages",
                reverse_relationship_name="managed-by",
                target="project",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="organization-003-04",
                source="organization",
                relationship_name="coordinates",
                reverse_relationship_name="coordinated-by",
                target="project",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="organization-003-05",
                source="organization",
                relationship_name="affiliates",
                reverse_relationship_name="affiliated-with",
                target="person",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="organization-003-06",
                source="organization",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    NodeValidation(
        node_type="parameter-definition",
        min=1,
        validations=[
            NodePropertyValidation(
                identifier="parameter-definition-001-01",
                node_type="parameter-definition",
                node_property_name="name",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            EmbeddedRefValidation(
                identifier="parameter-definition-002-01",
                node_type="parameter-definition",
                node_property_name="parameter_type_ref",
                required=True,
                target_ref_types=["parameter-type"],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="parameter-definition-003-01",
                source="parameter-definition",
                relationship_name="has-instance",
                reverse_relationship_name="instance-of",
                target="parameter-value",
                min=1,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="parameter-definition-003-02",
                source="parameter-definition",
                relationship_name="has-type",
                reverse_relationship_name="type-of",
                target="parameter-type",
                min=0,
                min_for_each_source=1,
                max_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="parameter-definition-003-03",
                source="parameter-definition",
                relationship_name="used-in",
                reverse_relationship_name="has-parameter-definition",
                target="protocol",
                min=1,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="parameter-definition-003-04",
                source="parameter-definition",
                relationship_name="has-instance",
                reverse_relationship_name="instance-of",
                target="parameter-value",
                min=0,
                min_for_each_source=1,
                condition=[
                    FilterCondition(
                        name="mass spectrometry instrument",
                        relationship_name="[embedded].parameter_type_ref",
                        expression="parameter_type_ref.name",
                        expression_value="mass spectrometry instrument",
                    )
                ],
            ),
            RelationshipValidation(
                identifier="parameter-definition-003-05",
                source="parameter-definition",
                relationship_name="has-instance",
                reverse_relationship_name="instance-of",
                target="parameter-value",
                min=0,
                min_for_each_source=1,
                condition=[
                    FilterCondition(
                        name="acquisition polarity",
                        relationship_name="[embedded].parameter_type_ref",
                        expression="parameter_type_ref.name",
                        expression_value="acquisition polarity",
                    )
                ],
            ),
            RelationshipValidation(
                identifier="parameter-definition-003-06",
                source="parameter-definition",
                relationship_name="has-instance",
                reverse_relationship_name="instance-of",
                target="parameter-value",
                min=0,
                min_for_each_source=1,
                condition=[
                    FilterCondition(
                        name="acquisition polarity",
                        relationship_name="[embedded].parameter_type_ref",
                        expression="parameter_type_ref.name",
                        expression_value="acquisition polarity",
                    )
                ],
            ),
        ],
    ),
    NodeValidation(
        node_type="person",
        min=1,
        validations=[
            NodePropertyValidation(
                identifier="person-001-01",
                node_type="person",
                node_property_name="full_name",
                constraints=PropertyConstraint(required=True, min_length=5),
            ),
            NodePropertyValidation(
                identifier="person-001-02",
                node_type="person",
                node_property_name="email_list",
                constraints=PropertyConstraint(required=True, min_length=1),
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="person-003-01",
                source="person",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="person-003-02",
                source="person",
                relationship_name="affiliated-with",
                reverse_relationship_name="affiliates",
                target="organization",
                min=0,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="person-003-03",
                source="person",
                relationship_name="contributes",
                reverse_relationship_name="has-contributor",
                target="project",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="person-003-04",
                source="person",
                relationship_name="contributes",
                reverse_relationship_name="has-contributor",
                target="study",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="person-003-05",
                source="person",
                relationship_name="principal-investigator-of",
                reverse_relationship_name="has-principal-investigator",
                target="study",
                min=1,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="person-003-06",
                source="person",
                relationship_name="submits",
                reverse_relationship_name="submitted-by",
                target="study",
                min=1,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="person-003-07",
                source="person",
                relationship_name="author-of",
                reverse_relationship_name="has-author",
                target="publication",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    NodeValidation(
        node_type="project",
        min=0,
        validations=[
            NodePropertyValidation(
                identifier="project-001-01",
                node_type="project",
                node_property_name="title",
                constraints=PropertyConstraint(required=True, min_length=25),
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="project-003-01",
                source="project",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="project-003-02",
                source="project",
                relationship_name="funded-by",
                reverse_relationship_name="funds",
                target="organization",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="project-003-03",
                source="project",
                relationship_name="managed-by",
                reverse_relationship_name="manages",
                target="organization",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="project-003-04",
                source="project",
                relationship_name="coordinated-by",
                reverse_relationship_name="coordinates",
                target="organization",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="project-003-05",
                source="project",
                relationship_name="has-contributor",
                reverse_relationship_name="contributes",
                target="person",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="project-003-06",
                source="project",
                relationship_name="has-publication",
                reverse_relationship_name="describes",
                target="publication",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="project-003-07",
                source="project",
                relationship_name="has-study",
                reverse_relationship_name="part-of",
                target="study",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    NodeValidation(
        node_type="protocol",
        min=1,
        validations=[
            NodePropertyValidation(
                identifier="protocol-001-01",
                node_type="protocol",
                node_property_name="name",
                constraints=PropertyConstraint(required=True),
            ),
            NodePropertyValidation(
                identifier="protocol-001-02",
                node_type="protocol",
                node_property_name="description",
                constraints=PropertyConstraint(required=False),
            ),
            EmbeddedRefValidation(
                identifier="protocol-002-01",
                node_type="protocol",
                node_property_name="protocol_type_ref",
                required=True,
                target_ref_types=["protocol-type"],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="protocol-003-01",
                source="protocol",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="protocol-003-02",
                source="protocol",
                relationship_name="used-in",
                reverse_relationship_name="follows",
                target="assay",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="protocol-003-03",
                source="protocol",
                relationship_name="has-parameter-definition",
                reverse_relationship_name="used-in",
                target="parameter-definition",
                min=1,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="protocol-003-04",
                source="protocol",
                relationship_name="has-parameter-value",
                reverse_relationship_name="value-of",
                target="parameter-value",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="protocol-003-05",
                source="protocol",
                relationship_name="used-in",
                reverse_relationship_name="has-protocol",
                target="study",
                min=1,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="protocol-003-06",
                source="protocol",
                relationship_name="has-type",
                reverse_relationship_name="type-of",
                target="protocol-type",
                min=0,
                min_for_each_source=1,
                max_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="protocol-003-07",
                source="protocol",
                relationship_name="has-parameter-definition",
                reverse_relationship_name="used-in",
                target="parameter-definition",
                min=1,
                min_for_each_source=0,
                condition=[
                    FilterCondition(
                        name="mass spectrometry",
                        relationship_name="[embedded].protocol_type_ref",
                        expression="protocol_type_ref.name",
                        expression_value="mass spectrometry",
                    )
                ],
            ),
        ],
    ),
    NodeValidation(
        node_type="publication",
        min=0,
        validations=[
            NodePropertyValidation(
                identifier="publication-001-01",
                node_type="publication",
                node_property_name="title",
                constraints=PropertyConstraint(required=True),
            ),
            NodePropertyValidation(
                identifier="publication-001-02",
                node_type="publication",
                node_property_name="doi",
                constraints=PropertyConstraint(required=True),
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="publication-003-01",
                source="publication",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="publication-003-02",
                source="publication",
                relationship_name="describes",
                reverse_relationship_name="has-publication",
                target="project",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="publication-003-03",
                source="publication",
                relationship_name="describes",
                reverse_relationship_name="has-publication",
                target="study",
                min=0,
                min_for_each_source=0,
                max_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="publication-003-04",
                source="publication",
                relationship_name="has-author",
                reverse_relationship_name="author-of",
                target="person",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    NodeValidation(
        node_type="raw-data-file",
        min=0,
        validations=[
            NodePropertyValidation(
                identifier="raw-data-file-001-01",
                node_type="raw-data-file",
                node_property_name="url_list",
                constraints=PropertyConstraint(required=True, min_length=1),
            ),
            NodePropertyValidation(
                identifier="raw-data-file-001-02",
                node_type="raw-data-file",
                node_property_name="name",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            NodePropertyValidation(
                identifier="raw-data-file-001-03",
                node_type="raw-data-file",
                node_property_name="extension",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            EmbeddedRefValidation(
                identifier="raw-data-file-002-01",
                node_type="raw-data-file",
                node_property_name="format_ref",
                constraints=PropertyConstraint(required=False),
                target_ref_types=["descriptor"],
            ),
            EmbeddedRefValidation(
                identifier="raw-data-file-002-02",
                node_type="raw-data-file",
                node_property_name="compression_format_refs",
                constraints=PropertyConstraint(required=False),
                target_ref_types=["descriptor"],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="raw-data-file-003-01",
                source="raw-data-file",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="raw-data-file-003-02",
                source="raw-data-file",
                relationship_name="created-in",
                reverse_relationship_name="has-raw-data-file",
                target="study",
                min=0,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="raw-data-file-003-03",
                source="raw-data-file",
                relationship_name="referenced-in",
                reverse_relationship_name="references",
                target="metadata-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="raw-data-file-003-04",
                source="raw-data-file",
                relationship_name="measures",
                reverse_relationship_name="measured-in",
                target="metabolite",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    NodeValidation(
        node_type="result-file",
        min=0,
        validations=[
            NodePropertyValidation(
                identifier="result-file-001-01",
                node_type="result-file",
                node_property_name="url_list",
                constraints=PropertyConstraint(required=True, min_length=1),
            ),
            NodePropertyValidation(
                identifier="result-file-001-02",
                node_type="result-file",
                node_property_name="name",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            NodePropertyValidation(
                identifier="result-file-001-03",
                node_type="result-file",
                node_property_name="extension",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            EmbeddedRefValidation(
                identifier="result-file-002-01",
                node_type="result-file",
                node_property_name="format_ref",
                constraints=PropertyConstraint(required=False),
                target_ref_types=["descriptor"],
            ),
            EmbeddedRefValidation(
                identifier="result-file-002-02",
                node_type="result-file",
                node_property_name="compression_format_refs",
                constraints=PropertyConstraint(required=False),
                target_ref_types=["descriptor"],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="result-file-003-01",
                source="result-file",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="result-file-003-02",
                source="result-file",
                relationship_name="created-in",
                reverse_relationship_name="has-result-file",
                target="study",
                min=0,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="result-file-003-03",
                source="result-file",
                relationship_name="referenced-in",
                reverse_relationship_name="references",
                target="metadata-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="result-file-003-04",
                source="result-file",
                relationship_name="reports",
                reverse_relationship_name="reported-in",
                target="metabolite",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    NodeValidation(
        node_type="sample",
        min=1,
        validations=[
            NodePropertyValidation(
                identifier="sample-001-01",
                node_type="sample",
                node_property_name="name",
                constraints=PropertyConstraint(required=True, min_length=1),
            ),
            NodePropertyValidation(
                identifier="sample-001-02",
                node_type="sample",
                node_property_name="repository_identifier",
                constraints=PropertyConstraint(required=False),
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="sample-003-01",
                source="sample",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="sample-003-02",
                source="sample",
                relationship_name="has-factor-value",
                reverse_relationship_name="value-of",
                target="factor-value",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="sample-003-03",
                source="sample",
                relationship_name="used-in",
                reverse_relationship_name="has-sample",
                target="study",
                min=0,
                min_for_each_source=1,
                max_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="sample-003-04",
                source="sample",
                relationship_name="derived-from",
                reverse_relationship_name="source-of",
                target="subject",
                min=0,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="sample-003-05",
                source="sample",
                relationship_name="derived-from",
                reverse_relationship_name="source-of",
                target="specimen",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="sample-003-06",
                source="sample",
                relationship_name="has-characteristic-value",
                reverse_relationship_name="value-of",
                target="characteristic-value",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    NodeValidation(
        node_type="sample-run",
        min=1,
        validations=[
            NodePropertyValidation(
                identifier="sample-run-001-01",
                node_type="sample-run",
                node_property_name="name",
                constraints=PropertyConstraint(required=False),
            ),
            EmbeddedRefValidation(
                identifier="sample-run-002-01",
                node_type="sample-run",
                node_property_name="sample_ref",
                required=True,
                target_ref_types=["sample"],
            ),
            EmbeddedRefValidation(
                identifier="sample-run-002-02",
                node_type="sample-run",
                node_property_name="sample_run_configuration_refs",
                required=False,
                target_ref_types=["sample-run-configuration"],
            ),
            EmbeddedRefValidation(
                identifier="sample-run-002-03",
                node_type="sample-run",
                node_property_name="raw_data_file_refs",
                required=True,
                target_ref_types=["raw-data-file"],
            ),
            EmbeddedRefValidation(
                identifier="sample-run-002-04",
                node_type="sample-run",
                node_property_name="derived_data_file_refs",
                required=False,
                target_ref_types=["derived-data-file"],
            ),
            EmbeddedRefValidation(
                identifier="sample-run-002-05",
                node_type="sample-run",
                node_property_name="result_file_refs",
                required=False,
                target_ref_types=["result-file"],
            ),
            EmbeddedRefValidation(
                identifier="sample-run-002-06",
                node_type="sample-run",
                node_property_name="supplementary_file_refs",
                required=False,
                target_ref_types=["supplementary-file"],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="sample-run-003-01",
                source="sample-run",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    NodeValidation(
        node_type="sample-run-configuration",
        min=0,
        validations=[
            EmbeddedRefValidation(
                identifier="sample-run-configuration-002-01",
                node_type="sample-run-configuration",
                node_property_name="protocol_ref",
                required=True,
                target_ref_types=["protocol"],
            ),
            EmbeddedRefValidation(
                identifier="sample-run-configuration-002-02",
                node_type="sample-run-configuration",
                node_property_name="parameter_value_refs",
                required=False,
                target_ref_types=["parameter-value"],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="sample-run-configuration-003-01",
                source="sample-run-configuration",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    NodeValidation(
        node_type="study",
        min=1,
        max=1,
        validations=[
            # CvTermValidation(
            #     node_type="study",
            #     node_property_name="additional_identifier_list",
            #     validation=AllowAnyCvTerm(
            #         allowed_other_sources=["wikidata", "ILX"],
            #     ),
            #     required=False,
            # ),
            NodePropertyValidation(
                identifier="study-001-01",
                node_type="study",
                node_property_name="mhd_identifier",
                constraints=PropertyConstraint(
                    required=True, min_length=8, pattern="^MHD[A-Z]?[0-9]{6,8}$"
                ),
            ),
            NodePropertyValidation(
                identifier="study-001-02",
                node_type="study",
                node_property_name="repository_identifier",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            NodePropertyValidation(
                identifier="study-001-03",
                node_type="study",
                node_property_name="title",
                constraints=PropertyConstraint(required=True, min_length=25),
            ),
            NodePropertyValidation(
                identifier="study-001-04",
                node_type="study",
                node_property_name="description",
                constraints=PropertyConstraint(required=True, min_length=60),
            ),
            NodePropertyValidation(
                identifier="study-001-05",
                node_type="study",
                node_property_name="submission_date",
                constraints=PropertyConstraint(required=True),
            ),
            NodePropertyValidation(
                identifier="study-001-06",
                node_type="study",
                node_property_name="public_release_date",
                constraints=PropertyConstraint(required=True),
            ),
            NodePropertyValidation(
                identifier="study-001-07",
                node_type="study",
                node_property_name="dataset_url_list",
                constraints=PropertyConstraint(required=True),
            ),
            NodePropertyValidation(
                identifier="study-001-08",
                node_type="study",
                node_property_name="license",
                constraints=PropertyConstraint(required=True),
            ),
            EmbeddedRefValidation(
                identifier="study-002-01",
                node_type="study",
                node_property_name="created_by_ref",
                required=True,
                target_ref_types=["data-provider"],
            ),
            EmbeddedRefValidation(
                identifier="study-002-02",
                node_type="study",
                node_property_name="protocol_refs",
                required=True,
                target_ref_types=["protocol"],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="study-003-01",
                source="study",
                relationship_name="provided-by",
                reverse_relationship_name="provides",
                target="data-provider",
                min=0,
                min_for_each_source=1,
                max_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="study-003-02",
                source="study",
                relationship_name="has-assay",
                reverse_relationship_name="part-of",
                target="assay",
                min=1,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="study-003-03",
                source="study",
                relationship_name="funded-by",
                reverse_relationship_name="funds",
                target="organization",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="study-003-04",
                source="study",
                relationship_name="has-characteristic-definition",
                reverse_relationship_name="used-in",
                target="characteristic-definition",
                min=2,
                min_for_each_source=2,
            ),
            RelationshipValidation(
                identifier="study-003-05",
                source="study",
                relationship_name="has-derived-data-file",
                reverse_relationship_name="created-in",
                target="derived-data-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="study-003-06",
                source="study",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="study-003-07",
                source="study",
                relationship_name="has-factor-definition",
                reverse_relationship_name="used-in",
                target="factor-definition",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="study-003-08",
                source="study",
                relationship_name="has-repository-keyword",
                reverse_relationship_name="keyword-of",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="study-003-09",
                source="study",
                relationship_name="has-submitter-keyword",
                reverse_relationship_name="keyword-of",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="study-003-10",
                source="study",
                relationship_name="reports",
                reverse_relationship_name="reported-in",
                target="metabolite",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="study-003-11",
                source="study",
                relationship_name="has-metadata-file",
                reverse_relationship_name="describes",
                target="metadata-file",
                min=1,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="study-003-12",
                source="study",
                relationship_name="has-contributor",
                reverse_relationship_name="contributes",
                target="person",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="study-003-13",
                source="study",
                relationship_name="has-principal-investigator",
                reverse_relationship_name="principal-investigator-of",
                target="person",
                min=1,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="study-003-14",
                source="study",
                relationship_name="submitted-by",
                reverse_relationship_name="submits",
                target="person",
                min=1,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="study-003-15",
                source="study",
                relationship_name="part-of",
                reverse_relationship_name="has-study",
                target="project",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="study-003-16",
                source="study",
                relationship_name="has-protocol",
                reverse_relationship_name="used-in",
                target="protocol",
                min=1,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="study-003-17",
                source="study",
                relationship_name="has-publication",
                reverse_relationship_name="describes",
                target="publication",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="study-003-18",
                source="study",
                relationship_name="has-raw-data-file",
                reverse_relationship_name="created-in",
                target="raw-data-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="study-003-19",
                source="study",
                relationship_name="has-result-file",
                reverse_relationship_name="created-in",
                target="result-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="study-003-20",
                source="study",
                relationship_name="has-sample",
                reverse_relationship_name="used-in",
                target="sample",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="study-003-21",
                source="study",
                relationship_name="has-supplementary-file",
                reverse_relationship_name="created-in",
                target="supplementary-file",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    NodeValidation(
        node_type="specimen",
        min=0,
        validations=[
            NodePropertyValidation(
                identifier="specimen-001-01",
                node_type="specimen",
                node_property_name="name",
                constraints=PropertyConstraint(required=True, min_length=1),
            ),
            NodePropertyValidation(
                identifier="specimen-001-02",
                node_type="specimen",
                node_property_name="repository_identifier",
                constraints=PropertyConstraint(required=False, min_length=1),
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="specimen-003-01",
                source="specimen",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="specimen-003-02",
                source="specimen",
                relationship_name="has-characteristic-value",
                reverse_relationship_name="value-of",
                target="characteristic-value",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="specimen-003-03",
                source="specimen",
                relationship_name="source-of",
                reverse_relationship_name="derived-from",
                target="sample",
                min=0,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="specimen-003-04",
                source="specimen",
                relationship_name="derived-from",
                reverse_relationship_name="source-of",
                target="subject",
                min=0,
                min_for_each_source=1,
            ),
        ],
    ),
    NodeValidation(
        node_type="subject",
        min=1,
        validations=[
            NodePropertyValidation(
                identifier="subject-001-01",
                node_type="subject",
                node_property_name="name",
                constraints=PropertyConstraint(required=True, min_length=1),
            ),
            NodePropertyValidation(
                identifier="subject-001-02",
                node_type="subject",
                node_property_name="repository_identifier",
                constraints=PropertyConstraint(required=False, min_length=1),
            ),
            EmbeddedRefValidation(
                identifier="subject-002-01",
                node_type="subject",
                node_property_name="subject_type_ref",
                required=False,
                target_ref_types=["descriptor"],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="subject-003-01",
                source="subject",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="subject-003-02",
                source="subject",
                relationship_name="has-characteristic-value",
                reverse_relationship_name="value-of",
                target="characteristic-value",
                min=0,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="subject-003-03",
                source="subject",
                relationship_name="source-of",
                reverse_relationship_name="derived-from",
                target="sample",
                min=0,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="subject-003-04",
                source="subject",
                relationship_name="has-factor-value",
                reverse_relationship_name="value-of",
                target="factor-value",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="subject-003-05",
                source="subject",
                relationship_name="source-of",
                reverse_relationship_name="derived-from",
                target="specimen",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    NodeValidation(
        node_type="supplementary-file",
        min=0,
        validations=[
            NodePropertyValidation(
                identifier="supplementary-file-001-01",
                node_type="supplementary-file",
                node_property_name="url_list",
                constraints=PropertyConstraint(required=True, min_length=1),
            ),
            NodePropertyValidation(
                identifier="supplementary-file-001-02",
                node_type="supplementary-file",
                node_property_name="name",
                constraints=PropertyConstraint(required=True, min_length=2),
            ),
            NodePropertyValidation(
                identifier="supplementary-file-001-03",
                node_type="supplementary-file",
                node_property_name="extension",
                constraints=PropertyConstraint(required=False),
            ),
            EmbeddedRefValidation(
                identifier="supplementary-file-002-01",
                node_type="supplementary-file",
                node_property_name="format_ref",
                constraints=PropertyConstraint(required=False),
                target_ref_types=["descriptor"],
            ),
            EmbeddedRefValidation(
                identifier="supplementary-file-002-02",
                node_type="supplementary-file",
                node_property_name="compression_format_refs",
                constraints=PropertyConstraint(required=False),
                target_ref_types=["descriptor"],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="supplementary-file-003-01",
                source="supplementary-file",
                relationship_name="described-as",
                reverse_relationship_name="describes",
                target="descriptor",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="supplementary-file-003-02",
                source="supplementary-file",
                relationship_name="created-in",
                reverse_relationship_name="has-supplementary-file",
                target="study",
                min=0,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="supplementary-file-003-03",
                source="supplementary-file",
                relationship_name="referenced-in",
                reverse_relationship_name="references",
                target="metadata-file",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
]

MHD_MS_PROFILE_V0_1.cv_nodes = [
    CvNodeValidation(
        node_type="characteristic-type",
        min=2,
        validations=[
            NodePropertyValidation(
                identifier="characteristic-type-001-01",
                node_type="characteristic-type",
                node_property_name="name",
                constraints=PropertyConstraint(required=True),
            ),
            CvTermValidation(
                identifier="characteristic-type-004-01",
                node_type="characteristic-type",
                validation=AllowAnyCvTerm(
                    allowed_placeholder_values=[CvTermPlaceholder()],
                    allowed_other_sources=["wikidata", "ILX"],
                ),
            ),
            CvTermValidation(
                identifier="characteristic-type-004-02",
                node_type="characteristic-type",
                min_count=1,
                validation=AllowedCvTerms(
                    cv_terms=list(COMMON_CHARACTERISTIC_DEFINITIONS.values())
                ),
                condition=[
                    FilterCondition(
                        name="Characteristic Type",
                        relationship_name="[embedded].characteristic_type_ref",
                        start_node_type="characteristic-definition",
                        expression="characteristic_type_ref",
                    )
                ],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="characteristic-type-003-01",
                source="characteristic-type",
                relationship_name="type-of",
                reverse_relationship_name="has-type",
                target="characteristic-definition",
                min=2,
                min_for_each_source=1,
            ),
        ],
    ),
    CvNodeValidation(
        node_type="characteristic-value",
        has_value=True,
        min=1,
        validations=[
            CvTermValidation(
                identifier="characteristic-value-004-01",
                node_type="characteristic-value",
                validation=AllowAnyCvTerm(
                    allowed_placeholder_values=[CvTermPlaceholder()],
                    allowed_other_sources=["wikidata", "ILX"],
                ),
            ),
            *[
                CvTermValidation(
                    identifier=f"characteristic-value-001-{(idx + 10):02}",
                    node_type="characteristic-value",
                    min_count=1
                    if parameter_name
                    in COMMON_CHARACTERISTIC_DEFINITION_ENFORCEMENT_LEVELS["required"]
                    else 0,
                    validation=rule,
                    condition=[
                        FilterCondition(
                            name=parameter_name,
                            relationship_name="instance-of",
                            start_node_type="characteristic-value",
                            expression="[instance-of].characteristic_type_ref.name",
                            expression_value=parameter_name,
                        )
                    ],
                )
                for idx, (parameter_name, rule) in enumerate(
                    MANAGED_CHARACTERISTIC_VALUE_RULES.items()
                )
            ],
        ],
        relationships=[
            RelationshipValidation(
                identifier="characteristic-value-003-01",
                source="characteristic-value",
                relationship_name="instance-of",
                reverse_relationship_name="has-instance",
                target="characteristic-definition",
                min=2,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="characteristic-value-003-02",
                source="characteristic-value",
                relationship_name="value-of",
                reverse_relationship_name="has-characteristic-value",
                target="subject",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="characteristic-value-003-03",
                source="characteristic-value",
                relationship_name="value-of",
                reverse_relationship_name="has-characteristic-value",
                target="specimen",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="characteristic-value-003-04",
                source="characteristic-value",
                relationship_name="value-of",
                reverse_relationship_name="has-characteristic-value",
                target="sample",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    CvNodeValidation(
        node_type="data-provider",
        has_value=True,
        value_required=True,
        min=1,
        validations=[
            NodePropertyValidation(
                identifier="data-provider-001-01",
                node_type="data-provider",
                node_property_name="value",
                constraints=PropertyConstraint(required=True, allowed_types="str"),
            ),
            CvTermValidation(
                identifier="data-provider-004-01",
                node_type="data-provider",
                validation=AllowAnyCvTerm(allowed_other_sources=["wikidata", "ILX"]),
            ),
            CvTermValidation(
                identifier="data-provider-004-02",
                node_type="data-provider",
                validation=AllowAnyCvTerm(allowed_other_sources=["wikidata", "ILX"]),
                condition=[
                    FilterCondition(
                        name="Data Provider",
                        relationship_name="[embedded].created_by_ref",
                        start_node_type=None,
                        expression="created_by_ref",
                    )
                ],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="data-provider-003-01",
                source="data-provider",
                relationship_name="provides",
                reverse_relationship_name="provided-by",
                target="study",
                min=0,
                min_for_each_source=1,
                max_for_each_source=1,
            ),
        ],
    ),
    CvNodeValidation(
        node_type="descriptor",
        min=1,
        validations=[
            CvTermValidation(
                identifier="descriptor-004-01",
                node_type="descriptor",
                validation=AllowAnyCvTerm(
                    allowed_other_sources=["wikidata", "ILX"],
                    allowed_placeholder_values=[CvTermPlaceholder()],
                ),
            ),
            CvTermValidation(
                identifier="descriptor-004-02",
                node_type="descriptor",
                validation=MANAGED_FILE_FORMAT_RULES["general file format"],
                condition=[
                    FilterCondition(
                        name="File Format",
                        relationship_name="[embedded].format_ref",
                        start_node_type=None,
                        expression="format_ref",
                    )
                ],
            ),
            CvTermValidation(
                identifier="descriptor-004-03",
                node_type="descriptor",
                validation=MANAGED_FILE_FORMAT_RULES["general file format"],
                condition=[
                    FilterCondition(
                        name="File Format",
                        relationship_name="[embedded].compression_format_refs",
                        start_node_type=None,
                        expression="compression_format_refs",
                    )
                ],
            ),
            CvTermValidation(
                identifier="descriptor-004-04",
                node_type="descriptor",
                validation=AllowedCvTerms(cv_terms=list(COMMON_ASSAY_TYPES.values())),
                condition=[
                    FilterCondition(
                        name="Analysis Type",
                        relationship_name="[embedded].assay_type_ref",
                        start_node_type="assay",
                        expression="assay_type_ref",
                    )
                ],
            ),
            CvTermValidation(
                identifier="descriptor-004-05",
                node_type="descriptor",
                validation=AllowedCvTerms(
                    cv_terms=list(COMMON_MEASUREMENT_TYPES.values())
                ),
                condition=[
                    FilterCondition(
                        name="Measurement Type",
                        relationship_name="[embedded].measurement_type_ref",
                        start_node_type="assay",
                        expression="measurement_type_ref",
                    )
                ],
            ),
            CvTermValidation(
                identifier="descriptor-004-06",
                node_type="descriptor",
                validation=AllowedCvTerms(
                    cv_terms=list(COMMON_TECHNOLOGY_TYPES.values())
                ),
                condition=[
                    FilterCondition(
                        name="Technology Type",
                        relationship_name="[embedded].technology_type_ref",
                        start_node_type="assay",
                        expression="technology_type_ref",
                    )
                ],
            ),
            CvTermValidation(
                identifier="descriptor-004-07",
                node_type="descriptor",
                validation=AllowedCvTerms(cv_terms=list(COMMON_OMICS_TYPES.values())),
                condition=[
                    FilterCondition(
                        name="Omics Type",
                        relationship_name="[embedded].omics_type_ref",
                        start_node_type="assay",
                        expression="omics_type_ref",
                    )
                ],
            ),
            CvTermValidation(
                identifier="descriptor-004-08",
                node_type="descriptor",
                validation=AllowAnyCvTerm(
                    allowed_other_sources=["wikidata", "ILX"],
                    allowed_placeholder_values=[CvTermPlaceholder()],
                ),
                condition=[
                    FilterCondition(
                        name="Keyword",
                        relationship_name="has-submitter-keyword",
                        start_node_type="study",
                    )
                ],
            ),
            CvTermValidation(
                identifier="descriptor-004-09",
                node_type="descriptor",
                validation=AllowAnyCvTerm(
                    allowed_other_sources=["wikidata", "ILX"],
                    allowed_placeholder_values=[CvTermPlaceholder()],
                ),
                condition=[
                    FilterCondition(
                        name="Keyword",
                        relationship_name="has-repository-keyword",
                        start_node_type="study",
                    )
                ],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="descriptor-003-01",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="assay",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-02",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="study",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-03",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="metadata-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-04",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="raw-data-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-05",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="derived-data-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-06",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="supplementary-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-07",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="result-file",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-08",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="metabolite",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-09",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="organization",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-10",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="person",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-11",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="project",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-12",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="publication",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-13",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="protocol",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-14",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="sample",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-15",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="subject",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-16",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="sample-run",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-17",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="sample-run-configuration",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-18",
                source="descriptor",
                relationship_name="describes",
                reverse_relationship_name="described-as",
                target="metabolite",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-18",
                source="descriptor",
                relationship_name="keyword-of",
                reverse_relationship_name="has-submitter-keyword",
                target="study",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-20",
                source="descriptor",
                relationship_name="keyword-of",
                reverse_relationship_name="has-repository-keyword",
                target="study",
                min=0,
                min_for_each_source=0,
            ),
            RelationshipValidation(
                identifier="descriptor-003-21",
                source="descriptor",
                relationship_name="keyword-of",
                reverse_relationship_name="has-repository-keyword",
                target="specimen",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    CvNodeValidation(
        node_type="factor-type",
        min=0,
        validations=[
            NodePropertyValidation(
                identifier="factor-type-001-01",
                node_type="factor-type",
                node_property_name="name",
                constraints=PropertyConstraint(required=True),
            ),
            CvTermValidation(
                identifier="factor-type-004-01",
                node_type="factor-type",
                validation=AllowAnyCvTerm(
                    allowed_placeholder_values=[CvTermPlaceholder()],
                    allowed_other_sources=["wikidata", "ILX"],
                ),
            ),
            CvTermValidation(
                identifier="factor-type-004-02",
                node_type="factor-type",
                validation=AllowedCvTerms(
                    cv_terms=list(COMMON_STUDY_FACTOR_DEFINITIONS.values())
                ),
                condition=[
                    FilterCondition(
                        name="Factor Type",
                        relationship_name="[embedded].factor_type_ref",
                        start_node_type="factor-definition",
                        expression="factor_type_ref",
                    )
                ],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="factor-type-003-01",
                source="factor-type",
                relationship_name="type-of",
                reverse_relationship_name="has-type",
                target="factor-definition",
                min=0,
                min_for_each_source=1,
            ),
        ],
    ),
    CvNodeValidation(
        node_type="factor-value",
        has_value=True,
        min=0,
        validations=[
            CvTermValidation(
                identifier="factor-value-004-01",
                node_type="factor-value",
                validation=AllowAnyCvTerm(
                    allowed_placeholder_values=[CvTermPlaceholder()],
                    allowed_other_sources=["wikidata", "ILX"],
                ),
            ),
            *[
                CvTermValidation(
                    identifier=f"factor-value-004-{(idx + 10):02}",
                    node_type="factor-value",
                    min_count=1
                    if factor_name
                    in COMMON_STUDY_FACTOR_DEFINITION_ENFORCEMENT_LEVELS["required"]
                    else 0,
                    validation=rule,
                    condition=[
                        FilterCondition(
                            name=factor_name,
                            relationship_name="instance-of",
                            start_node_type="factor-value",
                            expression="[instance-of].factor_type_ref.name",
                            expression_value=factor_name,
                        )
                    ],
                )
                for idx, (factor_name, rule) in enumerate(
                    MANAGED_FACTOR_VALUE_RULES.items()
                )
            ],
        ],
        relationships=[
            RelationshipValidation(
                identifier="factor-type-003-01",
                source="factor-value",
                relationship_name="instance-of",
                reverse_relationship_name="has-instance",
                target="factor-definition",
                min=0,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="factor-type-003-02",
                source="factor-value",
                relationship_name="value-of",
                reverse_relationship_name="has-factor-value",
                target="sample",
                min=0,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="factor-type-003-03",
                source="factor-value",
                relationship_name="value-of",
                reverse_relationship_name="has-factor-value",
                target="specimen",
                min=0,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="factor-type-003-04",
                source="factor-value",
                relationship_name="value-of",
                reverse_relationship_name="has-factor-value",
                target="subject",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    CvNodeValidation(
        node_type="metabolite-identifier",
        min=0,
        has_value=True,
        value_required=True,
        validations=[
            NodePropertyValidation(
                identifier="metabolite-identifier-001-01",
                description="Value MUST be identifier of metabolite.",
                node_type="metabolite-identifier",
                node_property_name="value",
                constraints=PropertyConstraint(required=True),
            ),
            CvTermValidation(
                identifier="metabolite-identifier-001-02",
                node_type="metabolite-identifier",
                validation=AllowAnyCvTerm(
                    allowed_other_sources=["wikidata", "ILX"],
                ),
            ),
            CvTermValidation(
                identifier="metabolite-identifier-004-01",
                description="metabolite identifier in value. "
                "Metabolite Database Identifier. e.g. CHEBI, REFET, HMDB, etc.",
                node_type="metabolite-identifier",
                validation=MANAGED_CHEMICAL_DATABASE_IDENTIFIER_RULE,
                condition=[
                    FilterCondition(
                        name="Compound Database Identifier",
                        relationship_name="identified-as",
                        start_node_type="metabolite",
                    )
                ],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="metabolite-identifier-003-01",
                source="metabolite-identifier",
                relationship_name="reported-identifier-of",
                reverse_relationship_name="identified-as",
                target="metabolite",
                min=0,
                min_for_each_source=1,
            ),
        ],
    ),
    CvNodeValidation(
        node_type="parameter-type",
        min=1,
        validations=[
            NodePropertyValidation(
                identifier="parameter-type-001-01",
                node_type="parameter-type",
                node_property_name="name",
                constraints=PropertyConstraint(required=True),
            ),
            CvTermValidation(
                identifier="parameter-type-004-01",
                node_type="parameter-type",
                validation=AllowedCvTerms(
                    cv_terms=list(COMMON_PARAMETER_DEFINITIONS.values()),
                    allowed_other_sources=["wikidata", "ILX"],
                ),
            ),
            CvTermValidation(
                identifier="parameter-type-004-02",
                node_type="parameter-type",
                min_count=1,
                validation=AllowedCvTerms(
                    cv_terms=COMMON_PROTOCOL_PARAMETER_MAPPINGS[
                        "mass spectrometry"
                    ].values()
                ),
                condition=[
                    FilterCondition(
                        name="Mass spectrometry protocol",
                        relationship_name="[embedded].parameter_type_ref",
                        start_node_type="parameter-definition",
                        expression="[used-in].protocol_type_ref.name",
                        expression_value="mass spectrometry",
                    ),
                ],
            ),
            CvTermValidation(
                identifier="parameter-type-004-03",
                node_type="parameter-type",
                validation=AllowedCvTerms(
                    cv_terms=COMMON_PROTOCOL_PARAMETER_MAPPINGS[
                        "chromatography"
                    ].values()
                ),
                condition=[
                    FilterCondition(
                        name="Chromatography protocol",
                        relationship_name="[embedded].parameter_definition_refs.parameter_type_ref",
                        start_node_type="protocol",
                        expression="protocol_type_ref.name",
                        expression_value="chromatography",
                    )
                ],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="parameter-type-003-01",
                source="parameter-type",
                relationship_name="type-of",
                reverse_relationship_name="has-type",
                target="parameter-definition",
                min=0,
                min_for_each_source=1,
            ),
        ],
    ),
    CvNodeValidation(
        node_type="parameter-value",
        has_value=True,
        min=1,
        validations=[
            CvTermValidation(
                identifier="parameter-value-004-01",
                node_type="parameter-value",
                validation=AllowAnyCvTerm(
                    allowed_placeholder_values=[CvTermPlaceholder()],
                    allowed_other_sources=["wikidata", "ILX"],
                ),
            ),
            *[
                CvTermValidation(
                    identifier=f"parameter-value-004-{(idx + 10):02}",
                    node_type="parameter-value",
                    min_count=1
                    if parameter_name
                    in COMMON_PARAMETER_ENFORCEMENT_LEVELS[protocol_name]["required"]
                    else 0,
                    validation=rule,
                    condition=[
                        FilterCondition(
                            name=parameter_name,
                            relationship_name="instance-of",
                            start_node_type="parameter-value",
                            expression="[instance-of].parameter_type_ref.name",
                            expression_value=parameter_name,
                        )
                    ],
                )
                for idx, (protocol_name, parameter_name, rule) in enumerate(
                    [
                        (k, k2, v2)
                        for k, d in MANAGED_PARAMETER_VALUE_RULES.items()
                        for k2, v2 in d.items()
                    ]
                )
            ],
        ],
        relationships=[
            RelationshipValidation(
                identifier="parameter-value-003-01",
                source="parameter-value",
                relationship_name="instance-of",
                reverse_relationship_name="has-instance",
                target="parameter-definition",
                min=1,
                min_for_each_source=1,
            ),
            RelationshipValidation(
                identifier="parameter-value-003-02",
                source="parameter-value",
                relationship_name="value-of",
                reverse_relationship_name="has-parameter-value",
                target="protocol",
                min=0,
                min_for_each_source=0,
            ),
        ],
    ),
    CvNodeValidation(
        node_type="protocol-type",
        min=1,
        validations=[
            NodePropertyValidation(
                identifier="protocol-type-001-01",
                node_type="protocol-type",
                node_property_name="name",
                constraints=PropertyConstraint(required=True),
            ),
            CvTermValidation(
                identifier="protocol-type-004-01",
                node_type="protocol-type",
                validation=AllowAnyCvTerm(
                    allowed_other_sources=["wikidata", "ILX"],
                ),
            ),
            CvTermValidation(
                identifier="protocol-type-004-02",
                node_type="protocol-type",
                min_count=1,
                validation=AllowedCvTerms(
                    cv_terms=list(COMMON_PROTOCOLS.values()),
                    allowed_other_sources=["wikidata", "ILX"],
                ),
                condition=[
                    FilterCondition(
                        name="Protocol Type",
                        relationship_name="[embedded].protocol_type_ref",
                        start_node_type="protocol",
                        expression="protocol_type_ref",
                    )
                ],
            ),
        ],
        relationships=[
            RelationshipValidation(
                identifier="protocol-type-003-01",
                source="protocol-type",
                relationship_name="type-of",
                reverse_relationship_name="has-type",
                target="protocol",
                min=0,
                min_for_each_source=1,
            ),
        ],
    ),
]

MHD_MS_PROFILE_V0_1.mhd_nodes.sort(key=lambda x: x.node_type)

MHD_MS_PROFILE_V0_1.cv_nodes.sort(key=lambda x: x.node_type)


def validate_model():
    unique_ids = {}
    invalid_names = {}
    for node in MHD_MS_PROFILE_V0_1.mhd_nodes:
        for validation in node.validations:
            if not node.node_type.startswith(validation.identifier):
                if node.node_type not in invalid_names:
                    invalid_names[node.node_type] = []
                invalid_names[node.node_type].append(validation.identifier)
            if validation.identifier not in unique_ids:
                unique_ids[validation.identifier] = []
            unique_ids[validation.identifier].append(node.node_type)
        for validation in node.relationships:
            if validation.identifier not in unique_ids:
                unique_ids[validation.identifier] = []
            unique_ids[validation.identifier].append(node.node_type)

    non_unique_terms = {}
    for item, values in unique_ids.items():
        if len(values) != 1:
            non_unique_terms[item] = values
    if not invalid_names:
        raise ValueError(
            "Invalid names. Node type and identifier prefix do not match",
            str(invalid_names),
        )
    if non_unique_terms:
        raise ValueError("Non unique identifiers in validation", str(non_unique_terms))


validate_model()
