Skip to content

Commit b54d8c8

Browse files
authored
Ontology-based blocks are attached to properties, not classes (#267)
Includes support for "inverse blocks"
1 parent 65b3278 commit b54d8c8

File tree

6 files changed

+63
-34
lines changed

6 files changed

+63
-34
lines changed

src/main/resources/com/atomgraph/linkeddatahub/app/admin/adm.ttl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,10 @@ owl:Ontology spin:constructor [
6565
owl:versionInfo "1.0-SNAPSHOT" .
6666
}
6767
WHERE {}"""
68-
] ;
68+
] .
6969
# spin:constraint :MissingRDFSLabel .
70-
ldh:template :OntologyClassView .
70+
71+
rdfs:isDefinedBy ldh:inverseBlock :OntologyClassView .
7172

7273
:OntologyClassView a ldh:View ;
7374
dct:title "Ontology classes" ;
@@ -215,8 +216,9 @@ acl:Authorization spin:constructor [
215216
[
216217
a ldh:MissingPropertyValue ;
217218
sp:arg1 acl:mode
218-
] ;
219-
ldh:template :AuthorizationAgentView .
219+
] .
220+
221+
acl:agent ldh:block :AuthorizationAgentView .
220222

221223
:AuthorizationAgentView a ldh:View ;
222224
dct:title "Authorization agents" ;

src/main/resources/com/atomgraph/linkeddatahub/ldh.ttl

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,18 @@
9191
rdfs:label "Series variable name" ;
9292
rdfs:isDefinedBy : .
9393

94-
:template a owl:ObjectProperty ;
95-
rdfs:domain rdfs:Class ;
96-
rdfs:label "Class-level content block" ;
94+
:block a owl:ObjectProperty ;
95+
rdfs:domain rdf:Property ;
96+
rdfs:range :View ;
97+
rdfs:label "Property block" ;
98+
rdfs:comment "Attaches a view block to a property for forward relationships ($about property ?value)" ;
99+
rdfs:isDefinedBy : .
100+
101+
:inverseBlock a owl:ObjectProperty ;
102+
rdfs:domain rdf:Property ;
103+
rdfs:range :View ;
104+
rdfs:label "Inverse property block" ;
105+
rdfs:comment "Attaches a view block to a property for inverse relationships (?value property $about)" ;
97106
rdfs:isDefinedBy : .
98107

99108
# CLASSES

src/main/resources/com/linkeddatahub/packages/skos/ns.ttl

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
# Concept
1515

1616
skos:Concept spin:constructor :ConceptConstructor ;
17-
spin:constraint :MissingPrefLabel ;
18-
ldh:template :NarrowerConcepts .
17+
spin:constraint :MissingPrefLabel .
1918

2019
:ConceptConstructor a ldh:Constructor ;
2120
rdfs:label "Concept constructor" ;
@@ -37,6 +36,8 @@ skos:Concept spin:constructor :ConceptConstructor ;
3736

3837
# narrower
3938

39+
skos:narrower ldh:block :NarrowerConcepts .
40+
4041
:NarrowerConcepts a ldh:View ;
4142
dct:title "Narrower concepts" ;
4243
spin:query :SelectNarrowerConcepts ;
@@ -64,7 +65,7 @@ ORDER BY ?prefLabel
6465

6566
# broader
6667

67-
skos:Concept ldh:template :BroaderConcepts.
68+
skos:broader ldh:block :BroaderConcepts .
6869

6970
:BroaderConcepts a ldh:View ;
7071
dct:title "Broader concepts" ;
@@ -94,8 +95,7 @@ ORDER BY ?prefLabel
9495
# Collection
9596

9697
skos:Collection spin:constructor :CollectionConstructor ;
97-
spin:constraint :MissingPrefLabel ;
98-
ldh:template :CollectionMembers.
98+
spin:constraint :MissingPrefLabel .
9999

100100
:CollectionConstructor a ldh:Constructor ;
101101
rdfs:label "Collection constructor" ;
@@ -111,6 +111,8 @@ skos:Collection spin:constructor :CollectionConstructor ;
111111
WHERE {}""" ;
112112
rdfs:isDefinedBy : .
113113

114+
skos:member ldh:block :CollectionMembers .
115+
114116
:CollectionMembers a ldh:View ;
115117
dct:title "Collection members" ;
116118
spin:query :SelectCollectionMembers ;
@@ -138,8 +140,7 @@ ORDER BY ?prefLabel
138140

139141
# ConceptScheme
140142

141-
skos:ConceptScheme spin:constructor :ConceptSchemeConstructor ;
142-
ldh:template :ConceptsInScheme.
143+
skos:ConceptScheme spin:constructor :ConceptSchemeConstructor .
143144

144145
:ConceptSchemeConstructor a ldh:Constructor ;
145146
rdfs:label "Concept scheme constructor" ;
@@ -156,6 +157,8 @@ skos:ConceptScheme spin:constructor :ConceptSchemeConstructor ;
156157
WHERE {}""" ;
157158
rdfs:isDefinedBy : .
158159

160+
skos:inScheme ldh:inverseBlock :ConceptsInScheme .
161+
159162
:ConceptsInScheme a ldh:View ;
160163
dct:title "Concepts in scheme" ;
161164
spin:query :SelectConceptsInScheme ;

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block.xsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ exclude-result-prefixes="#all"
161161
<xsl:variable name="offset-x-treshold" select="120" as="xs:double"/>
162162
<xsl:variable name="offset-y-treshold" select="20" as="xs:double"/>
163163

164-
<!-- there might be multiple .row-block-controls in a block if the main block is followed by blocks rendered from ldh:template -->
164+
<!-- there might be multiple .row-block-controls in a block if the main block is followed by blocks rendered from ldh:block -->
165165
<xsl:variable name="row-block-controls" select="key('elements-by-class', 'row-block-controls', .)[1]" as="element()"/>
166166
<xsl:variable name="btn-edit" select="key('elements-by-class', 'btn-edit', $row-block-controls)" as="element()"/>
167167
<!-- check that the mouse is on the top edge and show the block controls if they're not already shown -->

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,9 @@ exclude-result-prefixes="#all">
119119
<xsl:param name="google:clientID" as="xs:string?"/>
120120
<xsl:param name="orcid:clientID" as="xs:string?"/>
121121
<xsl:param name="doc-types" select="key('resources', ac:absolute-path(ldh:base-uri(.)))/rdf:type/@rdf:resource[ . = ('&def;Root', '&dh;Container', '&dh;Item')]" as="xs:anyURI*"/>
122-
<!-- take care not to load unnecessary documents over HTTP when $doc-types is empty -->
123-
<xsl:param name="template-block-uris" select="if (exists($doc-types)) then (if (doc-available(resolve-uri('ns?query=ASK%20%7B%7D', $ldt:base))) then (ldh:query-result(resolve-uri('ns', $ldt:base), $template-query || ' VALUES $Type { ' || string-join(for $type in $doc-types return '&lt;' || $type || '&gt;', ' ') || ' }')//srx:binding[@name = 'block']/srx:uri/xs:anyURI(.)) else ()) else ()" as="xs:anyURI*"/>
124122
<xsl:param name="block-uris" select="key('resources', ac:absolute-path(ldh:base-uri(.)))/rdf:*[starts-with(local-name(), '_')]/@rdf:resource" as="xs:anyURI*"/>
125-
<!-- document has content when there are are content sequence properties or template-declared class-level blocks exist -->
126-
<xsl:param name="has-content" select="exists($block-uris) or exists($template-block-uris)" as="xs:boolean"/>
123+
<!-- document has content when there are content sequence properties -->
124+
<xsl:param name="has-content" select="exists($block-uris)" as="xs:boolean"/>
127125
<xsl:param name="ac:mode" select="if ($has-content) then xs:anyURI('&ldh;ContentMode') else xs:anyURI('&ac;ReadMode')" as="xs:anyURI*"/>
128126
<xsl:param name="location-mapping" as="map(xs:anyURI, xs:anyURI)">
129127
<xsl:map>
@@ -177,17 +175,37 @@ LIMIT 100
177175
]]>
178176
</xsl:variable>
179177
<xsl:variable name="app-request-uri" select="ac:build-uri(resolve-uri('sparql', $ldt:base), map{ 'query': $app-query })" as="xs:anyURI"/>
180-
<xsl:variable name="template-query" as="xs:string">
178+
<xsl:variable name="forward-block-query" as="xs:string">
181179
<![CDATA[
180+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
182181
PREFIX ldh: <https://w3id.org/atomgraph/linkeddatahub#>
183182
184-
SELECT *
183+
SELECT DISTINCT ?block
185184
WHERE
186185
{
187-
$Type ldh:template ?block
186+
?property ldh:block ?block .
187+
{ ?property rdfs:domain $domain }
188+
UNION
189+
{ ?property rdfs:subPropertyOf+/rdfs:domain $domain }
188190
}
189191
]]>
190-
<!-- VALUES $Type goes here -->
192+
<!-- VALUES $domain goes here -->
193+
</xsl:variable>
194+
<xsl:variable name="inverse-block-query" as="xs:string">
195+
<![CDATA[
196+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
197+
PREFIX ldh: <https://w3id.org/atomgraph/linkeddatahub#>
198+
199+
SELECT DISTINCT ?block
200+
WHERE
201+
{
202+
?property ldh:inverseBlock ?block .
203+
{ ?property rdfs:range $range }
204+
UNION
205+
{ ?property rdfs:subPropertyOf+/rdfs:range $range }
206+
}
207+
]]>
208+
<!-- VALUES $range goes here -->
191209
</xsl:variable>
192210
<xsl:variable name="constraint-query" as="xs:string">
193211
<![CDATA[
@@ -875,17 +893,10 @@ LIMIT 100
875893
<!-- error responses always rendered in bs2:Row mode, no matter what $ac:mode specifies -->
876894
<xsl:when test="key('resources-by-type', '&http;Response') and not(key('resources-by-type', '&spin;ConstraintViolation')) and not(key('resources-by-type', '&sh;ValidationResult'))">
877895
<xsl:apply-templates select="." mode="bs2:Row">
878-
<xsl:with-param name="template-query" select="$template-query" tunnel="yes"/>
879896
<xsl:sort select="ac:label(.)"/>
880897
</xsl:apply-templates>
881898
</xsl:when>
882899
<xsl:when test="$ac:mode = '&ldh;ContentMode'">
883-
<xsl:for-each select="$template-block-uris">
884-
<xsl:if test="doc-available(ac:document-uri(.))">
885-
<xsl:apply-templates select="key('resources', ., document(ac:document-uri(.)))" mode="bs2:Row"/>
886-
</xsl:if>
887-
</xsl:for-each>
888-
889900
<xsl:apply-templates select="." mode="ldh:ContentList"/>
890901
</xsl:when>
891902
<xsl:when test="$ac:mode = '&ac;MapMode'">

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/resource.xsl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ extension-element-prefixes="ixsl"
609609
<!-- hide instances of system classes -->
610610
<xsl:template match="*[not($ldh:renderSystemResources)][@rdf:about = ac:absolute-path(ldh:base-uri(.)) and rdf:type/@rdf:resource = ('&def;Root', '&dh;Container', '&dh;Item')]" mode="bs2:Row" priority="1" use-when="system-property('xsl:product-name') = 'SAXON'"/>
611611

612-
<!-- overriding template used to inject ldh:template blocks (server-side only) -->
612+
<!-- overriding template used to inject ldh:block blocks (server-side only) -->
613613
<xsl:template match="*[*][@rdf:about][not(rdf:type/@rdf:resource = '&http;Response')] | *[*][@rdf:nodeID][not(rdf:type/@rdf:resource = '&http;Response')]" mode="bs2:Row" priority="0.7" use-when="system-property('xsl:product-name') = 'SAXON'">
614614
<!-- TO-DO: use ldh:request-uri() to resolve URIs server-side -->
615615
<xsl:param name="id" select="if (contains(@rdf:about, ac:absolute-path(ldh:base-uri(.)) || '#')) then substring-after(@rdf:about, ac:absolute-path(ldh:base-uri(.)) || '#') else generate-id()" as="xs:string?"/>
@@ -618,8 +618,12 @@ extension-element-prefixes="ixsl"
618618
<xsl:param name="typeof" select="rdf:type/@rdf:resource/xs:anyURI(.)" as="xs:anyURI*"/>
619619
<xsl:param name="mode" as="xs:anyURI?"/>
620620
<xsl:param name="style" as="xs:string?"/>
621-
<!-- take care not to load unnecessary documents over HTTP when $typeof is empty -->
622-
<xsl:variable name="block-values" select="if (exists($typeof)) then (if (doc-available(resolve-uri('ns?query=ASK%20%7B%7D', $ldt:base))) then (ldh:query-result(resolve-uri('ns', $ldt:base), $template-query || ' VALUES $Type { ' || string-join(for $type in $typeof return '&lt;' || $type || '&gt;', ' ') || ' }')//srx:binding[@name = 'block']/srx:uri/xs:anyURI(.)) else ()) else ()" as="xs:anyURI*" use-when="system-property('xsl:product-name') = 'SAXON'"/>
621+
<!-- query ontology for forward blocks where rdfs:domain matches instance types (check direct domain and inherited via rdfs:subPropertyOf) -->
622+
<xsl:variable name="forward-block-values" select="if (exists($typeof) and doc-available(resolve-uri('ns?query=ASK%20%7B%7D', $ldt:base))) then ldh:query-result(resolve-uri('ns', $ldt:base), $forward-block-query || ' VALUES $domain { ' || string-join(for $type in $typeof return '&lt;' || $type || '&gt;', ' ') || ' }')//srx:binding[@name = 'block']/srx:uri/xs:anyURI(.) else ()" as="xs:anyURI*" use-when="system-property('xsl:product-name') = 'SAXON'"/>
623+
<!-- query ontology for inverse blocks where rdfs:range matches instance types (check direct range and inherited via rdfs:subPropertyOf) -->
624+
<xsl:variable name="inverse-block-values" select="if (exists($typeof) and doc-available(resolve-uri('ns?query=ASK%20%7B%7D', $ldt:base))) then ldh:query-result(resolve-uri('ns', $ldt:base), $inverse-block-query || ' VALUES $range { ' || string-join(for $type in $typeof return '&lt;' || $type || '&gt;', ' ') || ' }')//srx:binding[@name = 'block']/srx:uri/xs:anyURI(.) else ()" as="xs:anyURI*" use-when="system-property('xsl:product-name') = 'SAXON'"/>
625+
<!-- combine both forward and inverse blocks -->
626+
<xsl:variable name="block-values" select="($forward-block-values, $inverse-block-values)" as="xs:anyURI*" use-when="system-property('xsl:product-name') = 'SAXON'"/>
623627

624628
<xsl:choose>
625629
<xsl:when test="exists($block-values)">
@@ -652,7 +656,7 @@ extension-element-prefixes="ixsl"
652656
</xsl:next-match>
653657

654658
<xsl:variable name="base-uri" select="ac:absolute-path(ldh:base-uri(.))" as="xs:anyURI"/>
655-
<!-- render contents attached to the types of this resource using ldh:template -->
659+
<!-- render blocks applicable to this resource's types (forward blocks via rdfs:domain, inverse blocks via rdfs:range) -->
656660
<xsl:for-each select="$block-values" use-when="system-property('xsl:product-name') = 'SAXON'">
657661
<xsl:if test="doc-available(ac:document-uri(.))">
658662
<xsl:variable name="id" select="'id' || ac:uuid()" as="xs:string"/>

0 commit comments

Comments
 (0)