diff --git a/demo/northwind-traders/admin/model/corporation-template.ttl b/demo/northwind-traders/admin/model/corporation-template.ttl deleted file mode 100644 index e99dbb1..0000000 --- a/demo/northwind-traders/admin/model/corporation-template.ttl +++ /dev/null @@ -1,54 +0,0 @@ -@prefix : <#> . -@prefix ns: . -@prefix ldh: . -@prefix rdfs: . -@prefix sp: . -@prefix spin: . -@prefix dct: . -@prefix schema: . - -# orders from this customer - -schema:Corporation ldh:template ns:OrdersFromCustomer . - -ns:OrdersFromCustomer a ldh:View ; - dct:title "Orders from this customer" ; - spin:query ns:SelectOrdersFromCustomer ; - rdfs:isDefinedBy ns: . - -ns:SelectOrdersFromCustomer a sp:Select ; - rdfs:label "Select orders from customer" ; - sp:text """ -PREFIX schema: - -SELECT DISTINCT ?order -WHERE - { GRAPH ?graph - { ?order schema:customer $about } - } -ORDER BY DESC(?order) -""" ; - rdfs:isDefinedBy ns: . - -# products supplied by this supplier - -schema:Corporation ldh:template ns:ProductsFromSupplier . - -ns:ProductsFromSupplier a ldh:View ; - dct:title "Products supplied by this supplier" ; - spin:query ns:SelectProductsFromSupplier ; - rdfs:isDefinedBy ns: . - -ns:SelectProductsFromSupplier a sp:Select ; - rdfs:label "Select products from supplier" ; - sp:text """ -PREFIX schema: - -SELECT DISTINCT ?product -WHERE - { GRAPH ?graph - { ?product schema:provider $about } - } -ORDER BY ?product -""" ; - rdfs:isDefinedBy ns: . diff --git a/demo/northwind-traders/admin/model/import-ontologies.sh b/demo/northwind-traders/admin/model/import-ontologies.sh index aa6830a..e21b395 100755 --- a/demo/northwind-traders/admin/model/import-ontologies.sh +++ b/demo/northwind-traders/admin/model/import-ontologies.sh @@ -29,7 +29,7 @@ pwd=$(realpath "$PWD") printf "\n### Creating ontology item\n\n" -target=$(create-item.sh \ +create-item.sh \ -b "$admin_base" \ -f "$cert_pem_file" \ -p "$cert_password" \ @@ -37,13 +37,3 @@ target=$(create-item.sh \ --title "Northwind Traders" \ --slug "northwind-traders" \ --container "${admin_base}ontologies/" -) - -printf "\n### Appending ontology document\n\n" - -cat "$pwd"/northwind-traders.ttl | turtle --base="$target" | post.sh \ - -f "$cert_pem_file" \ - -p "$cert_password" \ - --proxy "$admin_proxy" \ - -t "application/n-triples" \ - "$target" diff --git a/demo/northwind-traders/admin/model/northwind-traders.ttl b/demo/northwind-traders/admin/model/northwind-traders.ttl deleted file mode 100644 index 18e4d5f..0000000 --- a/demo/northwind-traders/admin/model/northwind-traders.ttl +++ /dev/null @@ -1,63 +0,0 @@ -@prefix : . -@prefix rdf: . -@prefix rdfs: . -@prefix xsd: . -@prefix owl: . -@prefix dh: . -@prefix sioc: . -@prefix foaf: . -@prefix dct: . - -: a owl:Ontology . - -# classes - -:Person a owl:Class ; - rdfs:label "Person" ; - rdfs:isDefinedBy : . - -:Order a owl:Class ; - rdfs:label "Order" ; - rdfs:isDefinedBy : . - -:City a owl:Class ; - rdfs:label "City" ; - rdfs:isDefinedBy : . - -:PostalAddress a owl:Class ; - rdfs:label "Postal address" ; - rdfs:isDefinedBy : . - -# properties - -:broker a owl:ObjectProperty ; - rdfs:label "Broker"; - rdfs:domain :Order ; - rdfs:range :Person ; - rdfs:isDefinedBy : . - -:areaServed a owl:ObjectProperty ; - rdfs:label "Area served"; - rdfs:domain :Person ; - rdfs:range :City ; - rdfs:isDefinedBy : . - -:address a owl:ObjectProperty ; - rdfs:label "Address"; - rdfs:domain :Person ; - rdfs:range :PostalAddress ; - rdfs:isDefinedBy : . - -# restrictions - -[] a owl:Restriction ; - owl:onProperty :broker ; - owl:minCardinality 1 ; - owl:maxCardinality 1 ; - rdfs:isDefinedBy : . - -[] a owl:Restriction ; - owl:onProperty :address ; - owl:minCardinality 1 ; - owl:maxCardinality 1 ; - rdfs:isDefinedBy : . diff --git a/demo/northwind-traders/admin/model/ns.ttl b/demo/northwind-traders/admin/model/ns.ttl new file mode 100644 index 0000000..5f6bf12 --- /dev/null +++ b/demo/northwind-traders/admin/model/ns.ttl @@ -0,0 +1,193 @@ +@prefix : <#> . +@prefix ns: . +@prefix ldh: . +@prefix rdfs: . +@prefix rdf: . +@prefix xsd: . +@prefix owl: . +@prefix sp: . +@prefix spin: . +@prefix dct: . +@prefix dh: . +@prefix sioc: . +@prefix foaf: . +@prefix schema: . + +ns: a owl:Ontology . + +# classes + +schema:Person a owl:Class ; + rdfs:label "Person" ; + rdfs:isDefinedBy ns: . + +schema:Order a owl:Class ; + rdfs:label "Order" ; + rdfs:isDefinedBy ns: . + +schema:City a owl:Class ; + rdfs:label "City" ; + rdfs:isDefinedBy ns: . + +schema:PostalAddress a owl:Class ; + rdfs:label "Postal address" ; + rdfs:isDefinedBy ns: . + +# properties + +schema:broker a owl:ObjectProperty ; + rdfs:label "Broker"; + rdfs:domain schema:Order ; + rdfs:range schema:Person ; + rdfs:isDefinedBy ns: . + +schema:areaServed a owl:ObjectProperty ; + rdfs:label "Area served"; + rdfs:domain schema:Person ; + rdfs:range schema:City ; + rdfs:isDefinedBy ns: . + +schema:address a owl:ObjectProperty ; + rdfs:label "Address"; + rdfs:domain schema:Person ; + rdfs:range schema:PostalAddress ; + rdfs:isDefinedBy ns: . + +# restrictions + +[] a owl:Restriction ; + owl:onProperty schema:broker ; + owl:minCardinality 1 ; + owl:maxCardinality 1 ; + rdfs:isDefinedBy ns: . + +[] a owl:Restriction ; + owl:onProperty schema:address ; + owl:minCardinality 1 ; + owl:maxCardinality 1 ; + rdfs:isDefinedBy ns: . + +# Person + +# orders handled by this employee + +schema:Person ldh:template ns:OrdersHandledByEmployee . + +ns:OrdersHandledByEmployee a ldh:View ; + dct:title "Orders handled by this employee" ; + spin:query ns:SelectOrdersHandledByEmployee ; + rdfs:isDefinedBy ns: . + +ns:SelectOrdersHandledByEmployee a sp:Select ; + rdfs:label "Select orders handled by employee" ; + sp:text """ +PREFIX schema: + +SELECT DISTINCT ?order +WHERE + { GRAPH ?graph + { ?order schema:broker $about } + } +ORDER BY DESC(?order) +""" ; + rdfs:isDefinedBy ns: . + +# Corporation + +# orders from this customer + +schema:Corporation ldh:template ns:OrdersFromCustomer . + +ns:OrdersFromCustomer a ldh:View ; + dct:title "Orders from this customer" ; + spin:query ns:SelectOrdersFromCustomer ; + rdfs:isDefinedBy ns: . + +ns:SelectOrdersFromCustomer a sp:Select ; + rdfs:label "Select orders from customer" ; + sp:text """ +PREFIX schema: + +SELECT DISTINCT ?order +WHERE + { GRAPH ?graph + { ?order schema:customer $about } + } +ORDER BY DESC(?order) +""" ; + rdfs:isDefinedBy ns: . + +# products supplied by this supplier + +schema:Corporation ldh:template ns:ProductsFromSupplier . + +ns:ProductsFromSupplier a ldh:View ; + dct:title "Products supplied by this supplier" ; + spin:query ns:SelectProductsFromSupplier ; + rdfs:isDefinedBy ns: . + +ns:SelectProductsFromSupplier a sp:Select ; + rdfs:label "Select products from supplier" ; + sp:text """ +PREFIX schema: + +SELECT DISTINCT ?product +WHERE + { GRAPH ?graph + { ?product schema:provider $about } + } +ORDER BY ?product +""" ; + rdfs:isDefinedBy ns: . + +# Place + +# cities in this region + +schema:Place ldh:template ns:CitiesInRegion . + +ns:CitiesInRegion a ldh:View ; + dct:title "Cities in this region" ; + spin:query ns:SelectCitiesInRegion ; + rdfs:isDefinedBy ns: . + +ns:SelectCitiesInRegion a sp:Select ; + rdfs:label "Select cities in region" ; + sp:text """ +PREFIX schema: + +SELECT DISTINCT ?city +WHERE + { GRAPH ?graph + { ?city schema:containedInPlace $about } + } +ORDER BY ?city +""" ; + rdfs:isDefinedBy ns: . + +# Product + +# orders containing this product + +schema:Product ldh:template ns:OrdersContainingProduct . + +ns:OrdersContainingProduct a ldh:View ; + dct:title "Orders containing this product" ; + spin:query ns:SelectOrdersContainingProduct ; + rdfs:isDefinedBy ns: . + +ns:SelectOrdersContainingProduct a sp:Select ; + rdfs:label "Select orders containing product" ; + sp:text """ +PREFIX schema: + +SELECT DISTINCT ?order +WHERE + { GRAPH ?graph + { ?order schema:orderedItem ?orderItem . + ?orderItem schema:orderedItem $about + } + } +ORDER BY DESC(?order) +""" ; + rdfs:isDefinedBy ns: . diff --git a/demo/northwind-traders/admin/model/person-template.ttl b/demo/northwind-traders/admin/model/person-template.ttl deleted file mode 100644 index 6300015..0000000 --- a/demo/northwind-traders/admin/model/person-template.ttl +++ /dev/null @@ -1,31 +0,0 @@ -@prefix : <#> . -@prefix ns: . -@prefix ldh: . -@prefix rdfs: . -@prefix sp: . -@prefix spin: . -@prefix dct: . -@prefix schema: . - -# orders handled by this employee - -schema:Person ldh:template ns:OrdersHandledByEmployee . - -ns:OrdersHandledByEmployee a ldh:View ; - dct:title "Orders handled by this employee" ; - spin:query ns:SelectOrdersHandledByEmployee ; - rdfs:isDefinedBy ns: . - -ns:SelectOrdersHandledByEmployee a sp:Select ; - rdfs:label "Select orders handled by employee" ; - sp:text """ -PREFIX schema: - -SELECT DISTINCT ?order -WHERE - { GRAPH ?graph - { ?order schema:broker $about } - } -ORDER BY DESC(?order) -""" ; - rdfs:isDefinedBy ns: . diff --git a/demo/northwind-traders/admin/model/place-template.ttl b/demo/northwind-traders/admin/model/place-template.ttl deleted file mode 100644 index 9398f06..0000000 --- a/demo/northwind-traders/admin/model/place-template.ttl +++ /dev/null @@ -1,31 +0,0 @@ -@prefix : <#> . -@prefix ns: . -@prefix ldh: . -@prefix rdfs: . -@prefix sp: . -@prefix spin: . -@prefix dct: . -@prefix schema: . - -# cities in this region - -schema:Place ldh:template ns:CitiesInRegion . - -ns:CitiesInRegion a ldh:View ; - dct:title "Cities in this region" ; - spin:query ns:SelectCitiesInRegion ; - rdfs:isDefinedBy ns: . - -ns:SelectCitiesInRegion a sp:Select ; - rdfs:label "Select cities in region" ; - sp:text """ -PREFIX schema: - -SELECT DISTINCT ?city -WHERE - { GRAPH ?graph - { ?city schema:containedInPlace $about } - } -ORDER BY ?city -""" ; - rdfs:isDefinedBy ns: . diff --git a/demo/northwind-traders/admin/model/post-class-templates.sh b/demo/northwind-traders/admin/model/post-ns.sh similarity index 62% rename from demo/northwind-traders/admin/model/post-class-templates.sh rename to demo/northwind-traders/admin/model/post-ns.sh index 3cb66d5..83d7603 100755 --- a/demo/northwind-traders/admin/model/post-class-templates.sh +++ b/demo/northwind-traders/admin/model/post-ns.sh @@ -35,32 +35,11 @@ admin_proxy=$(admin_uri "$proxy") # append the new class templates to the namespace ontology # prepend @base directive using end-user base URI so that the ns: prefix -# (defined as in the templates) resolves to the end-user namespace +# (defined as in ns.ttl) resolves to the end-user namespace # (e.g. https://northwind-traders.localhost:4443/ns#) instead of the admin namespace # (e.g. https://admin.northwind-traders.localhost:4443/ns#) -{ echo "@base <${base}> ."; cat person-template.ttl; } | post.sh \ - -f "$cert_pem_file" \ - -p "$cert_password" \ - --proxy "$admin_proxy" \ - --content-type "text/turtle" \ - "${admin_base}ontologies/namespace/" - -{ echo "@base <${base}> ."; cat corporation-template.ttl; } | post.sh \ - -f "$cert_pem_file" \ - -p "$cert_password" \ - --proxy "$admin_proxy" \ - --content-type "text/turtle" \ - "${admin_base}ontologies/namespace/" - -{ echo "@base <${base}> ."; cat place-template.ttl; } | post.sh \ - -f "$cert_pem_file" \ - -p "$cert_password" \ - --proxy "$admin_proxy" \ - --content-type "text/turtle" \ - "${admin_base}ontologies/namespace/" - -{ echo "@base <${base}> ."; cat product-template.ttl; } | post.sh \ +{ echo "@base <${base}> ."; cat ns.ttl; } | post.sh \ -f "$cert_pem_file" \ -p "$cert_password" \ --proxy "$admin_proxy" \ diff --git a/demo/northwind-traders/admin/model/product-template.ttl b/demo/northwind-traders/admin/model/product-template.ttl deleted file mode 100644 index 7914c18..0000000 --- a/demo/northwind-traders/admin/model/product-template.ttl +++ /dev/null @@ -1,33 +0,0 @@ -@prefix : <#> . -@prefix ns: . -@prefix ldh: . -@prefix rdfs: . -@prefix sp: . -@prefix spin: . -@prefix dct: . -@prefix schema: . - -# orders containing this product - -schema:Product ldh:template ns:OrdersContainingProduct . - -ns:OrdersContainingProduct a ldh:View ; - dct:title "Orders containing this product" ; - spin:query ns:SelectOrdersContainingProduct ; - rdfs:isDefinedBy ns: . - -ns:SelectOrdersContainingProduct a sp:Select ; - rdfs:label "Select orders containing product" ; - sp:text """ -PREFIX schema: - -SELECT DISTINCT ?order -WHERE - { GRAPH ?graph - { ?order schema:orderedItem ?orderItem . - ?orderItem schema:orderedItem $about - } - } -ORDER BY DESC(?order) -""" ; - rdfs:isDefinedBy ns: . diff --git a/demo/northwind-traders/install.sh b/demo/northwind-traders/install.sh index e7fee21..6539c58 100755 --- a/demo/northwind-traders/install.sh +++ b/demo/northwind-traders/install.sh @@ -35,7 +35,7 @@ printf "\n### Adding ontology import\n\n" printf "\n### Creating block templates\n\n" -./post-class-templates.sh "$base" "$cert_pem_file" "$cert_password" "$proxy" +./post-ns.sh "$base" "$cert_pem_file" "$cert_password" "$proxy" printf "\n### Clearing ontologies\n\n" diff --git a/demo/skos/admin/acl/create-authorizations.sh b/demo/skos/admin/acl/create-authorizations.sh index 0c75b68..bee09a0 100755 --- a/demo/skos/admin/acl/create-authorizations.sh +++ b/demo/skos/admin/acl/create-authorizations.sh @@ -27,14 +27,14 @@ admin_proxy=$(admin_uri "$proxy") pwd=$(realpath "$PWD") -sha1sum=$(sha1sum "$pwd"/../../files/skos.xsl | cut -d ' ' -f 1) +sha1sum=$(sha1sum "$pwd"/../../files/layout.xsl | cut -d ' ' -f 1) create-authorization.sh \ -b "$admin_base" \ -f "$cert_pem_file" \ -p "$cert_password" \ --proxy "$admin_proxy" \ - --label "Public SKOS XSLT stylesheet" \ + --label "Public layout XSLT stylesheet" \ --agent-class http://xmlns.com/foaf/0.1/Agent \ --to "${base}uploads/${sha1sum}/" \ --read diff --git a/demo/skos/admin/model/collection-template.ttl b/demo/skos/admin/model/collection-template.ttl deleted file mode 100644 index d358cde..0000000 --- a/demo/skos/admin/model/collection-template.ttl +++ /dev/null @@ -1,35 +0,0 @@ -@prefix : <#> . -@prefix ns: . -@prefix ldh: . -@prefix rdfs: . -@prefix sp: . -@prefix spin: . -@prefix dct: . -@prefix skos: . - -skos:Collection ldh:template ns:CollectionMembers. - -ns:CollectionMembers a ldh:View ; - dct:title "Collection members" ; - spin:query ns:SelectCollectionMembers ; - rdfs:isDefinedBy ns: . - -ns:SelectCollectionMembers a sp:Select ; - rdfs:label "Select collection members" ; - sp:text """ -PREFIX skos: - -SELECT DISTINCT ?member -WHERE - { GRAPH ?graph - { $about skos:member ?member . - GRAPH ?memberGraph - { - ?member skos:prefLabel ?prefLabel . - FILTER (langMatches(lang(?prefLabel), "en")) - } - } - } -ORDER BY ?prefLabel -""" ; - rdfs:isDefinedBy ns: . diff --git a/demo/skos/admin/model/concept-scheme-template.ttl b/demo/skos/admin/model/concept-scheme-template.ttl deleted file mode 100644 index 92507ef..0000000 --- a/demo/skos/admin/model/concept-scheme-template.ttl +++ /dev/null @@ -1,32 +0,0 @@ -@prefix : <#> . -@prefix ns: . -@prefix ldh: . -@prefix rdfs: . -@prefix sp: . -@prefix spin: . -@prefix dct: . -@prefix skos: . - -skos:ConceptScheme ldh:template ns:ConceptsInScheme. - -ns:ConceptsInScheme a ldh:View ; - dct:title "Concepts in scheme" ; - spin:query ns:SelectConceptsInScheme ; - rdfs:isDefinedBy ns: . - -ns:SelectConceptsInScheme a sp:Select ; - rdfs:label "Select concepts in scheme" ; - sp:text """ -PREFIX skos: - -SELECT DISTINCT ?concept -WHERE - { GRAPH ?graph - { ?concept skos:inScheme $about ; - skos:prefLabel ?prefLabel . - FILTER (langMatches(lang(?prefLabel), "en")) - } - } -ORDER BY ?prefLabel -""" ; - rdfs:isDefinedBy ns: . diff --git a/demo/skos/admin/model/concept-template.ttl b/demo/skos/admin/model/ns.ttl similarity index 54% rename from demo/skos/admin/model/concept-template.ttl rename to demo/skos/admin/model/ns.ttl index f94b5c7..60bf737 100644 --- a/demo/skos/admin/model/concept-template.ttl +++ b/demo/skos/admin/model/ns.ttl @@ -2,11 +2,13 @@ @prefix ns: . @prefix ldh: . @prefix rdfs: . -@prefix sp: . +@prefix sp: . @prefix spin: . @prefix dct: . @prefix skos: . +# Concept + # narrower skos:Concept ldh:template ns:NarrowerConcepts. @@ -65,3 +67,57 @@ ORDER BY ?prefLabel """ ; rdfs:isDefinedBy ns: . +# Collection + +skos:Collection ldh:template ns:CollectionMembers. + +ns:CollectionMembers a ldh:View ; + dct:title "Collection members" ; + spin:query ns:SelectCollectionMembers ; + rdfs:isDefinedBy ns: . + +ns:SelectCollectionMembers a sp:Select ; + rdfs:label "Select collection members" ; + sp:text """ +PREFIX skos: + +SELECT DISTINCT ?member +WHERE + { GRAPH ?graph + { $about skos:member ?member . + GRAPH ?memberGraph + { + ?member skos:prefLabel ?prefLabel . + FILTER (langMatches(lang(?prefLabel), "en")) + } + } + } +ORDER BY ?prefLabel +""" ; + rdfs:isDefinedBy ns: . + +# ConceptScheme + +skos:ConceptScheme ldh:template ns:ConceptsInScheme. + +ns:ConceptsInScheme a ldh:View ; + dct:title "Concepts in scheme" ; + spin:query ns:SelectConceptsInScheme ; + rdfs:isDefinedBy ns: . + +ns:SelectConceptsInScheme a sp:Select ; + rdfs:label "Select concepts in scheme" ; + sp:text """ +PREFIX skos: + +SELECT DISTINCT ?concept +WHERE + { GRAPH ?graph + { ?concept skos:inScheme $about ; + skos:prefLabel ?prefLabel . + FILTER (langMatches(lang(?prefLabel), "en")) + } + } +ORDER BY ?prefLabel +""" ; + rdfs:isDefinedBy ns: . diff --git a/demo/skos/admin/model/post-class-templates.sh b/demo/skos/admin/model/post-ns.sh similarity index 68% rename from demo/skos/admin/model/post-class-templates.sh rename to demo/skos/admin/model/post-ns.sh index b641a45..10bbaf2 100755 --- a/demo/skos/admin/model/post-class-templates.sh +++ b/demo/skos/admin/model/post-ns.sh @@ -35,25 +35,11 @@ admin_proxy=$(admin_uri "$proxy") # append the new class templates to the namespace ontology # prepend @base directive using end-user base URI so that the ns: prefix -# (defined as in the templates) resolves to the end-user namespace +# (defined as in ns.ttl) resolves to the end-user namespace # (e.g. https://swib.localhost:4443/ns#) instead of the admin namespace # (e.g. https://admin.swib.localhost:4443/ns#) -{ echo "@base <${base}> ."; cat concept-template.ttl; } | post.sh \ - -f "$cert_pem_file" \ - -p "$cert_password" \ - --proxy "$admin_proxy" \ - --content-type "text/turtle" \ - "${admin_base}ontologies/namespace/" - -{ echo "@base <${base}> ."; cat collection-template.ttl; } | post.sh \ - -f "$cert_pem_file" \ - -p "$cert_password" \ - --proxy "$admin_proxy" \ - --content-type "text/turtle" \ - "${admin_base}ontologies/namespace/" - -{ echo "@base <${base}> ."; cat concept-scheme-template.ttl; } | post.sh \ +{ echo "@base <${base}> ."; cat ns.ttl; } | post.sh \ -f "$cert_pem_file" \ -p "$cert_password" \ --proxy "$admin_proxy" \ diff --git a/demo/skos/files/skos.xsl b/demo/skos/files/layout.xsl similarity index 100% rename from demo/skos/files/skos.xsl rename to demo/skos/files/layout.xsl diff --git a/demo/skos/install.sh b/demo/skos/install.sh index 5af00eb..0b1db3c 100755 --- a/demo/skos/install.sh +++ b/demo/skos/install.sh @@ -43,7 +43,7 @@ printf "\n### Creating constraints\n\n" printf "\n### Creating block templates\n\n" -./post-class-templates.sh "$base" "$cert_pem_file" "$cert_password" "$proxy" +./post-ns.sh "$base" "$cert_pem_file" "$cert_password" "$proxy" cd .. diff --git a/packages/README.md b/packages/README.md new file mode 100644 index 0000000..8d43117 --- /dev/null +++ b/packages/README.md @@ -0,0 +1,233 @@ +# LinkedDataHub Packages + +This directory contains reusable packages for LinkedDataHub dataspaces. Packages provide vocabulary support with custom ontologies and XSLT templates for rendering specific RDF vocabularies. + +## Package Structure + +Each package consists of: + +``` +packages// +├── package.ttl # Package metadata (ldhp:Package resource) +├── ns.ttl # Ontology with template blocks (ldh:template) +└── layout.xsl # XSLT stylesheet with custom templates +``` + +### Example: SKOS Package + +``` +packages/skos/ +├── package.ttl # Metadata: https://packages.linkeddatahub.com/skos/#this +├── ns.ttl # SKOS vocabulary with ldh:template blocks +└── layout.xsl # XSLT templates for SKOS concepts, schemes, collections +``` + +## How Packages Work + +### 1. Package Metadata (`package.ttl`) + +Describes the package using standard LinkedDataHub properties: + +```turtle +@prefix ldhp: . +@prefix ldt: . +@prefix ac: . + + a ldhp:Package ; + rdfs:label "SKOS Package" ; + dct:description "SKOS vocabulary support with custom templates" ; + ldt:ontology ; + ac:stylesheet . +``` + +**Note**: Uses standard `ldt:ontology` and `ac:stylesheet` properties instead of inventing new ones. + +### 2. Ontology (`ns.ttl`) + +Contains two layers: + +**A. RDF Vocabulary Classes and Properties** +```turtle +skos:Concept a owl:Class ; + rdfs:label "Concept" . + +skos:narrower a owl:ObjectProperty ; + rdfs:label "has narrower" . +``` + +**B. Template Blocks (ldh:template)** + +SPARQL-based views attached to RDF types: + +```turtle +skos:Concept ldh:template ns:NarrowerConcepts . + +ns:NarrowerConcepts a ldh:View ; + dct:title "Narrower concepts" ; + spin:query ns:SelectNarrowerConcepts . + +ns:SelectNarrowerConcepts a sp:Select ; + sp:text """ + SELECT DISTINCT ?narrower + WHERE { GRAPH ?graph { $about skos:narrower ?narrower } } + ORDER BY ?narrower + """ . +``` + +### 3. XSLT Stylesheet (`layout.xsl`) + +XSLT templates using `bs2:*` modes to override default rendering: + +```xsl + + + + + + + +``` + +## Installing Packages + +### Method 1: CLI Script + +```bash +install-package.sh \ + -b https://localhost:4443/ \ + -f ssl/owner/cert.pem \ + -p Password \ + --package https://packages.linkeddatahub.com/skos/#this +``` + +### Method 2: From Application Install Script + +```bash +# In LinkedDataHub-Apps/demo/skos/install.sh +install-package.sh \ + -b "$base" \ + -f "$cert_pem_file" \ + -p "$cert_password" \ + --package "https://packages.linkeddatahub.com/skos/#this" +``` + +## Prerequisites + +Before installing packages, a **master stylesheet** must exist at `/static//layout.xsl` in the webapp directory. A default template is provided at: + +``` +src/main/webapp/static/localhost/layout.xsl +``` + +This file should be deployed with the application. It contains: + +```xml + + + + + + + + + +``` + +## What Installation Does + +When you install a package, the system: + +1. **Fetches package metadata** from the package URI +2. **Downloads package ontology** (`ns.ttl`) and POSTs it to the namespace graph (`${admin_base}ontologies/namespace/`) +3. **Downloads package stylesheet** (`layout.xsl`) and saves it to `/static/packages//layout.xsl` +4. **Updates master stylesheet** at `/static//layout.xsl` by adding import: + ```xml + + + ``` +5. **Adds import to application** (currently manual): ` ldh:import ` + +**Note**: The master stylesheet must already exist or installation will fail with `InternalServerErrorException`. + +## Architecture + +### Installation-Time vs Runtime + +Packages use **installation-time composition**, NOT runtime composition: + +- ✅ Package content is integrated during installation (via JAX-RS endpoints) +- ✅ Ontology and XSLT are pre-composed before being loaded +- ✅ No runtime overhead +- ❌ No dynamic package loading at request time + +### JAX-RS Endpoints + +- **POST `/admin/install-package`** - Installs a package + - Parameter: `packageUri` (form-urlencoded) + - Requires admin authentication + +- **POST `/admin/uninstall-package`** - Uninstalls a package + - Parameter: `packageUri` (form-urlencoded) + - Requires admin authentication + +### File System Structure + +After installation: + +``` +webapp/ +├── static/ +│ ├── packages/ +│ │ └── skos/ +│ │ └── layout.xsl # Package stylesheet +│ └── localhost/ +│ └── layout.xsl # Generated master stylesheet +``` + +### SPARQL Data Structure + +```turtle +# In system.trig (application config) + a lapp:Application ; + ldt:ontology ; + ac:stylesheet ; # Master stylesheet + ldh:import . + +# In admin SPARQL endpoint (namespace graph) +# Contains merged package ontologies via owl:imports +``` + +## Available Packages + +- **skos** - SKOS vocabulary support (concepts, schemes, collections) + +## Creating New Packages + +1. Create directory: `packages//` +2. Write `package.ttl` with metadata +3. Write `ns.ttl` with vocabulary and template blocks +4. Write `layout.xsl` with XSLT templates (using `bs2:*` modes) +5. Publish as Linked Data at `https://packages.linkeddatahub.com//#this` + +## Vocabulary Reference + +### LDHP Vocabulary (`https://w3id.org/atomgraph/linkeddatahub/package#`) + +- `ldhp:Package` - Package class + +### Standard Properties (Reused) + +- `ldt:ontology` - Points to package ontology URI (from LDT vocabulary) +- `ac:stylesheet` - Points to package stylesheet URI (from AtomGraph Client vocabulary) +- `ldh:import` - Application property linking to imported packages (from LDH vocabulary) + +## Notes + +- Packages are **declarative only** (RDF + XSLT, no Java code) +- Package ontologies use `owl:imports` (handled automatically by Jena) +- Package stylesheets use `xsl:import` (handled by master stylesheet generation) +- Template blocks (`ldh:template`) are separate from XSLT overrides +- Both mechanisms work independently and complement each other diff --git a/packages/skos/layout.xsl b/packages/skos/layout.xsl new file mode 100644 index 0000000..bea9ee2 --- /dev/null +++ b/packages/skos/layout.xsl @@ -0,0 +1,61 @@ + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/skos/ns.ttl b/packages/skos/ns.ttl new file mode 100644 index 0000000..60bf737 --- /dev/null +++ b/packages/skos/ns.ttl @@ -0,0 +1,123 @@ +@prefix : <#> . +@prefix ns: . +@prefix ldh: . +@prefix rdfs: . +@prefix sp: . +@prefix spin: . +@prefix dct: . +@prefix skos: . + +# Concept + +# narrower + +skos:Concept ldh:template ns:NarrowerConcepts. + +ns:NarrowerConcepts a ldh:View ; + dct:title "Narrower concepts" ; + spin:query ns:SelectNarrowerConcepts ; + rdfs:isDefinedBy ns: . + +ns:SelectNarrowerConcepts a sp:Select ; + rdfs:label "Select narrower concepts" ; + sp:text """ +PREFIX skos: + +SELECT DISTINCT ?narrower +WHERE + { GRAPH ?graph + { $about skos:narrower ?narrower . + GRAPH ?narrowerGraph + { + ?narrower skos:prefLabel ?prefLabel . + FILTER (langMatches(lang(?prefLabel), "en")) + } + } + } +ORDER BY ?prefLabel +""" ; + rdfs:isDefinedBy ns: . + +# broader + +skos:Concept ldh:template ns:BroaderConcepts. + +ns:BroaderConcepts a ldh:View ; + dct:title "Broader concepts" ; + spin:query ns:SelectBroaderConcepts ; + rdfs:isDefinedBy ns: . + +ns:SelectBroaderConcepts a sp:Select ; + rdfs:label "Select broader concepts" ; + sp:text """ +PREFIX skos: + +SELECT DISTINCT ?broader +WHERE + { GRAPH ?graph + { $about skos:broader ?broader . + GRAPH ?broaderGraph + { + ?broader skos:prefLabel ?prefLabel . + FILTER (langMatches(lang(?prefLabel), "en")) + } + } + } +ORDER BY ?prefLabel +""" ; + rdfs:isDefinedBy ns: . + +# Collection + +skos:Collection ldh:template ns:CollectionMembers. + +ns:CollectionMembers a ldh:View ; + dct:title "Collection members" ; + spin:query ns:SelectCollectionMembers ; + rdfs:isDefinedBy ns: . + +ns:SelectCollectionMembers a sp:Select ; + rdfs:label "Select collection members" ; + sp:text """ +PREFIX skos: + +SELECT DISTINCT ?member +WHERE + { GRAPH ?graph + { $about skos:member ?member . + GRAPH ?memberGraph + { + ?member skos:prefLabel ?prefLabel . + FILTER (langMatches(lang(?prefLabel), "en")) + } + } + } +ORDER BY ?prefLabel +""" ; + rdfs:isDefinedBy ns: . + +# ConceptScheme + +skos:ConceptScheme ldh:template ns:ConceptsInScheme. + +ns:ConceptsInScheme a ldh:View ; + dct:title "Concepts in scheme" ; + spin:query ns:SelectConceptsInScheme ; + rdfs:isDefinedBy ns: . + +ns:SelectConceptsInScheme a sp:Select ; + rdfs:label "Select concepts in scheme" ; + sp:text """ +PREFIX skos: + +SELECT DISTINCT ?concept +WHERE + { GRAPH ?graph + { ?concept skos:inScheme $about ; + skos:prefLabel ?prefLabel . + FILTER (langMatches(lang(?prefLabel), "en")) + } + } +ORDER BY ?prefLabel +""" ; + rdfs:isDefinedBy ns: . diff --git a/packages/skos/package.ttl b/packages/skos/package.ttl new file mode 100644 index 0000000..2fee9d7 --- /dev/null +++ b/packages/skos/package.ttl @@ -0,0 +1,19 @@ +@prefix : <#> . +@prefix lapp: . +@prefix ldt: . +@prefix ac: . +@prefix rdfs: . +@prefix dct: . +@prefix foaf: . + + a lapp:Package ; + rdfs:label "SKOS Package" ; + dct:title "SKOS Package for LinkedDataHub" ; + dct:description "Provides SKOS (Simple Knowledge Organization System) vocabulary support with custom templates for concept hierarchies, schemes, and collections." ; + dct:creator ; + ldt:ontology ; + ac:stylesheet . + + a foaf:Organization ; + foaf:name "AtomGraph" ; + foaf:homepage .