feat: set scope of operation for worship administrative units

Add migrations to set the initial scope of operation for worship administrative
units. These migrations work in several steps:
1. Extract the necessary relations between worship administrative units and
   locations based on the rules provided by business and insert this data in a
   temporary graph.
2. For worship administrative units related to only a single location. Simply
   add the triple setting that location as its scope of operation.
3. For worship administrative units related to multiple locations. Create new
   location resources that aggregates all locations linked to a single worship
   administrative unit and set this new location resource as scope of operation.
4. Clear the temporary graph.
This commit is contained in:
mirdono
2025-07-08 15:44:12 +02:00
parent 5a3ae13eb0
commit 387ef1eeea
4 changed files with 186 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
PREFIX ere: <http://data.lblod.info/vocabularies/erediensten/>
PREFIX org: <http://www.w3.org/ns/org#>
PREFIX besluit: <http://data.vlaanderen.be/ns/besluit#>
# This migration extracts the relations between (central) worship services and
# their locations according to the rules provided by business. These links are
# inserted into a temporary graph for further processing.
# Worship services
## Municipality organised
INSERT {
GRAPH <http://mu.semte.ch/graphs/temp-for-worship-organizations-scope> {
?ws besluit:werkingsgebied ?scope .
}
} WHERE {
GRAPH <http://mu.semte.ch/graphs/worship-service> {
?ws a ere:BestuurVanDeEredienst ;
ere:typeEredienst ?worshipType .
VALUES ?worshipType {
<http://lblod.data.gift/concepts/99536dd6eb0d2ef38a89efafb17e7389> # Anglicaans
<http://lblod.data.gift/concepts/1a1abeafc973d27cebcb2d7a15b2d823> # Israëlitisch
<http://lblod.data.gift/concepts/e8cba1540b35a32e9cb45126c38c03c6> # Protestants
<http://lblod.data.gift/concepts/b13d1d623626bc1ee75c7d20bc60e3c0> # Rooms-Katholiek
}
?involvement a ere:BetrokkenLokaleBesturen ;
org:organization ?ws ;
ere:typebetrokkenheid ?involvementType .
VALUES ?involvementType {
<http://lblod.data.gift/concepts/86fcbbbff764f1cba4c7e10dbbae578e> # Mede-financierend
<http://lblod.data.gift/concepts/ac400cc9f135ac7873fb3e551ec738c1> # Toezichthoudend
}
?org ere:betrokkenBestuur ?involvement .
}
GRAPH <http://mu.semte.ch/graphs/administrative-unit> {
?org besluit:werkingsgebied ?scope .
}
}
;
## Province organised
INSERT {
GRAPH <http://mu.semte.ch/graphs/temp-for-worship-organizations-scope> {
?ws besluit:werkingsgebied ?scope .
}
} WHERE {
GRAPH <http://mu.semte.ch/graphs/worship-service> {
?ws a ere:BestuurVanDeEredienst ;
ere:typeEredienst ?worshipType .
VALUES ?worshipType {
<http://lblod.data.gift/concepts/9d8bd472a00bf0a5c7b7186606365a52> # Islamitisch
<http://lblod.data.gift/concepts/84bcd6896f575bae4857ff8d2764bed8> # Orthodox
}
?involvement a ere:BetrokkenLokaleBesturen ;
org:organization ?ws ;
ere:typebetrokkenheid ?involvementType .
VALUES ?involvementType {
<http://lblod.data.gift/concepts/0f845f00ee76099c89518cbaf6a7b77f> # Adviserend
}
?org ere:betrokkenBestuur ?involvement .
}
GRAPH <http://mu.semte.ch/graphs/administrative-unit> {
?org besluit:werkingsgebied ?scope .
}
}
;
# Central worship services
## Municipality organised
INSERT {
GRAPH <http://mu.semte.ch/graphs/temp-for-worship-organizations-scope> {
?ws besluit:werkingsgebied ?scope .
}
} WHERE {
GRAPH <http://mu.semte.ch/graphs/worship-service> {
?ws a ere:CentraalBestuurVanDeEredienst ;
ere:typeEredienst ?worshipType .
VALUES ?worshipType {
<http://lblod.data.gift/concepts/b13d1d623626bc1ee75c7d20bc60e3c0> # Rooms-Katholiek
}
?involvement a ere:BetrokkenLokaleBesturen ;
org:organization ?ws ;
ere:typebetrokkenheid ?involvementType .
VALUES ?involvementType {
<http://lblod.data.gift/concepts/ac400cc9f135ac7873fb3e551ec738c1> # Toezichthoudend
}
?org ere:betrokkenBestuur ?involvement .
}
GRAPH <http://mu.semte.ch/graphs/administrative-unit> {
?org besluit:werkingsgebied ?scope .
}
}
;
## Province organised
## Note: Business requested to use the location for the municipality of Ghent as
## default value. They will update it manually afterwards.
INSERT {
GRAPH <http://mu.semte.ch/graphs/temp-for-worship-organizations-scope> {
?ws besluit:werkingsgebied ?locationGhent .
}
} WHERE {
GRAPH <http://mu.semte.ch/graphs/worship-service> {
?ws a ere:CentraalBestuurVanDeEredienst ;
ere:typeEredienst ?worshipType .
VALUES ?worshipType {
<http://lblod.data.gift/concepts/9d8bd472a00bf0a5c7b7186606365a52> # Islamitisch
<http://lblod.data.gift/concepts/84bcd6896f575bae4857ff8d2764bed8> # Orthodox
}
BIND(URI("http://data.lblod.info/id/werkingsgebieden/ce94eeae827cdc5c00f3f2f4276ff628580edefb3aa5861e4669b0c5d93adc57") AS ?locationGhent)
}
}

