Skip to main content

The project as RDF

This document was generated using AI assistance

Content may include inaccuracies, outdated information, or technical errors. Users are advised to cross-check critical information before implementation.

The content of a project is available as RDF: an object becomes a resource, an attribute and a reference become triples, a model becomes a named graph. A project has a SPARQL endpoint of its own, and a model can be downloaded as Turtle or TriG.

Download a model

  1. Right-click a model in the model explorer and open Download.
  2. Choose RDF Turtle or RDF TriG.

Both files carry the same triples. Turtle writes them flat, declaring a prefix for every metamodel the model uses; TriG wraps them in a named graph whose IRI is the download URL of the model - the same IRI the SPARQL endpoint uses.

Both begin with an ontology header: the model is declared an owl:Ontology, and every metamodel it depends on is listed with owl:imports.

How objects are represented

Open the file. An object is a resource named after its identifier:

urn:uuid:8b1f0d38-6c40-4a1e-9a20-2f8b7d1c5e44

Its rdf:type names its concrete class, and the IRI of a class is the namespace of the metamodel, #, and the class name:

http://www.archimatetool.com/archimate#BusinessActor

The IRI of a property has one more part: the class that declares the feature, a dot, and the feature name. BusinessActor has a name, but Nameable declares it:

?actor archimate:Nameable.name "Customer" .

The same holds for relationships: source and target are declared by ArchimateRelationship, whatever the concrete type of the relationship is.

An attribute becomes a triple whose object is a literal, a reference becomes a triple whose object is the IRI of the target - containment included, so the folder tree of a model is a chain of reference triples. Only the features that are set produce triples; derived and transient ones produce none.

Queries

Every project has its own SPARQL 1.1 endpoint, answering over all its models at once:

curl -X POST https://architeezy.com/api/projects/$PROJECT/sparql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/sparql-query" \
--data 'SELECT DISTINCT ?g WHERE { GRAPH ?g { ?s ?p ?o } }'

That first query lists the graphs, one per model; keep the IRIs, because an update has to name its graph. A query without GRAPH reads every model of the project.

All four query forms work, and the response type follows the form: SELECT gives application/sparql-results+json, ASK a JSON boolean, CONSTRUCT and DESCRIBE Turtle.

Add ?inference=rdfs to the URL, and the query runs over the inferred graph, so a query by a supertype also finds instances of its subtypes.

An anonymous request is refused with 401. A project you may not see answers 404, exactly as a project that does not exist.

Updates

Updates go to a separate address, POST /api/projects/<projectId>/sparql/update with the content type application/sparql-update, and a successful one answers 204.

Every INSERT and DELETE has to wrap its triples in GRAPH; an update that leaves them in the default graph is refused with 400. Take the graph IRI from the query above:

PREFIX archimate: <http://www.archimatetool.com/archimate#>

DELETE {
GRAPH <https://architeezy.com/api/models/acme/landscape/1.0.0/core/content> {
?actor archimate:Nameable.name ?old .
}
}
INSERT {
GRAPH <https://architeezy.com/api/models/acme/landscape/1.0.0/core/content> {
?actor archimate:Nameable.name "Customer" .
}
}
WHERE {
GRAPH <https://architeezy.com/api/models/acme/landscape/1.0.0/core/content> {
?actor a archimate:BusinessActor ;
archimate:Nameable.name ?old .
FILTER (str(?old) = "Client")
}
}

Each model whose graph changed is written back to the repository, and the change appears in open editors like any other edit. Models you did not touch are left alone, and an update into a model you may not write is refused with 403.

Uploading RDF

Upload model in the project menu reads .ttl as Turtle and .trig as TriG. The same content goes through the API with PUT /api/models/<id>/content?format=ttl.

An import maps RDF onto a metamodel that is already in the repository: it resolves every rdf:type IRI to a class and every predicate IRI to a feature of the declaring class, and creates neither. So the file has to match the metamodel it was written for, and that metamodel has to be visible to the target project. A statement whose class or property does not resolve is skipped rather than fatal, and an object of an abstract class is not created.

Identifiers survive: urn:uuid:<id> comes back as the object with that identifier, so a download and an upload give you the original objects rather than copies.

A metamodel as an ontology

A metamodel is exported not as data but as the ontology that describes it. Add /owl to its address:

GET /api/models/<scope>/<project>/<version>/<model>/owl?format=ttl
GET /api/predefined-metamodels/<id>/owl?format=ttl

Classes become resources with rdfs:label and rdfs:subClassOf; attributes and references become properties with rdfs:domain and rdfs:range, and a single-valued one is also an owl:FunctionalProperty; opposite references are joined by owl:inverseOf; an identifying attribute becomes owl:hasKey; enumerations keep their literals; and a data type implemented by a standard XML Schema type is declared owl:equivalentClass of it, so String matches xsd:string.

Further reading