Skip to content

Ontology Validation

How to validate Linked.Archi ontology files for syntax correctness and SHACL conformance.


Overview

The validation script (.scripts/validate.sh) provides two levels of validation:

  1. Turtle syntax — parses every .ttl file using the RDF4J Rio Turtle parser. Catches malformed IRIs, missing prefixes, unclosed strings, and other syntax errors.

  2. SHACL conformance — loads ontology data into an RDF4J ShaclSail and validates it against the SHACL shapes. Catches missing required properties, wrong types, cardinality violations, and domain/range constraint violations.

Both levels use Eclipse RDF4J 4.3.14. The SDK is downloaded automatically on first run (~50MB, cached in .scripts/.lib/).

Prerequisites

  • Java 17+ (tested with OpenJDK 21)
  • curl and unzip (for SDK download)

Usage

# Syntax-check all .ttl files in the repo
./validate.sh

# Syntax-check a single file
./validate.sh --syntax path/to/file.ttl

# SHACL validate a preset profile
./validate.sh --shacl archimate
./validate.sh --shacl archimate-derived
./validate.sh --shacl archimate-principles
./validate.sh --shacl c4
./validate.sh --shacl backstage
./validate.sh --shacl bpmn

# SHACL validate all presets
./validate.sh --shacl all

# SHACL validate custom data against custom shapes
./validate.sh --shacl mydata.ttl core-shapes.ttl my-shapes.ttl

# Full CI run (syntax + all SHACL profiles)
./validate.sh --ci

Exit Codes

Code Meaning
0 All validations passed
1 One or more validations failed
2 Usage error (wrong arguments)

SHACL Validation Architecture

Validation uses a two-layer shapes architecture:

flowchart TD
    core["core-shapes.ttl<br/>(base contract — applies to all metamodels)"]
    MCS["ModelConceptShape:<br/>every ModelConcept must have skos:prefLabel"]
    QRS["QualifiedRelationshipShape:<br/>exactly one arch:source + arch:target"]
    COS["ConceptOwnerShape:<br/>arch:conceptOwner must be a Stakeholder"]

    core --> MCS & QRS & COS

    amrel["archimate3.2-relationship-shapes.ttl<br/>11 qualified + 62 unqualified shapes"]
    amelem["archimate3.2-element-shapes.ttl<br/>24 shapes: structural integrity, metamodel patterns"]
    amprin["archimate3.2-principle-shapes.ttl<br/>20 shapes: governance principles"]
    amderiv["archimate3.2-derivation-rules.ttl<br/>SHACL Rules: DR1-DR8 + PDR1-PDR12"]
    c4s["c4-shapes.ttl<br/>4 per-relationship-type shapes"]
    bss["backstage-shapes.ttl<br/>7 per-relationship-type shapes"]

    core -->|"imports"| amrel & amelem & amprin & amderiv & c4s & bss

When you run --shacl archimate, the script loads: 1. core-shapes.ttl into the SHACL shapes graph 2. archimate3.2-relationship-shapes.ttl into the SHACL shapes graph 3. archimate3.2-element-shapes.ttl into the SHACL shapes graph 4. archimate3.2-onto.ttl as data

When you run --shacl archimate-derived, it loads all of the above plus: 5. archimate3.2-derivation-rules.ttl (DR1-DR8, PDR1-PDR12 SHACL Rules)

The ShaclSail validates the data against all loaded shapes on commit. Violations are reported as a SHACL validation report in Turtle format.

SHACL Profiles

Profile Data File Shapes
archimate archimate3.2-onto.ttl core-shapes.ttl + archimate3.2-relationship-shapes.ttl (generated) + archimate3.2-element-shapes.ttl
archimate-derived archimate3.2-onto.ttl All archimate shapes + archimate3.2-derivation-rules.ttl (DR1-DR8, PDR1-PDR12)
archimate-principles archimate3.2-onto.ttl core-shapes.ttl + archimate3.2-principle-shapes.ttl (20 governance principle shapes)
c4 c4-onto.ttl core-shapes.ttl + c4-shapes.ttl
backstage backstage-onto.ttl core-shapes.ttl + backstage-shapes.ttl
bpmn linkedarchi-bpmn-onto.ttl core-shapes.ttl

GitLab CI Integration

The .gitlab-ci.yml runs validate.sh --ci on every push that changes .ttl files. It uses a custom Docker image (validator) with Java 21, RDF4J 4.3.14 SDK, and pre-compiled validators baked in — no download or compilation at runtime.

Building the Validator Image

docker build --platform linux/amd64 --no-cache \
  -t linked-archi/validator .scripts/

Push to your GitLab container registry:

docker tag linked-archi/validator registry.gitlab.com/<namespace>/linked-archi-meta/validator:latest
docker push registry.gitlab.com/<namespace>/linked-archi-meta/validator:latest

Why --platform linux/amd64: Apple Silicon Macs build ARM images by default. GitLab shared runners are x86_64 and will reject ARM images.

Why --no-cache: Prevents Docker from reusing cached ARM layers when switching platforms.

The image contains: - Eclipse Temurin JDK 21 - RDF4J 4.3.14 SDK (/opt/rdf4j/lib/) - Pre-compiled TurtleSyntaxCheck.class and ShaclValidator.class (/opt/rdf4j/build/)

The validate.sh script detects the pre-built paths via RDF4J_LIB and RDF4J_BUILD environment variables and skips download/compilation entirely. For local development without Docker, the script falls back to downloading the SDK on first run (cached in .scripts/.lib/).

The CI job: 1. Downloads the RDF4J SDK (cached after first run) 2. Compiles the Java validation tools (cached) 3. Runs syntax validation on all 69+ .ttl files 4. Runs SHACL validation on all 5 profiles 5. Reports pass/fail with proper exit codes

Adding a New SHACL Profile

To add validation for a new metamodel:

  1. Create a shapes file (e.g., my-metamodel-shapes.ttl) that imports core-shapes:

    owl:imports <https://meta.linked.archi/core-shapes#> ;
    

  2. Add per-relationship-type shapes with domain/range constraints

  3. Add a new case to the run_profile() function in validate.sh:

    my-metamodel)
        validate_shacl \
            "$REPO_ROOT/path/to/my-metamodel-onto.ttl" \
            "$core_shapes" \
            "$REPO_ROOT/path/to/my-metamodel-shapes.ttl"
        ;;
    

  4. Add the profile name to the PROFILES variable

Files

File Purpose
.scripts/validate.sh Main validation script
.scripts/TurtleSyntaxCheck.java RDF4J-based Turtle parser wrapper
.scripts/ShaclValidator.java RDF4J ShaclSail-based SHACL validator
.scripts/.lib/ Auto-downloaded RDF4J SDK (gitignored)
.scripts/.build/ Compiled Java classes (gitignored)
.gitlab-ci.yml CI pipeline configuration
core/core-shapes.ttl Base SHACL shapes for all metamodels
modelingLanguages/archimate/archimate3.2-relationship-shapes.ttl Generated SHACL shapes for relationship source-target pairs
modelingLanguages/archimate/archimate3.2-element-shapes.ttl SHACL shapes for element/metamodel pattern constraints
modelingLanguages/archimate/archimate3.2-principle-shapes.ttl SHACL shapes for architecture governance principles
modelingLanguages/archimate/archimate3.2-derivation-rules.ttl ArchiMate derivation rules (DR1-DR8, PDR1-PDR12)
.scripts/generate-archimate-shapes.py Generator for relationship shapes from XML matrix