Skip to content

Commit cff9deb

Browse files
namedgraphclaude
andcommitted
Simplify external doc tab rendering and add lapp:application Link header
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c6a19b4 commit cff9deb

10 files changed

Lines changed: 65 additions & 123 deletions

File tree

src/main/java/com/atomgraph/linkeddatahub/server/filter/response/ResponseHeadersFilter.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.atomgraph.linkeddatahub.server.model.impl.Dispatcher;
2727
import com.atomgraph.linkeddatahub.server.security.AuthorizationContext;
2828
import com.atomgraph.linkeddatahub.vocabulary.ACL;
29+
import com.atomgraph.linkeddatahub.vocabulary.LAPP;
2930
import java.io.IOException;
3031
import java.net.URI;
3132
import java.util.Optional;
@@ -80,6 +81,8 @@ public void filter(ContainerRequestContext request, ContainerResponseContext res
8081
if (!isProxyRequest && getApplication().isPresent())
8182
{
8283
Application application = getApplication().get();
84+
// add Link rel=lapp:application
85+
response.getHeaders().add(HttpHeaders.LINK, new Link(URI.create(application.getURI()), LAPP.application.getURI(), null));
8386
// add Link rel=ldt:ontology, if the ontology URI is specified
8487
if (application.getOntology() != null)
8588
response.getHeaders().add(HttpHeaders.LINK, new Link(URI.create(application.getOntology().getURI()), LDT.ontology.getURI(), null));

src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,7 @@ public static String getURI()
9191
/** Origin property for subdomain-based application matching */
9292
public static final ObjectProperty origin = m_model.createObjectProperty(NS + "origin");
9393

94+
/** Application property (for Link header rel) */
95+
public static final ObjectProperty application = m_model.createObjectProperty( NS + "application" );
96+
9497
}

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

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,26 +80,19 @@ exclude-result-prefixes="#all"
8080
</xsl:function>
8181

8282
<xsl:function name="sd:endpoint" as="xs:anyURI">
83-
<!-- check for an active tab with a known endpoint; data-endpoint is on the <li> -->
8483
<xsl:variable name="active-tab-li" select="id('tab-bar-list', ixsl:page())/li[contains-token(@class, 'active')]" as="element()?"/>
85-
<xsl:variable name="tab-endpoint" select="
86-
if ($active-tab-li and ixsl:contains($active-tab-li, 'dataset.endpoint'))
87-
then xs:anyURI(ixsl:get($active-tab-li, 'dataset.endpoint'))
88-
else ()" as="xs:anyURI?"/>
89-
<!-- priority: active tab endpoint > global LinkedDataHub.endpoint > local SPARQL -->
90-
<xsl:sequence select="(
91-
$tab-endpoint,
92-
if (ixsl:contains(ixsl:get(ixsl:window(), 'LinkedDataHub'), 'endpoint'))
93-
then xs:anyURI(ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub'), 'endpoint'))
94-
else (),
95-
resolve-uri('sparql', ldt:base())
96-
)[1]"/>
84+
<xsl:sequence select="if ($active-tab-li) then xs:anyURI(ixsl:get($active-tab-li, 'dataset.endpoint')) else resolve-uri('sparql', ldt:base())"/>
85+
</xsl:function>
86+
87+
<xsl:function name="lapp:application" as="xs:anyURI?">
88+
<xsl:variable name="active-tab-li" select="id('tab-bar-list', ixsl:page())/li[contains-token(@class, 'active')]" as="element()?"/>
89+
<xsl:sequence select="if ($active-tab-li) then xs:anyURI(ixsl:get($active-tab-li, 'dataset.application')) else ()"/>
9790
</xsl:function>
9891

9992
<xsl:function name="ldh:query-type" as="xs:string?">
10093
<xsl:param name="query-string" as="xs:string"/>
10194

102-
<xsl:sequence xmlns:fn="http://www.w3.org/2005/xpath-functions" select="analyze-string($query-string, '[^a-zA-Z]?(SELECT|ASK|DESCRIBE|CONSTRUCT)[^a-zA-Z]', 'i')/fn:match[1]/fn:group[@nr = '1']/string() => upper-case()"/>
95+
<xsl:sequence select="analyze-string($query-string, '[^a-zA-Z]?(SELECT|ASK|DESCRIBE|CONSTRUCT)[^a-zA-Z]', 'i')/fn:match[1]/fn:group[@nr = '1']/string() => upper-case()"/>
10396
</xsl:function>
10497

10598
<xsl:function name="ldh:new-object">

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,7 +1004,7 @@ LIMIT 10
10041004

10051005
<xsl:for-each select="$content-body">
10061006
<xsl:result-document href="?." method="ixsl:append-content">
1007-
<div class="modal modal-constructor fade in" about="{$lapp:application}">
1007+
<div class="modal modal-constructor fade in" about="{lapp:application()}">
10081008
<xsl:if test="$id">
10091009
<xsl:attribute name="id" select="$id"/>
10101010
</xsl:if>
@@ -1032,7 +1032,7 @@ LIMIT 10
10321032
map{
10331033
'request': $request,
10341034
'block': $block,
1035-
'about': $lapp:application,
1035+
'about': lapp:application(),
10361036
'method': $method,
10371037
'action': resolve-uri('settings', ldt:base())
10381038
}"/>

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ extension-element-prefixes="ixsl"
432432

433433
<!-- CONTENT BODY -->
434434

435-
<xsl:template match="rdf:RDF[exists($ldh:requestUri) and key('resources-by-type', '&http;Response') and not(key('resources-by-type', '&spin;ConstraintViolation')) and not(key('resources-by-type', '&sh;ValidationResult'))]" mode="bs2:ContentBody" priority="1">
435+
<xsl:template match="rdf:RDF[key('resources-by-type', '&http;Response') and not(key('resources-by-type', '&spin;ConstraintViolation')) and not(key('resources-by-type', '&sh;ValidationResult'))]" mode="bs2:ContentBody" priority="1">
436436
<xsl:param name="id" as="xs:string?"/>
437437
<xsl:param name="class" select="'container-fluid content-body'" as="xs:string?"/>
438438

@@ -611,7 +611,7 @@ extension-element-prefixes="ixsl"
611611
</xsl:param>
612612
<xsl:param name="anchor-column" as="xs:boolean" select="true()" tunnel="yes"/>
613613
<xsl:param name="object-uris" select="rdf:Description/*/@rdf:resource[not(key('resources', .))]" as="xs:anyURI*"/>
614-
<xsl:param name="object-metadata" select="if (exists($object-uris)) then ldh:send-request($sd:endpoint, 'POST', 'application/sparql-query', $object-metadata-query || ' VALUES $this { ' || string-join(for $uri in $object-uris return '&lt;' || $uri || '&gt;', ' ') || ' }', map{ 'Accept': 'application/rdf+xml' }) else ()" as="document-node()?" tunnel="yes"/>
614+
<xsl:param name="object-metadata" select="if (exists($object-uris)) then ldh:send-request(sd:endpoint(), 'POST', 'application/sparql-query', $object-metadata-query || ' VALUES $this { ' || string-join(for $uri in $object-uris return '&lt;' || $uri || '&gt;', ' ') || ' }', map{ 'Accept': 'application/rdf+xml' }) else ()" as="document-node()?" tunnel="yes"/>
615615

616616
<xsl:next-match>
617617
<xsl:with-param name="id" select="$id"/>

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

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<!ENTITY srx "http://www.w3.org/2005/sparql-results#">
1414
<!ENTITY http "http://www.w3.org/2011/http#">
1515
<!ENTITY acl "http://www.w3.org/ns/auth/acl#">
16+
<!ENTITY sd "http://www.w3.org/ns/sparql-service-description#">
1617
<!ENTITY ldt "https://www.w3.org/ns/ldt#">
1718
<!ENTITY dh "https://www.w3.org/ns/ldt/document-hierarchy#">
1819
<!ENTITY sh "http://www.w3.org/ns/shacl#">
@@ -39,6 +40,7 @@ xmlns:xsd="&xsd;"
3940
xmlns:srx="&srx;"
4041
xmlns:http="&http;"
4142
xmlns:acl="&acl;"
43+
xmlns:sd="&sd;"
4244
xmlns:ldt="&ldt;"
4345
xmlns:sh="&sh;"
4446
xmlns:sp="&sp;"
@@ -117,6 +119,14 @@ exclude-result-prefixes="#all"
117119
<xsl:sequence select="base-uri($arg)"/>
118120
</xsl:function>
119121

122+
<xsl:function name="ldt:base" as="xs:anyURI">
123+
<xsl:sequence select="$ldt:base"/>
124+
</xsl:function>
125+
126+
<xsl:function name="sd:endpoint" as="xs:anyURI">
127+
<xsl:sequence select="resolve-uri('sparql', ldt:base())"/>
128+
</xsl:function>
129+
120130
<xsl:function name="ldh:href" as="xs:anyURI">
121131
<xsl:param name="uri" as="xs:anyURI?"/>
122132

@@ -137,7 +147,7 @@ exclude-result-prefixes="#all"
137147

138148
<xsl:choose>
139149
<!-- proxy URI - internal ones (relative to application's base URI) will be rewritten as absolute path in ApplicationFilter -->
140-
<xsl:when test="$uri and not(starts-with($uri, $ldt:base))">
150+
<xsl:when test="$uri and not(starts-with($uri, ldt:base()))">
141151
<xsl:sequence select="xs:anyURI(ac:build-uri(ac:absolute-path(ldh:request-uri()), map:merge((map{ 'uri': string($uri) }, $query-params))) || (if ($fragment) then ('#' || $fragment) else ()))"/>
142152
</xsl:when>
143153
<!-- local URI -->
@@ -199,7 +209,7 @@ exclude-result-prefixes="#all"
199209

200210
<xsl:function name="ldh:construct-forClass" as="document-node()" cache="yes">
201211
<xsl:param name="forClass" as="xs:anyURI+"/>
202-
<xsl:variable name="results-uri" select="ac:build-uri(resolve-uri('ns', $ldt:base), map{ 'forClass': for $class in $forClass return string($class), 'accept': 'application/rdf+xml' })" as="xs:anyURI"/>
212+
<xsl:variable name="results-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'forClass': for $class in $forClass return string($class), 'accept': 'application/rdf+xml' })" as="xs:anyURI"/>
203213
<xsl:variable name="request-uri" select="ldh:href($results-uri, map{})" as="xs:anyURI"/>
204214

205215
<xsl:sequence select="document($request-uri)"/>
@@ -524,7 +534,7 @@ exclude-result-prefixes="#all"
524534
<!-- subject resource -->
525535
<xsl:template match="@rdf:about" mode="xhtml:Anchor">
526536
<!-- <xsl:param name="graph" as="xs:anyURI?" tunnel="yes"/>-->
527-
<xsl:param name="fragment" select="if (starts-with(., $ldt:base)) then (if (contains(., '#')) then substring-after(., '#') else ()) else encode-for-uri(.)" as="xs:string?"/>
537+
<xsl:param name="fragment" select="if (starts-with(., ldt:base())) then (if (contains(., '#')) then substring-after(., '#') else ()) else encode-for-uri(.)" as="xs:string?"/>
528538
<xsl:param name="href" select="ldh:href(xs:anyURI(.), map{}, $fragment)" as="xs:anyURI"/>
529539
<xsl:param name="id" as="xs:string?"/>
530540
<xsl:param name="title" select="." as="xs:string?"/>
@@ -535,13 +545,13 @@ exclude-result-prefixes="#all"
535545
<xsl:with-param name="href" select="$href"/>
536546
<xsl:with-param name="id" select="$id"/>
537547
<xsl:with-param name="title" select="$title"/>
538-
<xsl:with-param name="class" select="$class || (if (not(starts-with(., $ldt:base))) then ' external' else())"/>
548+
<xsl:with-param name="class" select="$class || (if (not(starts-with(., ldt:base()))) then ' external' else())"/>
539549
<xsl:with-param name="target" select="$target"/>
540550
</xsl:next-match>
541551
</xsl:template>
542552

543553
<xsl:template match="@rdf:about | @rdf:resource" mode="svg:Anchor">
544-
<xsl:param name="fragment" select="if (starts-with(., $ldt:base)) then (if (contains(., '#')) then substring-after(., '#') else ()) else encode-for-uri(.)" as="xs:string?"/>
554+
<xsl:param name="fragment" select="if (starts-with(., ldt:base())) then (if (contains(., '#')) then substring-after(., '#') else ()) else encode-for-uri(.)" as="xs:string?"/>
545555
<xsl:param name="href" select="ldh:href(xs:anyURI(.), map{}, $fragment)" as="xs:anyURI"/>
546556
<xsl:param name="id" select="$fragment" as="xs:string?"/>
547557
<xsl:param name="label" select="if (parent::rdf:Description) then ac:svg-label(..) else ac:svg-object-label(.)" as="xs:string"/>
@@ -554,7 +564,7 @@ exclude-result-prefixes="#all"
554564
<xsl:with-param name="id" select="$id"/>
555565
<xsl:with-param name="label" select="$label"/>
556566
<xsl:with-param name="title" select="$title"/>
557-
<xsl:with-param name="class" select="$class || (if (not(starts-with(., $ldt:base))) then ' external' else())"/>
567+
<xsl:with-param name="class" select="$class || (if (not(starts-with(., ldt:base()))) then ' external' else())"/>
558568
<xsl:with-param name="target" select="$target"/>
559569
</xsl:next-match>
560570
</xsl:template>
@@ -563,7 +573,7 @@ exclude-result-prefixes="#all"
563573

564574
<!-- proxy link URIs if they are external -->
565575
<xsl:template match="@rdf:resource | srx:uri" priority="2">
566-
<xsl:param name="fragment" select="if (starts-with(., $ldt:base)) then (if (contains(., '#')) then substring-after(., '#') else ()) else encode-for-uri(.)" as="xs:string?"/>
576+
<xsl:param name="fragment" select="if (starts-with(., ldt:base())) then (if (contains(., '#')) then substring-after(., '#') else ()) else encode-for-uri(.)" as="xs:string?"/>
567577
<xsl:param name="href" select="ldh:href(xs:anyURI(.), map{}, $fragment)" as="xs:anyURI"/>
568578
<xsl:param name="id" as="xs:string?"/>
569579
<xsl:param name="title" select="." as="xs:string?"/>
@@ -574,7 +584,7 @@ exclude-result-prefixes="#all"
574584
<xsl:with-param name="href" select="$href"/>
575585
<xsl:with-param name="id" select="$id"/>
576586
<xsl:with-param name="title" select="$title"/>
577-
<xsl:with-param name="class" select="$class || (if (not(starts-with(., $ldt:base))) then ' external' else())"/>
587+
<xsl:with-param name="class" select="$class || (if (not(starts-with(., ldt:base()))) then ' external' else())"/>
578588
<xsl:with-param name="target" select="$target"/>
579589
</xsl:next-match>
580590
</xsl:template>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ exclude-result-prefixes="#all">
3030
<xsl:param name="id" select="generate-id()" as="xs:string"/>
3131
<xsl:param name="class" as="xs:string?"/>
3232
<xsl:param name="accept" as="xs:string?"/>
33-
<xsl:param name="container" select="resolve-uri('uploads/', $ldt:base)" as="xs:anyURI"/> <!-- TO-DO: get container URI from the ns:ItemOfFileContainer restriction -->
33+
<xsl:param name="container" select="resolve-uri('uploads/', ldt:base())" as="xs:anyURI"/> <!-- TO-DO: get container URI from the ns:ItemOfFileContainer restriction -->
3434
<xsl:param name="type-label" select="true()" as="xs:boolean"/>
3535

3636
<xsl:call-template name="xhtml:Input">

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ exclude-result-prefixes="#all">
104104
<xsl:param name="id" select="generate-id()" as="xs:string"/>
105105
<xsl:param name="class" select="'subject input-xxlarge'" as="xs:string?"/>
106106
<xsl:param name="disabled" select="false()" as="xs:boolean"/>
107-
<xsl:param name="auto" select="local-name() = 'nodeID' or starts-with(., $ldt:base)" as="xs:boolean"/>
107+
<xsl:param name="auto" select="local-name() = 'nodeID' or starts-with(., ldt:base())" as="xs:boolean"/>
108108
<xsl:param name="type-metadata" as="document-node()?" tunnel="yes"/>
109109
<xsl:param name="lookup-class" select="'type-typeahead typeahead'" as="xs:string"/>
110110
<xsl:param name="lookup-list-class" select="'type-typeahead typeahead dropdown-menu'" as="xs:string"/>

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

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ exclude-result-prefixes="#all">
102102

103103
<xsl:param name="lapp:origin" as="xs:anyURI?"/>
104104
<xsl:param name="ldh:requestUri" as="xs:anyURI"/>
105-
<xsl:param name="ac:endpoint" select="if ($ldt:base) then resolve-uri('sparql', $ldt:base) else ()" as="xs:anyURI?"/>
106-
<xsl:param name="sd:endpoint" as="xs:anyURI?"/>
105+
<!-- <xsl:param name="ac:endpoint" select="if ($ldt:base) then resolve-uri('sparql', $ldt:base) else ()" as="xs:anyURI?"/>
106+
<xsl:param name="sd:endpoint" as="xs:anyURI?"/>-->
107107
<xsl:param name="acl:agent" as="xs:anyURI?"/>
108108
<xsl:param name="lapp:Context" as="document-node()"/>
109109
<xsl:param name="foaf:Agent" select="if ($acl:agent) then document(ac:document-uri($acl:agent)) else ()" as="document-node()?"/>
@@ -158,7 +158,7 @@ exclude-result-prefixes="#all">
158158
}
159159
]]>
160160
</xsl:variable>
161-
<xsl:variable name="app-request-uri" select="ac:build-uri(resolve-uri('sparql', $ldt:base), map{ 'query': $app-query })" as="xs:anyURI"/>
161+
<xsl:variable name="app-request-uri" select="ac:build-uri(sd:endpoint(), map{ 'query': $app-query })" as="xs:anyURI"/>
162162
<xsl:variable name="forward-view-query" as="xs:string">
163163
<![CDATA[
164164
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
@@ -381,19 +381,9 @@ exclude-result-prefixes="#all">
381381
<xsl:text disable-output-escaping="yes">
382382
//&lt;![CDATA[
383383
</xsl:text>
384-
<xsl:if test="$lapp:origin">
385-
<![CDATA[
386-
var appUri = ]]><xsl:value-of select="'&quot;' || key('apps-by-origin', $lapp:origin, $lapp:Context)/@rdf:about || '&quot;'" disable-output-escaping="yes"/><![CDATA[;
387-
var baseUri = ]]><xsl:value-of select="'&quot;' || $ldt:base || '&quot;'" disable-output-escaping="yes"/><![CDATA[;
388-
var ontologyUri = ]]><xsl:value-of select="'&quot;' || $ldt:ontology || '&quot;'" disable-output-escaping="yes"/><![CDATA[;
389-
var endpointUri = ]]><xsl:value-of select="if ($sd:endpoint) then '&quot;' || $sd:endpoint || '&quot;' else 'null'" disable-output-escaping="yes"/><![CDATA[;
390-
]]>
391-
</xsl:if>
392384
<![CDATA[
393-
var absolutePath = ]]><xsl:value-of select="'&quot;' || ac:absolute-path(ldh:base-uri(.)) || '&quot;'" disable-output-escaping="yes"/><![CDATA[;
394385
var contextUri = ]]><xsl:value-of select="if ($ac:contextUri) then '&quot;' || $ac:contextUri || '&quot;' else 'null'" disable-output-escaping="yes"/><![CDATA[;
395386
var agentUri = []]><xsl:value-of select="if ($acl:agent) then '&quot;' || $acl:agent || '&quot;' else 'null'" disable-output-escaping="yes"/><![CDATA[];
396-
var accessModeUri = []]><xsl:value-of select="string-join(for $mode in $acl:mode return '&quot;' || $mode || '&quot;', ', ')" disable-output-escaping="yes"/><![CDATA[];
397387
]]>
398388
<xsl:text disable-output-escaping="yes">
399389
//]]&gt;
@@ -457,13 +447,7 @@ exclude-result-prefixes="#all">
457447
const servicesRequestUri = "]]></xsl:text><xsl:value-of select="$app-request-uri"/><xsl:text disable-output-escaping="yes"><![CDATA[";
458448
const stylesheetParams = {
459449
"Q{https://w3id.org/atomgraph/client#}contextUri": contextUri, // servlet context URI
460-
"Q{https://w3id.org/atomgraph/linkeddatahub/apps#}application": appUri,
461-
"Q{https://www.w3.org/ns/ldt#}base": baseUri,
462-
"Q{https://www.w3.org/ns/ldt#}ontology": ontologyUri,
463-
"Q{http://www.w3.org/ns/sparql-service-description#}endpoint": endpointUri,
464-
"Q{https://w3id.org/atomgraph/linkeddatahub#}absolutePath": absolutePath,
465450
"Q{http://www.w3.org/ns/auth/acl#}agent": agentUri,
466-
"Q{http://www.w3.org/ns/auth/acl#}mode": accessModeUri,
467451
"Q{}app-request-uri": servicesRequestUri
468452
};
469453
@@ -795,7 +779,7 @@ exclude-result-prefixes="#all">
795779

796780
<!-- only lookup resource locally using DESCRIBE if it's external (not relative to the app's base URI) and the agent is authenticated -->
797781
<xsl:template match="*[*][@rdf:about = ac:absolute-path(ldh:base-uri(.))][not(starts-with(@rdf:about, $ldt:base))][$foaf:Agent//@rdf:about]" mode="bs2:PropertyList">
798-
<xsl:param name="endpoint" select="($sd:endpoint, $ac:endpoint)[1]" as="xs:anyURI"/>
782+
<xsl:param name="endpoint" select="sd:endpoint()" as="xs:anyURI"/>
799783
<xsl:param name="property-uris" select="distinct-values(*/concat(namespace-uri(), local-name()))" as="xs:anyURI*"/>
800784
<xsl:param name="property-metadata" select="ldh:send-request(resolve-uri('ns', $ldt:base), 'POST', 'application/sparql-query', 'DESCRIBE ' || string-join(for $uri in distinct-values(/rdf:RDF/*/*/concat(namespace-uri(), local-name())) return '&lt;' || $uri || '&gt;', ' '), map{ 'Accept': 'application/rdf+xml' })" as="document-node()"/>
801785
<xsl:variable name="local-doc" select="ldh:query-result($endpoint, 'DESCRIBE &lt;' || @rdf:about || '&gt;')" as="document-node()"/>

0 commit comments

Comments
 (0)