Skip to content

Commit 17160c3

Browse files
namedgraphclaude
andcommitted
Serve namespace ontology terms from ProxyRequestFilter
After the DataManager cache check, run a DESCRIBE query against the app's in-memory OntModel (full imports closure) before falling through to the external proxy or 405. Covers both slash-based term URIs (e.g. schema:category) and hash-based namespaces (e.g. sioc:ns → describes all sioc:ns#* terms via the WHERE clause). This allows facet headers and other term lookups to resolve from imported ontologies without requiring ENABLE_LINKED_DATA_PROXY=true. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent e20d1c1 commit 17160c3

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

src/main/java/com/atomgraph/linkeddatahub/server/filter/request/ProxyRequestFilter.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.atomgraph.core.util.ModelUtils;
2424
import com.atomgraph.core.util.ResultSetUtils;
2525
import com.atomgraph.linkeddatahub.apps.model.Dataset;
26+
import org.apache.jena.ontology.Ontology;
2627
import com.atomgraph.linkeddatahub.client.GraphStoreClient;
2728
import com.atomgraph.linkeddatahub.client.filter.auth.IDTokenDelegationFilter;
2829
import com.atomgraph.linkeddatahub.client.filter.auth.WebIDDelegationFilter;
@@ -36,6 +37,8 @@
3637
import java.util.ArrayList;
3738
import java.util.List;
3839
import java.util.Optional;
40+
import org.apache.jena.query.QueryExecution;
41+
import org.apache.jena.query.QueryFactory;
3942
import jakarta.annotation.Priority;
4043
import jakarta.inject.Inject;
4144
import jakarta.ws.rs.NotAcceptableException;
@@ -91,6 +94,7 @@ public class ProxyRequestFilter implements ContainerRequestFilter
9194

9295
@Inject com.atomgraph.linkeddatahub.Application system;
9396
@Inject MediaTypes mediaTypes;
97+
@Inject Optional<Ontology> ontology;
9498
@Context Request request;
9599

96100
@Override
@@ -123,6 +127,26 @@ public void filter(ContainerRequestContext requestContext) throws IOException
123127
return;
124128
}
125129

130+
// serve terms from the app's in-memory namespace ontology (full imports closure) via DESCRIBE.
131+
// covers both slash-based term URIs (e.g. schema:category) and hash-based namespaces
132+
// (e.g. sioc:UserAccount → ac:document-uri strips to sioc:ns, so we also describe all
133+
// ?term where STR(?term) starts with "<targetURI>#")
134+
if (getOntology().isPresent())
135+
{
136+
String describeQueryStr = "DESCRIBE <" + targetURI + "> ?term " +
137+
"WHERE { ?term ?p ?o FILTER(STRSTARTS(STR(?term), CONCAT(STR(<" + targetURI + ">), \"#\"))) }";
138+
try (QueryExecution qe = QueryExecution.create(QueryFactory.create(describeQueryStr), getOntology().get().getOntModel()))
139+
{
140+
Model description = qe.execDescribe();
141+
if (!description.isEmpty())
142+
{
143+
if (log.isDebugEnabled()) log.debug("Serving URI from namespace ontology: {}", targetURI);
144+
requestContext.abortWith(getResponse(description, Response.Status.OK));
145+
return;
146+
}
147+
}
148+
}
149+
126150
boolean isRegisteredApp = getSystem().matchApp(targetURI) != null;
127151
if (!isRegisteredApp && !getSystem().isEnableLinkedDataProxy())
128152
throw new NotAllowedException("Linked Data proxy not enabled");
@@ -312,6 +336,16 @@ public com.atomgraph.linkeddatahub.Application getSystem()
312336
return system;
313337
}
314338

339+
/**
340+
* Returns the current application's namespace ontology, if available.
341+
*
342+
* @return optional ontology
343+
*/
344+
public Optional<Ontology> getOntology()
345+
{
346+
return ontology;
347+
}
348+
315349
/**
316350
* Returns the media types registry.
317351
*

0 commit comments

Comments
 (0)