View File

@@ -0,0 +1,24 @@
PREFIX besluit: <http://data.vlaanderen.be/ns/besluit#>
# This migration sets the scope of operation for worship organisations that have
# single, already existing, location as scope. This migration depends on
# `20250707132349-chore--extract-scopes-for-worship-organisations` being
# executed first, as it uses the data created by the migration.
INSERT {
GRAPH <http://mu.semte.ch/graphs/worship-service> {
?ws besluit:werkingsgebied ?scope .
}
} WHERE {
{
SELECT DISTINCT ?ws (count(DISTINCT ?scope) as ?count)
WHERE {
GRAPH <http://mu.semte.ch/graphs/temp-for-worship-organizations-scope> {
?ws besluit:werkingsgebied ?scope .
}
}
}
FILTER (?count = 1)
GRAPH <http://mu.semte.ch/graphs/temp-for-worship-organizations-scope> {
?ws besluit:werkingsgebied ?scope .
}
}

View File

@@ -0,0 +1,49 @@
PREFIX prov: <http://www.w3.org/ns/prov#>
PREFIX mu: <http://mu.semte.ch/vocabularies/core/>
PREFIX ext: <http://mu.semte.ch/vocabularies/ext/>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX besluit: <http://data.vlaanderen.be/ns/besluit#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
# This migration sets the scope of operation for worship organisations that have
# multiple location as scope. It creates new aggregate locations to contain the
# already existing municipality/province level ones. This migration depends on
# `20250707132349-chore--extract-scopes-for-worship-organisations` being
# executed first, as it uses the data created by the migration.
INSERT {
GRAPH <http://mu.semte.ch/graphs/public> {
?location a prov:Location ;
mu:uuid ?locationUuid ;
rdfs:label ?scopeLabel ;
ext:werkingsgebiedNiveau """Samengesteld werkingsgebied""" .
?scope geo:sfWithin ?location .
}
GRAPH <http://mu.semte.ch/graphs/worship-service> {
?ws besluit:werkingsgebied ?location .
}
} WHERE {
{
SELECT DISTINCT ?ws (count(DISTINCT ?scope) AS ?count) (GROUP_CONCAT(?uuid," ") AS ?scopeUuids) (GROUP_CONCAT(?label,", ") AS ?scopeLabel)
WHERE {
GRAPH <http://mu.semte.ch/graphs/temp-for-worship-organizations-scope> {
?ws besluit:werkingsgebied ?scope .
}
GRAPH <http://mu.semte.ch/graphs/public> {
?scope mu:uuid ?uuid ;
rdfs:label ?label .
}
}
}
FILTER (?count > 1)
GRAPH <http://mu.semte.ch/graphs/temp-for-worship-organizations-scope> {
?ws besluit:werkingsgebied ?scope .
}
# NOTE (10/07/2025): The SPARQL specification does not specify any order for
# `GROUP_CONCAT`. But virtuoso does seem to concatenate elements always in the
# same order. Therefore, this way of generating a UUID is a bit of a hack to
# ensure that new locations that contain the same locations will receive the
# same UUUID, which results in the same location resource being inserted
# twice.
BIND (STR(SHA256(?scopeUuids)) AS ?locationUuid)
BIND (URI(CONCAT("http://data.lblod.info/id/werkingsgebieden/", ?locationUuid)) AS ?location)
}

View File

@@ -0,0 +1 @@
CLEAR GRAPH <http://mu.semte.ch/graphs/temp-for-worship-organizations-scope>