Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
35314d4
fix(ns): add dprod-shapes prefix to normative namespaces table
jgeluk Feb 18, 2026
c37a608
fix(spec-gen): prevent SHACL shape labels from leaking into spec
jgeluk Feb 18, 2026
0b7fb24
fix(ontology): add Retire to DataProductLifecycleStatus enumeration
jgeluk Feb 18, 2026
a51d9d3
fix(examples): correct ODRL modeling in data-rights example
jgeluk Feb 18, 2026
fcadb00
fix(examples): incorporate improvements from PR #132
jgeluk Feb 18, 2026
3185d95
chore: ballot 4 base for consolidation PRs
jgeluk Feb 25, 2026
a010650
fix: typo DataProductagreement -> DataProductAgreement in Example 2 (…
jgeluk Feb 25, 2026
25c0ae3
fix(ontology,shapes): protocol/securitySchemaType use dprod classes; …
jgeluk Feb 25, 2026
de2fe44
Ballot 4: add Retire to DataProductLifecycleStatus (#28) (#161)
jgeluk Mar 4, 2026
3804751
Ballot 4: add dprod-shapes prefix to normative namespaces (#29) (#162)
jgeluk Mar 4, 2026
215d451
Ballot 4: prevent SHACL shape labels leaking into spec (#79) (#163)
jgeluk Mar 4, 2026
d404805
Ballot 4: correct ODRL modeling in data-rights example (#81, #82, #83…
jgeluk Mar 4, 2026
0b9f369
Ballot 4: fix typo DataProductagreement in Example 2 (DPROD-23, #101)…
jgeluk Mar 4, 2026
979be51
Ballot 4: fix protocol/securitySchemaType to dprod classes; rdfs:labe…
jgeluk Mar 4, 2026
31a05ee
fix(examples): apply #165 data-rights JSON-LD variant on ballot/4
jgeluk Mar 4, 2026
270bb44
Ballot 4: apply data-rights example variant from #165 (#83) (#171)
jgeluk Mar 4, 2026
d4ca3c7
Ballot 4: show class identifier in generated spec (DPROD-21, #97) (#173)
jgeluk Apr 13, 2026
bf2eec0
Ballot 4: remove dprod:Protocol class (DPROD-33, #143) (#172)
jgeluk May 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/core-data-product-extensions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Below is an example of a Data Product with an associated Data Product Agreement
},
"ex:iSubjectToAgreement": {
"@id": "ex:VVSimpleAgreement",
"@type": "ex:DataProductagreement"
"@type": "ex:DataProductAgreement"
}
}
],
Expand Down
19 changes: 11 additions & 8 deletions examples/data-rights/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@ examplePolicyA odrl:target exampleProduct:ProductA .
examplePolicyB odrl:target exampleDataset:DatasetA1 .
```

An example of a policy follows, that describes permission to distribute the data only within a specific geographic region:
An example of an agreement follows, that describes permission to use all the datasets of the product if the user is working inside EMEA or APAC:

```json
examplePolicyA odrl:permission
{
"action": "odrl:distribute",
"constraint": [
{"leftOperand": "spatial",
"operator": "eq",
"rightOperator": "region:EMEA"
}
]
"action": "odrl:use",
"assignee": {
"@type": "odrl:PartyCollection",
"refinement": [
{"leftOperand": "odrl:spatial",
"operator": "odrl:isAnyOf",
"rightOperand": ["reg:EMEA", "reg:APAC"]
}
]
}
}
```

33 changes: 17 additions & 16 deletions examples/data-rights/example.jsonld
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
{
"@type": "Offer",
"@type": "Agreement",
"@context": [
{
"odrl": "http://www.w3.org/ns/odrl/2/",
"reg": "https://www.region.taxonomy/v/1/"
}
],
"uid": "56456df-dfg-34535345-5545",
"assigner": "https://schema.org/person/AdamSmith",
"target": "https://data.org/data-product/equity-trade-xxx",

"permission": [
{
"action": "odrl:read",
"constraint": [
{
"@type": "odrl:Constraint",
"leftOperand": "odrl:spatial",
"operator": "odrl:isAnyOf",
"rightOperand": [
"reg:EMEA",
"reg:APAC"
],
"description": " Permission to read all the datasets of the product if user is working inside EMEA or APAC"
}
]
"target": "https://data.org/data-product/equity-trade-xxx",
"assigner": "https://schema.org/person/AdamSmith",
"assignee": {
"@type": "PartyCollection",
"source": "https://example.org/DataDepartment",
"refinement": [{
"leftOperand": "odrl:spatial",
"operator": "odrl:isAnyOf",
"rightOperand": [
"reg:EMEA",
"reg:APAC"
],
"description": " Permission to read all the datasets of the product if user is working inside EMEA or APAC"
}]
},
"action": "odrl:use",
}
]
}
13 changes: 3 additions & 10 deletions ontology/dprod/dprod-ontology.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ dprod:DataProduct
dprod:DataProductLifecycleStatus
a owl:Class, rdfs:Class ;
dct:description
"The development status of the data product taken from a controlled list (e.g. Ideation, Design, Build, Deploy, Consume)."@en ;
"The development status of the data product taken from a controlled list (e.g. Ideation, Design, Build, Deploy, Consume, Retire)."@en ;
rdfs:comment "The lifecycle of the data product as defined by EDM Council CDMC"@en ;
rdfs:isDefinedBy dprod: ;
rdfs:label "data product lifecycle status" ;
Expand All @@ -78,13 +78,6 @@ dprod:Enumeration
rdfs:label "enumeration" ;
.

dprod:Protocol
a owl:Class, rdfs:Class ;
dct:description "A detailed specification, possibly including a specific version, for how to communicate with a service."@en ;
rdfs:isDefinedBy dprod: ;
rdfs:label "protocol" ;
.

dprod:SecuritySchemaType
a owl:Class, rdfs:Class ;
dct:description "A classification encompassing a set of rules used for authentication and communication."@en ;
Expand Down Expand Up @@ -211,7 +204,7 @@ dprod:protocol
dct:description "A protocol (possibly one of many options) used to communicate with this data service."@en ;
rdfs:isDefinedBy dprod: ;
rdfs:domain dcat:DataService ;
# rdfs:range rdf:resource ; # better let user decide whether they want Protocol class or own class or skos
# rdfs:range not specified; users reference external URIs or SKOS concepts (DPROD-33)
rdfs:label "protocol" ;
.

Expand All @@ -221,5 +214,5 @@ dprod:securitySchemaType
rdfs:isDefinedBy dprod: ;
rdfs:domain dcat:DataService ;
# rdfs:range rdf:resource ; # better let user decide whether they want SecuritySchemaType class or own class or skos
rdf:label "security schema type" ;
rdfs:label "security schema type" ;
.
14 changes: 2 additions & 12 deletions ontology/dprod/dprod-shapes.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix sdo: <http://schema.org/> .

dprod-shapes:
a owl:Ontology ;
Expand Down Expand Up @@ -125,19 +124,11 @@ dprod-shapes:InformationSensitivityClassificationShape
dprod-shapes:DataProductLifecycleStatusShape
a sh:NodeShape;
rdfs:label "data product lifecycle status shape" ;
dct:description "The development status of the data product taken from a controlled list (e.g. Ideation, Design, Build, Deploy, Consume)."@en ;
dct:description "The development status of the data product taken from a controlled list (e.g. Ideation, Design, Build, Deploy, Consume, Retire)."@en ;
sh:targetClass dprod:DataProductLifecycleStatus;
rdfs:isDefinedBy dprod-shapes:;
.

dprod-shapes:ProtocolShape
a sh:NodeShape;
rdfs:label "protocol shape" ;
dct:description "A detailed specification, possibly including a specific version, for how to communicate with a service."@en ;
rdfs:isDefinedBy dprod-shapes:;
sh:targetClass dprod:Protocol;
.

dprod-shapes:SecuritySchemaTypeShape
a sh:NodeShape;
rdfs:label "security schema type shape" ;
Expand Down Expand Up @@ -362,7 +353,6 @@ dprod-shapes:DataService-protocol
a sh:PropertyShape;
rdfs:isDefinedBy dprod-shapes:;
sh:path dprod:protocol;
sh:class dcat:Protocol;
dct:description "A protocol (possibly one of many options) used to communicate with this data service."@en ;
rdfs:label "data service protocol shape" ;
.
Expand All @@ -371,7 +361,7 @@ dprod-shapes:DataService-securitySchemaType
a sh:PropertyShape;
rdfs:isDefinedBy dprod-shapes:;
sh:path dprod:securitySchemaType;
sh:class dcat:SecuritySchemaType;
sh:class dprod:SecuritySchemaType;
dct:description "The security schema type used for authentication and communication with this Data Service."@en ;
rdfs:label "data service security schema type shape" ;
.
Expand Down
20 changes: 20 additions & 0 deletions respec/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,15 @@ <h2>Normative namespaces</h2>
</td>
<td>[[dprod]]</td>
</tr>
<tr>
<td>
<code>dprod-shapes</code>
</td>
<td>
<code>https://ekgf.github.io/dprod/shapes/</code>
</td>
<td>[[dprod]]</td>
</tr>
<tr>
<td>
<code>dcat</code>
Expand Down Expand Up @@ -807,6 +816,17 @@ <h2>Data Product (DPROD) Model</h2>
{% for cls in classes %}
<section>
<h3 id="{{cls.html_id()}}">{{cls.name}}</h3>
<table class="def classdef">
<tbody>
<tr>
<th>Identifier:</th>
<td>
<!--suppress HtmlUnknownTarget -->
<a href="{{cls.href()}}">{{cls.axiom_iri_normalized}}</a>
</td>
</tr>
</tbody>
</table>
{% if cls.description is not none %}
<p>{{cls.description}}</p>
{% endif %}
Expand Down
1 change: 1 addition & 0 deletions spec-generator/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

IGNORED_NODE_SHAPE_PREDICATES = (
RDF.type,
RDFS.label,
RDFS.isDefinedBy,
SKOS.altLabel,
SKOS.changeNote,
Expand Down
1 change: 0 additions & 1 deletion spec-generator/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ def main():
'Dataset',
'DataProductLifecycleStatus',
'InformationSensitivityClassification',
'Protocol',
'SecuritySchemaType',
'Enumeration'
])
Expand Down
12 changes: 11 additions & 1 deletion spec-generator/node_shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from rdflib import URIRef, Graph, SH, DCTERMS, Literal, RDFS

from functions import short_name, null_html_string, cast_to_uri_ref
from globals import IGNORED_NODE_SHAPE_PREDICATES, shapes_graph_ns_iri
from globals import IGNORED_NODE_SHAPE_PREDICATES, ontology_namespace_iri, shapes_graph_ns_iri


@dataclass(init=False)
Expand All @@ -25,6 +25,7 @@ def __init__(self, g: Graph, **kwargs):
self.axiom_iri = cast_to_uri_ref(g.value(self.shape_iri, SH.targetClass))
if self.axiom_iri is None:
raise ValueError("No sh:axiom_iri provided for NodeShape")
self.axiom_iri_normalized = g.namespace_manager.normalizeUri(self.axiom_iri)
# First load the properties of the OWL target class
for rdf_predicate, rdf_object in g.predicate_objects(self.axiom_iri):
self._set_prop(g, rdf_predicate, rdf_object, 'OWL')
Expand Down Expand Up @@ -85,3 +86,12 @@ def html_id(self) -> str | None:
if self.shape_iri.__contains__(shapes_graph_ns_iri):
return self.shape_iri.replace(shapes_graph_ns_iri, '').lower()
return self.name.lower()

def href(self) -> str:
"""Return the href value for the class's canonical identifier.
For DPROD-local classes this points back to the in-page section
(consistent with PropertyShape.href); for external classes such as
dcat:DataService it points to the defining vocabulary."""
if self.axiom_iri.__contains__(ontology_namespace_iri):
return f"#{self.html_id()}"
return str(self.axiom_iri)
Loading