From 8e31cfc8ba884085125e2550a0e2ba7c1725b56d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?=
Date: Thu, 18 Jun 2026 13:36:40 +0200
Subject: [PATCH 01/14] Migrate vocabularies to Jena ontapi; add ontology
characterization tests
- Bump client dependency to 4.3.1-SNAPSHOT (pulls jena-ontapi transitively via Core)
- Migrate 19 vocabularies off the deprecated-for-removal org.apache.jena.ontology API to org.apache.jena.ontapi (OntModelFactory/OntSpecification), with a top-of-class static JenaSystem.init() guard (ontapi NPEs if a vocab class is the first Jena touch)
- Add characterization tests pinning current ontology behavior so the migration can be proven to retain it: imports closure + RDFS materialization, dual-key cache (addDocumentModel), SPARQL-first resolution (OntologyModelGetter), vocab triples
Co-Authored-By: Claude Opus 4.8 (1M context)
---
pom.xml | 4 +-
.../linkeddatahub/vocabulary/ACL.java | 45 ++--
.../linkeddatahub/vocabulary/Admin.java | 14 +-
.../linkeddatahub/vocabulary/Cert.java | 28 ++-
.../linkeddatahub/vocabulary/DH.java | 26 ++-
.../linkeddatahub/vocabulary/Default.java | 17 +-
.../linkeddatahub/vocabulary/FOAF.java | 46 ++--
.../linkeddatahub/vocabulary/Google.java | 20 +-
.../linkeddatahub/vocabulary/LACL.java | 38 ++--
.../linkeddatahub/vocabulary/LAPP.java | 46 ++--
.../linkeddatahub/vocabulary/LDH.java | 56 ++---
.../linkeddatahub/vocabulary/LDHC.java | 107 ++++-----
.../linkeddatahub/vocabulary/LDHT.java | 21 +-
.../linkeddatahub/vocabulary/NFO.java | 21 +-
.../linkeddatahub/vocabulary/ORCID.java | 20 +-
.../linkeddatahub/vocabulary/PROV.java | 38 ++--
.../linkeddatahub/vocabulary/SIOC.java | 206 +++++++++---------
.../linkeddatahub/vocabulary/VoID.java | 28 ++-
.../com/atomgraph/server/vocabulary/HTTP.java | 30 +--
.../com/atomgraph/server/vocabulary/LDT.java | 64 +++---
.../filter/request/OntologyFilterTest.java | 79 +++++++
.../OntologyImportsCharacterizationTest.java | 96 ++++++++
.../server/util/OntologyModelGetterTest.java | 117 ++++++++++
.../vocabulary/VocabularyHolderTest.java | 63 ++++++
24 files changed, 838 insertions(+), 392 deletions(-)
create mode 100644 src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilterTest.java
create mode 100644 src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
create mode 100644 src/test/java/com/atomgraph/linkeddatahub/server/util/OntologyModelGetterTest.java
create mode 100644 src/test/java/com/atomgraph/linkeddatahub/vocabulary/VocabularyHolderTest.java
diff --git a/pom.xml b/pom.xml
index bcdd7851c0..fc68de8c63 100644
--- a/pom.xml
+++ b/pom.xml
@@ -163,13 +163,13 @@
${project.groupId}
client
- 4.3.0
+ 4.3.1-SNAPSHOT
classes
${project.groupId}
client
- 4.3.0
+ 4.3.1-SNAPSHOT
war
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ACL.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ACL.java
index 259d34a0ed..ab8afcc1c0 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ACL.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ACL.java
@@ -16,11 +16,11 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.ObjectProperty;
-import org.apache.jena.ontology.OntClass;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -30,8 +30,13 @@
*/
public class ACL
{
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://www.w3.org/ns/auth/acl#";
@@ -49,45 +54,45 @@ public static String getURI()
public static final Resource NAMESPACE = m_model.createResource( NS );
/** acl:Authorization class */
- public static final OntClass Authorization = m_model.createClass( NS + "Authorization" );
+ public static final Resource Authorization = m_model.createOntClass( NS + "Authorization" );
/** acl:Read access mode */
- public static final OntClass Read = m_model.createClass( NS + "Read" );
+ public static final Resource Read = m_model.createOntClass( NS + "Read" );
/** acl:Write access mode */
- public static final OntClass Write = m_model.createClass( NS + "Write" );
+ public static final Resource Write = m_model.createOntClass( NS + "Write" );
/** acl:Append access mode */
- public static final OntClass Append = m_model.createClass( NS + "Append" );
+ public static final Resource Append = m_model.createOntClass( NS + "Append" );
/** acl:Control access mode */
- public static final OntClass Control = m_model.createClass( NS + "Control" );
+ public static final Resource Control = m_model.createOntClass( NS + "Control" );
/** acl:AuthenticatedAgent class */
- public static final OntClass AuthenticatedAgent = m_model.createClass( NS + "AuthenticatedAgent" );
+ public static final Resource AuthenticatedAgent = m_model.createOntClass( NS + "AuthenticatedAgent" );
/** acl:delegates property **/
- public static final ObjectProperty delegates = m_model.createObjectProperty( NS + "delegates" );
+ public static final Property delegates = m_model.createObjectProperty( NS + "delegates" );
/** acl:owner property */
- public static final ObjectProperty owner = m_model.createObjectProperty( NS + "owner" );
+ public static final Property owner = m_model.createObjectProperty( NS + "owner" );
/** acl:agent property */
- public static final ObjectProperty agent = m_model.createObjectProperty( NS + "agent" );
+ public static final Property agent = m_model.createObjectProperty( NS + "agent" );
/** acl:agentClass property */
- public static final ObjectProperty agentClass = m_model.createObjectProperty( NS + "agentClass" );
+ public static final Property agentClass = m_model.createObjectProperty( NS + "agentClass" );
/** acl:agentGroup property */
- public static final ObjectProperty agentGroup = m_model.createObjectProperty( NS + "agentGroup" );
+ public static final Property agentGroup = m_model.createObjectProperty( NS + "agentGroup" );
/** acl:mode property */
- public static final ObjectProperty mode = m_model.createObjectProperty( NS + "mode" );
+ public static final Property mode = m_model.createObjectProperty( NS + "mode" );
/** acl:accessTo property */
- public static final ObjectProperty accessTo = m_model.createObjectProperty( NS + "accessTo" );
+ public static final Property accessTo = m_model.createObjectProperty( NS + "accessTo" );
/** acl:accessToClass property */
- public static final ObjectProperty accessToClass = m_model.createObjectProperty( NS + "accessToClass" );
+ public static final Property accessToClass = m_model.createObjectProperty( NS + "accessToClass" );
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Admin.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Admin.java
index d2bda94534..8f8901c666 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Admin.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Admin.java
@@ -16,9 +16,10 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -28,9 +29,14 @@
*/
public class Admin
{
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/admin#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Cert.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Cert.java
index c0906f3767..655a2582d9 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Cert.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Cert.java
@@ -16,12 +16,11 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.ObjectProperty;
-import org.apache.jena.ontology.OntClass;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -32,8 +31,13 @@
public class Cert
{
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://www.w3.org/ns/auth/cert#";
@@ -50,18 +54,18 @@ public static String getURI()
public static final Resource NAMESPACE = m_model.createResource( NS );
/** Public key class */
- public static final OntClass PublicKey = m_model.createClass(NS + "PublicKey");
+ public static final Resource PublicKey = m_model.createOntClass(NS + "PublicKey");
/** RSA public key class */
- public static final OntClass RSAPublicKey = m_model.createClass(NS + "RSAPublicKey");
+ public static final Resource RSAPublicKey = m_model.createOntClass(NS + "RSAPublicKey");
/** Key property */
- public static final ObjectProperty key = m_model.createObjectProperty( NS + "key" );
+ public static final Property key = m_model.createObjectProperty( NS + "key" );
/** Modulus property */
- public static final DatatypeProperty modulus = m_model.createDatatypeProperty( NS + "modulus" );
+ public static final Property modulus = m_model.createDataProperty( NS + "modulus" );
/** Exponent property */
- public static final DatatypeProperty exponent = m_model.createDatatypeProperty( NS + "exponent" );
+ public static final Property exponent = m_model.createDataProperty( NS + "exponent" );
}
\ No newline at end of file
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/DH.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/DH.java
index 7ea41b3058..30e4b486ff 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/DH.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/DH.java
@@ -15,12 +15,11 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.ObjectProperty;
-import org.apache.jena.ontology.OntClass;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -31,8 +30,13 @@
public class DH
{
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
+
/** The RDF model that holds the vocabulary terms
*/
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string
*/
public static final String NS = "https://www.w3.org/ns/ldt/document-hierarchy#";
@@ -49,15 +53,15 @@ public static String getURI()
public static final Resource NAMESPACE = m_model.createResource( NS );
/** Document class */
- public static final OntClass Document = m_model.createClass( NS + "Document" );
+ public static final Resource Document = m_model.createOntClass( NS + "Document" );
/** Container class */
- public static final OntClass Container = m_model.createClass( NS + "Container" );
+ public static final Resource Container = m_model.createOntClass( NS + "Container" );
/** Item class */
- public static final OntClass Item = m_model.createClass( NS + "Item" );
+ public static final Resource Item = m_model.createOntClass( NS + "Item" );
/** Slug property */
- public static final DatatypeProperty slug = m_model.createDatatypeProperty( NS + "slug" );
+ public static final Property slug = m_model.createDataProperty( NS + "slug" );
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Default.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Default.java
index 03d36f4293..41182134b3 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Default.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Default.java
@@ -16,10 +16,10 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.OntClass;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -29,8 +29,13 @@
*/
public class Default
{
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/default#";
@@ -50,6 +55,6 @@ public static String getURI()
// DOMAIN
/** Root document class */
- public static final OntClass Root = m_model.createClass(NS + "Root");
+ public static final Resource Root = m_model.createOntClass(NS + "Root");
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/FOAF.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/FOAF.java
index a71875fe53..b816439510 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/FOAF.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/FOAF.java
@@ -16,12 +16,11 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.ObjectProperty;
-import org.apache.jena.ontology.OntClass;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -31,8 +30,13 @@
*/
public class FOAF
{
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://xmlns.com/foaf/0.1/";
@@ -52,45 +56,45 @@ public static String getURI()
public static final Resource NAMESPACE = m_model.createResource( NS );
/** Agent class */
- public static final OntClass Agent = m_model.createClass( NS + "Agent" );
+ public static final Resource Agent = m_model.createOntClass( NS + "Agent" );
/** Person class */
- public static final OntClass Person = m_model.createClass( NS + "Person" );
+ public static final Resource Person = m_model.createOntClass( NS + "Person" );
/** Document class */
- public static final OntClass Document = m_model.createClass( NS + "Document" );
+ public static final Resource Document = m_model.createOntClass( NS + "Document" );
/** Name property */
- public static final DatatypeProperty name = m_model.createDatatypeProperty( NS + "name" );
+ public static final Property name = m_model.createDataProperty( NS + "name" );
/** Given name property */
- public static final DatatypeProperty givenName = m_model.createDatatypeProperty( NS + "givenName" );
+ public static final Property givenName = m_model.createDataProperty( NS + "givenName" );
/** Family name property */
- public static final DatatypeProperty familyName = m_model.createDatatypeProperty( NS + "familyName" );
+ public static final Property familyName = m_model.createDataProperty( NS + "familyName" );
/** Mailbox property */
- public static final ObjectProperty mbox = m_model.createObjectProperty( NS + "mbox" );
+ public static final Property mbox = m_model.createObjectProperty( NS + "mbox" );
/** Based near property */
- public static final ObjectProperty based_near = m_model.createObjectProperty( NS + "based_near" );
+ public static final Property based_near = m_model.createObjectProperty( NS + "based_near" );
/** Member property */
- public static final ObjectProperty member = m_model.createObjectProperty( NS + "member" );
+ public static final Property member = m_model.createObjectProperty( NS + "member" );
/** Primary topic property */
- public static final ObjectProperty primaryTopic = m_model.createObjectProperty( NS + "primaryTopic" );
+ public static final Property primaryTopic = m_model.createObjectProperty( NS + "primaryTopic" );
/** Is primary topic of property */
- public static final ObjectProperty isPrimaryTopicOf = m_model.createObjectProperty( NS + "isPrimaryTopicOf" );
+ public static final Property isPrimaryTopicOf = m_model.createObjectProperty( NS + "isPrimaryTopicOf" );
/** Maker property */
- public static final ObjectProperty maker = m_model.createObjectProperty( NS + "maker" );
+ public static final Property maker = m_model.createObjectProperty( NS + "maker" );
/** Account property */
- public static final ObjectProperty account = m_model.createObjectProperty( NS + "account" );
+ public static final Property account = m_model.createObjectProperty( NS + "account" );
/** Image property */
- public static final ObjectProperty img = m_model.createObjectProperty( NS + "img" );
+ public static final Property img = m_model.createObjectProperty( NS + "img" );
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Google.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Google.java
index cd68c45f5e..a1ed9a6c64 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Google.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Google.java
@@ -1,9 +1,10 @@
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -14,8 +15,13 @@
public class Google
{
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
+
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/services/google#";
@@ -35,9 +41,9 @@ public static String getURI()
public static final Resource NAMESPACE = m_model.createResource( NS );
/** Client ID property */
- public static final DatatypeProperty clientID = m_model.createDatatypeProperty( NS + "clientID" );
+ public static final Property clientID = m_model.createDataProperty( NS + "clientID" );
/** Client secret property */
- public static final DatatypeProperty clientSecret = m_model.createDatatypeProperty( NS + "clientSecret" );
+ public static final Property clientSecret = m_model.createDataProperty( NS + "clientSecret" );
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LACL.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LACL.java
index fd2af9e58f..5ced24b0c2 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LACL.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LACL.java
@@ -16,12 +16,11 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.ObjectProperty;
-import org.apache.jena.ontology.OntClass;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -31,8 +30,13 @@
*/
public class LACL
{
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/admin/acl#";
@@ -52,33 +56,33 @@ public static String getURI()
public static final Resource NAMESPACE = m_model.createResource( NS );
/** Authorization request class */
- public static final OntClass AuthorizationRequest = m_model.createClass( NS + "AuthorizationRequest" );
+ public static final Resource AuthorizationRequest = m_model.createOntClass( NS + "AuthorizationRequest" );
/** Authorization request class */
- public static final OntClass OwnerAuthorization = m_model.createClass( NS + "OwnerAuthorization" );
+ public static final Resource OwnerAuthorization = m_model.createOntClass( NS + "OwnerAuthorization" );
/** Password property */
- public static final DatatypeProperty password = m_model.createDatatypeProperty( NS + "password" );
+ public static final Property password = m_model.createDataProperty( NS + "password" );
/** Issuer property */
- public static final DatatypeProperty issuer = m_model.createDatatypeProperty( NS + "issuer" );
+ public static final Property issuer = m_model.createDataProperty( NS + "issuer" );
/** Request agent property **/
- public static final ObjectProperty requestMode = m_model.createObjectProperty( NS + "requestMode" );
+ public static final Property requestMode = m_model.createObjectProperty( NS + "requestMode" );
/** Request agent property **/
- public static final ObjectProperty requestAgent = m_model.createObjectProperty( NS + "requestAgent" );
+ public static final Property requestAgent = m_model.createObjectProperty( NS + "requestAgent" );
/** Request agent group property **/
- public static final ObjectProperty requestAgentGroup = m_model.createObjectProperty( NS + "requestAgentGroup" );
+ public static final Property requestAgentGroup = m_model.createObjectProperty( NS + "requestAgentGroup" );
/** Request access to property */
- public static final ObjectProperty requestAccessTo = m_model.createObjectProperty( NS + "requestAccessTo" );
+ public static final Property requestAccessTo = m_model.createObjectProperty( NS + "requestAccessTo" );
/** Request access to class property */
- public static final ObjectProperty requestAccessToClass = m_model.createObjectProperty( NS + "requestAccessToClass" );
+ public static final Property requestAccessToClass = m_model.createObjectProperty( NS + "requestAccessToClass" );
/** Request access property */
- public static final ObjectProperty requestAccess = m_model.createObjectProperty( NS + "requestAccess" );
+ public static final Property requestAccess = m_model.createObjectProperty( NS + "requestAccess" );
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java
index 7ef0a28f12..13daf790cd 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java
@@ -16,12 +16,11 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.ObjectProperty;
-import org.apache.jena.ontology.OntClass;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -32,8 +31,13 @@
public class LAPP
{
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
+
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/apps#";
@@ -53,45 +57,45 @@ public static String getURI()
public static final Resource NAMESPACE = m_model.createResource( NS );
/** Application class */
- public static final OntClass Context = m_model.createClass( NS + "Context" );
+ public static final Resource Context = m_model.createOntClass( NS + "Context" );
/** Dataset class */
- public static final OntClass Dataset = m_model.createClass( NS + "Dataset" );
+ public static final Resource Dataset = m_model.createOntClass( NS + "Dataset" );
/** Application class */
- public static final OntClass Application = m_model.createClass( NS + "Application" );
+ public static final Resource Application = m_model.createOntClass( NS + "Application" );
/** Admin application class */
- public static final OntClass AdminApplication = m_model.createClass( NS + "AdminApplication" );
+ public static final Resource AdminApplication = m_model.createOntClass( NS + "AdminApplication" );
/** End-user application class */
- public static final OntClass EndUserApplication = m_model.createClass( NS + "EndUserApplication" );
+ public static final Resource EndUserApplication = m_model.createOntClass( NS + "EndUserApplication" );
/** Package class */
- public static final OntClass Package = m_model.createClass( NS + "Package" );
+ public static final Resource Package = m_model.createOntClass( NS + "Package" );
/** Admin application class */
-// public static final ObjectProperty adminApplication = m_model.createObjectProperty( NS + "adminApplication" );
+// public static final Property adminApplication = m_model.createObjectProperty( NS + "adminApplication" );
//
// /** End-user application class */
-// public static final ObjectProperty endUserApplication = m_model.createObjectProperty( NS + "endUserApplication" );
+// public static final Property endUserApplication = m_model.createObjectProperty( NS + "endUserApplication" );
/** Frontend proxy property */
- public static final ObjectProperty frontendProxy = m_model.createObjectProperty( NS + "frontendProxy" );
+ public static final Property frontendProxy = m_model.createObjectProperty( NS + "frontendProxy" );
/** Backend proxy property */
- public static final ObjectProperty backendProxy = m_model.createObjectProperty( NS + "backendProxy" );
+ public static final Property backendProxy = m_model.createObjectProperty( NS + "backendProxy" );
/** Prefix property */
- public static final ObjectProperty prefix = m_model.createObjectProperty( NS + "prefix" );
+ public static final Property prefix = m_model.createObjectProperty( NS + "prefix" );
/** Read-only property */
- public static final DatatypeProperty allowRead = m_model.createDatatypeProperty( NS + "allowRead" );
+ public static final Property allowRead = m_model.createDataProperty( NS + "allowRead" );
/** Origin property for subdomain-based application matching */
- public static final ObjectProperty origin = m_model.createObjectProperty(NS + "origin");
+ public static final Property origin = m_model.createObjectProperty(NS + "origin");
/** Application property (for Link header rel) */
- public static final ObjectProperty application = m_model.createObjectProperty( NS + "application" );
+ public static final Property application = m_model.createObjectProperty( NS + "application" );
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java
index 629fe4d4af..dff4f44de3 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java
@@ -16,12 +16,11 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.ObjectProperty;
-import org.apache.jena.ontology.OntClass;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -31,8 +30,13 @@
*/
public class LDH
{
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub#";
@@ -51,62 +55,62 @@ public static String getURI()
public static final Resource NAMESPACE = m_model.createResource( NS );
/** Dataset class */
- public static final OntClass Dataset = m_model.createClass(NS + "Dataset");
+ public static final Resource Dataset = m_model.createOntClass(NS + "Dataset");
/** Generic service class */
- public static final OntClass GenericService = m_model.createClass(NS + "GenericService");
+ public static final Resource GenericService = m_model.createOntClass(NS + "GenericService");
/** Import class */
- public static final OntClass Import = m_model.createClass(NS + "Import");
+ public static final Resource Import = m_model.createOntClass(NS + "Import");
/** CSV import class */
- public static final OntClass CSVImport = m_model.createClass(NS + "CSVImport");
+ public static final Resource CSVImport = m_model.createOntClass(NS + "CSVImport");
/** RDF import class */
- public static final OntClass RDFImport = m_model.createClass(NS + "RDFImport");
+ public static final Resource RDFImport = m_model.createOntClass(NS + "RDFImport");
/** File class */
- public static final OntClass File = m_model.createClass(NS + "File");
+ public static final Resource File = m_model.createOntClass(NS + "File");
/** Object class */
- public static final OntClass Object = m_model.createClass(NS + "Object");
+ public static final Resource Object = m_model.createOntClass(NS + "Object");
/** View class */
- public static final OntClass View = m_model.createClass(NS + "View");
+ public static final Resource View = m_model.createOntClass(NS + "View");
/** URI syntax violation class */
- public static final OntClass URISyntaxViolation = m_model.createClass(NS + "URISyntaxViolation");
+ public static final Resource URISyntaxViolation = m_model.createOntClass(NS + "URISyntaxViolation");
/** Base property */
- public static final ObjectProperty base = m_model.createObjectProperty( NS + "base" );
+ public static final Property base = m_model.createObjectProperty( NS + "base" );
/** File property */
- public static final ObjectProperty file = m_model.createObjectProperty( NS + "file" );
+ public static final Property file = m_model.createObjectProperty( NS + "file" );
/** Action property */
- public static final ObjectProperty action = m_model.createObjectProperty( NS + "action" );
+ public static final Property action = m_model.createObjectProperty( NS + "action" );
/** Delimiter property */
- public static final DatatypeProperty delimiter = m_model.createDatatypeProperty( NS + "delimiter" );
+ public static final Property delimiter = m_model.createDataProperty( NS + "delimiter" );
/** Violation value property */
- public static final DatatypeProperty violationValue = m_model.createDatatypeProperty( NS + "violationValue" );
+ public static final Property violationValue = m_model.createDataProperty( NS + "violationValue" );
/** Request URI property */
- public static final ObjectProperty requestUri = m_model.createObjectProperty(NS + "requestUri");
+ public static final Property requestUri = m_model.createObjectProperty(NS + "requestUri");
/** HTTP headers property */
- public static final ObjectProperty httpHeaders = m_model.createObjectProperty(NS + "httpHeaders");
+ public static final Property httpHeaders = m_model.createObjectProperty(NS + "httpHeaders");
/** Service property */
- public static final ObjectProperty service = m_model.createObjectProperty( NS + "service" );
+ public static final Property service = m_model.createObjectProperty( NS + "service" );
/**
* For shape property */
- public static final ObjectProperty forShape = m_model.createObjectProperty( NS + "forShape" );
+ public static final Property forShape = m_model.createObjectProperty( NS + "forShape" );
/**
* Import property - used to import packages into an application */
- public static final ObjectProperty importPackage = m_model.createObjectProperty( NS + "import" );
+ public static final Property importPackage = m_model.createObjectProperty( NS + "import" );
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHC.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHC.java
index 5daf5c3899..7c972af205 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHC.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHC.java
@@ -16,11 +16,11 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.ObjectProperty;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -30,8 +30,13 @@
*/
public class LDHC
{
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/config#";
@@ -51,138 +56,138 @@ public static String getURI()
public static final Resource NAMESPACE = m_model.createResource( NS );
/** Base URI property */
- public static final ObjectProperty baseUri = m_model.createObjectProperty( NS + "baseUri" );
+ public static final Property baseUri = m_model.createObjectProperty( NS + "baseUri" );
/** Proxy scheme property */
- public static final DatatypeProperty proxyScheme = m_model.createDatatypeProperty( NS + "proxyScheme" );
+ public static final Property proxyScheme = m_model.createDataProperty( NS + "proxyScheme" );
/** Proxy host property */
- public static final DatatypeProperty proxyHost = m_model.createDatatypeProperty( NS + "proxyHost" );
+ public static final Property proxyHost = m_model.createDataProperty( NS + "proxyHost" );
/** Proxy port property */
- public static final DatatypeProperty proxyPort = m_model.createDatatypeProperty( NS + "proxyPort" );
+ public static final Property proxyPort = m_model.createDataProperty( NS + "proxyPort" );
/** Document type query property */
- public static final DatatypeProperty documentTypeQuery = m_model.createDatatypeProperty( NS + "documentTypeQuery" );
+ public static final Property documentTypeQuery = m_model.createDataProperty( NS + "documentTypeQuery" );
/** Document owner query property */
- public static final DatatypeProperty documentOwnerQuery = m_model.createDatatypeProperty( NS + "documentOwnerQuery" );
+ public static final Property documentOwnerQuery = m_model.createDataProperty( NS + "documentOwnerQuery" );
/** ACL query property */
- public static final DatatypeProperty aclQuery = m_model.createDatatypeProperty( NS + "aclQuery" );
+ public static final Property aclQuery = m_model.createDataProperty( NS + "aclQuery" );
/** Owner's ACL property */
- public static final DatatypeProperty ownerAclQuery = m_model.createDatatypeProperty( NS + "ownerAclQuery" );
+ public static final Property ownerAclQuery = m_model.createDataProperty( NS + "ownerAclQuery" );
/** WebID query property */
- public static final DatatypeProperty webIDQuery = m_model.createDatatypeProperty( NS + "webIDQuery" );
+ public static final Property webIDQuery = m_model.createDataProperty( NS + "webIDQuery" );
/** Agent query property */
- public static final DatatypeProperty agentQuery = m_model.createDatatypeProperty( NS + "agentQuery" );
+ public static final Property agentQuery = m_model.createDataProperty( NS + "agentQuery" );
/** User account query property */
- public static final DatatypeProperty userAccountQuery = m_model.createDatatypeProperty( NS + "userAccountQuery" );
+ public static final Property userAccountQuery = m_model.createDataProperty( NS + "userAccountQuery" );
/** Ontology query property */
- public static final DatatypeProperty ontologyQuery = m_model.createDatatypeProperty( NS + "ontologyQuery" );
+ public static final Property ontologyQuery = m_model.createDataProperty( NS + "ontologyQuery" );
/** Upload root property */
- public static final ObjectProperty uploadRoot = m_model.createObjectProperty( NS + "uploadRoot" );
+ public static final Property uploadRoot = m_model.createObjectProperty( NS + "uploadRoot" );
/** Invalidate cache property */
- public static final DatatypeProperty invalidateCache = m_model.createDatatypeProperty( NS + "invalidateCache" );
+ public static final Property invalidateCache = m_model.createDataProperty( NS + "invalidateCache" );
/** Cookie max age property */
- public static final DatatypeProperty cookieMaxAge = m_model.createDatatypeProperty( NS + "cookieMaxAge" );
+ public static final Property cookieMaxAge = m_model.createDataProperty( NS + "cookieMaxAge" );
/** Client keystore property */
- public static final ObjectProperty clientKeyStore = m_model.createObjectProperty( NS + "clientKeyStore" );
+ public static final Property clientKeyStore = m_model.createObjectProperty( NS + "clientKeyStore" );
/** Client keystore password property */
- public static final DatatypeProperty clientKeyStorePassword = m_model.createDatatypeProperty( NS + "clientKeyStorePassword" );
+ public static final Property clientKeyStorePassword = m_model.createDataProperty( NS + "clientKeyStorePassword" );
/** Secretary cert alias property */
- public static final DatatypeProperty secretaryCertAlias = m_model.createDatatypeProperty( NS + "secretaryCertAlias" );
+ public static final Property secretaryCertAlias = m_model.createDataProperty( NS + "secretaryCertAlias" );
/** Client truststore property */
- public static final ObjectProperty clientTrustStore = m_model.createObjectProperty( NS + "clientTrustStore" );
+ public static final Property clientTrustStore = m_model.createObjectProperty( NS + "clientTrustStore" );
/** Client truststore password property */
- public static final DatatypeProperty clientTrustStorePassword = m_model.createDatatypeProperty( NS + "clientTrustStorePassword" );
+ public static final Property clientTrustStorePassword = m_model.createDataProperty( NS + "clientTrustStorePassword" );
/** Signup email subject property */
- public static final DatatypeProperty signUpEMailSubject = m_model.createDatatypeProperty( NS + "signUpEMailSubject" );
+ public static final Property signUpEMailSubject = m_model.createDataProperty( NS + "signUpEMailSubject" );
/** WebID signup email text property */
- public static final DatatypeProperty webIDSignUpEMailText = m_model.createDatatypeProperty( NS + "webIDSignUpEMailText" );
+ public static final Property webIDSignUpEMailText = m_model.createDataProperty( NS + "webIDSignUpEMailText" );
/** OAuth signup email text property */
- public static final DatatypeProperty oAuthSignUpEMailText = m_model.createDatatypeProperty( NS + "oAuthSignUpEMailText" );
+ public static final Property oAuthSignUpEMailText = m_model.createDataProperty( NS + "oAuthSignUpEMailText" );
/** Notification address property */
- public static final DatatypeProperty notificationAddress = m_model.createDatatypeProperty( NS + "notificationAddress" );
+ public static final Property notificationAddress = m_model.createDataProperty( NS + "notificationAddress" );
/** Request access email subject property */
- public static final DatatypeProperty requestAccessEMailSubject = m_model.createDatatypeProperty( NS + "requestAccessEMailSubject" );
+ public static final Property requestAccessEMailSubject = m_model.createDataProperty( NS + "requestAccessEMailSubject" );
/** Request access email text property */
- public static final DatatypeProperty requestAccessEMailText = m_model.createDatatypeProperty( NS + "requestAccessEMailText" );
+ public static final Property requestAccessEMailText = m_model.createDataProperty( NS + "requestAccessEMailText" );
/** Authorization email subject property */
- public static final DatatypeProperty authorizationEMailSubject = m_model.createDatatypeProperty( NS + "authorizationEMailSubject" );
+ public static final Property authorizationEMailSubject = m_model.createDataProperty( NS + "authorizationEMailSubject" );
/** Authorization email text property */
- public static final DatatypeProperty authorizationEMailText = m_model.createDatatypeProperty( NS + "authorizationEMailText" );
+ public static final Property authorizationEMailText = m_model.createDataProperty( NS + "authorizationEMailText" );
/** Signup cert validity property */
- public static final DatatypeProperty signUpCertValidity = m_model.createDatatypeProperty( NS + "signUpCertValidity" );
+ public static final Property signUpCertValidity = m_model.createDataProperty( NS + "signUpCertValidity" );
/** Context dataset property */
- public static final ObjectProperty contextDataset = m_model.createObjectProperty( NS + "contextDataset" );
+ public static final Property contextDataset = m_model.createObjectProperty( NS + "contextDataset" );
/** Max connections per route property */
- public static final DatatypeProperty maxConnPerRoute = m_model.createDatatypeProperty( NS + "maxConnPerRoute" );
+ public static final Property maxConnPerRoute = m_model.createDataProperty( NS + "maxConnPerRoute" );
/** Max total connections property */
- public static final DatatypeProperty maxTotalConn = m_model.createDatatypeProperty( NS + "maxTotalConn" );
+ public static final Property maxTotalConn = m_model.createDataProperty( NS + "maxTotalConn" );
/** Import keep-alive property */
- public static final DatatypeProperty importKeepAlive = m_model.createDatatypeProperty( NS + "importKeepAlive" );
+ public static final Property importKeepAlive = m_model.createDataProperty( NS + "importKeepAlive" );
/** HTTP client request retry count */
- public static final DatatypeProperty maxRequestRetries = m_model.createDatatypeProperty( NS + "maxRequestRetries" );
+ public static final Property maxRequestRetries = m_model.createDataProperty( NS + "maxRequestRetries" );
/** Timeout in milliseconds waiting for a connection from the HTTP client pool */
- public static final DatatypeProperty connectionRequestTimeout = m_model.createDatatypeProperty( NS + "connectionRequestTimeout" );
+ public static final Property connectionRequestTimeout = m_model.createDataProperty( NS + "connectionRequestTimeout" );
/** Max content length property */
- public static final DatatypeProperty maxContentLength = m_model.createDatatypeProperty( NS + "maxContentLength" );
+ public static final Property maxContentLength = m_model.createDataProperty( NS + "maxContentLength" );
/** Support languages property */
- public static final DatatypeProperty supportedLanguages = m_model.createDatatypeProperty( NS + "supportedLanguages" );
+ public static final Property supportedLanguages = m_model.createDataProperty( NS + "supportedLanguages" );
/** Max import threads property */
- public static final DatatypeProperty maxImportThreads = m_model.createDatatypeProperty( NS + "maxImportThreads" );
+ public static final Property maxImportThreads = m_model.createDataProperty( NS + "maxImportThreads" );
/** Enable WebID signup property **/
- public static final DatatypeProperty enableWebIDSignUp = m_model.createDatatypeProperty( NS + "enableWebIDSignUp" );
+ public static final Property enableWebIDSignUp = m_model.createDataProperty( NS + "enableWebIDSignUp" );
/** Enable Linked Data proxy property */
- public static final DatatypeProperty enableLinkedDataProxy = m_model.createDatatypeProperty( NS + "enableLinkedDataProxy" );
+ public static final Property enableLinkedDataProxy = m_model.createDataProperty( NS + "enableLinkedDataProxy" );
/** Allow internal URLs property */
- public static final DatatypeProperty allowInternalUrls = m_model.createDatatypeProperty( NS + "allowInternalUrls" );
+ public static final Property allowInternalUrls = m_model.createDataProperty( NS + "allowInternalUrls" );
/** OIDC refresh token properties property */
- public static final DatatypeProperty oidcRefreshTokens = m_model.createDatatypeProperty( NS + "oidcRefreshTokens" );
+ public static final Property oidcRefreshTokens = m_model.createDataProperty( NS + "oidcRefreshTokens" );
/** Frontend proxy URI property (Varnish frontend cache, used for cache invalidation) */
- public static final ObjectProperty frontendProxy = m_model.createObjectProperty( NS + "frontendProxy" );
+ public static final Property frontendProxy = m_model.createObjectProperty( NS + "frontendProxy" );
/** Backend proxy URI for the admin SPARQL service (used for cache invalidation and endpoint URI rewriting) */
- public static final ObjectProperty backendProxyAdmin = m_model.createObjectProperty( NS + "backendProxyAdmin" );
+ public static final Property backendProxyAdmin = m_model.createObjectProperty( NS + "backendProxyAdmin" );
/** Backend proxy URI for the end-user SPARQL service (used for cache invalidation and endpoint URI rewriting) */
- public static final ObjectProperty backendProxyEndUser = m_model.createObjectProperty( NS + "backendProxyEndUser" );
+ public static final Property backendProxyEndUser = m_model.createObjectProperty( NS + "backendProxyEndUser" );
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHT.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHT.java
index e43185459d..7741c9e8d3 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHT.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHT.java
@@ -16,11 +16,11 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.ObjectProperty;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -31,8 +31,13 @@
@Deprecated
public class LDHT
{
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/templates#";
@@ -52,9 +57,9 @@ public static String getURI()
public static final Resource NAMESPACE = m_model.createResource( NS );
/** For class property */
- //public static final ObjectProperty forClass = m_model.createObjectProperty( NS + "forClass" );
+ //public static final Property forClass = m_model.createObjectProperty( NS + "forClass" );
/** Ban property */
- public static final DatatypeProperty ban = m_model.createDatatypeProperty( NS + "ban" );
+ public static final Property ban = m_model.createDataProperty( NS + "ban" );
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/NFO.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/NFO.java
index 6aba1781b3..5c5e79d738 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/NFO.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/NFO.java
@@ -16,11 +16,11 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.OntClass;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -30,8 +30,13 @@
*/
public class NFO
{
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#";
@@ -51,9 +56,9 @@ public static String getURI()
public static final Resource NAMESPACE = m_model.createResource( NS );
/** File data object class */
- public static final OntClass FileDataObject = m_model.createClass(NS + "FileDataObject");
+ public static final Resource FileDataObject = m_model.createOntClass(NS + "FileDataObject");
/** Filename property */
- public static final DatatypeProperty fileName = m_model.createDatatypeProperty( NS + "fileName" );
+ public static final Property fileName = m_model.createDataProperty( NS + "fileName" );
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ORCID.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ORCID.java
index 7998fc9073..42c21d60d9 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ORCID.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ORCID.java
@@ -1,9 +1,10 @@
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -14,8 +15,13 @@
public class ORCID
{
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
+
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/services/orcid#";
@@ -35,9 +41,9 @@ public static String getURI()
public static final Resource NAMESPACE = m_model.createResource( NS );
/** Client ID property */
- public static final DatatypeProperty clientID = m_model.createDatatypeProperty( NS + "clientID" );
+ public static final Property clientID = m_model.createDataProperty( NS + "clientID" );
/** Client secret property */
- public static final DatatypeProperty clientSecret = m_model.createDatatypeProperty( NS + "clientSecret" );
+ public static final Property clientSecret = m_model.createDataProperty( NS + "clientSecret" );
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/PROV.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/PROV.java
index efd61c6693..e536478aa2 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/PROV.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/PROV.java
@@ -16,12 +16,11 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.ObjectProperty;
-import org.apache.jena.ontology.OntClass;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -30,9 +29,14 @@
* @author Martynas Jusevičius {@literal }
*/
public class PROV {
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://www.w3.org/ns/prov#";
@@ -52,33 +56,33 @@ public static String getURI()
public static final Resource NAMESPACE = m_model.createResource( NS );
/** Entity class */
- public static final OntClass Entity = m_model.createClass( NS + "Entity" );
+ public static final Resource Entity = m_model.createOntClass( NS + "Entity" );
/** Activity class */
- public static final OntClass Activity = m_model.createClass( NS + "Activity" );
+ public static final Resource Activity = m_model.createOntClass( NS + "Activity" );
/** Agent class */
- public static final OntClass Agent = m_model.createClass( NS + "Agent" );
+ public static final Resource Agent = m_model.createOntClass( NS + "Agent" );
/** Was attributed to property */
- public static final ObjectProperty wasAttributedTo = m_model.createObjectProperty( NS + "wasAttributedTo" );
+ public static final Property wasAttributedTo = m_model.createObjectProperty( NS + "wasAttributedTo" );
/** Was derived from property */
- public static final ObjectProperty wasDerivedFrom = m_model.createObjectProperty( NS + "wasDerivedFrom" );
+ public static final Property wasDerivedFrom = m_model.createObjectProperty( NS + "wasDerivedFrom" );
/** Was generated by property */
- public static final ObjectProperty wasGeneratedBy = m_model.createObjectProperty( NS + "wasGeneratedBy" );
+ public static final Property wasGeneratedBy = m_model.createObjectProperty( NS + "wasGeneratedBy" );
/** Was started by property */
- public static final ObjectProperty wasStartedBy = m_model.createObjectProperty( NS + "wasStartedBy" );
+ public static final Property wasStartedBy = m_model.createObjectProperty( NS + "wasStartedBy" );
/** Started at time property */
- public static final DatatypeProperty startedAtTime = m_model.createDatatypeProperty( NS + "startedAtTime" );
+ public static final Property startedAtTime = m_model.createDataProperty( NS + "startedAtTime" );
/** Ended at time property */
- public static final DatatypeProperty endedAtTime = m_model.createDatatypeProperty( NS + "endedAtTime" );
+ public static final Property endedAtTime = m_model.createDataProperty( NS + "endedAtTime" );
/** Generated at time property */
- public static final DatatypeProperty generatedAtTime = m_model.createDatatypeProperty( NS + "generatedAtTime" );
+ public static final Property generatedAtTime = m_model.createDataProperty( NS + "generatedAtTime" );
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/SIOC.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/SIOC.java
index 302ef9f397..4a19b93cc4 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/SIOC.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/SIOC.java
@@ -16,8 +16,11 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.*;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -27,12 +30,17 @@
*/
public class SIOC {
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
/**
*
* The ontology model that holds the vocabulary terms
*
*/
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/**
*
@@ -74,7 +82,7 @@ public static String getURI() {
* etc.
*
*/
- public static final ObjectProperty ABOUT = m_model
+ public static final Property ABOUT = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#about");
/**
@@ -82,7 +90,7 @@ public static String getURI() {
* Refers to the foaf:Agent or foaf:Person who owns this sioc:User online account.
*
*/
- public static final ObjectProperty ACCOUNT_OF = m_model
+ public static final Property ACCOUNT_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#account_of");
/**
@@ -90,7 +98,7 @@ public static String getURI() {
* A Site that the User is an administrator of.
*
*/
- public static final ObjectProperty ADMINISTRATOR_OF = m_model
+ public static final Property ADMINISTRATOR_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#administrator_of");
/**
@@ -98,7 +106,7 @@ public static String getURI() {
* The URI of a file attached to an Item.
*
*/
- public static final ObjectProperty ATTACHMENT = m_model
+ public static final Property ATTACHMENT = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#attachment");
/**
@@ -106,7 +114,7 @@ public static String getURI() {
* An image or depiction used to represent this User.
*
*/
- public static final ObjectProperty AVATAR = m_model
+ public static final Property AVATAR = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#avatar");
/**
@@ -114,7 +122,7 @@ public static String getURI() {
* An Item that this Container contains.
*
*/
- public static final ObjectProperty CONTAINER_OF = m_model
+ public static final Property CONTAINER_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#container_of");
/**
@@ -122,7 +130,7 @@ public static String getURI() {
* A resource that the User is a creator of.
*
*/
- public static final ObjectProperty CREATOR_OF = m_model
+ public static final Property CREATOR_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#creator_of");
/**
@@ -130,7 +138,7 @@ public static String getURI() {
* An electronic mail address of the User.
*
*/
- public static final ObjectProperty EMAIL = m_model
+ public static final Property EMAIL = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#email");
/**
@@ -138,7 +146,7 @@ public static String getURI() {
* A feed (e.g. RSS, Atom, etc.) pertaining to this resource (e.g. for a Forum, Site, User, etc.).
*
*/
- public static final ObjectProperty FEED = m_model
+ public static final Property FEED = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#feed");
/**
@@ -147,7 +155,7 @@ public static String getURI() {
* updates).
*
*/
- public static final ObjectProperty FOLLOWS = m_model
+ public static final Property FOLLOWS = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#follows");
/**
@@ -155,13 +163,13 @@ public static String getURI() {
* A User who has this Role.
*
*/
- public static final ObjectProperty FUNCTION_OF = m_model
+ public static final Property FUNCTION_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#function_of");
/**
* This property has been renamed. Use sioc:sioc:usergroup_of instead.
*/
- public static final ObjectProperty GROUP_OF = m_model
+ public static final Property GROUP_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#group_of");
/**
@@ -169,7 +177,7 @@ public static String getURI() {
* A User who is an administrator of this Site.
*
*/
- public static final ObjectProperty HAS_ADMINISTRATOR = m_model
+ public static final Property HAS_ADMINISTRATOR = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_administrator");
/**
@@ -177,7 +185,7 @@ public static String getURI() {
* The Container to which this Item belongs.
*
*/
- public static final ObjectProperty HAS_CONTAINER = m_model
+ public static final Property HAS_CONTAINER = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_container");
/**
@@ -185,7 +193,7 @@ public static String getURI() {
* This is the User who made this resource.
*
*/
- public static final ObjectProperty HAS_CREATOR = m_model
+ public static final Property HAS_CREATOR = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_creator");
/**
@@ -193,7 +201,7 @@ public static String getURI() {
* The discussion that is related to this Item.
*
*/
- public static final ObjectProperty HAS_DISCUSSION = m_model
+ public static final Property HAS_DISCUSSION = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_discussion");
/**
@@ -201,13 +209,13 @@ public static String getURI() {
* A Role that this User has.
*
*/
- public static final ObjectProperty HAS_FUNCTION = m_model
+ public static final Property HAS_FUNCTION = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_function");
/**
* This property has been renamed. Use sioc:has_usergroup instead.
*/
- public static final ObjectProperty HAS_GROUP = m_model
+ public static final Property HAS_GROUP = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_group");
/**
@@ -215,7 +223,7 @@ public static String getURI() {
* The Site that hosts this Forum.
*
*/
- public static final ObjectProperty HAS_HOST = m_model
+ public static final Property HAS_HOST = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_host");
/**
@@ -223,7 +231,7 @@ public static String getURI() {
* A User who is a member of this Usergroup.
*
*/
- public static final ObjectProperty HAS_MEMBER = m_model
+ public static final Property HAS_MEMBER = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_member");
/**
@@ -231,7 +239,7 @@ public static String getURI() {
* A User who is a moderator of this Forum.
*
*/
- public static final ObjectProperty HAS_MODERATOR = m_model
+ public static final Property HAS_MODERATOR = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_moderator");
/**
@@ -239,7 +247,7 @@ public static String getURI() {
* A User who modified this Item.
*
*/
- public static final ObjectProperty HAS_MODIFIER = m_model
+ public static final Property HAS_MODIFIER = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_modifier");
/**
@@ -247,7 +255,7 @@ public static String getURI() {
* A User that this resource is owned by.
*
*/
- public static final ObjectProperty HAS_OWNER = m_model
+ public static final Property HAS_OWNER = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_owner");
/**
@@ -255,7 +263,7 @@ public static String getURI() {
* A Container or Forum that this Container or Forum is a child of.
*
*/
- public static final ObjectProperty HAS_PARENT = m_model
+ public static final Property HAS_PARENT = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_parent");
/**
@@ -263,7 +271,7 @@ public static String getURI() {
* An resource that is a part of this subject.
*
*/
- public static final ObjectProperty HAS_PART = m_model
+ public static final Property HAS_PART = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_part");
/**
@@ -271,7 +279,7 @@ public static String getURI() {
* Points to an Item or Post that is a reply or response to this Item or Post.
*
*/
- public static final ObjectProperty HAS_REPLY = m_model
+ public static final Property HAS_REPLY = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_reply");
/**
@@ -279,7 +287,7 @@ public static String getURI() {
* A resource that this Role applies to.
*
*/
- public static final ObjectProperty HAS_SCOPE = m_model
+ public static final Property HAS_SCOPE = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_scope");
/**
@@ -287,7 +295,7 @@ public static String getURI() {
* A data Space which this resource is a part of.
*
*/
- public static final ObjectProperty HAS_SPACE = m_model
+ public static final Property HAS_SPACE = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_space");
/**
@@ -295,7 +303,7 @@ public static String getURI() {
* A User who is subscribed to this Container.
*
*/
- public static final ObjectProperty HAS_SUBSCRIBER = m_model
+ public static final Property HAS_SUBSCRIBER = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_subscriber");
/**
@@ -303,7 +311,7 @@ public static String getURI() {
* Points to a Usergroup that has certain access to this Space.
*
*/
- public static final ObjectProperty HAS_USERGROUP = m_model
+ public static final Property HAS_USERGROUP = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#has_usergroup");
/**
@@ -311,7 +319,7 @@ public static String getURI() {
* A Forum that is hosted on this Site.
*
*/
- public static final ObjectProperty HOST_OF = m_model
+ public static final Property HOST_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#host_of");
/**
@@ -319,7 +327,7 @@ public static String getURI() {
* Links to the latest revision of this Item or Post.
*
*/
- public static final ObjectProperty LATEST_VERSION = m_model
+ public static final Property LATEST_VERSION = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#latest_version");
/**
@@ -327,7 +335,7 @@ public static String getURI() {
* A URI of a document which contains this SIOC object.
*
*/
- public static final ObjectProperty LINK = m_model
+ public static final Property LINK = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#link");
/**
@@ -335,7 +343,7 @@ public static String getURI() {
* Links extracted from hyperlinks within a SIOC concept, e.g. Post or Site.
*
*/
- public static final ObjectProperty LINKS_TO = m_model
+ public static final Property LINKS_TO = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#links_to");
/**
@@ -343,7 +351,7 @@ public static String getURI() {
* A Usergroup that this User is a member of.
*
*/
- public static final ObjectProperty MEMBER_OF = m_model
+ public static final Property MEMBER_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#member_of");
/**
@@ -351,7 +359,7 @@ public static String getURI() {
* A Forum that User is a moderator of.
*
*/
- public static final ObjectProperty MODERATOR_OF = m_model
+ public static final Property MODERATOR_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#moderator_of");
/**
@@ -359,7 +367,7 @@ public static String getURI() {
* An Item that this User has modified.
*
*/
- public static final ObjectProperty MODIFIER_OF = m_model
+ public static final Property MODIFIER_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#modifier_of");
/**
@@ -367,7 +375,7 @@ public static String getURI() {
* Next Item or Post in a given Container sorted by date.
*
*/
- public static final ObjectProperty NEXT_BY_DATE = m_model
+ public static final Property NEXT_BY_DATE = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#next_by_date");
/**
@@ -375,7 +383,7 @@ public static String getURI() {
* Links to the next revision of this Item or Post.
*
*/
- public static final ObjectProperty NEXT_VERSION = m_model
+ public static final Property NEXT_VERSION = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#next_version");
/**
@@ -383,7 +391,7 @@ public static String getURI() {
* A resource owned by a particular User, for example, a weblog or image gallery.
*
*/
- public static final ObjectProperty OWNER_OF = m_model
+ public static final Property OWNER_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#owner_of");
/**
@@ -391,7 +399,7 @@ public static String getURI() {
* A child Container or Forum that this Container or Forum is a parent of.
*
*/
- public static final ObjectProperty PARENT_OF = m_model
+ public static final Property PARENT_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#parent_of");
/**
@@ -399,7 +407,7 @@ public static String getURI() {
* A resource that the subject is a part of.
*
*/
- public static final ObjectProperty PART_OF = m_model
+ public static final Property PART_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#part_of");
/**
@@ -407,7 +415,7 @@ public static String getURI() {
* Previous Item or Post in a given Container sorted by date.
*
*/
- public static final ObjectProperty PREVIOUS_BY_DATE = m_model
+ public static final Property PREVIOUS_BY_DATE = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#previous_by_date");
/**
@@ -415,7 +423,7 @@ public static String getURI() {
* Links to the previous revision of this Item or Post.
*
*/
- public static final ObjectProperty PREVIOUS_VERSION = m_model
+ public static final Property PREVIOUS_VERSION = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#previous_version");
/**
@@ -423,7 +431,7 @@ public static String getURI() {
* Links either created explicitly or extracted implicitly on the HTML level from the Post.
*
*/
- public static final ObjectProperty REFERENCE = m_model
+ public static final Property REFERENCE = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#reference");
/**
@@ -431,7 +439,7 @@ public static String getURI() {
* Related Posts for this Post, perhaps determined implicitly from topics or references.
*
*/
- public static final ObjectProperty RELATED_TO = m_model
+ public static final Property RELATED_TO = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#related_to");
/**
@@ -439,7 +447,7 @@ public static String getURI() {
* Links to an Item or Post which this Item or Post is a reply to.
*
*/
- public static final ObjectProperty REPLY_OF = m_model
+ public static final Property REPLY_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#reply_of");
/**
@@ -447,7 +455,7 @@ public static String getURI() {
* A Role that has a scope of this resource.
*
*/
- public static final ObjectProperty SCOPE_OF = m_model
+ public static final Property SCOPE_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#scope_of");
/**
@@ -455,7 +463,7 @@ public static String getURI() {
* A resource which belongs to this data Space.
*
*/
- public static final ObjectProperty SPACE_OF = m_model
+ public static final Property SPACE_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#space_of");
/**
@@ -463,7 +471,7 @@ public static String getURI() {
* A Container that a User is subscribed to.
*
*/
- public static final ObjectProperty SUBSCRIBER_OF = m_model
+ public static final Property SUBSCRIBER_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#subscriber_of");
/**
@@ -472,7 +480,7 @@ public static String getURI() {
* SKOS category.
*
*/
- public static final ObjectProperty TOPIC = m_model
+ public static final Property TOPIC = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#topic");
/**
@@ -480,7 +488,7 @@ public static String getURI() {
* A Space that the Usergroup has access to.
*
*/
- public static final ObjectProperty USERGROUP_OF = m_model
+ public static final Property USERGROUP_OF = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#usergroup_of");
/**
@@ -488,48 +496,48 @@ public static String getURI() {
* The content of the Item in plain text format.
*
*/
- public static final DatatypeProperty CONTENT = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#content");
+ public static final Property CONTENT = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#content");
/**
*
* The encoded content of the Post, contained in CDATA areas.
*
*/
- public static final DatatypeProperty CONTENT_ENCODED = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#content_encoded");
+ public static final Property CONTENT_ENCODED = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#content_encoded");
/**
*
* When this was created, in ISO 8601 format.
*
*/
- public static final DatatypeProperty CREATED_AT = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#created_at");
+ public static final Property CREATED_AT = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#created_at");
/**
*
* The content of the Post.
*
*/
- public static final DatatypeProperty DESCRIPTION = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#description");
+ public static final Property DESCRIPTION = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#description");
/**
*
* An electronic mail address of the User, encoded using SHA1.
*
*/
- public static final DatatypeProperty EMAIL_SHA1 = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#email_sha1");
+ public static final Property EMAIL_SHA1 = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#email_sha1");
/**
*
* First (real) name of this User. Synonyms include given name or christian name.
*
*/
- public static final DatatypeProperty FIRST_NAME = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#first_name");
+ public static final Property FIRST_NAME = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#first_name");
/**
*
@@ -537,8 +545,8 @@ public static String getURI() {
* of each type of SIOC concept within the same site.
*
*/
- public static final DatatypeProperty ID = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#id");
+ public static final Property ID = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#id");
/**
*
@@ -546,47 +554,47 @@ public static String getURI() {
* articles list the IP addresses for the creator or modifiers when the usernames are absent.
*
*/
- public static final DatatypeProperty IP_ADDRESS = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#ip_address");
+ public static final Property IP_ADDRESS = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#ip_address");
/**
*
* Last (real) name of this user. Synonyms include surname or family name.
*
*/
- public static final DatatypeProperty LAST_NAME = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#last_name");
+ public static final Property LAST_NAME = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#last_name");
/**
*
* When this was modified, in ISO 8601 format.
*
*/
- public static final DatatypeProperty MODIFIED_AT = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#modified_at");
+ public static final Property MODIFIED_AT = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#modified_at");
/**
*
* The name of a SIOC instance, e.g. a username for a User, group name for a Usergroup, etc.
*
*/
- public static final DatatypeProperty NAME = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#name");
+ public static final Property NAME = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#name");
/**
*
* A note associated with this resource, for example, if it has been edited by a User.
*
*/
- public static final DatatypeProperty NOTE = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#note");
+ public static final Property NOTE = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#note");
/**
*
* The number of posts that this person has posted.
*
*/
- public static final ObjectProperty NUM_POSTS = m_model
+ public static final Property NUM_POSTS = m_model
.createObjectProperty("http://rdfs.org/sioc/ns#num_posts");
/**
@@ -595,24 +603,24 @@ public static String getURI() {
* structure is absent.
*
*/
- public static final DatatypeProperty NUM_REPLIES = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#num_replies");
+ public static final Property NUM_REPLIES = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#num_replies");
/**
*
* The number of times this Item, Thread, User profile, etc. has been viewed.
*
*/
- public static final DatatypeProperty NUM_VIEWS = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#num_views");
+ public static final Property NUM_VIEWS = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#num_views");
/**
*
* Keyword(s) describing subject of the Post.
*
*/
- public static final DatatypeProperty SUBJECT = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#subject");
+ public static final Property SUBJECT = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#subject");
/**
*
@@ -620,8 +628,8 @@ public static String getURI() {
* that has no parents, it would detail the topic thread.
*
*/
- public static final DatatypeProperty TITLE = m_model
- .createDatatypeProperty("http://rdfs.org/sioc/ns#title");
+ public static final Property TITLE = m_model
+ .createDataProperty("http://rdfs.org/sioc/ns#title");
// Vocabulary classes
// /////////////////////////
@@ -631,42 +639,42 @@ public static String getURI() {
* Community is a high-level concept that defines an online community and what it consists of.
*
*/
- public static final OntClass COMMUNITY = m_model.createClass("http://rdfs.org/sioc/ns#Community");
+ public static final Resource COMMUNITY = m_model.createOntClass("http://rdfs.org/sioc/ns#Community");
/**
*
* An area in which content Items are contained.
*
*/
- public static final OntClass CONTAINER = m_model.createClass("http://rdfs.org/sioc/ns#Container");
+ public static final Resource CONTAINER = m_model.createOntClass("http://rdfs.org/sioc/ns#Container");
/**
*
* A discussion area on which Posts or entries are made.
*
*/
- public static final OntClass FORUM = m_model.createClass("http://rdfs.org/sioc/ns#Forum");
+ public static final Resource FORUM = m_model.createOntClass("http://rdfs.org/sioc/ns#Forum");
/**
*
* An Item is something which can be in a Container.
*
*/
- public static final OntClass ITEM = m_model.createClass("http://rdfs.org/sioc/ns#Item");
+ public static final Resource ITEM = m_model.createOntClass("http://rdfs.org/sioc/ns#Item");
/**
*
* An article or message that can be posted to a Forum.
*
*/
- public static final OntClass POST = m_model.createClass("http://rdfs.org/sioc/ns#Post");
+ public static final Resource POST = m_model.createOntClass("http://rdfs.org/sioc/ns#Post");
/**
*
* A Role is a function of a User within a scope of a particular Forum, Site, etc.
*
*/
- public static final OntClass ROLE = m_model.createClass("http://rdfs.org/sioc/ns#Role");
+ public static final Resource ROLE = m_model.createOntClass("http://rdfs.org/sioc/ns#Role");
/**
*
@@ -675,28 +683,28 @@ public static String getURI() {
* Space.
*
*/
- public static final OntClass SITE = m_model.createClass("http://rdfs.org/sioc/ns#Site");
+ public static final Resource SITE = m_model.createOntClass("http://rdfs.org/sioc/ns#Site");
/**
*
* A Space is a place where data resides, e.g. on a website, desktop, fileshare, etc.
*
*/
- public static final OntClass SPACE = m_model.createClass("http://rdfs.org/sioc/ns#Space");
+ public static final Resource SPACE = m_model.createOntClass("http://rdfs.org/sioc/ns#Space");
/**
*
* A container for a series of threaded discussion Posts or Items.
*
*/
- public static final OntClass THREAD = m_model.createClass("http://rdfs.org/sioc/ns#Thread");
+ public static final Resource THREAD = m_model.createOntClass("http://rdfs.org/sioc/ns#Thread");
/**
*
* A User account in an online community site.
*
*/
- public static final OntClass USER_ACCOUNT = m_model.createClass("http://rdfs.org/sioc/ns#UserAccount");
+ public static final Resource USER_ACCOUNT = m_model.createOntClass("http://rdfs.org/sioc/ns#UserAccount");
/**
*
@@ -704,7 +712,7 @@ public static String getURI() {
* control purposes.
*
*/
- public static final OntClass USERGROUP = m_model.createClass("http://rdfs.org/sioc/ns#Usergroup");
+ public static final Resource USERGROUP = m_model.createOntClass("http://rdfs.org/sioc/ns#Usergroup");
// Vocabulary individuals
// /////////////////////////
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/VoID.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/VoID.java
index 9d31bc7a97..f2f787b797 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/VoID.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/VoID.java
@@ -16,12 +16,11 @@
*/
package com.atomgraph.linkeddatahub.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.ObjectProperty;
-import org.apache.jena.ontology.OntClass;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -30,9 +29,14 @@
* @author Martynas Jusevičius {@literal }
*/
public class VoID {
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://rdfs.org/ns/void#";
@@ -52,18 +56,18 @@ public static String getURI()
public static final Resource NAMESPACE = m_model.createResource( NS );
/** Dataset class */
- public static final OntClass Dataset = m_model.createClass( NS + "Dataset" );
+ public static final Resource Dataset = m_model.createOntClass( NS + "Dataset" );
/** Triples property */
- public static final DatatypeProperty triples = m_model.createDatatypeProperty( NS + "triples" );
+ public static final Property triples = m_model.createDataProperty( NS + "triples" );
/** Distinct subject property */
- public static final DatatypeProperty distinctSubjects = m_model.createDatatypeProperty( NS + "distinctSubjects" );
+ public static final Property distinctSubjects = m_model.createDataProperty( NS + "distinctSubjects" );
/** In dataset property */
- public static final ObjectProperty inDataset = m_model.createObjectProperty( NS + "inDataset" );
+ public static final Property inDataset = m_model.createObjectProperty( NS + "inDataset" );
/** Class property */
- public static final ObjectProperty _class = m_model.createObjectProperty( NS + "class" );
+ public static final Property _class = m_model.createObjectProperty( NS + "class" );
}
diff --git a/src/main/java/com/atomgraph/server/vocabulary/HTTP.java b/src/main/java/com/atomgraph/server/vocabulary/HTTP.java
index e9316e1eec..77213e1cfb 100644
--- a/src/main/java/com/atomgraph/server/vocabulary/HTTP.java
+++ b/src/main/java/com/atomgraph/server/vocabulary/HTTP.java
@@ -16,12 +16,11 @@
package com.atomgraph.server.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.ObjectProperty;
-import org.apache.jena.ontology.OntClass;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -33,8 +32,13 @@
public class HTTP
{
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
+
/** The RDF model that holds the vocabulary terms
*/
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string
*/
public static final String NS = "http://www.w3.org/2011/http#";
@@ -49,16 +53,16 @@ public static String getURI()
/** The namespace of the vocabulary as a resource
*/
public static final Resource NAMESPACE = m_model.createResource( NS );
- public static final OntClass Response = m_model.createClass( NS + "Response" );
+ public static final Resource Response = m_model.createOntClass( NS + "Response" );
- public static final ObjectProperty sc = m_model.createObjectProperty( NS + "sc" );
+ public static final Property sc = m_model.createObjectProperty( NS + "sc" );
- public static final DatatypeProperty statusCodeValue = m_model.createDatatypeProperty( NS + "statusCodeValue" );
+ public static final Property statusCodeValue = m_model.createDataProperty( NS + "statusCodeValue" );
- public static final DatatypeProperty reasonPhrase = m_model.createDatatypeProperty( NS + "reasonPhrase" );
+ public static final Property reasonPhrase = m_model.createDataProperty( NS + "reasonPhrase" );
- public static final DatatypeProperty absoluteURI = m_model.createDatatypeProperty( NS + "absoluteURI" );
+ public static final Property absoluteURI = m_model.createDataProperty( NS + "absoluteURI" );
- public static final DatatypeProperty absolutePath = m_model.createDatatypeProperty( NS + "absolutePath" );
+ public static final Property absolutePath = m_model.createDataProperty( NS + "absolutePath" );
}
diff --git a/src/main/java/com/atomgraph/server/vocabulary/LDT.java b/src/main/java/com/atomgraph/server/vocabulary/LDT.java
index 5b59ee7f8a..b48ad91fef 100644
--- a/src/main/java/com/atomgraph/server/vocabulary/LDT.java
+++ b/src/main/java/com/atomgraph/server/vocabulary/LDT.java
@@ -16,12 +16,11 @@
*/
package com.atomgraph.server.vocabulary;
-import org.apache.jena.ontology.DatatypeProperty;
-import org.apache.jena.ontology.ObjectProperty;
-import org.apache.jena.ontology.OntClass;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Property;
+
import org.apache.jena.rdf.model.Resource;
/**
@@ -31,8 +30,13 @@
*/
public final class LDT
{
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
+ }
/** The RDF model that holds the vocabulary terms
*/
- private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
/** The namespace of the vocabulary as a string
*/
public static final String NS = "https://www.w3.org/ns/ldt#";
@@ -47,51 +51,51 @@ public static String getURI()
/** The namespace of the vocabulary as a resource
*/
public static final Resource NAMESPACE = m_model.createResource( NS );
- public static final OntClass Application = m_model.createClass( NS + "Application" );
+ public static final Resource Application = m_model.createOntClass( NS + "Application" );
- public static final OntClass Ontology = m_model.createClass( NS + "Ontology" );
+ public static final Resource Ontology = m_model.createOntClass( NS + "Ontology" );
- public static final OntClass Template = m_model.createClass( NS + "Template" );
+ public static final Resource Template = m_model.createOntClass( NS + "Template" );
- public static final OntClass Parameter = m_model.createClass( NS + "Parameter" );
+ public static final Resource Parameter = m_model.createOntClass( NS + "Parameter" );
- public static final OntClass TemplateCall = m_model.createClass( NS + "TemplateCall" );
+ public static final Resource TemplateCall = m_model.createOntClass( NS + "TemplateCall" );
- public static final OntClass Argument = m_model.createClass( NS + "Argument" );
+ public static final Resource Argument = m_model.createOntClass( NS + "Argument" );
- public static final ObjectProperty base = m_model.createObjectProperty( NS + "base" );
+ public static final Property base = m_model.createObjectProperty( NS + "base" );
- public static final ObjectProperty ontology = m_model.createObjectProperty( NS + "ontology" );
+ public static final Property ontology = m_model.createObjectProperty( NS + "ontology" );
- public static final ObjectProperty service = m_model.createObjectProperty( NS + "service" );
+ public static final Property service = m_model.createObjectProperty( NS + "service" );
- public static final ObjectProperty arg = m_model.createObjectProperty( NS + "arg" );
+ public static final Property arg = m_model.createObjectProperty( NS + "arg" );
- public static final DatatypeProperty paramName = m_model.createDatatypeProperty( NS + "paramName" );
+ public static final Property paramName = m_model.createDataProperty( NS + "paramName" );
// "extends" is a reserved keyword in Java, obviously
- public static final ObjectProperty extends_ = m_model.createObjectProperty( NS + "extends" );
+ public static final Property extends_ = m_model.createObjectProperty( NS + "extends" );
- public static final DatatypeProperty path = m_model.createDatatypeProperty( NS + "path" );
+ public static final Property path = m_model.createDataProperty( NS + "path" );
- public static final ObjectProperty query = m_model.createObjectProperty( NS + "query" );
+ public static final Property query = m_model.createObjectProperty( NS + "query" );
- public static final ObjectProperty update = m_model.createObjectProperty( NS + "update" );
+ public static final Property update = m_model.createObjectProperty( NS + "update" );
- public static final DatatypeProperty match = m_model.createDatatypeProperty( NS + "match" );
+ public static final Property match = m_model.createDataProperty( NS + "match" );
- public static final DatatypeProperty priority = m_model.createDatatypeProperty( NS + "priority" );
+ public static final Property priority = m_model.createDataProperty( NS + "priority" );
- public static final DatatypeProperty fragment = m_model.createDatatypeProperty( NS + "fragment" );
+ public static final Property fragment = m_model.createDataProperty( NS + "fragment" );
- public static final ObjectProperty param = m_model.createObjectProperty( NS + "param" );
+ public static final Property param = m_model.createObjectProperty( NS + "param" );
- public static final ObjectProperty loadClass = m_model.createObjectProperty( NS + "loadClass" );
+ public static final Property loadClass = m_model.createObjectProperty( NS + "loadClass" );
- public static final DatatypeProperty cacheControl = m_model.createDatatypeProperty( NS + "cacheControl" );
+ public static final Property cacheControl = m_model.createDataProperty( NS + "cacheControl" );
- public static final ObjectProperty lang = m_model.createObjectProperty( NS + "lang" );
+ public static final Property lang = m_model.createObjectProperty( NS + "lang" );
- public static final ObjectProperty template = m_model.createObjectProperty( NS + "template" );
+ public static final Property template = m_model.createObjectProperty( NS + "template" );
}
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilterTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilterTest.java
new file mode 100644
index 0000000000..76787051fc
--- /dev/null
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilterTest.java
@@ -0,0 +1,79 @@
+/**
+ * Copyright 2026 Martynas Jusevičius
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.atomgraph.linkeddatahub.server.filter.request;
+
+import org.apache.jena.ontology.OntDocumentManager;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Characterization tests for {@link OntologyFilter#addDocumentModel}, which caches an
+ * imported ontology model under a SECONDARY key: the fragment-stripped document URI.
+ *
+ * This pins the current dual-key caching behavior so the migration to the new ontology
+ * API ({@code GraphRepository}) can be proven to retain it.
+ *
+ * @author Martynas Jusevičius {@literal }
+ */
+public class OntologyFilterTest
+{
+
+ /** An import URI with a fragment is also cached under its fragment-stripped document URI. */
+ @Test
+ public void testAddDocumentModelCachesUnderStrippedDocumentURI()
+ {
+ OntDocumentManager odm = new OntDocumentManager();
+ String importURI = "http://example.org/onto#";
+ String docURI = "http://example.org/onto";
+
+ Model imported = ModelFactory.createDefaultModel();
+ imported.createResource(importURI + "Thing");
+ odm.addModel(importURI, imported, true);
+
+ // precondition: only the ontology (fragment) URI is known
+ assertNotNull(odm.getModel(importURI));
+
+ OntologyFilter.addDocumentModel(odm, importURI);
+
+ // the same model is now retrievable under the fragment-stripped document URI
+ assertNotNull(odm.getModel(docURI), "import model should be cached under the document URI");
+ assertSame(imported, odm.getModel(docURI));
+ }
+
+ /** If the document URI is mapped (mapURI != docURI), the secondary cache write is skipped. */
+ @Test
+ public void testAddDocumentModelSkipsWhenDocumentURIMapped()
+ {
+ OntDocumentManager odm = new OntDocumentManager();
+ String importURI = "http://example.org/mapped#";
+ String docURI = "http://example.org/mapped";
+
+ // map the document URI to a different location -> guard mappedURI.equals(docURI) is false
+ odm.getFileManager().getLocationMapper().addAltEntry(docURI, "file:elsewhere.ttl");
+
+ Model imported = ModelFactory.createDefaultModel();
+ odm.addModel(importURI, imported, true);
+
+ OntologyFilter.addDocumentModel(odm, importURI);
+
+ // no secondary cache entry created under the document URI
+ assertNull(odm.getModel(docURI), "mapped document URI should not be cached as a secondary key");
+ }
+
+}
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
new file mode 100644
index 0000000000..3009ef1693
--- /dev/null
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
@@ -0,0 +1,96 @@
+/**
+ * Copyright 2026 Martynas Jusevičius
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.atomgraph.linkeddatahub.server.filter.request;
+
+import org.apache.jena.ontology.OntDocumentManager;
+import org.apache.jena.ontology.OntModel;
+import org.apache.jena.ontology.OntModelSpec;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.rdf.model.ResourceFactory;
+import org.apache.jena.vocabulary.OWL;
+import org.apache.jena.vocabulary.RDF;
+import org.apache.jena.vocabulary.RDFS;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Oracle for the ontology-load mechanism used by {@link OntologyFilter}: build an
+ * OWL_MEM_RDFS_INF model over a base ontology that owl:imports another, then materialize
+ * the inferences into a plain OWL_MEM model that is cached.
+ *
+ * Pins (a) the owl:imports transitive closure, (b) RDFS inference, and (c) that the
+ * materialized model retains inferred triples but carries no reasoner — the three
+ * behaviors the {@code GraphRepository}/{@code OntSpecification} migration must reproduce.
+ *
+ * @author Martynas Jusevičius {@literal }
+ */
+public class OntologyImportsCharacterizationTest
+{
+
+ private static final String BASE_URI = "http://example.org/base";
+ private static final String IMPORT_URI = "http://example.org/imported";
+ private static final String NS = "http://example.org/ns#";
+
+ @Test
+ public void testImportClosureRdfsInferenceAndMaterialization()
+ {
+ OntModelSpec spec = new OntModelSpec(OntModelSpec.OWL_MEM_RDFS_INF);
+ OntDocumentManager odm = new OntDocumentManager();
+ spec.setDocumentManager(odm);
+
+ // imported ontology: B rdfs:subClassOf A; individual x a B
+ Resource a = ResourceFactory.createResource(NS + "A");
+ Resource b = ResourceFactory.createResource(NS + "B");
+ Resource x = ResourceFactory.createResource(NS + "x");
+ Model imported = ModelFactory.createDefaultModel();
+ imported.add(imported.createResource(IMPORT_URI), RDF.type, OWL.Ontology);
+ imported.add(b, RDFS.subClassOf, a);
+ imported.add(x, RDF.type, b);
+ odm.addModel(IMPORT_URI, imported);
+
+ // base ontology owl:imports the imported one
+ Model base = ModelFactory.createDefaultModel();
+ base.add(base.createResource(BASE_URI), RDF.type, OWL.Ontology);
+ base.add(base.createResource(BASE_URI), OWL.imports, base.createResource(IMPORT_URI));
+
+ OntModel ontModel = ModelFactory.createOntologyModel(spec, base);
+
+ // (a) transitive import closure includes the imported ontology
+ assertTrue(ontModel.listImportedOntologyURIs(true).contains(IMPORT_URI), "import closure should contain the imported ontology URI");
+ // imported asserted triple is visible through the union
+ assertTrue(ontModel.contains(b, RDFS.subClassOf, a), "imported terms should be visible");
+ // (b) RDFS inference: x a A is entailed from (x a B) + (B subClassOf A)
+ assertTrue(ontModel.contains(x, RDF.type, a), "RDFS reasoner should infer x a A");
+
+ // (c) materialize into a plain OWL_MEM model (no inference)
+ OntModel materialized = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
+ materialized.add(ontModel);
+ // inferred triple is now asserted in the materialized copy
+ assertTrue(materialized.contains(x, RDF.type, a), "materialized model retains the inferred triple");
+ // and the materialized model carries no reasoner
+ assertNull(materialized.getSpecification().getReasonerFactory(), "OWL_MEM materialized model must have no reasoner factory");
+ // proof it is plain: a fresh entailment is NOT auto-derived
+ Resource c = ResourceFactory.createResource(NS + "C");
+ Resource y = ResourceFactory.createResource(NS + "y");
+ materialized.add(c, RDFS.subClassOf, b);
+ materialized.add(y, RDF.type, c);
+ assertFalse(materialized.contains(y, RDF.type, a), "no reasoner: y a A must not be inferred");
+ }
+
+}
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/util/OntologyModelGetterTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/util/OntologyModelGetterTest.java
new file mode 100644
index 0000000000..4db93eac45
--- /dev/null
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/util/OntologyModelGetterTest.java
@@ -0,0 +1,117 @@
+/**
+ * Copyright 2026 Martynas Jusevičius
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.atomgraph.linkeddatahub.server.util;
+
+import com.atomgraph.core.client.SPARQLClient;
+import com.atomgraph.linkeddatahub.apps.model.AdminApplication;
+import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
+import com.atomgraph.linkeddatahub.model.Service;
+import com.atomgraph.linkeddatahub.model.ServiceContext;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import org.apache.jena.ontology.OntModelSpec;
+import org.apache.jena.query.Query;
+import org.apache.jena.query.QueryFactory;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.util.FileManager;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Characterization tests for {@link OntologyModelGetter}, which resolves an ontology model
+ * SPARQL-first (admin endpoint CONSTRUCT) and falls back to the FileManager only when the
+ * SPARQL result is empty.
+ *
+ * Pins the current resolution order so the migration to a {@code GraphRepository.get(uri)}
+ * can be proven to retain it.
+ *
+ * @author Martynas Jusevičius {@literal }
+ */
+@ExtendWith(MockitoExtension.class)
+public class OntologyModelGetterTest
+{
+
+ private static final String ONTOLOGY_URI = "http://example.org/ontology#";
+ private static final Query ONTOLOGY_QUERY = QueryFactory.create("CONSTRUCT { ?ontology ?p ?o } WHERE { ?ontology ?p ?o }");
+
+ @Mock com.atomgraph.linkeddatahub.Application system;
+ @Mock EndUserApplication app;
+ @Mock AdminApplication adminApp;
+ @Mock Service service;
+ @Mock ServiceContext serviceContext;
+ @Mock SPARQLClient sparqlClient;
+ @Mock Response response;
+
+ private void stubSPARQLChain(Model sparqlResult)
+ {
+ when(app.getAdminApplication()).thenReturn(adminApp);
+ when(adminApp.getService()).thenReturn(service);
+ when(system.getServiceContext(service)).thenReturn(serviceContext);
+ when(serviceContext.getSPARQLClient()).thenReturn(sparqlClient);
+ when(sparqlClient.query(any(Query.class), eq(Model.class), any(MultivaluedMap.class), any(MultivaluedMap.class))).thenReturn(response);
+ when(response.readEntity(Model.class)).thenReturn(sparqlResult);
+ }
+
+ /** A non-empty admin SPARQL CONSTRUCT result is returned directly; the FileManager is not consulted. */
+ @Test
+ public void testSPARQLResultUsedWhenNonEmpty()
+ {
+ Model sparqlResult = ModelFactory.createDefaultModel();
+ sparqlResult.createResource(ONTOLOGY_URI).addProperty(org.apache.jena.vocabulary.RDF.type, org.apache.jena.vocabulary.OWL.Ontology);
+ stubSPARQLChain(sparqlResult);
+
+ OntModelSpec spec = new OntModelSpec(OntModelSpec.OWL_MEM);
+ FileManager fileManager = org.mockito.Mockito.mock(FileManager.class);
+ spec.getDocumentManager().setFileManager(fileManager);
+
+ OntologyModelGetter getter = new OntologyModelGetter(app, system, spec, ONTOLOGY_QUERY);
+ Model result = getter.getModel(ONTOLOGY_URI);
+
+ assertSame(sparqlResult, result);
+ verify(fileManager, never()).loadModel(any());
+ }
+
+ /** An empty SPARQL result falls back to FileManager.loadModel(uri). */
+ @Test
+ public void testFallsBackToFileManagerWhenSPARQLEmpty()
+ {
+ Model empty = ModelFactory.createDefaultModel();
+ stubSPARQLChain(empty);
+
+ OntModelSpec spec = new OntModelSpec(OntModelSpec.OWL_MEM);
+ FileManager fileManager = org.mockito.Mockito.mock(FileManager.class);
+ spec.getDocumentManager().setFileManager(fileManager);
+ Model fallback = ModelFactory.createDefaultModel();
+ fallback.createResource(ONTOLOGY_URI);
+ when(fileManager.loadModel(ONTOLOGY_URI)).thenReturn(fallback);
+
+ OntologyModelGetter getter = new OntologyModelGetter(app, system, spec, ONTOLOGY_QUERY);
+ Model result = getter.getModel(ONTOLOGY_URI);
+
+ assertSame(fallback, result);
+ }
+
+}
diff --git a/src/test/java/com/atomgraph/linkeddatahub/vocabulary/VocabularyHolderTest.java b/src/test/java/com/atomgraph/linkeddatahub/vocabulary/VocabularyHolderTest.java
new file mode 100644
index 0000000000..c416b712bb
--- /dev/null
+++ b/src/test/java/com/atomgraph/linkeddatahub/vocabulary/VocabularyHolderTest.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright 2026 Martynas Jusevičius
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.atomgraph.linkeddatahub.vocabulary;
+
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.vocabulary.OWL;
+import org.apache.jena.vocabulary.RDF;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Characterization snapshot for the vocabulary holders (representative: {@link DH}).
+ *
+ * All ~19 vocabulary classes follow the identical pattern — a static OntModel built with
+ * {@code ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null)} on which
+ * {@code createClass} / {@code createDatatypeProperty} mint typed terms. Phase A swaps the
+ * factory to {@code OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM)} and renames
+ * {@code createClass}→{@code createOntClass}, {@code createDatatypeProperty}→{@code createDataProperty}.
+ *
+ * Asserted via the migration-stable {@link Resource} interface: the term URIs and the
+ * {@code rdf:type owl:Class} / {@code rdf:type owl:DatatypeProperty} triples they produce
+ * must stay identical after the rename.
+ *
+ * @author Martynas Jusevičius {@literal }
+ */
+public class VocabularyHolderTest
+{
+
+ @Test
+ public void testClassTermsHaveStableUriAndType()
+ {
+ Resource document = DH.Document;
+ assertEquals(DH.NS + "Document", document.getURI());
+ assertTrue(document.hasProperty(RDF.type, OWL.Class), "DH.Document must be typed owl:Class");
+
+ Resource container = DH.Container;
+ assertEquals(DH.NS + "Container", container.getURI());
+ assertTrue(container.hasProperty(RDF.type, OWL.Class), "DH.Container must be typed owl:Class");
+ }
+
+ @Test
+ public void testDatatypePropertyTermHasStableUriAndType()
+ {
+ Resource slug = DH.slug;
+ assertEquals(DH.NS + "slug", slug.getURI());
+ assertTrue(slug.hasProperty(RDF.type, OWL.DatatypeProperty), "DH.slug must be typed owl:DatatypeProperty");
+ }
+
+}
From 2011ff9f1c9b2c4672cac76a7918970657a86e48 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?=
Date: Thu, 18 Jun 2026 15:04:04 +0200
Subject: [PATCH 02/14] Phase D: dissolve DataManager + migrate ontology
pipeline to ontapi
Completes the dissolution in LinkedDataHub (0 [removal] warnings, was ~90):
- DataManagerImpl -> SameSiteSourceResolver (RDFSourceResolver subclass, same-site restriction)
- OntologyModelGetter -> OntologyRepository (SPARQL-first PrefixGraphRepository subclass)
- DataManagerFactory -> SourceResolverFactory (provides request-scoped RDFSourceResolver)
- Application: per-app OntModelSpec/OntDocumentManager -> per-app OntologyRepository; global repository + resolver; remove PrefixMapper/LocationMapper/OntDocumentManager wiring
- OntologyFilter/ClearOntology: ontapi OntModelFactory.createModel with OWL2_DL_MEM_RDFS_INF + materialize into OWL2_DL_MEM cached in the repository; dual-key import-closure caching preserved
- request ontology property Optional -> Optional (ontapi) across OntologyFactory + ~8 consumers (.getOntModel() dropped)
- Validator, ProxyRequestFilter, ValidatingModelProvider, Install/UninstallPackage: DataManager/OntModelSpec cache ops -> repository
- characterization tests adapted to new API (OntologyRepositoryTest, OntologyFilterTest); 69 tests green
Co-Authored-By: Claude Opus 4.8 (1M context)
---
.../atomgraph/linkeddatahub/Application.java | 152 ++++++++----------
.../linkeddatahub/resource/Generate.java | 10 +-
.../linkeddatahub/resource/Namespace.java | 18 +--
.../resource/admin/ClearOntology.java | 35 ++--
.../linkeddatahub/resource/admin/SignUp.java | 4 +-
.../resource/admin/pkg/InstallPackage.java | 34 ++--
.../resource/admin/pkg/UninstallPackage.java | 25 +--
.../server/event/AuthorizationCreated.java | 1 -
.../server/factory/OntologyFactory.java | 12 +-
.../server/filter/request/OntologyFilter.java | 134 +++++++--------
.../filter/request/ProxyRequestFilter.java | 12 +-
.../server/io/ValidatingModelProvider.java | 2 +-
.../impl/DocumentHierarchyGraphStoreImpl.java | 8 +-
...delGetter.java => OntologyRepository.java} | 74 ++++-----
.../linkeddatahub/writer/ModelXSLTWriter.java | 7 +-
.../writer/ResultSetXSLTWriter.java | 7 +-
.../linkeddatahub/writer/XSLTWriterBase.java | 38 ++---
...actory.java => SourceResolverFactory.java} | 47 +++---
...rImpl.java => SameSiteSourceResolver.java} | 72 +++------
.../server/io/ValidatingDatasetProvider.java | 10 +-
.../server/io/ValidatingModelProvider.java | 10 +-
.../com/atomgraph/server/util/Validator.java | 2 +-
.../filter/request/OntologyFilterTest.java | 45 ++----
...rTest.java => OntologyRepositoryTest.java} | 56 +++----
24 files changed, 342 insertions(+), 473 deletions(-)
rename src/main/java/com/atomgraph/linkeddatahub/server/util/{OntologyModelGetter.java => OntologyRepository.java} (64%)
rename src/main/java/com/atomgraph/linkeddatahub/writer/factory/{DataManagerFactory.java => SourceResolverFactory.java} (70%)
rename src/main/java/com/atomgraph/linkeddatahub/writer/impl/{DataManagerImpl.java => SameSiteSourceResolver.java} (59%)
rename src/test/java/com/atomgraph/linkeddatahub/server/util/{OntologyModelGetterTest.java => OntologyRepositoryTest.java} (64%)
diff --git a/src/main/java/com/atomgraph/linkeddatahub/Application.java b/src/main/java/com/atomgraph/linkeddatahub/Application.java
index abe64f03d6..46bc8f8dc0 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/Application.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/Application.java
@@ -16,6 +16,14 @@
*/
package com.atomgraph.linkeddatahub;
+import com.atomgraph.core.util.jena.PrefixGraphRepository;
+import com.atomgraph.client.util.RDFSourceResolver;
+import com.atomgraph.client.util.StylesheetResolver;
+import com.atomgraph.linkeddatahub.writer.impl.SameSiteSourceResolver;
+import com.atomgraph.linkeddatahub.server.util.OntologyRepository;
+import org.apache.jena.riot.RDFParser;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
import com.atomgraph.linkeddatahub.server.mapper.HttpHostConnectExceptionMapper;
import com.atomgraph.linkeddatahub.server.mapper.InternalURLExceptionMapper;
import com.atomgraph.linkeddatahub.server.mapper.MessagingExceptionMapper;
@@ -27,9 +35,6 @@
import com.atomgraph.linkeddatahub.server.mapper.auth.webid.WebIDCertificateExceptionMapper;
import com.atomgraph.client.MediaTypes;
import com.atomgraph.client.locator.PrefixMapper;
-import org.apache.jena.ontology.OntDocumentManager;
-import org.apache.jena.util.FileManager;
-import org.apache.jena.util.LocationMapper;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.ServletConfig;
import jakarta.ws.rs.core.Context;
@@ -37,8 +42,6 @@
import org.apache.jena.riot.RDFFormat;
import org.apache.jena.riot.RDFWriterRegistry;
import com.atomgraph.client.mapper.ClientErrorExceptionMapper;
-import com.atomgraph.client.util.DataManager;
-import com.atomgraph.client.util.DataManagerImpl;
import com.atomgraph.client.vocabulary.AC;
import com.atomgraph.client.writer.function.UUID;
import com.atomgraph.core.exception.ConfigurationException;
@@ -49,7 +52,7 @@
import com.atomgraph.core.io.UpdateRequestProvider;
import com.atomgraph.core.mapper.BadGatewayExceptionMapper;
import com.atomgraph.core.provider.QueryParamProvider;
-import com.atomgraph.linkeddatahub.writer.factory.DataManagerFactory;
+import com.atomgraph.linkeddatahub.writer.factory.SourceResolverFactory;
import com.atomgraph.server.vocabulary.LDT;
import com.atomgraph.server.mapper.NotFoundExceptionMapper;
import com.atomgraph.core.riot.RDFLanguages;
@@ -67,7 +70,6 @@
import com.atomgraph.linkeddatahub.model.Service;
import com.atomgraph.linkeddatahub.writer.factory.xslt.XsltExecutableSupplier;
import com.atomgraph.linkeddatahub.writer.factory.XsltExecutableSupplierFactory;
-import com.atomgraph.client.util.XsltResolver;
import com.atomgraph.linkeddatahub.client.GraphStoreClient;
import com.atomgraph.linkeddatahub.client.filter.ClientUriRewriteFilter;
import com.atomgraph.linkeddatahub.client.filter.JSONGRDDLFilter;
@@ -135,7 +137,6 @@
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import org.apache.jena.enhanced.BuiltinPersonalities;
-import org.apache.jena.ontology.OntModelSpec;
import org.apache.jena.riot.RDFParserRegistry;
import org.slf4j.Logger;
import java.net.URI;
@@ -164,7 +165,7 @@
import javax.net.ssl.TrustManagerFactory;
import jakarta.servlet.ServletContext;
import javax.xml.transform.Source;
-import org.apache.jena.ontology.Ontology;
+import org.apache.jena.ontapi.model.OntModel;
import org.apache.jena.query.Dataset;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
@@ -268,8 +269,9 @@ public class Application extends ResourceConfig
private final ExecutorService importThreadPool;
private final ServletConfig servletConfig;
private final EventBus eventBus = new EventBus();
- private final DataManager dataManager;
- private final Map endUserOntModelSpecs;
+ private final PrefixGraphRepository repository;
+ private final SameSiteSourceResolver resolver;
+ private final Map endUserRepositories;
private final MediaTypes mediaTypes;
private final Client client, externalClient, importClient, noCertClient;
private final Query documentTypeQuery, documentOwnerQuery, aclQuery, ownerAclQuery, webIDQuery, agentQuery, userAccountQuery, ontologyQuery; // no relative URIs
@@ -278,7 +280,6 @@ public class Application extends ResourceConfig
private final Processor xsltProc = new Processor(false);
private final XsltCompiler xsltComp;
private final XsltExecutable xsltExec;
- private final OntModelSpec ontModelSpec;
private final boolean cacheStylesheet;
private final boolean resolvingUncached;
private final URI baseURI, uploadRoot;
@@ -324,7 +325,7 @@ public Application(@Context ServletConfig servletConfig) throws URISyntaxExcepti
servletConfig.getServletContext().getInitParameter(A.maxGetRequestSize.getURI()) != null ? Integer.valueOf(servletConfig.getServletContext().getInitParameter(A.maxGetRequestSize.getURI())) : null,
servletConfig.getServletContext().getInitParameter(A.cacheModelLoads.getURI()) != null ? Boolean.parseBoolean(servletConfig.getServletContext().getInitParameter(A.cacheModelLoads.getURI())) : true,
servletConfig.getServletContext().getInitParameter(A.preemptiveAuth.getURI()) != null ? Boolean.parseBoolean(servletConfig.getServletContext().getInitParameter(A.preemptiveAuth.getURI())) : false,
- new PrefixMapper(servletConfig.getServletContext().getInitParameter(AC.prefixMapping.getURI()) != null ? servletConfig.getServletContext().getInitParameter(AC.prefixMapping.getURI()) : null),
+ servletConfig.getServletContext().getInitParameter(AC.prefixMapping.getURI()),
servletConfig.getServletContext().getInitParameter(LDHC.contextDataset.getURI()) != null ? servletConfig.getServletContext().getInitParameter(LDHC.contextDataset.getURI()) : null,
com.atomgraph.client.Application.getSource(servletConfig.getServletContext(), servletConfig.getServletContext().getInitParameter(AC.stylesheet.getURI()) != null ? servletConfig.getServletContext().getInitParameter(AC.stylesheet.getURI()) : null),
servletConfig.getServletContext().getInitParameter(AC.cacheStylesheet.getURI()) != null ? Boolean.parseBoolean(servletConfig.getServletContext().getInitParameter(AC.cacheStylesheet.getURI())) : false,
@@ -435,7 +436,7 @@ public Application(@Context ServletConfig servletConfig) throws URISyntaxExcepti
*/
public Application(final ServletConfig servletConfig, final MediaTypes mediaTypes,
final Integer maxGetRequestSize, final boolean cacheModelLoads, final boolean preemptiveAuth,
- final LocationMapper locationMapper, final String contextDatasetURIString,
+ final String prefixMappingConfig, final String contextDatasetURIString,
final Source stylesheet, final boolean cacheStylesheet, final boolean resolvingUncached,
final String clientKeyStoreURIString, final String clientKeyStorePassword,
final String secretaryCertAlias,
@@ -682,12 +683,8 @@ public Application(final ServletConfig servletConfig, final MediaTypes mediaType
}
// register plain RDF/XML writer as default
- RDFWriterRegistry.register(Lang.RDFXML, RDFFormat.RDFXML_PLAIN);
+ RDFWriterRegistry.register(Lang.RDFXML, RDFFormat.RDFXML_PLAIN);
- // initialize mapping for locally stored vocabularies
- LocationMapper.setGlobalLocationMapper(locationMapper);
- if (log.isTraceEnabled()) log.trace("LocationMapper.get(): {}", locationMapper);
-
try
{
this.contextDataset = getDataset(servletConfig.getServletContext(), contextDatasetURI);
@@ -792,14 +789,16 @@ else if (app.hasProperty(RDF.type, LAPP.EndUserApplication))
serviceIt.close();
}
- // TO-DO: config property for cacheModelLoads
- endUserOntModelSpecs = new HashMap<>();
- dataManager = new DataManagerImpl(locationMapper, new HashMap<>(), GraphStoreClient.create(client, mediaTypes), cacheModelLoads, preemptiveAuth, resolvingUncached);
- ontModelSpec = OntModelSpec.OWL_MEM_RDFS_INF;
- ontModelSpec.setImportModelGetter(dataManager);
- OntDocumentManager.getInstance().setFileManager((FileManager)dataManager);
- OntDocumentManager.getInstance().setCacheModels(true); // need to re-set after changing FileManager
- ontModelSpec.setDocumentManager(OntDocumentManager.getInstance());
+ endUserRepositories = new HashMap<>();
+ // global graph repository: bundled vocabularies/ontologies mapped from the prefix-mapping config
+ repository = new PrefixGraphRepository(GraphStoreClient.create(client, mediaTypes));
+ if (prefixMappingConfig != null)
+ {
+ Model prefixMappingModel = ModelFactory.createDefaultModel();
+ RDFParser.create().source(prefixMappingConfig).streamManager(repository.getStreamManager()).build().parse(prefixMappingModel);
+ repository.processConfig(prefixMappingModel);
+ }
+ resolver = new SameSiteSourceResolver(repository, GraphStoreClient.create(client, mediaTypes), resolvingUncached, baseURI);
if (mailUser != null && mailPassword != null) // enable SMTP authentication
{
@@ -836,19 +835,15 @@ protected PasswordAuthentication getPasswordAuthentication()
xsltProc.registerExtensionFunction(new com.atomgraph.linkeddatahub.writer.function.URLDecode());
xsltProc.registerExtensionFunction(new com.atomgraph.linkeddatahub.writer.function.SendHTTPRequest(xsltProc, client));
- Model mappingModel = locationMapper.toModel();
- ResIterator prefixedMappings = mappingModel.listResourcesWithProperty(LocationMappingVocab.prefix);
try
{
- while (prefixedMappings.hasNext())
+ for (String prefix : getRepository().getPrefixMappings().keySet())
{
- Resource prefixMapping = prefixedMappings.next();
- String prefix = prefixMapping.getRequiredProperty(LocationMappingVocab.prefix).getString();
// register mapped RDF documents in the XSLT processor so that document() returns them cached, throughout multiple transformations
- TreeInfo doc = xsltProc.getUnderlyingConfiguration().buildDocumentTree(dataManager.resolve("", prefix));
+ TreeInfo doc = xsltProc.getUnderlyingConfiguration().buildDocumentTree(getResolver().resolve("", prefix));
xsltProc.getUnderlyingConfiguration().getGlobalDocumentPool().add(doc, prefix);
}
-
+
// register HTTPS URL of translations.rdf so it doesn't have to be requested repeatedly
try (InputStream translations = servletConfig.getServletContext().getResourceAsStream(XSLTWriterBase.TRANSLATIONS_PATH))
{
@@ -861,14 +856,10 @@ protected PasswordAuthentication getPasswordAuthentication()
if (log.isErrorEnabled()) log.error("Error reading mapped RDF document: {}", ex);
throw new IllegalStateException(ex);
}
- finally
- {
- prefixedMappings.close();
- }
xsltComp = xsltProc.newXsltCompiler();
xsltComp.setParameter(new QName("ldh", LDH.base.getNameSpace(), LDH.base.getLocalName()), new XdmAtomicValue(baseURI));
- xsltComp.setURIResolver(new XsltResolver(LocationMapper.get(), new HashMap<>(), GraphStoreClient.create(client, mediaTypes), false, false, true)); // default Xerces parser does not support HTTPS
+ xsltComp.setURIResolver(new StylesheetResolver(getRepository(), GraphStoreClient.create(client, mediaTypes))); // resolves xsl:import to raw stylesheet sources
xsltExec = xsltComp.compile(stylesheet);
}
catch (FileNotFoundException ex)
@@ -935,8 +926,8 @@ public void init()
register(new QueryProvider());
register(new QueryParamProvider());
register(new UpdateRequestProvider());
- register(new ModelXSLTWriter(getXsltExecutable(), getOntModelSpec(), getDataManager(), getMessageDigest())); // writes (X)HTML responses
- register(new ResultSetXSLTWriter(getXsltExecutable(), getOntModelSpec(), getDataManager(), getMessageDigest())); // writes (X)HTML responses
+ register(new ModelXSLTWriter(getXsltExecutable(), getResolver(), getMessageDigest())); // writes (X)HTML responses
+ register(new ResultSetXSLTWriter(getXsltExecutable(), getResolver(), getMessageDigest())); // writes (X)HTML responses
final com.atomgraph.linkeddatahub.Application system = this;
register(new AbstractBinder()
@@ -1014,7 +1005,7 @@ protected void configure()
@Override
protected void configure()
{
- bindFactory(OntologyFactory.class).to(new TypeLiteral>() {}).
+ bindFactory(OntologyFactory.class).to(new TypeLiteral>() {}).
in(RequestScoped.class);
}
});
@@ -1023,15 +1014,7 @@ protected void configure()
@Override
protected void configure()
{
- bindFactory(new com.atomgraph.core.factory.DataManagerFactory(getDataManager())).to(com.atomgraph.core.util.jena.DataManager.class);
- }
- });
- register(new AbstractBinder()
- {
- @Override
- protected void configure()
- {
- bindFactory(DataManagerFactory.class).to(com.atomgraph.client.util.DataManager.class).
+ bindFactory(SourceResolverFactory.class).to(com.atomgraph.client.util.RDFSourceResolver.class).
in(RequestScoped.class);
}
});
@@ -1756,43 +1739,54 @@ public EventBus getEventBus()
}
/**
- * Gets Jena's DataManager implementation.
- *
- * @return data manager instance
+ * Returns the global graph repository (bundled vocabularies/ontologies + URI mapping + cache).
+ *
+ * @return graph repository
+ */
+ public PrefixGraphRepository getRepository()
+ {
+ return repository;
+ }
+
+ /**
+ * Returns the global XSLT source resolver.
+ *
+ * @return source resolver
*/
- public DataManager getDataManager()
+ public SameSiteSourceResolver getResolver()
{
- return dataManager;
+ return resolver;
}
-
+
/**
- * Returns a map of application URIs to ontology specifications.
- *
- * @return URI to ontology specification map
+ * Returns a map of application URIs to ontology repositories.
+ *
+ * @return URI to ontology repository map
*/
- protected Map getEndUserOntModelSpecs()
+ protected Map getEndUserRepositories()
{
- return endUserOntModelSpecs;
+ return endUserRepositories;
}
/**
- * Returns ontology specification for the specified end-user application.
- *
+ * Returns the SPARQL-first ontology repository for the specified end-user application.
+ *
* @param app end-user application resource
- * @return ontology specification
+ * @return ontology repository
*/
- public OntModelSpec getOntModelSpec(EndUserApplication app)
+ public OntologyRepository getRepository(EndUserApplication app)
{
- if (!getEndUserOntModelSpecs().containsKey(app.getURI()))
+ if (!getEndUserRepositories().containsKey(app.getURI()))
{
- OntModelSpec appOntModelSpec = new OntModelSpec(OntModelSpec.OWL_MEM_RDFS_INF);
- appOntModelSpec.setDocumentManager(new OntDocumentManager());
- appOntModelSpec.getDocumentManager().setFileManager(new DataManagerImpl(LocationMapper.get(), new HashMap<>(), GraphStoreClient.create(getClient(), getMediaTypes()), true, isPreemptiveAuth(), isResolvingUncached()));
-
- getEndUserOntModelSpecs().put(app.getURI(), appOntModelSpec);
+ OntologyRepository appRepository = new OntologyRepository(app, this, GraphStoreClient.create(getClient(), getMediaTypes()), getOntologyQuery());
+ // seed bundled vocabulary/ontology mappings from the global repository
+ getRepository().getLocationMappings().forEach(appRepository::addLocationMapping);
+ getRepository().getPrefixMappings().forEach(appRepository::addPrefixMapping);
+
+ getEndUserRepositories().put(app.getURI(), appRepository);
}
-
- return getEndUserOntModelSpecs().get(app.getURI());
+
+ return getEndUserRepositories().get(app.getURI());
}
/**
@@ -2002,16 +1996,6 @@ public boolean isPreemptiveAuth()
return preemptiveAuth;
}
- /**
- * The default specification of ontology models.
- *
- * @return spec object
- */
- public OntModelSpec getOntModelSpec()
- {
- return ontModelSpec;
- }
-
/**
* Returns Saxon's XSLT compiler.
*
diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java
index 34b68d81fd..27e2124ffc 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java
@@ -42,7 +42,7 @@
import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.core.UriBuilder;
import jakarta.ws.rs.core.UriInfo;
-import org.apache.jena.ontology.Ontology;
+import org.apache.jena.ontapi.model.OntModel;
import org.apache.jena.query.ParameterizedSparqlString;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryFactory;
@@ -69,7 +69,7 @@ public class Generate
private final UriInfo uriInfo;
private final MediaTypes mediaTypes;
private final Application application;
- private final Ontology ontology;
+ private final OntModel ontology;
private final Optional agentContext;
private final com.atomgraph.linkeddatahub.Application system;
private final ResourceContext resourceContext;
@@ -88,7 +88,7 @@ public class Generate
*/
@Inject
public Generate(@Context Request request, @Context UriInfo uriInfo, MediaTypes mediaTypes,
- com.atomgraph.linkeddatahub.apps.model.Application application, Optional ontology, Optional agentContext,
+ com.atomgraph.linkeddatahub.apps.model.Application application, Optional ontology, Optional agentContext,
com.atomgraph.linkeddatahub.Application system, @Context ResourceContext resourceContext)
{
if (ontology.isEmpty()) throw new InternalServerErrorException("Ontology is not specified");
@@ -134,7 +134,7 @@ public Response post(Model model)
if (queryRes == null) throw new BadRequestException("Container query string (spin:query) not provided");
// Lookup query in ontology
- Resource queryResource = getOntology().getOntModel().getResource(queryRes.getURI());
+ Resource queryResource = getOntology().getResource(queryRes.getURI());
if (queryResource == null || !queryResource.hasProperty(SP.text))
throw new BadRequestException("Query resource not found in ontology: " + queryRes.getURI());
@@ -265,7 +265,7 @@ public Application getApplication()
*
* @return the ontology
*/
- public Ontology getOntology()
+ public OntModel getOntology()
{
return ontology;
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Namespace.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Namespace.java
index 4ccefa319f..c055f957da 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/resource/Namespace.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Namespace.java
@@ -31,7 +31,7 @@
import com.atomgraph.core.model.impl.dataset.ServiceImpl;
import com.atomgraph.linkeddatahub.apps.model.Application;
import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
-import com.atomgraph.linkeddatahub.server.util.OntologyModelGetter;
+import com.atomgraph.linkeddatahub.server.util.OntologyRepository;
import java.net.URI;
import java.util.List;
import java.util.Optional;
@@ -47,7 +47,7 @@
import jakarta.ws.rs.core.SecurityContext;
import jakarta.ws.rs.core.UriInfo;
import org.apache.jena.irix.IRIx;
-import org.apache.jena.ontology.Ontology;
+import org.apache.jena.ontapi.model.OntModel;
import org.apache.jena.query.DatasetFactory;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryFactory;
@@ -70,7 +70,7 @@ public class Namespace extends com.atomgraph.core.model.impl.SPARQLEndpointImpl
private final URI uri;
private final UriInfo uriInfo;
private final Application application;
- private final Ontology ontology;
+ private final OntModel ontology;
private final com.atomgraph.linkeddatahub.Application system;
/**
@@ -86,10 +86,10 @@ public class Namespace extends com.atomgraph.core.model.impl.SPARQLEndpointImpl
*/
@Inject
public Namespace(@Context Request request, @Context UriInfo uriInfo,
- Application application, Optional ontology, MediaTypes mediaTypes,
+ Application application, Optional ontology, MediaTypes mediaTypes,
@Context SecurityContext securityContext, com.atomgraph.linkeddatahub.Application system)
{
- super(request, new ServiceImpl(DatasetFactory.create(ontology.get().getOntModel()), mediaTypes), mediaTypes);
+ super(request, new ServiceImpl(DatasetFactory.create(ontology.get()), mediaTypes), mediaTypes);
this.uri = uriInfo.getAbsolutePath();
this.uriInfo = uriInfo;
this.application = application;
@@ -128,7 +128,7 @@ public Response get(@QueryParam(QUERY) Query query,
Model instances = ModelFactory.createDefaultModel();
forClasses.stream().
- map(forClass -> Optional.ofNullable(getOntology().getOntModel().getOntClass(checkURI(forClass).toString()))).
+ map(forClass -> Optional.ofNullable(getOntology().getOntClass(checkURI(forClass).toString()))).
flatMap(Optional::stream).
forEach(forClass -> new Constructor().construct(forClass, instances, getApplication().getBase().getURI()));
@@ -141,8 +141,8 @@ public Response get(@QueryParam(QUERY) Query query,
String ontologyURI = getApplication().getOntology().getURI();
if (log.isDebugEnabled()) log.debug("Returning namespace ontology from OntDocumentManager: {}", ontologyURI);
// not returning the injected in-memory ontology because it has inferences applied to it
- OntologyModelGetter modelGetter = new OntologyModelGetter(getApplication().as(EndUserApplication.class), getSystem(), getSystem().getOntModelSpec(), getSystem().getOntologyQuery());
- return getResponseBuilder(modelGetter.getModel(ontologyURI)).build();
+ OntologyRepository repository = new OntologyRepository(getApplication().as(EndUserApplication.class), getSystem(), com.atomgraph.linkeddatahub.client.GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()), getSystem().getOntologyQuery());
+ return getResponseBuilder(org.apache.jena.rdf.model.ModelFactory.createModelForGraph(repository.get(ontologyURI))).build();
}
else throw new BadRequestException("SPARQL query string not provided");
}
@@ -223,7 +223,7 @@ public Application getApplication()
*
* @return application ontology
*/
- public Ontology getOntology()
+ public OntModel getOntology()
{
return ontology;
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/ClearOntology.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/ClearOntology.java
index 202f724291..5470d5ef97 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/ClearOntology.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/ClearOntology.java
@@ -18,9 +18,8 @@
import com.atomgraph.linkeddatahub.apps.model.AdminApplication;
import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
-import static com.atomgraph.linkeddatahub.server.filter.request.OntologyFilter.addDocumentModel;
import com.atomgraph.linkeddatahub.server.filter.response.CacheInvalidationFilter;
-import com.atomgraph.linkeddatahub.server.util.OntologyModelGetter;
+import com.atomgraph.linkeddatahub.server.util.OntologyRepository;
import java.net.URI;
import jakarta.inject.Inject;
import jakarta.ws.rs.BadRequestException;
@@ -31,8 +30,12 @@
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriBuilder;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.graph.Graph;
+import java.util.HashSet;
+import com.atomgraph.linkeddatahub.server.filter.request.OntologyFilter;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Resource;
@@ -82,11 +85,11 @@ public Response post(@FormParam("uri") String ontologyURI, @HeaderParam("Referer
if (ontologyURI == null) throw new BadRequestException("Ontology URI not specified");
EndUserApplication endUserApp = getApplication().as(AdminApplication.class).getEndUserApplication(); // we're assuming the current app is admin
- OntModelSpec ontModelSpec = new OntModelSpec(getSystem().getOntModelSpec(endUserApp));
- if (ontModelSpec.getDocumentManager().getFileManager().hasCachedModel(ontologyURI))
+ OntologyRepository repository = getSystem().getRepository(endUserApp);
+ if (repository.isCached(ontologyURI))
{
if (log.isDebugEnabled()) log.debug("Clearing ontology with URI '{}' from memory", ontologyURI);
- ontModelSpec.getDocumentManager().getFileManager().removeCacheModel(ontologyURI);
+ repository.remove(ontologyURI);
URI ontologyDocURI = UriBuilder.fromUri(ontologyURI).fragment(null).build(); // skip fragment from the ontology URI to get its graph URI
// frontend proxy still uses URL-pattern BAN for direct document GETs (until Stage 3 brings xkey tagging to varnish-frontend).
@@ -117,17 +120,15 @@ public Response post(@FormParam("uri") String ontologyURI, @HeaderParam("Referer
// !!! we need to reload the ontology model before returning a response, to make sure the next request already gets the new version !!!
// same logic as in OntologyFilter. TO-DO: encapsulate?
- OntologyModelGetter modelGetter = new OntologyModelGetter(endUserApp, getSystem(), ontModelSpec, getSystem().getOntologyQuery());
- ontModelSpec.setImportModelGetter(modelGetter);
if (log.isDebugEnabled()) log.debug("Started loading ontology with URI '{}' from the admin dataset", ontologyURI);
- Model baseModel = modelGetter.getModel(ontologyURI);
- OntModel ontModel = ModelFactory.createOntologyModel(ontModelSpec, baseModel);
- // materialize OntModel inferences to avoid invoking rules engine on every request
- OntModel materializedModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); // no inference
- materializedModel.add(ontModel);
- ontModel.getDocumentManager().addModel(ontologyURI, materializedModel, true); // make immutable and add as OntModel so that imports do not need to be reloaded during retrieval
- // make sure to cache imported models not only by ontology URI but also by document URI
- ontModel.listImportedOntologyURIs(true).forEach((String importURI) -> addDocumentModel(ontModel.getDocumentManager(), importURI));
+ Graph baseGraph = repository.get(ontologyURI);
+ OntModel inferred = OntModelFactory.createModel(baseGraph, OntSpecification.OWL2_DL_MEM_RDFS_INF, repository);
+ // materialize inferences to avoid invoking the rules engine on every request
+ OntModel materialized = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ materialized.add(inferred);
+ repository.put(ontologyURI, materialized.getGraph());
+ // cache imported graphs under their document URIs too
+ OntologyFilter.importClosure(inferred, new HashSet<>()).forEach(importURI -> OntologyFilter.addDocumentModel(repository, importURI));
if (log.isDebugEnabled()) log.debug("Finished loading ontology with URI '{}' from the admin dataset", ontologyURI);
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/SignUp.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/SignUp.java
index d71770a2cc..bc8467d0dd 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/SignUp.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/SignUp.java
@@ -72,7 +72,7 @@
import jakarta.ws.rs.core.UriInfo;
import jakarta.ws.rs.ext.Providers;
import static org.apache.jena.datatypes.xsd.XSDDatatype.XSDhexBinary;
-import org.apache.jena.ontology.Ontology;
+import org.apache.jena.ontapi.model.OntModel;
import org.apache.jena.query.ParameterizedSparqlString;
import org.apache.jena.query.Query;
import org.apache.jena.query.ResultSet;
@@ -144,7 +144,7 @@ public class SignUp extends DocumentHierarchyGraphStoreImpl
// TO-DO: move to AuthenticationExceptionMapper and handle as state instead of URI resource?
@Inject
public SignUp(@Context Request request, @Context UriInfo uriInfo, MediaTypes mediaTypes,
- com.atomgraph.linkeddatahub.apps.model.Application application, Optional ontology, Optional service,
+ com.atomgraph.linkeddatahub.apps.model.Application application, Optional ontology, Optional service,
@Context SecurityContext securityContext, Optional agentContext,
@Context Providers providers, com.atomgraph.linkeddatahub.Application system, @Context ServletConfig servletConfig)
{
diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java
index 9e760cd0b1..e178f6dc67 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java
@@ -17,7 +17,6 @@
package com.atomgraph.linkeddatahub.resource.admin.pkg;
import static com.atomgraph.client.MediaType.TEXT_XSL;
-import com.atomgraph.client.util.DataManager;
import com.atomgraph.linkeddatahub.apps.model.AdminApplication;
import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
import com.atomgraph.linkeddatahub.client.GraphStoreClient;
@@ -60,7 +59,6 @@
import org.apache.jena.ontology.ConversionException;
import org.apache.jena.update.UpdateFactory;
import org.apache.jena.update.UpdateRequest;
-import org.apache.jena.util.FileManager;
import com.atomgraph.linkeddatahub.vocabulary.DH;
import com.atomgraph.linkeddatahub.vocabulary.FOAF;
import com.atomgraph.linkeddatahub.vocabulary.SIOC;
@@ -88,7 +86,6 @@ public class InstallPackage
private final com.atomgraph.linkeddatahub.apps.model.Application application;
private final com.atomgraph.linkeddatahub.Application system;
- private final DataManager dataManager;
private final Optional agentContext;
@Context ServletContext servletContext;
@@ -105,12 +102,10 @@ public class InstallPackage
@Inject
public InstallPackage(com.atomgraph.linkeddatahub.apps.model.Application application,
com.atomgraph.linkeddatahub.Application system,
- DataManager dataManager,
Optional agentContext)
{
this.application = application;
this.system = system;
- this.dataManager = dataManager;
this.agentContext = agentContext;
}
@@ -242,12 +237,12 @@ private com.atomgraph.linkeddatahub.apps.model.Package getPackage(String package
final Model model;
// check if we have the model in the cache first and if yes, return it from there instead making an HTTP request
- if (((FileManager)getDataManager()).hasCachedModel(packageURI) ||
- (getDataManager().isResolvingMapped() && getDataManager().isMapped(packageURI))) // read mapped URIs (such as system ontologies) from a file
+ if (getSystem().getRepository().isCached(packageURI) ||
+ (getSystem().getRepository().isMapped(packageURI))) // read mapped URIs (such as system ontologies) from a file
{
- if (log.isDebugEnabled()) log.debug("hasCachedModel({}): {}", packageURI, ((FileManager)getDataManager()).hasCachedModel(packageURI));
- if (log.isDebugEnabled()) log.debug("isMapped({}): {}", packageURI, getDataManager().isMapped(packageURI));
- model = getDataManager().loadModel(packageURI);
+ if (log.isDebugEnabled()) log.debug("hasCachedModel({}): {}", packageURI, getSystem().getRepository().isCached(packageURI));
+ if (log.isDebugEnabled()) log.debug("isMapped({}): {}", packageURI, getSystem().getRepository().isMapped(packageURI));
+ model = ModelFactory.createModelForGraph(getSystem().getRepository().get(packageURI));
}
else
{
@@ -284,12 +279,12 @@ private Model downloadOntology(String uri)
if (log.isDebugEnabled()) log.debug("Downloading ontology from: {}", uri);
// check if we have the model in the cache first and if yes, return it from there instead making an HTTP request
- if (((FileManager)getDataManager()).hasCachedModel(uri) ||
- (getDataManager().isResolvingMapped() && getDataManager().isMapped(uri))) // read mapped URIs (such as system ontologies) from a file
+ if (getSystem().getRepository().isCached(uri) ||
+ (getSystem().getRepository().isMapped(uri))) // read mapped URIs (such as system ontologies) from a file
{
- if (log.isDebugEnabled()) log.debug("hasCachedModel({}): {}", uri, ((FileManager)getDataManager()).hasCachedModel(uri));
- if (log.isDebugEnabled()) log.debug("isMapped({}): {}", uri, getDataManager().isMapped(uri));
- return getDataManager().loadModel(uri);
+ if (log.isDebugEnabled()) log.debug("hasCachedModel({}): {}", uri, getSystem().getRepository().isCached(uri));
+ if (log.isDebugEnabled()) log.debug("isMapped({}): {}", uri, getSystem().getRepository().isMapped(uri));
+ return ModelFactory.createModelForGraph(getSystem().getRepository().get(uri));
}
else
{
@@ -522,15 +517,6 @@ public ServletContext getServletContext()
return servletContext;
}
- /**
- * Returns RDF data manager.
- *
- * @return RDF data manager
- */
- public DataManager getDataManager()
- {
- return dataManager;
- }
/**
* Returns JAX-RS resource context.
diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java
index fb0cb5f3c7..28d37ca9fa 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java
@@ -16,7 +16,6 @@
*/
package com.atomgraph.linkeddatahub.resource.admin.pkg;
-import com.atomgraph.client.util.DataManager;
import com.atomgraph.linkeddatahub.apps.model.AdminApplication;
import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
import com.atomgraph.linkeddatahub.client.GraphStoreClient;
@@ -39,10 +38,10 @@
import jakarta.ws.rs.core.UriBuilder;
import org.apache.commons.codec.binary.Hex;
import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.update.UpdateFactory;
import org.apache.jena.update.UpdateRequest;
-import org.apache.jena.util.FileManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
@@ -73,7 +72,6 @@ public class UninstallPackage
private final com.atomgraph.linkeddatahub.apps.model.Application application;
private final com.atomgraph.linkeddatahub.Application system;
- private final DataManager dataManager;
private final Optional agentContext;
@Context ServletContext servletContext;
@@ -90,12 +88,10 @@ public class UninstallPackage
@Inject
public UninstallPackage(com.atomgraph.linkeddatahub.apps.model.Application application,
com.atomgraph.linkeddatahub.Application system,
- DataManager dataManager,
Optional agentContext)
{
this.application = application;
this.system = system;
- this.dataManager = dataManager;
this.agentContext = agentContext;
}
@@ -317,12 +313,12 @@ private com.atomgraph.linkeddatahub.apps.model.Package getPackage(String package
final Model model;
// check if we have the model in the cache first and if yes, return it from there instead making an HTTP request
- if (((FileManager)getDataManager()).hasCachedModel(packageURI) ||
- (getDataManager().isResolvingMapped() && getDataManager().isMapped(packageURI))) // read mapped URIs (such as system ontologies) from a file
+ if (getSystem().getRepository().isCached(packageURI) ||
+ (getSystem().getRepository().isMapped(packageURI))) // read mapped URIs (such as system ontologies) from a file
{
- if (log.isDebugEnabled()) log.debug("hasCachedModel({}): {}", packageURI, ((FileManager)getDataManager()).hasCachedModel(packageURI));
- if (log.isDebugEnabled()) log.debug("isMapped({}): {}", packageURI, getDataManager().isMapped(packageURI));
- model = getDataManager().loadModel(packageURI);
+ if (log.isDebugEnabled()) log.debug("hasCachedModel({}): {}", packageURI, getSystem().getRepository().isCached(packageURI));
+ if (log.isDebugEnabled()) log.debug("isMapped({}): {}", packageURI, getSystem().getRepository().isMapped(packageURI));
+ model = ModelFactory.createModelForGraph(getSystem().getRepository().get(packageURI));
}
else
{
@@ -350,15 +346,6 @@ public com.atomgraph.linkeddatahub.Application getSystem()
return system;
}
- /**
- * Returns RDF data manager.
- *
- * @return RDF data manager
- */
- public DataManager getDataManager()
- {
- return dataManager;
- }
/**
* Returns JAX-RS resource context.
diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/event/AuthorizationCreated.java b/src/main/java/com/atomgraph/linkeddatahub/server/event/AuthorizationCreated.java
index 7353e02978..3b02124d24 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/server/event/AuthorizationCreated.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/server/event/AuthorizationCreated.java
@@ -16,7 +16,6 @@
*/
package com.atomgraph.linkeddatahub.server.event;
-import com.atomgraph.core.util.jena.DataManager;
import com.atomgraph.linkeddatahub.apps.model.Application;
import com.atomgraph.linkeddatahub.client.GraphStoreClient;
import org.apache.jena.rdf.model.Resource;
diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/factory/OntologyFactory.java b/src/main/java/com/atomgraph/linkeddatahub/server/factory/OntologyFactory.java
index 39fe494b6f..8fc56c6a24 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/server/factory/OntologyFactory.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/server/factory/OntologyFactory.java
@@ -20,7 +20,7 @@
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.ext.Provider;
-import org.apache.jena.ontology.Ontology;
+import org.apache.jena.ontapi.model.OntModel;
import org.apache.jena.vocabulary.OWL;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.api.ServiceLocator;
@@ -31,19 +31,19 @@
* @author Martynas Jusevičius {@literal }
*/
@Provider
-public class OntologyFactory implements Factory>
+public class OntologyFactory implements Factory>
{
@Context private ServiceLocator serviceLocator;
@Override
- public Optional provide()
+ public Optional provide()
{
return getOntology();
}
@Override
- public void dispose(Optional t)
+ public void dispose(Optional t)
{
}
@@ -52,9 +52,9 @@ public void dispose(Optional t)
*
* @return ontology
*/
- public Optional getOntology()
+ public Optional getOntology()
{
- return (Optional)getContainerRequestContext().getProperty(OWL.Ontology.getURI());
+ return (Optional)getContainerRequestContext().getProperty(OWL.Ontology.getURI());
}
/**
diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
index 03ef836621..a09b31bd07 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
@@ -18,26 +18,25 @@
import com.atomgraph.linkeddatahub.apps.model.Application;
import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
+import com.atomgraph.core.util.jena.PrefixGraphRepository;
import com.atomgraph.linkeddatahub.vocabulary.LAPP;
import com.atomgraph.server.exception.OntologyException;
-import com.atomgraph.linkeddatahub.server.util.OntologyModelGetter;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.HashSet;
import java.util.Optional;
+import java.util.Set;
import jakarta.annotation.Priority;
import jakarta.inject.Inject;
-import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.container.PreMatching;
-import org.apache.jena.ontology.OntDocumentManager;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
-import org.apache.jena.ontology.Ontology;
-import org.apache.jena.rdf.model.Model;
-import org.apache.jena.rdf.model.ModelFactory;
-import org.apache.jena.util.FileManager;
+import org.apache.jena.graph.Graph;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntID;
+import org.apache.jena.ontapi.model.OntModel;
import org.apache.jena.vocabulary.OWL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -100,7 +99,7 @@ public void filter(ContainerRequestContext crc) throws IOException
* @param crc request context
* @return optional ontology
*/
- public Optional getOntology(ContainerRequestContext crc)
+ public Optional getOntology(ContainerRequestContext crc)
{
Optional appOpt = getApplication(crc);
@@ -115,99 +114,86 @@ public Optional getOntology(ContainerRequestContext crc)
return Optional.empty();
}
}
-
+
/**
* Gets ontology of the specified application.
- *
+ *
* @param app application resource
- * @return ontology resource
+ * @return ontology model
*/
- public Ontology getOntology(Application app)
+ public OntModel getOntology(Application app)
{
if (app.getOntology() == null) return null;
return getOntology(app, app.getOntology().getURI());
}
-
+
/**
- * Loads ontology using the specified ontology URI.
- *
+ * Loads the ontology model for the specified ontology URI, building its owl:imports closure with
+ * RDFS inference and materializing the inferences into the repository cache.
+ *
* @param app application resource
* @param uri ontology URI
- * @return ontology resource
+ * @return ontology model
*/
- public Ontology getOntology(Application app, String uri)
+ public OntModel getOntology(Application app, String uri)
{
- if (app == null) throw new IllegalArgumentException("Application string cannot be null");
- if (uri == null) throw new IllegalArgumentException("Ontology URI string cannot be null");
+ if (app == null) throw new IllegalArgumentException("Application cannot be null");
+ if (uri == null) throw new IllegalArgumentException("Ontology URI cannot be null");
- final OntModelSpec ontModelSpec;
- if (app.canAs(EndUserApplication.class))
+ final PrefixGraphRepository repository = app.canAs(EndUserApplication.class) ?
+ getSystem().getRepository(app.as(EndUserApplication.class)) : getSystem().getRepository();
+
+ // only build the inferred model if the ontology is not already cached
+ if (!repository.isCached(uri))
{
- ontModelSpec = new OntModelSpec(getSystem().getOntModelSpec(app.as(EndUserApplication.class)));
- // only create InfModel if ontology is not already cached
- if (!ontModelSpec.getDocumentManager().getFileManager().hasCachedModel(uri))
- {
- OntologyModelGetter modelGetter = new OntologyModelGetter(app.as(EndUserApplication.class), getSystem(), ontModelSpec, getSystem().getOntologyQuery());
- ontModelSpec.setImportModelGetter(modelGetter);
- if (log.isDebugEnabled()) log.debug("Started loading ontology with URI '{}' from the admin dataset", uri);
- Model baseModel = modelGetter.getModel(uri);
- OntModel ontModel = ModelFactory.createOntologyModel(ontModelSpec, baseModel);
- // materialize OntModel inferences to avoid invoking rules engine on every request
- OntModel materializedModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); // no inference
- materializedModel.add(ontModel);
- ontModel.getDocumentManager().addModel(uri, materializedModel, true); // make immutable and add as OntModel so that imports do not need to be reloaded during retrieval
- // make sure to cache imported models not only by ontology URI but also by document URI
- ontModel.listImportedOntologyURIs(true).forEach((String importURI) -> addDocumentModel(ontModel.getDocumentManager(), importURI));
- if (log.isDebugEnabled()) log.debug("Finished loading ontology with URI '{}' from the admin dataset", uri);
- }
+ if (log.isDebugEnabled()) log.debug("Started loading ontology with URI '{}'", uri);
+ Graph baseGraph = repository.get(uri); // end-user: SPARQL-first; otherwise bundled mapping / HTTP
+ OntModel inferred = OntModelFactory.createModel(baseGraph, OntSpecification.OWL2_DL_MEM_RDFS_INF, repository);
+ // materialize inferences to avoid invoking the rules engine on every request
+ OntModel materialized = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ materialized.add(inferred);
+ repository.put(uri, materialized.getGraph());
+ // cache imported graphs under their (fragment-stripped) document URIs too
+ importClosure(inferred, new HashSet<>()).forEach(importURI -> addDocumentModel(repository, importURI));
+ if (log.isDebugEnabled()) log.debug("Finished loading ontology with URI '{}'", uri);
}
- else
+
+ return OntModelFactory.createModel(repository.get(uri), OntSpecification.OWL2_DL_MEM, repository);
+ }
+
+ /**
+ * Collects the transitive owl:imports closure URIs of the given ontology model.
+ *
+ * @param model ontology model
+ * @param seen accumulator of already-visited import URIs
+ * @return the import closure URIs
+ */
+ public static Set importClosure(OntModel model, Set seen)
+ {
+ model.imports().forEach(imp -> imp.id().map(OntID::getURI).ifPresent(importURI ->
{
- ontModelSpec = new OntModelSpec(getSystem().getOntModelSpec());
- FileManager fileManager = ontModelSpec.getDocumentManager().getFileManager();
- if (!fileManager.hasCachedModel(uri))
- {
- try
- {
- URI ontologyURI = URI.create(uri);
- // remove fragment and normalize
- URI ontDocURI = new URI(ontologyURI.getScheme(), ontologyURI.getSchemeSpecificPart(), null).normalize();
- Model baseModel = fileManager.loadModel(ontDocURI.toString());
- OntModel ontModel = ModelFactory.createOntologyModel(ontModelSpec, baseModel);
- ontModel.getDocumentManager().addModel(uri, ontModel, true);
- }
- catch (URISyntaxException ex)
- {
- if (log.isErrorEnabled()) log.error("Ontology URI syntax error: {}", ex.getInput());
- throw new InternalServerErrorException(ex);
- }
- }
- }
- return ontModelSpec.getDocumentManager().getOntology(uri, ontModelSpec).getOntology(uri); // reloads the imports using ModelGetter. TO-DO: optimize?
+ if (seen.add(importURI)) importClosure(imp, seen);
+ }));
+ return seen;
}
/**
- * Extracts document URI from ontology import URI and uses it as a secondary cache key.
- *
- * @param odm document manager
+ * Caches an imported graph under its fragment-stripped document URI as a secondary cache key.
+ *
+ * @param repository graph repository
* @param importURI ontology URI
*/
- public static void addDocumentModel(OntDocumentManager odm, String importURI)
+ public static void addDocumentModel(PrefixGraphRepository repository, String importURI)
{
try
{
URI ontologyURI = URI.create(importURI);
// remove fragment and normalize
URI docURI = new URI(ontologyURI.getScheme(), ontologyURI.getSchemeSpecificPart(), null).normalize();
- String mappedURI = odm.getFileManager().mapURI(docURI.toString());
- // only cache import document URI if it's not already cached or mapped
- if (!odm.getFileManager().hasCachedModel(docURI.toString()) && mappedURI.equals(docURI.toString()))
- {
- Model importModel = odm.getModel(importURI);
- if (importModel == null) throw new IllegalArgumentException("Import model is not cached");
- odm.addModel(docURI.toString(), importModel, true);
- }
+ // only cache the document URI if it is not already cached or mapped to a different location
+ if (!repository.isCached(docURI.toString()) && repository.resolve(docURI.toString()).equals(docURI.toString()))
+ repository.put(docURI.toString(), repository.get(importURI));
}
catch (URISyntaxException ex)
{
diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/ProxyRequestFilter.java b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/ProxyRequestFilter.java
index 4eeb6599e6..9166b28ea9 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/ProxyRequestFilter.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/ProxyRequestFilter.java
@@ -22,7 +22,7 @@
import com.atomgraph.core.exception.BadGatewayException;
import com.atomgraph.core.util.ModelUtils;
import com.atomgraph.linkeddatahub.apps.model.Dataset;
-import org.apache.jena.ontology.Ontology;
+import org.apache.jena.ontapi.model.OntModel;
import com.atomgraph.linkeddatahub.client.GraphStoreClient;
import com.atomgraph.linkeddatahub.client.filter.auth.IDTokenDelegationFilter;
import com.atomgraph.linkeddatahub.client.filter.auth.WebIDDelegationFilter;
@@ -133,7 +133,7 @@ public class ProxyRequestFilter implements ContainerRequestFilter
"Age");
@Inject com.atomgraph.linkeddatahub.Application system;
- @Inject jakarta.inject.Provider> ontology;
+ @Inject jakarta.inject.Provider> ontology;
@Inject MediaTypes mediaTypes;
@Context Request request;
@@ -178,10 +178,10 @@ public void filter(ContainerRequestContext requestContext) throws IOException
|| "HEAD".equalsIgnoreCase(requestContext.getMethod());
// serve mapped URIs (e.g. system ontologies) directly from the DataManager cache
- if (isSafeMethod && getSystem().getDataManager().isMapped(targetURI.toString()))
+ if (isSafeMethod && getSystem().getRepository().isMapped(targetURI.toString()))
{
if (log.isDebugEnabled()) log.debug("Serving mapped URI from DataManager cache: {}", targetURI);
- Model model = getSystem().getDataManager().loadModel(targetURI.toString());
+ Model model = org.apache.jena.rdf.model.ModelFactory.createModelForGraph(getSystem().getRepository().get(targetURI.toString()));
requestContext.abortWith(getResponse(model, Response.Status.OK));
return;
}
@@ -195,7 +195,7 @@ public void filter(ContainerRequestContext requestContext) throws IOException
ParameterizedSparqlString pss = new ParameterizedSparqlString(
"DESCRIBE ?doc ?term WHERE { ?term ?p ?o FILTER(STRSTARTS(STR(?term), CONCAT(STR(?doc), \"#\"))) }");
pss.setIri("doc", targetURI.toString());
- try (QueryExecution qe = QueryExecution.create(pss.asQuery(), getOntology().get().getOntModel()))
+ try (QueryExecution qe = QueryExecution.create(pss.asQuery(), getOntology().get()))
{
Model description = qe.execDescribe();
if (!description.isEmpty())
@@ -486,7 +486,7 @@ public com.atomgraph.linkeddatahub.Application getSystem()
*
* @return optional ontology
*/
- public Optional getOntology()
+ public Optional getOntology()
{
return ontology.get();
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/io/ValidatingModelProvider.java b/src/main/java/com/atomgraph/linkeddatahub/server/io/ValidatingModelProvider.java
index 206228401f..018bca6c29 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/server/io/ValidatingModelProvider.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/server/io/ValidatingModelProvider.java
@@ -240,7 +240,7 @@ public Resource processRead(Resource resource) // this logic really belongs in a
if (getApplication().isPresent() && getApplication().get().canAs(AdminApplication.class) && resource.hasProperty(RDF.type, OWL.Ontology))
{
// clear cached OntModel if ontology is updated. TO-DO: send event instead
- getSystem().getOntModelSpec().getDocumentManager().getFileManager().removeCacheModel(resource.getURI());
+ getSystem().getRepository().remove(resource.getURI());
}
if (getApplication().isPresent() && resource.hasProperty(RDF.type, ACL.Authorization))
diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/DocumentHierarchyGraphStoreImpl.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/DocumentHierarchyGraphStoreImpl.java
index 0b8b65674f..e8f1bcf8d0 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/DocumentHierarchyGraphStoreImpl.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/DocumentHierarchyGraphStoreImpl.java
@@ -89,7 +89,7 @@
import org.apache.commons.lang3.StringUtils;
import org.apache.jena.atlas.RuntimeIOException;
import org.apache.jena.datatypes.xsd.XSDDateTime;
-import org.apache.jena.ontology.Ontology;
+import org.apache.jena.ontapi.model.OntModel;
import org.apache.jena.query.Dataset;
import org.apache.jena.query.DatasetFactory;
import org.apache.jena.rdf.model.Model;
@@ -132,7 +132,7 @@ public class DocumentHierarchyGraphStoreImpl extends com.atomgraph.core.model.im
public static final String UPLOADS_PATH = "uploads";
private final com.atomgraph.linkeddatahub.apps.model.Application application;
- private final Ontology ontology;
+ private final OntModel ontology;
private final Service service;
private final Providers providers;
private final com.atomgraph.linkeddatahub.Application system;
@@ -160,7 +160,7 @@ public class DocumentHierarchyGraphStoreImpl extends com.atomgraph.core.model.im
*/
@Inject
public DocumentHierarchyGraphStoreImpl(@Context Request request, @Context UriInfo uriInfo, MediaTypes mediaTypes,
- com.atomgraph.linkeddatahub.apps.model.Application application, Optional ontology, Optional service,
+ com.atomgraph.linkeddatahub.apps.model.Application application, Optional ontology, Optional service,
@Context SecurityContext securityContext, Optional agentContext,
@Context Providers providers, com.atomgraph.linkeddatahub.Application system)
{
@@ -1030,7 +1030,7 @@ public com.atomgraph.linkeddatahub.apps.model.Application getApplication()
*
* @return ontology resource
*/
- public Ontology getOntology()
+ public OntModel getOntology()
{
return ontology;
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/util/OntologyModelGetter.java b/src/main/java/com/atomgraph/linkeddatahub/server/util/OntologyRepository.java
similarity index 64%
rename from src/main/java/com/atomgraph/linkeddatahub/server/util/OntologyModelGetter.java
rename to src/main/java/com/atomgraph/linkeddatahub/server/util/OntologyRepository.java
index 63c8d659d7..2d6044a8e6 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/server/util/OntologyModelGetter.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/server/util/OntologyRepository.java
@@ -17,56 +17,57 @@
package com.atomgraph.linkeddatahub.server.util;
import com.atomgraph.client.vocabulary.LDT;
+import com.atomgraph.core.client.GraphStoreClient;
+import com.atomgraph.core.util.jena.PrefixGraphRepository;
import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
-import com.atomgraph.server.exception.OntologyException;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
-import org.apache.jena.ontology.OntModelSpec;
+import org.apache.jena.graph.Graph;
import org.apache.jena.query.ParameterizedSparqlString;
import org.apache.jena.query.Query;
import org.apache.jena.rdf.model.Model;
-import org.apache.jena.rdf.model.ModelFactory;
-import org.apache.jena.rdf.model.ModelReader;
-import org.apache.jena.util.FileManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
/**
- * Application's ontology model getter.
- * Loads ontology model using the configured ontology query
+ * Ontology graph repository that resolves graphs SPARQL-first: it runs the configured ontology query
+ * against the admin endpoint and, only if that returns nothing, falls back to the bundled mappings /
+ * HTTP loading of the superclass. Replaces the legacy {@code ModelGetter} plugged into {@code OntModelSpec}.
+ *
+ * @author Martynas Jusevičius {@literal }
*/
-public class OntologyModelGetter implements org.apache.jena.ontology.models.ModelGetter
+public class OntologyRepository extends PrefixGraphRepository
{
- private static final Logger log = LoggerFactory.getLogger(OntologyModelGetter.class);
+ private static final Logger log = LoggerFactory.getLogger(OntologyRepository.class);
private final EndUserApplication app;
private final com.atomgraph.linkeddatahub.Application system;
- private final OntModelSpec ontModelSpec;
private final Query ontologyQuery;
/**
- * Constructs ontology getter for application.
+ * Constructs the repository for an application.
*
* @param app end-user application resource
* @param system system application
- * @param ontModelSpec ontology specification
+ * @param gsc Graph Store client for HTTP fallback loading
* @param ontologyQuery SPARQL query that loads ontology terms
*/
- public OntologyModelGetter(EndUserApplication app, com.atomgraph.linkeddatahub.Application system, OntModelSpec ontModelSpec, Query ontologyQuery)
+ public OntologyRepository(EndUserApplication app, com.atomgraph.linkeddatahub.Application system, GraphStoreClient gsc, Query ontologyQuery)
{
+ super(gsc);
this.app = app;
this.system = system;
- this.ontModelSpec = ontModelSpec;
this.ontologyQuery = ontologyQuery;
}
@Override
- public Model getModel(String uri)
+ public Graph get(String uri)
{
- // attempt to load ontology model from the admin endpoint. TO-DO: is that necessary if ontologies terms are now stored in a single graph?
+ if (isCached(uri)) return super.get(uri);
+
+ // attempt to load the ontology from the admin endpoint
ParameterizedSparqlString ontologyPss = new ParameterizedSparqlString(getOntologyQuery().toString());
ontologyPss.setIri(LDT.ontology.getLocalName(), uri);
@@ -82,24 +83,15 @@ public Model getModel(String uri)
model = cr.readEntity(Model.class);
}
- if (!model.isEmpty()) return model;
-
- // if SPARQL result model is empty, fallback to using FileManager
- FileManager fileManager = getOntModelSpec().getDocumentManager().getFileManager();
- return fileManager.loadModel(uri);
- }
-
- @Override
- public Model getModel(String uri, ModelReader loadIfAbsent)
- {
- try
- {
- return getModel(uri);
- }
- catch (OntologyException ex)
+ if (!model.isEmpty())
{
- return loadIfAbsent.readModel(ModelFactory.createDefaultModel(), uri);
+ Graph graph = model.getGraph();
+ put(uri, graph);
+ return graph;
}
+
+ // if the SPARQL result is empty, fall back to bundled mappings / HTTP loading
+ return super.get(uri);
}
/**
@@ -122,24 +114,14 @@ public com.atomgraph.linkeddatahub.Application getSystem()
return system;
}
- /**
- * Returns ontology specification.
- *
- * @return ontology specification
- */
- public OntModelSpec getOntModelSpec()
- {
- return ontModelSpec;
- }
-
/**
* Returns the SPARQL query used to load ontology terms.
- *
+ *
* @return SPARQL query
*/
public Query getOntologyQuery()
{
return ontologyQuery;
}
-
-}
\ No newline at end of file
+
+}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/writer/ModelXSLTWriter.java b/src/main/java/com/atomgraph/linkeddatahub/writer/ModelXSLTWriter.java
index bdf1ebb5c1..eb7b2daaf8 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/writer/ModelXSLTWriter.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/writer/ModelXSLTWriter.java
@@ -15,7 +15,7 @@
*/
package com.atomgraph.linkeddatahub.writer;
-import com.atomgraph.client.util.DataManager;
+import com.atomgraph.client.util.RDFSourceResolver;
import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
import com.atomgraph.linkeddatahub.model.auth.Agent;
import com.atomgraph.linkeddatahub.server.io.ValidatingModelProvider;
@@ -41,7 +41,6 @@
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XsltExecutable;
import org.apache.http.HttpHeaders;
-import org.apache.jena.ontology.OntModelSpec;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.riot.RDFFormat;
import org.apache.jena.riot.RDFWriter;
@@ -70,9 +69,9 @@ public class ModelXSLTWriter extends XSLTWriterBase implements MessageBodyWriter
* @param dataManager RDF data manager
* @param messageDigest message digest
*/
- public ModelXSLTWriter(XsltExecutable xsltExec, OntModelSpec ontModelSpec, DataManager dataManager, MessageDigest messageDigest)
+ public ModelXSLTWriter(XsltExecutable xsltExec, RDFSourceResolver resolver, MessageDigest messageDigest)
{
- super(xsltExec, ontModelSpec, dataManager, messageDigest);
+ super(xsltExec, resolver, messageDigest);
}
@Override
diff --git a/src/main/java/com/atomgraph/linkeddatahub/writer/ResultSetXSLTWriter.java b/src/main/java/com/atomgraph/linkeddatahub/writer/ResultSetXSLTWriter.java
index fd7b24cfe0..df0d42d64b 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/writer/ResultSetXSLTWriter.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/writer/ResultSetXSLTWriter.java
@@ -15,7 +15,7 @@
*/
package com.atomgraph.linkeddatahub.writer;
-import com.atomgraph.client.util.DataManager;
+import com.atomgraph.client.util.RDFSourceResolver;
import com.atomgraph.linkeddatahub.model.auth.Agent;
import jakarta.inject.Singleton;
import jakarta.ws.rs.Produces;
@@ -38,7 +38,6 @@
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XsltExecutable;
import org.apache.http.HttpHeaders;
-import org.apache.jena.ontology.OntModelSpec;
import org.apache.jena.query.ResultSetFormatter;
import org.apache.jena.query.ResultSetRewindable;
import org.slf4j.Logger;
@@ -65,9 +64,9 @@ public class ResultSetXSLTWriter extends XSLTWriterBase implements MessageBodyWr
* @param dataManager RDF data manager
* @param messageDigest message digest
*/
- public ResultSetXSLTWriter(XsltExecutable xsltExec, OntModelSpec ontModelSpec, DataManager dataManager, MessageDigest messageDigest)
+ public ResultSetXSLTWriter(XsltExecutable xsltExec, RDFSourceResolver resolver, MessageDigest messageDigest)
{
- super(xsltExec, ontModelSpec, dataManager, messageDigest);
+ super(xsltExec, resolver, messageDigest);
}
@Override
diff --git a/src/main/java/com/atomgraph/linkeddatahub/writer/XSLTWriterBase.java b/src/main/java/com/atomgraph/linkeddatahub/writer/XSLTWriterBase.java
index 50fc80af8f..31eb596c4b 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/writer/XSLTWriterBase.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/writer/XSLTWriterBase.java
@@ -15,7 +15,7 @@
*/
package com.atomgraph.linkeddatahub.writer;
-import com.atomgraph.client.util.DataManager;
+import com.atomgraph.client.util.RDFSourceResolver;
import com.atomgraph.client.vocabulary.AC;
import com.atomgraph.linkeddatahub.writer.factory.xslt.XsltExecutableSupplier;
import com.atomgraph.linkeddatahub.model.auth.Agent;
@@ -58,8 +58,7 @@
import net.sf.saxon.s9api.XdmValue;
import net.sf.saxon.s9api.XsltExecutable;
import org.apache.http.HttpHeaders;
-import org.apache.jena.ontology.ObjectProperty;
-import org.apache.jena.ontology.OntModelSpec;
+import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.riot.RDFLanguages;
import org.slf4j.Logger;
@@ -88,7 +87,7 @@ public abstract class XSLTWriterBase extends com.atomgraph.client.writer.XSLTWri
@Inject com.atomgraph.linkeddatahub.Application system;
@Inject jakarta.inject.Provider> application;
- @Inject jakarta.inject.Provider dataManager;
+ @Inject jakarta.inject.Provider resolver;
@Inject jakarta.inject.Provider xsltExecSupplier;
@Inject jakarta.inject.Provider crc;
@Inject jakarta.inject.Provider> authorizationContext;
@@ -97,15 +96,14 @@ public abstract class XSLTWriterBase extends com.atomgraph.client.writer.XSLTWri
/**
* Constructs XSLT writer.
- *
+ *
* @param xsltExec compiled XSLT stylesheet
- * @param ontModelSpec ontology specification
- * @param dataManager RDF data manager
+ * @param resolver XSLT source resolver
* @param messageDigest message digest
*/
- public XSLTWriterBase(XsltExecutable xsltExec, OntModelSpec ontModelSpec, DataManager dataManager, MessageDigest messageDigest)
+ public XSLTWriterBase(XsltExecutable xsltExec, RDFSourceResolver resolver, MessageDigest messageDigest)
{
- super(xsltExec, ontModelSpec, dataManager); // this DataManager will be unused as we override getDataManager() with the injected (subclassed) one
+ super(xsltExec, resolver); // this resolver is unused as we override getResolver() with the injected (request-scoped) one
this.messageDigest = messageDigest;
}
@@ -189,7 +187,7 @@ public Map getParameters(MultivaluedMap headerMap, ObjectProperty property)
+ public URI getLinkURI(MultivaluedMap headerMap, Property property)
{
if (headerMap.get(jakarta.ws.rs.core.HttpHeaders.LINK) == null) return null;
@@ -257,36 +255,30 @@ public com.atomgraph.linkeddatahub.Application getSystem()
return system;
}
- @Override
- public OntModelSpec getOntModelSpec()
- {
- return getSystem().getOntModelSpec();
- }
-
/**
* Returns JAX-RS security context.
- *
+ *
* @return security context
*/
public SecurityContext getSecurityContext()
{
return securityContext;
}
-
+
@Override
- public DataManager getDataManager()
+ public RDFSourceResolver getResolver()
{
- return getDataManagerProvider().get();
+ return getResolverProvider().get();
}
/**
- * Returns a JAX-RS provider for the RDF data manager.
+ * Returns a JAX-RS provider for the request-scoped source resolver.
*
* @return provider
*/
- public jakarta.inject.Provider getDataManagerProvider()
+ public jakarta.inject.Provider getResolverProvider()
{
- return dataManager;
+ return resolver;
}
@Override
diff --git a/src/main/java/com/atomgraph/linkeddatahub/writer/factory/DataManagerFactory.java b/src/main/java/com/atomgraph/linkeddatahub/writer/factory/SourceResolverFactory.java
similarity index 70%
rename from src/main/java/com/atomgraph/linkeddatahub/writer/factory/DataManagerFactory.java
rename to src/main/java/com/atomgraph/linkeddatahub/writer/factory/SourceResolverFactory.java
index a9774fd63a..a405a7ca23 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/writer/factory/DataManagerFactory.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/writer/factory/SourceResolverFactory.java
@@ -16,18 +16,16 @@
*/
package com.atomgraph.linkeddatahub.writer.factory;
-import org.apache.jena.util.LocationMapper;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.ext.Provider;
-import com.atomgraph.client.util.DataManager;
+import com.atomgraph.client.util.RDFSourceResolver;
+import com.atomgraph.core.util.jena.PrefixGraphRepository;
import com.atomgraph.linkeddatahub.apps.model.Application;
import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
import com.atomgraph.linkeddatahub.client.GraphStoreClient;
import com.atomgraph.linkeddatahub.server.security.AgentContext;
import com.atomgraph.linkeddatahub.vocabulary.LAPP;
-import com.atomgraph.linkeddatahub.writer.impl.DataManagerImpl;
-import java.net.URI;
-import java.util.HashMap;
+import com.atomgraph.linkeddatahub.writer.impl.SameSiteSourceResolver;
import java.util.Optional;
import jakarta.inject.Inject;
import jakarta.servlet.http.HttpServletRequest;
@@ -40,15 +38,15 @@
import org.slf4j.LoggerFactory;
/**
- * JAX-RS provider for DataManager.
- *
+ * JAX-RS provider for the request-scoped XSLT source resolver.
+ *
* @author Martynas Jusevičius {@literal }
- * @see com.atomgraph.client.util.DataManager
+ * @see com.atomgraph.client.util.RDFSourceResolver
*/
@Provider
-public class DataManagerFactory implements Factory
+public class SourceResolverFactory implements Factory
{
- private static final Logger log = LoggerFactory.getLogger(DataManagerFactory.class);
+ private static final Logger log = LoggerFactory.getLogger(SourceResolverFactory.class);
@Context UriInfo uriInfo;
@Context HttpServletRequest httpServletRequest;
@@ -58,40 +56,37 @@ public class DataManagerFactory implements Factory
@Inject com.atomgraph.linkeddatahub.Application system;
@Override
- public DataManager provide()
+ public RDFSourceResolver provide()
{
- // Always return DataManager, falling back to system DataManager if no Application (e.g., for error responses)
- return getDataManager(getApplication());
+ // falls back to the global repository if there is no application (e.g. for error responses)
+ return getResolver(getApplication());
}
@Override
- public void dispose(DataManager t)
+ public void dispose(RDFSourceResolver t)
{
}
/**
- * Returns RDF data manager.
+ * Returns the request-scoped source resolver, backed by the application's ontology repository
+ * (or the global repository) and a delegating Graph Store client.
*
- * @param appOpt optional end-user application (if empty, system DataManager is used)
- * @return data manager
+ * @param appOpt optional end-user application (if empty, the global repository is used)
+ * @return source resolver
*/
- public DataManager getDataManager(Optional appOpt)
+ public RDFSourceResolver getResolver(Optional appOpt)
{
- final com.atomgraph.core.util.jena.DataManager baseManager;
+ final PrefixGraphRepository repository;
if (appOpt.isPresent() && appOpt.get().canAs(EndUserApplication.class))
- baseManager = (com.atomgraph.core.util.jena.DataManager)getSystem().getOntModelSpec(appOpt.get().as(EndUserApplication.class)).getDocumentManager().getFileManager();
+ repository = getSystem().getRepository(appOpt.get().as(EndUserApplication.class));
else
- baseManager = getSystem().getDataManager();
+ repository = getSystem().getRepository();
GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()).
delegation(getUriInfo().getBaseUri(), getAgentContext());
- // copy cached models over from the app's FileManager
- return new DataManagerImpl(LocationMapper.get(), new HashMap<>(baseManager.getModelCache()),
- gsc, true, getSystem().isPreemptiveAuth(), getSystem().isResolvingUncached(),
- getSystem().getBaseURI(),
- getAgentContext());
+ return new SameSiteSourceResolver(repository, gsc, getSystem().isResolvingUncached(), getSystem().getBaseURI());
}
/**
diff --git a/src/main/java/com/atomgraph/linkeddatahub/writer/impl/DataManagerImpl.java b/src/main/java/com/atomgraph/linkeddatahub/writer/impl/SameSiteSourceResolver.java
similarity index 59%
rename from src/main/java/com/atomgraph/linkeddatahub/writer/impl/DataManagerImpl.java
rename to src/main/java/com/atomgraph/linkeddatahub/writer/impl/SameSiteSourceResolver.java
index b62cfefad9..3449bd2b3e 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/writer/impl/DataManagerImpl.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/writer/impl/SameSiteSourceResolver.java
@@ -16,67 +16,57 @@
*/
package com.atomgraph.linkeddatahub.writer.impl;
-import org.apache.jena.util.LocationMapper;
-import java.net.URI;
+import com.atomgraph.client.util.RDFSourceResolver;
import com.atomgraph.core.client.GraphStoreClient;
-import com.atomgraph.linkeddatahub.server.security.AgentContext;
+import com.atomgraph.core.util.jena.PrefixGraphRepository;
import com.google.common.net.InternetDomainName;
-import java.util.Map;
-import org.apache.jena.rdf.model.Model;
+import java.net.URI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Manager for remote RDF dataset access.
- * Documents can be mapped to local copies.
- *
+ * XSLT source resolver that restricts dereferencing of uncached URIs to the same site as the
+ * application. Mapped (bundled) and same-site URIs resolve; arbitrary external URIs do not.
+ * Backed by a {@link PrefixGraphRepository}; authenticated delegation is handled by the supplied
+ * {@link GraphStoreClient}.
+ *
* @author Martynas Jusevičius {@literal }
*/
-public class DataManagerImpl extends com.atomgraph.client.util.DataManagerImpl
+public class SameSiteSourceResolver extends RDFSourceResolver
{
- private static final Logger log = LoggerFactory.getLogger(DataManagerImpl.class);
-
+ private static final Logger log = LoggerFactory.getLogger(SameSiteSourceResolver.class);
+
private final URI rootContextURI;
- private final AgentContext agentContext;
/**
- * Constructs RDF data manager.
- *
- * @param mapper location mapper
- * @param modelCache model cache
- * @param gsc Graph Store client
- * @param cacheModelLoads true if loaded RDF models are cached
- * @param preemptiveAuth true if HTTP basic auth is sent preemptively
+ * Constructs the resolver.
+ *
+ * @param repository graph repository (bundled/cached graphs + URI→location mapping)
+ * @param gsc Graph Store client (with delegation)
* @param resolvingUncached true if uncached URLs are resolved
* @param rootContextURI the root URI of the JAX-RS application
- * @param agentContext agent context
*/
- public DataManagerImpl(LocationMapper mapper, Map modelCache,
- GraphStoreClient gsc,
- boolean cacheModelLoads, boolean preemptiveAuth, boolean resolvingUncached,
- URI rootContextURI,
- AgentContext agentContext)
+ public SameSiteSourceResolver(PrefixGraphRepository repository, GraphStoreClient gsc, boolean resolvingUncached, URI rootContextURI)
{
- super(mapper, modelCache, gsc, cacheModelLoads, preemptiveAuth, resolvingUncached);
+ super(repository, gsc, resolvingUncached);
this.rootContextURI = rootContextURI;
- this.agentContext = agentContext;
}
-
+
@Override
- public boolean resolvingUncached(String filenameOrURI)
+ protected boolean resolvingUncached(String filenameOrURI)
{
- if (super.resolvingUncached(filenameOrURI) && !isMapped(filenameOrURI))
+ if (super.resolvingUncached(filenameOrURI) && !getRepository().isMapped(filenameOrURI))
{
// Allow resolving URIs from the same site (e.g., localhost:4443/static/..., admin.localhost:4443/ns)
return isSameSite(getRootContextURI(), URI.create(filenameOrURI));
}
- return false; // super.resolvingUncached(filenameOrURI); // configured in web.xml
+ return false;
}
/**
* Checks if two URIs are from the same site (schemeful same-site).
- * This allows subdomains like admin.localhost and localhost to be considered part of the same LinkedDataHub instance.
+ * Allows subdomains like admin.localhost and localhost to be considered part of the same instance.
* Ports are ignored per the same-site definition.
*
* @param uri1 first URI
@@ -99,12 +89,9 @@ private boolean isSameSite(URI uri1, URI uri2)
InternetDomainName domain1 = InternetDomainName.from(host1);
InternetDomainName domain2 = InternetDomainName.from(host2);
- // For localhost domains, compare the full host (localhost == localhost, admin.localhost != localhost at domain level)
- // But we want to treat them as same root domain, so just check if both end with "localhost"
if (host1.equals("localhost") || host1.endsWith(".localhost"))
return host2.equals("localhost") || host2.endsWith(".localhost");
- // For regular domains, compare top private domains
if (domain1.isTopPrivateDomain() && domain2.isTopPrivateDomain())
return domain1.equals(domain2);
if (domain1.hasPublicSuffix() && domain2.hasPublicSuffix())
@@ -114,7 +101,6 @@ private boolean isSameSite(URI uri1, URI uri2)
}
catch (IllegalArgumentException ex)
{
- // Invalid domain name, fall back to simple equality check
if (log.isDebugEnabled()) log.debug("Could not parse domain names for comparison: {} and {}", host1, host2);
return false;
}
@@ -122,7 +108,7 @@ private boolean isSameSite(URI uri1, URI uri2)
/**
* Returns the root URI of the JAX-RS application.
- *
+ *
* @return root URI
*/
public URI getRootContextURI()
@@ -130,14 +116,4 @@ public URI getRootContextURI()
return rootContextURI;
}
- /**
- * Returns the agent context.
- *
- * @return agent context or null
- */
- public AgentContext getAgentContext()
- {
- return agentContext;
- }
-
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/atomgraph/server/io/ValidatingDatasetProvider.java b/src/main/java/com/atomgraph/server/io/ValidatingDatasetProvider.java
index 500fb2e5af..341e7c7eb3 100644
--- a/src/main/java/com/atomgraph/server/io/ValidatingDatasetProvider.java
+++ b/src/main/java/com/atomgraph/server/io/ValidatingDatasetProvider.java
@@ -30,7 +30,7 @@
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.ext.Providers;
-import org.apache.jena.ontology.Ontology;
+import org.apache.jena.ontapi.model.OntModel;
import org.apache.jena.query.Dataset;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,7 +52,7 @@ public class ValidatingDatasetProvider extends DatasetProvider
@Context private Providers providers;
- @Inject jakarta.inject.Provider> ontology;
+ @Inject jakarta.inject.Provider> ontology;
@Override
public Dataset readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream) throws IOException
@@ -70,7 +70,7 @@ public Dataset validate(Dataset dataset)
if (getOntology().isPresent())
{
// SPIN validation
- Validator validator = new Validator(getOntology().get().getOntModel());
+ Validator validator = new Validator(getOntology().get());
List cvs = validator.validate(dataset.getDefaultModel());
if (!cvs.isEmpty())
{
@@ -79,7 +79,7 @@ public Dataset validate(Dataset dataset)
}
// SHACL validation
- Shapes shapes = Shapes.parse(getOntology().get().getOntModel().getGraph());
+ Shapes shapes = Shapes.parse(getOntology().get().getGraph());
ValidationReport report = ShaclValidator.get().validate(shapes, dataset.getDefaultModel().getGraph());
if (!report.conforms())
{
@@ -113,7 +113,7 @@ public Dataset validate(Dataset dataset)
return dataset;
}
- public Optional getOntology()
+ public Optional getOntology()
{
return ontology.get();
}
diff --git a/src/main/java/com/atomgraph/server/io/ValidatingModelProvider.java b/src/main/java/com/atomgraph/server/io/ValidatingModelProvider.java
index 416d8ada1c..1b348127b7 100644
--- a/src/main/java/com/atomgraph/server/io/ValidatingModelProvider.java
+++ b/src/main/java/com/atomgraph/server/io/ValidatingModelProvider.java
@@ -16,7 +16,7 @@
package com.atomgraph.server.io;
-import org.apache.jena.ontology.Ontology;
+import org.apache.jena.ontapi.model.OntModel;
import org.apache.jena.rdf.model.Model;
import java.io.IOException;
import java.io.InputStream;
@@ -51,7 +51,7 @@ public class ValidatingModelProvider extends BasedModelProvider
@Context private Providers providers;
- @Inject jakarta.inject.Provider> ontology;
+ @Inject jakarta.inject.Provider> ontology;
@Override
public Model readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream) throws IOException
@@ -69,7 +69,7 @@ public Model validate(Model model)
if (getOntology().isPresent())
{
// SPIN validation
- List cvs = new Validator(getOntology().get().getOntModel()).validate(model);
+ List cvs = new Validator(getOntology().get()).validate(model);
if (!cvs.isEmpty())
{
if (log.isDebugEnabled()) log.debug("SPIN constraint violations: {}", cvs);
@@ -77,7 +77,7 @@ public Model validate(Model model)
}
// SHACL validation
- Shapes shapes = Shapes.parse(getOntology().get().getOntModel().getGraph());
+ Shapes shapes = Shapes.parse(getOntology().get().getGraph());
ValidationReport report = ShaclValidator.get().validate(shapes, model.getGraph());
if (!report.conforms())
{
@@ -100,7 +100,7 @@ public Model processWrite(Model model)
return model;
}
- public Optional getOntology()
+ public Optional getOntology()
{
return ontology.get();
}
diff --git a/src/main/java/com/atomgraph/server/util/Validator.java b/src/main/java/com/atomgraph/server/util/Validator.java
index fc66576e58..67a6afe98f 100644
--- a/src/main/java/com/atomgraph/server/util/Validator.java
+++ b/src/main/java/com/atomgraph/server/util/Validator.java
@@ -16,7 +16,7 @@
package com.atomgraph.server.util;
-import org.apache.jena.ontology.OntModel;
+import org.apache.jena.ontapi.model.OntModel;
import org.apache.jena.rdf.model.Model;
import java.util.List;
import org.slf4j.Logger;
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilterTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilterTest.java
index 76787051fc..aa6b7ac80a 100644
--- a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilterTest.java
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilterTest.java
@@ -16,18 +16,16 @@
*/
package com.atomgraph.linkeddatahub.server.filter.request;
-import org.apache.jena.ontology.OntDocumentManager;
-import org.apache.jena.rdf.model.Model;
+import com.atomgraph.core.util.jena.PrefixGraphRepository;
+import org.apache.jena.graph.Graph;
import org.apache.jena.rdf.model.ModelFactory;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
- * Characterization tests for {@link OntologyFilter#addDocumentModel}, which caches an
- * imported ontology model under a SECONDARY key: the fragment-stripped document URI.
- *
- * This pins the current dual-key caching behavior so the migration to the new ontology
- * API ({@code GraphRepository}) can be proven to retain it.
+ * Characterization tests for {@link OntologyFilter#addDocumentModel}, which caches an imported graph
+ * under a SECONDARY key: the fragment-stripped document URI. Pins the dual-key caching behavior
+ * retained from the legacy implementation.
*
* @author Martynas Jusevičius {@literal }
*/
@@ -38,42 +36,33 @@ public class OntologyFilterTest
@Test
public void testAddDocumentModelCachesUnderStrippedDocumentURI()
{
- OntDocumentManager odm = new OntDocumentManager();
+ PrefixGraphRepository repository = new PrefixGraphRepository(null);
String importURI = "http://example.org/onto#";
String docURI = "http://example.org/onto";
- Model imported = ModelFactory.createDefaultModel();
- imported.createResource(importURI + "Thing");
- odm.addModel(importURI, imported, true);
-
- // precondition: only the ontology (fragment) URI is known
- assertNotNull(odm.getModel(importURI));
+ Graph imported = ModelFactory.createDefaultModel().getGraph();
+ repository.put(importURI, imported);
- OntologyFilter.addDocumentModel(odm, importURI);
+ OntologyFilter.addDocumentModel(repository, importURI);
- // the same model is now retrievable under the fragment-stripped document URI
- assertNotNull(odm.getModel(docURI), "import model should be cached under the document URI");
- assertSame(imported, odm.getModel(docURI));
+ assertTrue(repository.isCached(docURI), "import graph should be cached under the document URI");
+ assertSame(imported, repository.get(docURI));
}
- /** If the document URI is mapped (mapURI != docURI), the secondary cache write is skipped. */
+ /** If the document URI is mapped to a different location, the secondary cache write is skipped. */
@Test
public void testAddDocumentModelSkipsWhenDocumentURIMapped()
{
- OntDocumentManager odm = new OntDocumentManager();
+ PrefixGraphRepository repository = new PrefixGraphRepository(null);
String importURI = "http://example.org/mapped#";
String docURI = "http://example.org/mapped";
- // map the document URI to a different location -> guard mappedURI.equals(docURI) is false
- odm.getFileManager().getLocationMapper().addAltEntry(docURI, "file:elsewhere.ttl");
-
- Model imported = ModelFactory.createDefaultModel();
- odm.addModel(importURI, imported, true);
+ repository.addLocationMapping(docURI, "file:elsewhere.ttl"); // resolve(docURI) != docURI -> skip
+ repository.put(importURI, ModelFactory.createDefaultModel().getGraph());
- OntologyFilter.addDocumentModel(odm, importURI);
+ OntologyFilter.addDocumentModel(repository, importURI);
- // no secondary cache entry created under the document URI
- assertNull(odm.getModel(docURI), "mapped document URI should not be cached as a secondary key");
+ assertFalse(repository.isCached(docURI), "mapped document URI should not be cached as a secondary key");
}
}
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/util/OntologyModelGetterTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/util/OntologyRepositoryTest.java
similarity index 64%
rename from src/test/java/com/atomgraph/linkeddatahub/server/util/OntologyModelGetterTest.java
rename to src/test/java/com/atomgraph/linkeddatahub/server/util/OntologyRepositoryTest.java
index 4db93eac45..33b3183f25 100644
--- a/src/test/java/com/atomgraph/linkeddatahub/server/util/OntologyModelGetterTest.java
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/util/OntologyRepositoryTest.java
@@ -16,19 +16,22 @@
*/
package com.atomgraph.linkeddatahub.server.util;
-import com.atomgraph.core.client.SPARQLClient;
+import com.atomgraph.core.client.GraphStoreClient;
import com.atomgraph.linkeddatahub.apps.model.AdminApplication;
import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
import com.atomgraph.linkeddatahub.model.Service;
import com.atomgraph.linkeddatahub.model.ServiceContext;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
-import org.apache.jena.ontology.OntModelSpec;
+import org.apache.jena.graph.Graph;
+import org.apache.jena.graph.NodeFactory;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
-import org.apache.jena.util.FileManager;
+import org.apache.jena.vocabulary.OWL;
+import org.apache.jena.vocabulary.RDF;
+import org.apache.jena.vocabulary.RDFS;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
@@ -41,17 +44,14 @@
import static org.mockito.Mockito.when;
/**
- * Characterization tests for {@link OntologyModelGetter}, which resolves an ontology model
- * SPARQL-first (admin endpoint CONSTRUCT) and falls back to the FileManager only when the
- * SPARQL result is empty.
- *
- * Pins the current resolution order so the migration to a {@code GraphRepository.get(uri)}
- * can be proven to retain it.
+ * Characterization tests for {@link OntologyRepository}, which resolves an ontology graph
+ * SPARQL-first (admin endpoint CONSTRUCT) and falls back to the superclass (bundled mapping / HTTP)
+ * only when the SPARQL result is empty.
*
* @author Martynas Jusevičius {@literal }
*/
@ExtendWith(MockitoExtension.class)
-public class OntologyModelGetterTest
+public class OntologyRepositoryTest
{
private static final String ONTOLOGY_URI = "http://example.org/ontology#";
@@ -62,8 +62,9 @@ public class OntologyModelGetterTest
@Mock AdminApplication adminApp;
@Mock Service service;
@Mock ServiceContext serviceContext;
- @Mock SPARQLClient sparqlClient;
+ @Mock com.atomgraph.core.client.SPARQLClient sparqlClient;
@Mock Response response;
+ @Mock GraphStoreClient gsc;
private void stubSPARQLChain(Model sparqlResult)
{
@@ -75,43 +76,36 @@ private void stubSPARQLChain(Model sparqlResult)
when(response.readEntity(Model.class)).thenReturn(sparqlResult);
}
- /** A non-empty admin SPARQL CONSTRUCT result is returned directly; the FileManager is not consulted. */
+ /** A non-empty admin SPARQL CONSTRUCT result is returned directly; the HTTP fallback is not used. */
@Test
public void testSPARQLResultUsedWhenNonEmpty()
{
Model sparqlResult = ModelFactory.createDefaultModel();
- sparqlResult.createResource(ONTOLOGY_URI).addProperty(org.apache.jena.vocabulary.RDF.type, org.apache.jena.vocabulary.OWL.Ontology);
+ sparqlResult.createResource(ONTOLOGY_URI).addProperty(RDF.type, OWL.Ontology);
stubSPARQLChain(sparqlResult);
- OntModelSpec spec = new OntModelSpec(OntModelSpec.OWL_MEM);
- FileManager fileManager = org.mockito.Mockito.mock(FileManager.class);
- spec.getDocumentManager().setFileManager(fileManager);
-
- OntologyModelGetter getter = new OntologyModelGetter(app, system, spec, ONTOLOGY_QUERY);
- Model result = getter.getModel(ONTOLOGY_URI);
+ OntologyRepository repository = new OntologyRepository(app, system, gsc, ONTOLOGY_QUERY);
+ Graph result = repository.get(ONTOLOGY_URI);
- assertSame(sparqlResult, result);
- verify(fileManager, never()).loadModel(any());
+ assertTrue(result.contains(NodeFactory.createURI(ONTOLOGY_URI), RDF.type.asNode(), OWL.Ontology.asNode()));
+ verify(gsc, never()).getModel(any());
}
- /** An empty SPARQL result falls back to FileManager.loadModel(uri). */
+ /** An empty SPARQL result falls back to the Graph Store client (HTTP) load. */
@Test
- public void testFallsBackToFileManagerWhenSPARQLEmpty()
+ public void testFallsBackToHttpWhenSPARQLEmpty()
{
Model empty = ModelFactory.createDefaultModel();
stubSPARQLChain(empty);
- OntModelSpec spec = new OntModelSpec(OntModelSpec.OWL_MEM);
- FileManager fileManager = org.mockito.Mockito.mock(FileManager.class);
- spec.getDocumentManager().setFileManager(fileManager);
Model fallback = ModelFactory.createDefaultModel();
- fallback.createResource(ONTOLOGY_URI);
- when(fileManager.loadModel(ONTOLOGY_URI)).thenReturn(fallback);
+ fallback.createResource(ONTOLOGY_URI).addProperty(RDFS.label, "fallback");
+ when(gsc.getModel(ONTOLOGY_URI)).thenReturn(fallback);
- OntologyModelGetter getter = new OntologyModelGetter(app, system, spec, ONTOLOGY_QUERY);
- Model result = getter.getModel(ONTOLOGY_URI);
+ OntologyRepository repository = new OntologyRepository(app, system, gsc, ONTOLOGY_QUERY);
+ Graph result = repository.get(ONTOLOGY_URI);
- assertSame(fallback, result);
+ assertTrue(result.contains(NodeFactory.createURI(ONTOLOGY_URI), RDFS.label.asNode(), NodeFactory.createLiteralString("fallback")));
}
}
From cae83a6da2bf4ca22665a477f483ef9fe36fbb88 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?=
Date: Thu, 18 Jun 2026 19:17:17 +0200
Subject: [PATCH 03/14] Fix OntologyFilter: flatten owl:imports closure
manually, not via ontapi union-graph repository
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
OntModelFactory.createModel(graph, spec, repository) registers graphs in an OntUnionGraphRepository keyed by ontology ID, which collided with the same graph already in our flat PrefixGraphRepository cache (OntJenaException: 'Another graph with name <...#> is already in the hierarchy', thrown at runtime on the first /ns request).
Replace it with explicit owl:imports closure traversal (loadClosure) that unions the base + imports into one graph, runs RDFS inference over that, and materializes — so createModel is only ever called WITHOUT a repository (no union-hierarchy registration). Encapsulates the duplicated OntologyFilter/ClearOntology load logic into OntologyFilter.loadOntology. OntologyImportsCharacterizationTest now exercises loadOntology and asserts the materialized closure.
Co-Authored-By: Claude Opus 4.8 (1M context)
---
.../resource/admin/ClearOntology.java | 17 +----
.../server/filter/request/OntologyFilter.java | 68 ++++++++++++-------
.../OntologyImportsCharacterizationTest.java | 60 ++++++----------
3 files changed, 64 insertions(+), 81 deletions(-)
diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/ClearOntology.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/ClearOntology.java
index 5470d5ef97..75ab778a90 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/ClearOntology.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/ClearOntology.java
@@ -30,11 +30,6 @@
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriBuilder;
-import org.apache.jena.ontapi.OntModelFactory;
-import org.apache.jena.ontapi.OntSpecification;
-import org.apache.jena.ontapi.model.OntModel;
-import org.apache.jena.graph.Graph;
-import java.util.HashSet;
import com.atomgraph.linkeddatahub.server.filter.request.OntologyFilter;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
@@ -119,17 +114,7 @@ public Response post(@FormParam("uri") String ontologyURI, @HeaderParam("Referer
}
// !!! we need to reload the ontology model before returning a response, to make sure the next request already gets the new version !!!
- // same logic as in OntologyFilter. TO-DO: encapsulate?
- if (log.isDebugEnabled()) log.debug("Started loading ontology with URI '{}' from the admin dataset", ontologyURI);
- Graph baseGraph = repository.get(ontologyURI);
- OntModel inferred = OntModelFactory.createModel(baseGraph, OntSpecification.OWL2_DL_MEM_RDFS_INF, repository);
- // materialize inferences to avoid invoking the rules engine on every request
- OntModel materialized = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
- materialized.add(inferred);
- repository.put(ontologyURI, materialized.getGraph());
- // cache imported graphs under their document URIs too
- OntologyFilter.importClosure(inferred, new HashSet<>()).forEach(importURI -> OntologyFilter.addDocumentModel(repository, importURI));
- if (log.isDebugEnabled()) log.debug("Finished loading ontology with URI '{}' from the admin dataset", ontologyURI);
+ OntologyFilter.loadOntology(repository, ontologyURI);
}
if (referer != null) return Response.seeOther(referer).build();
diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
index a09b31bd07..cbf43d9e8e 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
@@ -32,11 +32,11 @@
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.container.PreMatching;
-import org.apache.jena.graph.Graph;
import org.apache.jena.ontapi.OntModelFactory;
import org.apache.jena.ontapi.OntSpecification;
-import org.apache.jena.ontapi.model.OntID;
import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.vocabulary.OWL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -144,38 +144,54 @@ public OntModel getOntology(Application app, String uri)
final PrefixGraphRepository repository = app.canAs(EndUserApplication.class) ?
getSystem().getRepository(app.as(EndUserApplication.class)) : getSystem().getRepository();
- // only build the inferred model if the ontology is not already cached
- if (!repository.isCached(uri))
- {
- if (log.isDebugEnabled()) log.debug("Started loading ontology with URI '{}'", uri);
- Graph baseGraph = repository.get(uri); // end-user: SPARQL-first; otherwise bundled mapping / HTTP
- OntModel inferred = OntModelFactory.createModel(baseGraph, OntSpecification.OWL2_DL_MEM_RDFS_INF, repository);
- // materialize inferences to avoid invoking the rules engine on every request
- OntModel materialized = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
- materialized.add(inferred);
- repository.put(uri, materialized.getGraph());
- // cache imported graphs under their (fragment-stripped) document URIs too
- importClosure(inferred, new HashSet<>()).forEach(importURI -> addDocumentModel(repository, importURI));
- if (log.isDebugEnabled()) log.debug("Finished loading ontology with URI '{}'", uri);
- }
+ // only build the materialized model if the ontology is not already cached
+ if (!repository.isCached(uri)) loadOntology(repository, uri);
+
+ return OntModelFactory.createModel(repository.get(uri), OntSpecification.OWL2_DL_MEM);
+ }
- return OntModelFactory.createModel(repository.get(uri), OntSpecification.OWL2_DL_MEM, repository);
+ /**
+ * Builds and caches the materialized ontology model. Assembles the owl:imports closure into a single
+ * graph (so ontapi never manages a union-graph hierarchy over the shared repository), applies RDFS
+ * inference over the flattened closure, and materializes the inferences into the repository cache so
+ * the rules engine is not invoked on every request.
+ *
+ * @param repository graph repository
+ * @param uri ontology URI
+ */
+ public static void loadOntology(PrefixGraphRepository repository, String uri)
+ {
+ if (log.isDebugEnabled()) log.debug("Started loading ontology with URI '{}'", uri);
+ Model union = ModelFactory.createDefaultModel();
+ Set closure = new HashSet<>();
+ loadClosure(repository, uri, union, closure);
+ OntModel inferred = OntModelFactory.createModel(union.getGraph(), OntSpecification.OWL2_DL_MEM_RDFS_INF);
+ OntModel materialized = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ materialized.add(inferred);
+ repository.put(uri, materialized.getGraph());
+ // cache imported graphs under their fragment-stripped document URIs too
+ closure.stream().filter(closureURI -> !closureURI.equals(uri)).forEach(importURI -> addDocumentModel(repository, importURI));
+ if (log.isDebugEnabled()) log.debug("Finished loading ontology with URI '{}'", uri);
}
/**
- * Collects the transitive owl:imports closure URIs of the given ontology model.
+ * Recursively loads the transitive owl:imports closure of an ontology into a single union model,
+ * fetching each graph via the repository (SPARQL-first / bundled mappings).
*
- * @param model ontology model
- * @param seen accumulator of already-visited import URIs
- * @return the import closure URIs
+ * @param repository graph repository
+ * @param uri ontology URI
+ * @param union accumulator model
+ * @param seen accumulator of visited URIs (prevents cycles)
*/
- public static Set importClosure(OntModel model, Set seen)
+ public static void loadClosure(PrefixGraphRepository repository, String uri, Model union, Set seen)
{
- model.imports().forEach(imp -> imp.id().map(OntID::getURI).ifPresent(importURI ->
+ if (!seen.add(uri)) return;
+ Model model = ModelFactory.createModelForGraph(repository.get(uri));
+ union.add(model);
+ model.listObjectsOfProperty(OWL.imports).toList().forEach(imp ->
{
- if (seen.add(importURI)) importClosure(imp, seen);
- }));
- return seen;
+ if (imp.isURIResource()) loadClosure(repository, imp.asResource().getURI(), union, seen);
+ });
}
/**
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
index 3009ef1693..ecfe40af08 100644
--- a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
@@ -16,9 +16,7 @@
*/
package com.atomgraph.linkeddatahub.server.filter.request;
-import org.apache.jena.ontology.OntDocumentManager;
-import org.apache.jena.ontology.OntModel;
-import org.apache.jena.ontology.OntModelSpec;
+import com.atomgraph.core.util.jena.PrefixGraphRepository;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Resource;
@@ -30,13 +28,9 @@
import static org.junit.jupiter.api.Assertions.*;
/**
- * Oracle for the ontology-load mechanism used by {@link OntologyFilter}: build an
- * OWL_MEM_RDFS_INF model over a base ontology that owl:imports another, then materialize
- * the inferences into a plain OWL_MEM model that is cached.
- *
- * Pins (a) the owl:imports transitive closure, (b) RDFS inference, and (c) that the
- * materialized model retains inferred triples but carries no reasoner — the three
- * behaviors the {@code GraphRepository}/{@code OntSpecification} migration must reproduce.
+ * Pins {@link OntologyFilter#loadOntology}: it flattens the owl:imports closure into one graph,
+ * applies RDFS inference, and materializes the inferences into the repository cache — without ontapi
+ * managing a union-graph hierarchy over the shared repository (which collides on duplicate ontology IDs).
*
* @author Martynas Jusevičius {@literal }
*/
@@ -48,49 +42,37 @@ public class OntologyImportsCharacterizationTest
private static final String NS = "http://example.org/ns#";
@Test
- public void testImportClosureRdfsInferenceAndMaterialization()
+ public void testLoadOntologyFlattensClosureWithMaterializedRDFSInference()
{
- OntModelSpec spec = new OntModelSpec(OntModelSpec.OWL_MEM_RDFS_INF);
- OntDocumentManager odm = new OntDocumentManager();
- spec.setDocumentManager(odm);
+ PrefixGraphRepository repository = new PrefixGraphRepository(null);
- // imported ontology: B rdfs:subClassOf A; individual x a B
Resource a = ResourceFactory.createResource(NS + "A");
Resource b = ResourceFactory.createResource(NS + "B");
Resource x = ResourceFactory.createResource(NS + "x");
+
+ // imported ontology: B rdfs:subClassOf A; individual x a B
Model imported = ModelFactory.createDefaultModel();
imported.add(imported.createResource(IMPORT_URI), RDF.type, OWL.Ontology);
imported.add(b, RDFS.subClassOf, a);
imported.add(x, RDF.type, b);
- odm.addModel(IMPORT_URI, imported);
+ repository.put(IMPORT_URI, imported.getGraph());
// base ontology owl:imports the imported one
Model base = ModelFactory.createDefaultModel();
- base.add(base.createResource(BASE_URI), RDF.type, OWL.Ontology);
- base.add(base.createResource(BASE_URI), OWL.imports, base.createResource(IMPORT_URI));
-
- OntModel ontModel = ModelFactory.createOntologyModel(spec, base);
+ Resource baseOnt = base.createResource(BASE_URI);
+ base.add(baseOnt, RDF.type, OWL.Ontology);
+ base.add(baseOnt, OWL.imports, base.createResource(IMPORT_URI));
+ repository.put(BASE_URI, base.getGraph());
- // (a) transitive import closure includes the imported ontology
- assertTrue(ontModel.listImportedOntologyURIs(true).contains(IMPORT_URI), "import closure should contain the imported ontology URI");
- // imported asserted triple is visible through the union
- assertTrue(ontModel.contains(b, RDFS.subClassOf, a), "imported terms should be visible");
- // (b) RDFS inference: x a A is entailed from (x a B) + (B subClassOf A)
- assertTrue(ontModel.contains(x, RDF.type, a), "RDFS reasoner should infer x a A");
+ OntologyFilter.loadOntology(repository, BASE_URI);
- // (c) materialize into a plain OWL_MEM model (no inference)
- OntModel materialized = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
- materialized.add(ontModel);
- // inferred triple is now asserted in the materialized copy
- assertTrue(materialized.contains(x, RDF.type, a), "materialized model retains the inferred triple");
- // and the materialized model carries no reasoner
- assertNull(materialized.getSpecification().getReasonerFactory(), "OWL_MEM materialized model must have no reasoner factory");
- // proof it is plain: a fresh entailment is NOT auto-derived
- Resource c = ResourceFactory.createResource(NS + "C");
- Resource y = ResourceFactory.createResource(NS + "y");
- materialized.add(c, RDFS.subClassOf, b);
- materialized.add(y, RDF.type, c);
- assertFalse(materialized.contains(y, RDF.type, a), "no reasoner: y a A must not be inferred");
+ Model result = ModelFactory.createModelForGraph(repository.get(BASE_URI));
+ // (a) imported terms flattened into the cached graph
+ assertTrue(result.contains(b, RDFS.subClassOf, a), "imported terms should be flattened in");
+ // (b) RDFS inference materialized as a concrete triple: x a A
+ assertTrue(result.contains(x, RDF.type, a), "RDFS-inferred 'x a A' should be materialized in the cached graph");
+ // (c) the import is also cached under its (fragment-stripped) document URI
+ assertTrue(repository.isCached(IMPORT_URI), "import should remain cached");
}
}
From 50480c8722a2bd6de3ff8ce7e49f580995e87816 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?=
Date: Thu, 18 Jun 2026 23:05:22 +0200
Subject: [PATCH 04/14] Fix empty constructed response: use OWL1_FULL_MEM so
rdfs:Class is recognized
GET /ns?forClass=...#Item returned an empty graph: dh:Item is declared 'a rdfs:Class' (dh.ttl), and the ontapi OWL2_DL_MEM profile I'd used does not recognize rdfs:Class as an OntClass, so Namespace's getOntClass(uri) returned null and no SPIN constructor ran. Legacy OntModelSpec.OWL_MEM is OWL 1 Full (recognizes rdfs:Class); the correct ontapi mapping is OWL1_FULL_MEM, not OWL2_DL_MEM. Applied across OntologyFilter pipeline + all vocab holders. OntologyImportsCharacterizationTest now guards getOntClass(rdfs:Class) != null.
Co-Authored-By: Claude Opus 4.8 (1M context)
---
.../server/filter/request/OntologyFilter.java | 6 +++---
.../com/atomgraph/linkeddatahub/vocabulary/ACL.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/Admin.java | 2 +-
.../com/atomgraph/linkeddatahub/vocabulary/Cert.java | 2 +-
.../com/atomgraph/linkeddatahub/vocabulary/DH.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/Default.java | 2 +-
.../com/atomgraph/linkeddatahub/vocabulary/FOAF.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/Google.java | 2 +-
.../com/atomgraph/linkeddatahub/vocabulary/LACL.java | 2 +-
.../com/atomgraph/linkeddatahub/vocabulary/LAPP.java | 2 +-
.../com/atomgraph/linkeddatahub/vocabulary/LDH.java | 2 +-
.../com/atomgraph/linkeddatahub/vocabulary/LDHC.java | 2 +-
.../com/atomgraph/linkeddatahub/vocabulary/LDHT.java | 2 +-
.../com/atomgraph/linkeddatahub/vocabulary/NFO.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/ORCID.java | 2 +-
.../com/atomgraph/linkeddatahub/vocabulary/PROV.java | 2 +-
.../com/atomgraph/linkeddatahub/vocabulary/SIOC.java | 2 +-
.../com/atomgraph/linkeddatahub/vocabulary/VoID.java | 2 +-
.../java/com/atomgraph/server/vocabulary/HTTP.java | 2 +-
.../java/com/atomgraph/server/vocabulary/LDT.java | 2 +-
.../request/OntologyImportsCharacterizationTest.java | 12 +++++++++++-
.../vocabulary/VocabularyHolderTest.java | 2 +-
22 files changed, 34 insertions(+), 24 deletions(-)
diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
index cbf43d9e8e..6b7e9fa788 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
@@ -147,7 +147,7 @@ public OntModel getOntology(Application app, String uri)
// only build the materialized model if the ontology is not already cached
if (!repository.isCached(uri)) loadOntology(repository, uri);
- return OntModelFactory.createModel(repository.get(uri), OntSpecification.OWL2_DL_MEM);
+ return OntModelFactory.createModel(repository.get(uri), OntSpecification.OWL1_FULL_MEM);
}
/**
@@ -165,8 +165,8 @@ public static void loadOntology(PrefixGraphRepository repository, String uri)
Model union = ModelFactory.createDefaultModel();
Set closure = new HashSet<>();
loadClosure(repository, uri, union, closure);
- OntModel inferred = OntModelFactory.createModel(union.getGraph(), OntSpecification.OWL2_DL_MEM_RDFS_INF);
- OntModel materialized = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ OntModel inferred = OntModelFactory.createModel(union.getGraph(), OntSpecification.OWL1_FULL_MEM_RDFS_INF);
+ OntModel materialized = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
materialized.add(inferred);
repository.put(uri, materialized.getGraph());
// cache imported graphs under their fragment-stripped document URIs too
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ACL.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ACL.java
index ab8afcc1c0..d7197ac61c 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ACL.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ACL.java
@@ -36,7 +36,7 @@ public class ACL
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://www.w3.org/ns/auth/acl#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Admin.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Admin.java
index 8f8901c666..2ff7cb2223 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Admin.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Admin.java
@@ -36,7 +36,7 @@ public class Admin
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/admin#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Cert.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Cert.java
index 655a2582d9..d27f9d8b6f 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Cert.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Cert.java
@@ -37,7 +37,7 @@ public class Cert
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://www.w3.org/ns/auth/cert#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/DH.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/DH.java
index 30e4b486ff..f59a8c2517 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/DH.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/DH.java
@@ -36,7 +36,7 @@ public class DH
}
/** The RDF model that holds the vocabulary terms
*/
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string
*/
public static final String NS = "https://www.w3.org/ns/ldt/document-hierarchy#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Default.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Default.java
index 41182134b3..0cf4da59f8 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Default.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Default.java
@@ -35,7 +35,7 @@ public class Default
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/default#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/FOAF.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/FOAF.java
index b816439510..67607e16a2 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/FOAF.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/FOAF.java
@@ -36,7 +36,7 @@ public class FOAF
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://xmlns.com/foaf/0.1/";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Google.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Google.java
index a1ed9a6c64..07726a01e2 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Google.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Google.java
@@ -21,7 +21,7 @@ public class Google
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/services/google#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LACL.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LACL.java
index 5ced24b0c2..7a54880e17 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LACL.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LACL.java
@@ -36,7 +36,7 @@ public class LACL
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/admin/acl#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java
index 13daf790cd..9ff8b6d81a 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java
@@ -37,7 +37,7 @@ public class LAPP
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/apps#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java
index dff4f44de3..2e3b89a85c 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java
@@ -36,7 +36,7 @@ public class LDH
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHC.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHC.java
index 7c972af205..0d48df8c81 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHC.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHC.java
@@ -36,7 +36,7 @@ public class LDHC
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/config#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHT.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHT.java
index 7741c9e8d3..54058c063b 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHT.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHT.java
@@ -37,7 +37,7 @@ public class LDHT
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/templates#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/NFO.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/NFO.java
index 5c5e79d738..bbdc8a21b0 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/NFO.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/NFO.java
@@ -36,7 +36,7 @@ public class NFO
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ORCID.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ORCID.java
index 42c21d60d9..9b6786a257 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ORCID.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ORCID.java
@@ -21,7 +21,7 @@ public class ORCID
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/services/orcid#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/PROV.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/PROV.java
index e536478aa2..2934134988 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/PROV.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/PROV.java
@@ -36,7 +36,7 @@ public class PROV {
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://www.w3.org/ns/prov#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/SIOC.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/SIOC.java
index 4a19b93cc4..db061d92a0 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/SIOC.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/SIOC.java
@@ -40,7 +40,7 @@ public class SIOC {
* The ontology model that holds the vocabulary terms
*
*/
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/**
*
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/VoID.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/VoID.java
index f2f787b797..c8d52e3067 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/VoID.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/VoID.java
@@ -36,7 +36,7 @@ public class VoID {
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://rdfs.org/ns/void#";
diff --git a/src/main/java/com/atomgraph/server/vocabulary/HTTP.java b/src/main/java/com/atomgraph/server/vocabulary/HTTP.java
index 77213e1cfb..0cd17cee33 100644
--- a/src/main/java/com/atomgraph/server/vocabulary/HTTP.java
+++ b/src/main/java/com/atomgraph/server/vocabulary/HTTP.java
@@ -38,7 +38,7 @@ public class HTTP
}
/**
The RDF model that holds the vocabulary terms
*/
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string
*/
public static final String NS = "http://www.w3.org/2011/http#";
diff --git a/src/main/java/com/atomgraph/server/vocabulary/LDT.java b/src/main/java/com/atomgraph/server/vocabulary/LDT.java
index b48ad91fef..0b07c859db 100644
--- a/src/main/java/com/atomgraph/server/vocabulary/LDT.java
+++ b/src/main/java/com/atomgraph/server/vocabulary/LDT.java
@@ -36,7 +36,7 @@ public final class LDT
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms
*/
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
/** The namespace of the vocabulary as a string
*/
public static final String NS = "https://www.w3.org/ns/ldt#";
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
index ecfe40af08..a4321e573d 100644
--- a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
@@ -17,6 +17,9 @@
package com.atomgraph.linkeddatahub.server.filter.request;
import com.atomgraph.core.util.jena.PrefixGraphRepository;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Resource;
@@ -50,9 +53,11 @@ public void testLoadOntologyFlattensClosureWithMaterializedRDFSInference()
Resource b = ResourceFactory.createResource(NS + "B");
Resource x = ResourceFactory.createResource(NS + "x");
- // imported ontology: B rdfs:subClassOf A; individual x a B
+ // imported ontology: A, B declared as rdfs:Class (as in dh.ttl, NOT owl:Class); B rdfs:subClassOf A; individual x a B
Model imported = ModelFactory.createDefaultModel();
imported.add(imported.createResource(IMPORT_URI), RDF.type, OWL.Ontology);
+ imported.add(a, RDF.type, RDFS.Class);
+ imported.add(b, RDF.type, RDFS.Class);
imported.add(b, RDFS.subClassOf, a);
imported.add(x, RDF.type, b);
repository.put(IMPORT_URI, imported.getGraph());
@@ -73,6 +78,11 @@ public void testLoadOntologyFlattensClosureWithMaterializedRDFSInference()
assertTrue(result.contains(x, RDF.type, a), "RDFS-inferred 'x a A' should be materialized in the cached graph");
// (c) the import is also cached under its (fragment-stripped) document URI
assertTrue(repository.isCached(IMPORT_URI), "import should remain cached");
+ // (d) REGRESSION GUARD: an rdfs:Class must be recognized as an OntClass by the model the pipeline returns.
+ // Legacy OntModelSpec.OWL_MEM is OWL 1 Full and recognizes rdfs:Class; ontapi's OWL2_* profiles do NOT — so
+ // the earlier OWL2_DL_MEM made GET /ns?forClass=...#Item return an empty graph (getOntClass -> null -> no SPIN construct).
+ OntModel ontology = OntModelFactory.createModel(repository.get(BASE_URI), OntSpecification.OWL1_FULL_MEM);
+ assertNotNull(ontology.getOntClass(NS + "B"), "rdfs:Class must be recognized as an OntClass (OWL1_FULL_MEM == legacy OWL_MEM)");
}
}
diff --git a/src/test/java/com/atomgraph/linkeddatahub/vocabulary/VocabularyHolderTest.java b/src/test/java/com/atomgraph/linkeddatahub/vocabulary/VocabularyHolderTest.java
index c416b712bb..1bdf967335 100644
--- a/src/test/java/com/atomgraph/linkeddatahub/vocabulary/VocabularyHolderTest.java
+++ b/src/test/java/com/atomgraph/linkeddatahub/vocabulary/VocabularyHolderTest.java
@@ -28,7 +28,7 @@
* All ~19 vocabulary classes follow the identical pattern — a static OntModel built with
* {@code ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null)} on which
* {@code createClass} / {@code createDatatypeProperty} mint typed terms. Phase A swaps the
- * factory to {@code OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM)} and renames
+ * factory to {@code OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM)} and renames
* {@code createClass}→{@code createOntClass}, {@code createDatatypeProperty}→{@code createDataProperty}.
*
* Asserted via the migration-stable {@link Resource} interface: the term URIs and the
From 88fff4a51f2b036ee9425f4cbf206109c172980b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?=
Date: Fri, 19 Jun 2026 10:58:45 +0200
Subject: [PATCH 05/14] Use twirl 1.2.0-SNAPSHOT; drop redundant SPIN
personality registration
twirl 1.2.0 re-bases the constraint model onto its own SPIN personality, so the ontapi ontology model can be passed straight to SPINConstraints.check; LDH no longer needs to register SPIN into the global personality.
- twirl 1.1.0 -> 1.2.0-SNAPSHOT
- Remove SP.init(BuiltinPersonalities.model) from Application (Web-Client Constructor reads sp:text directly; nothing else needed the global registration)
- Add SPINConstraintValidationTest: guards the Validator path and the raw-ontapi-via-twirl-rebase path
Co-Authored-By: Claude Opus 4.8 (1M context)
---
pom.xml | 2 +-
.../atomgraph/linkeddatahub/Application.java | 2 -
.../util/SPINConstraintValidationTest.java | 98 +++++++++++++++++++
3 files changed, 99 insertions(+), 3 deletions(-)
create mode 100644 src/test/java/com/atomgraph/linkeddatahub/server/util/SPINConstraintValidationTest.java
diff --git a/pom.xml b/pom.xml
index fc68de8c63..2f436e4f87 100644
--- a/pom.xml
+++ b/pom.xml
@@ -146,7 +146,7 @@
${project.groupId}
twirl
- 1.1.0
+ 1.2.0-SNAPSHOT
diff --git a/src/main/java/com/atomgraph/linkeddatahub/Application.java b/src/main/java/com/atomgraph/linkeddatahub/Application.java
index 46bc8f8dc0..ba3efb8b56 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/Application.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/Application.java
@@ -175,7 +175,6 @@
import org.slf4j.LoggerFactory;
import com.atomgraph.server.mapper.SHACLConstraintViolationExceptionMapper;
import com.atomgraph.server.mapper.SPINConstraintViolationExceptionMapper;
-import com.atomgraph.spinrdf.vocabulary.SP;
import com.apicatalog.jsonld.JsonLdError;
import com.apicatalog.jsonld.JsonLdOptions;
import java.io.FileOutputStream;
@@ -744,7 +743,6 @@ public Application(final ServletConfig servletConfig, final MediaTypes mediaType
throw new IllegalStateException(new CertificateException("Secretary certificate with alias " + secretaryCertAlias + " not a valid WebID sertificate (SNA URI is missing)"));
}
- SP.init(BuiltinPersonalities.model);
BuiltinPersonalities.model.add(Authorization.class, AuthorizationImpl.factory);
BuiltinPersonalities.model.add(Agent.class, AgentImpl.factory);
BuiltinPersonalities.model.add(UserAccount.class, UserAccountImpl.factory);
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/util/SPINConstraintValidationTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/util/SPINConstraintValidationTest.java
new file mode 100644
index 0000000000..ac274f4d55
--- /dev/null
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/util/SPINConstraintValidationTest.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright 2026 Martynas Jusevičius
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.atomgraph.linkeddatahub.server.util;
+
+import com.atomgraph.server.util.Validator;
+import com.atomgraph.spinrdf.constraints.ConstraintViolation;
+import com.atomgraph.spinrdf.constraints.SPINConstraints;
+import java.util.List;
+import org.apache.jena.ontapi.OntModelFactory;
+import org.apache.jena.ontapi.OntSpecification;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.riot.RDFDataMgr;
+import org.apache.jena.vocabulary.RDF;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Regression guard for SPIN constraint validation under the ontapi migration.
+ *
+ * {@code SPINConstraints} resolves a constraint through Jena enhanced-node polymorphism
+ * ({@code canAs(Query)}/{@code canAs(TemplateCall)}), which an ontapi {@link OntModel}'s profile-aware personality
+ * does not carry — so before the fix, validation silently fired nothing. twirl now re-bases the constraint model
+ * onto its SPIN personality internally (twirl {@code SPINConstraints.check}), so {@link Validator} can hand it the
+ * ontapi model directly. This pins that the real {@code dh:Item spin:constraint :MissingTitle} template constraint
+ * flags a {@code dh:Item} that lacks {@code dct:title}.
+ *
+ * @author Martynas Jusevičius {@literal }
+ */
+public class SPINConstraintValidationTest
+{
+
+ static
+ {
+ org.apache.jena.sys.JenaSystem.init();
+ }
+
+ private static final String DH = "https://www.w3.org/ns/ldt/document-hierarchy#";
+
+ /** The full owl:imports closure the ontology pipeline assembles for the document-hierarchy ontology. */
+ private OntModel loadOntology()
+ {
+ Model closure = ModelFactory.createDefaultModel();
+ for (String classpath : new String[] {
+ "etc/sp.ttl", "etc/spl.spin.ttl", "etc/spin.ttl",
+ "com/atomgraph/linkeddatahub/dh.ttl",
+ "com/atomgraph/linkeddatahub/def.ttl",
+ "com/atomgraph/linkeddatahub/ldh.ttl" })
+ RDFDataMgr.read(closure, classpath);
+
+ // mirror OntologyFilter.loadOntology: RDFS-infer then materialize into a plain OWL1_FULL_MEM graph
+ OntModel inferred = OntModelFactory.createModel(closure.getGraph(), OntSpecification.OWL1_FULL_MEM_RDFS_INF);
+ OntModel materialized = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ materialized.add(inferred);
+ return materialized;
+ }
+
+ /** A dh:Item with NO dct:title — violates the MissingTitle constraint. */
+ private Model violatingItem()
+ {
+ Model data = ModelFactory.createDefaultModel();
+ data.createResource("http://example.org/doc").addProperty(RDF.type, data.createResource(DH + "Item"));
+ return data;
+ }
+
+ @Test
+ public void testMissingTitleConstraintFiresThroughValidator()
+ {
+ List violations = new Validator(loadOntology()).validate(violatingItem());
+ assertFalse(violations.isEmpty(), "MissingTitle SPIN constraint must fire on a dh:Item without dct:title");
+ }
+
+ @Test
+ public void testRawOntApiModelFiresViaTwirlRebase()
+ {
+ // The ontapi OntModel's profile-aware personality lacks the SPIN views, so canAs(...) is false on it.
+ // twirl's SPINConstraints.check re-bases the constraint model onto its own SPIN personality, so passing the
+ // ontapi model straight in still fires. Guards against twirl regressing that re-base.
+ List direct = SPINConstraints.check(violatingItem(), loadOntology());
+ assertFalse(direct.isEmpty(), "SPINConstraints.check must fire on a raw ontapi OntModel (twirl re-bases internally)");
+ }
+
+}
From 11b9d210e2ca7634ca0b500ed4cf7be4cae46811 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?=
Date: Fri, 19 Jun 2026 12:32:54 +0200
Subject: [PATCH 06/14] ci: re-run against deployed twirl/core snapshots
From ae0c69ebda65bb285c65fd7d67843e180144bb00 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?=
Date: Fri, 19 Jun 2026 14:26:34 +0200
Subject: [PATCH 07/14] ci: re-run against deployed twirl/core snapshots
From 4a2e7d3594069f3347c5fe9ed749034436fef0b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?=
Date: Fri, 19 Jun 2026 15:07:42 +0200
Subject: [PATCH 08/14] Normalize ontologies to owl:Class; use OWL2_FULL_MEM
profile
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The document/LDT/ACL ontology classes were declared bare rdfs:Class, which no OWL2 ontapi profile recognizes as an OntClass — forcing OWL1_FULL_MEM (which in turn bans named individuals, breaking SD). Declare them owl:Class (dual with rdfs:Class) and switch all OntSpecification usages from OWL1_FULL_MEM to OWL2_FULL_MEM, so getOntClass/forClass works and named individuals are allowed.
- dh.ttl/ldt.ttl/lacl.ttl: class declarations now 'a rdfs:Class, owl:Class'
- vocab holders + OntologyFilter + ConstructForClass: OWL1_FULL_MEM -> OWL2_FULL_MEM
- remove dead 'import com.atomgraph.client.locator.PrefixMapper' (deleted in Web-Client)
- OntologyImportsCharacterizationTest: assert owl:Class (not rdfs:Class) is recognized
Co-Authored-By: Claude Opus 4.8 (1M context)
---
.../com/atomgraph/linkeddatahub/Application.java | 1 -
.../server/filter/request/OntologyFilter.java | 6 +++---
.../atomgraph/linkeddatahub/vocabulary/ACL.java | 2 +-
.../linkeddatahub/vocabulary/Admin.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/Cert.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/DH.java | 2 +-
.../linkeddatahub/vocabulary/Default.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/FOAF.java | 2 +-
.../linkeddatahub/vocabulary/Google.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/LACL.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/LAPP.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/LDH.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/LDHC.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/LDHT.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/NFO.java | 2 +-
.../linkeddatahub/vocabulary/ORCID.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/PROV.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/SIOC.java | 2 +-
.../atomgraph/linkeddatahub/vocabulary/VoID.java | 2 +-
.../com/atomgraph/server/vocabulary/HTTP.java | 2 +-
.../com/atomgraph/server/vocabulary/LDT.java | 2 +-
.../atomgraph/linkeddatahub/app/admin/lacl.ttl | 4 ++--
.../resources/com/atomgraph/linkeddatahub/dh.ttl | 6 +++---
.../com/atomgraph/linkeddatahub/ldt.ttl | 14 +++++++-------
.../OntologyImportsCharacterizationTest.java | 16 ++++++++--------
.../util/SPINConstraintValidationTest.java | 6 +++---
.../vocabulary/VocabularyHolderTest.java | 2 +-
27 files changed, 46 insertions(+), 47 deletions(-)
diff --git a/src/main/java/com/atomgraph/linkeddatahub/Application.java b/src/main/java/com/atomgraph/linkeddatahub/Application.java
index ba3efb8b56..f294aea127 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/Application.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/Application.java
@@ -34,7 +34,6 @@
import com.atomgraph.linkeddatahub.server.mapper.ForbiddenExceptionMapper;
import com.atomgraph.linkeddatahub.server.mapper.auth.webid.WebIDCertificateExceptionMapper;
import com.atomgraph.client.MediaTypes;
-import com.atomgraph.client.locator.PrefixMapper;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.ServletConfig;
import jakarta.ws.rs.core.Context;
diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
index 6b7e9fa788..ea9befb2b6 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
@@ -147,7 +147,7 @@ public OntModel getOntology(Application app, String uri)
// only build the materialized model if the ontology is not already cached
if (!repository.isCached(uri)) loadOntology(repository, uri);
- return OntModelFactory.createModel(repository.get(uri), OntSpecification.OWL1_FULL_MEM);
+ return OntModelFactory.createModel(repository.get(uri), OntSpecification.OWL2_FULL_MEM);
}
/**
@@ -165,8 +165,8 @@ public static void loadOntology(PrefixGraphRepository repository, String uri)
Model union = ModelFactory.createDefaultModel();
Set closure = new HashSet<>();
loadClosure(repository, uri, union, closure);
- OntModel inferred = OntModelFactory.createModel(union.getGraph(), OntSpecification.OWL1_FULL_MEM_RDFS_INF);
- OntModel materialized = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ OntModel inferred = OntModelFactory.createModel(union.getGraph(), OntSpecification.OWL2_FULL_MEM_RDFS_INF);
+ OntModel materialized = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
materialized.add(inferred);
repository.put(uri, materialized.getGraph());
// cache imported graphs under their fragment-stripped document URIs too
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ACL.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ACL.java
index d7197ac61c..c31bca2089 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ACL.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ACL.java
@@ -36,7 +36,7 @@ public class ACL
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://www.w3.org/ns/auth/acl#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Admin.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Admin.java
index 2ff7cb2223..8c463d9ca6 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Admin.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Admin.java
@@ -36,7 +36,7 @@ public class Admin
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/admin#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Cert.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Cert.java
index d27f9d8b6f..ad869bae69 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Cert.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Cert.java
@@ -37,7 +37,7 @@ public class Cert
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://www.w3.org/ns/auth/cert#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/DH.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/DH.java
index f59a8c2517..140b2e511e 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/DH.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/DH.java
@@ -36,7 +36,7 @@ public class DH
}
/** The RDF model that holds the vocabulary terms
*/
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string
*/
public static final String NS = "https://www.w3.org/ns/ldt/document-hierarchy#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Default.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Default.java
index 0cf4da59f8..47ba21532c 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Default.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Default.java
@@ -35,7 +35,7 @@ public class Default
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/default#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/FOAF.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/FOAF.java
index 67607e16a2..c2bfcc475e 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/FOAF.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/FOAF.java
@@ -36,7 +36,7 @@ public class FOAF
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://xmlns.com/foaf/0.1/";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Google.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Google.java
index 07726a01e2..6a21142b4e 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Google.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/Google.java
@@ -21,7 +21,7 @@ public class Google
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/services/google#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LACL.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LACL.java
index 7a54880e17..bf4123de90 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LACL.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LACL.java
@@ -36,7 +36,7 @@ public class LACL
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/admin/acl#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java
index 9ff8b6d81a..9e991e04fe 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java
@@ -37,7 +37,7 @@ public class LAPP
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/apps#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java
index 2e3b89a85c..a55c1fbce7 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java
@@ -36,7 +36,7 @@ public class LDH
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHC.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHC.java
index 0d48df8c81..e808098ae1 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHC.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHC.java
@@ -36,7 +36,7 @@ public class LDHC
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/config#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHT.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHT.java
index 54058c063b..e2fdfc4182 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHT.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDHT.java
@@ -37,7 +37,7 @@ public class LDHT
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/templates#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/NFO.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/NFO.java
index bbdc8a21b0..d828638b6b 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/NFO.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/NFO.java
@@ -36,7 +36,7 @@ public class NFO
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ORCID.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ORCID.java
index 9b6786a257..c64923c8e6 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ORCID.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/ORCID.java
@@ -21,7 +21,7 @@ public class ORCID
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "https://w3id.org/atomgraph/linkeddatahub/services/orcid#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/PROV.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/PROV.java
index 2934134988..fb4655c533 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/PROV.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/PROV.java
@@ -36,7 +36,7 @@ public class PROV {
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://www.w3.org/ns/prov#";
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/SIOC.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/SIOC.java
index db061d92a0..6e2f11f0bc 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/SIOC.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/SIOC.java
@@ -40,7 +40,7 @@ public class SIOC {
* The ontology model that holds the vocabulary terms
*
*/
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/**
*
diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/VoID.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/VoID.java
index c8d52e3067..12d04d9168 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/VoID.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/VoID.java
@@ -36,7 +36,7 @@ public class VoID {
}
/** The RDF model that holds the vocabulary terms */
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string */
public static final String NS = "http://rdfs.org/ns/void#";
diff --git a/src/main/java/com/atomgraph/server/vocabulary/HTTP.java b/src/main/java/com/atomgraph/server/vocabulary/HTTP.java
index 0cd17cee33..316d6e3b9d 100644
--- a/src/main/java/com/atomgraph/server/vocabulary/HTTP.java
+++ b/src/main/java/com/atomgraph/server/vocabulary/HTTP.java
@@ -38,7 +38,7 @@ public class HTTP
}
/**
The RDF model that holds the vocabulary terms
*/
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string
*/
public static final String NS = "http://www.w3.org/2011/http#";
diff --git a/src/main/java/com/atomgraph/server/vocabulary/LDT.java b/src/main/java/com/atomgraph/server/vocabulary/LDT.java
index 0b07c859db..28cb52bcf9 100644
--- a/src/main/java/com/atomgraph/server/vocabulary/LDT.java
+++ b/src/main/java/com/atomgraph/server/vocabulary/LDT.java
@@ -36,7 +36,7 @@ public final class LDT
org.apache.jena.sys.JenaSystem.init(); // ensure Jena (RDFS vocab) is initialized before ontapi touches it
}
/** The RDF model that holds the vocabulary terms
*/
- private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ private static OntModel m_model = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
/** The namespace of the vocabulary as a string
*/
public static final String NS = "https://www.w3.org/ns/ldt#";
diff --git a/src/main/resources/com/atomgraph/linkeddatahub/app/admin/lacl.ttl b/src/main/resources/com/atomgraph/linkeddatahub/app/admin/lacl.ttl
index ae9068ccfd..a45a58977a 100644
--- a/src/main/resources/com/atomgraph/linkeddatahub/app/admin/lacl.ttl
+++ b/src/main/resources/com/atomgraph/linkeddatahub/app/admin/lacl.ttl
@@ -69,7 +69,7 @@
# authorization requests
-:AuthorizationRequest a rdfs:Class ;
+:AuthorizationRequest a rdfs:Class, owl:Class ;
spin:constructor :AuthorizationRequestConstructor ;
spin:constraint :MissingRequestMode, :MissingRequestAgent, :MissingRequestAccessTo ;
rdfs:label "Authorization request" ;
@@ -108,7 +108,7 @@
WHERE {}""" ;
rdfs:isDefinedBy : .
-:CreatorAuthorization a rdfs:Class ;
+:CreatorAuthorization a rdfs:Class, owl:Class ;
rdfs:subClassOf acl:Authorization ;
rdfs:label "Creator access" ;
rdfs:comment "Creators have full control of their created resources" ;
diff --git a/src/main/resources/com/atomgraph/linkeddatahub/dh.ttl b/src/main/resources/com/atomgraph/linkeddatahub/dh.ttl
index 2c80455940..a3dae50f24 100644
--- a/src/main/resources/com/atomgraph/linkeddatahub/dh.ttl
+++ b/src/main/resources/com/atomgraph/linkeddatahub/dh.ttl
@@ -34,21 +34,21 @@
# CLASSES
-:Document a rdfs:Class ;
+:Document a rdfs:Class, owl:Class ;
rdfs:subClassOf foaf:Document ;
# ldt:path "{slug}/" ;
rdfs:label "Document" ;
# spin:constructor :DocumentConstructor ;
rdfs:isDefinedBy : .
-:Container a rdfs:Class ;
+:Container a rdfs:Class, owl:Class ;
rdfs:subClassOf :Document, sioc:Container ;
# spin:constructor :ContainerConstructor ;
rdfs:label "Container" ;
rdfs:comment "An area in which content Items are contained" ;
rdfs:isDefinedBy : .
-:Item a rdfs:Class ;
+:Item a rdfs:Class, owl:Class ;
rdfs:subClassOf :Document, sioc:Item ;
# spin:constructor :ItemConstructor ;
rdfs:label "Item" ;
diff --git a/src/main/resources/com/atomgraph/linkeddatahub/ldt.ttl b/src/main/resources/com/atomgraph/linkeddatahub/ldt.ttl
index 5c847a307a..120859f87f 100644
--- a/src/main/resources/com/atomgraph/linkeddatahub/ldt.ttl
+++ b/src/main/resources/com/atomgraph/linkeddatahub/ldt.ttl
@@ -155,29 +155,29 @@
# CLASSES
-:InheritedProperty a rdfs:Class ;
+:InheritedProperty a rdfs:Class, owl:Class ;
rdfs:subClassOf owl:AnnotationProperty ;
rdfs:label "Inherited property" ;
rdfs:comment "Values of this property are inherited by subclasses that do not have this property" ;
rdfs:isDefinedBy : .
-:Application a rdfs:Class ;
+:Application a rdfs:Class, owl:Class ;
rdfs:label "Application" ;
rdfs:comment "Declarative Linked Data application which structure is defined by its ontology and data is access via its SPARQL service" ;
rdfs:isDefinedBy : .
-:Ontology a rdfs:Class ;
+:Ontology a rdfs:Class, owl:Class ;
rdfs:subClassOf owl:Ontology ;
rdfs:label "Ontology" ;
rdfs:comment "Ontology annotated with Linked Data Templates" ;
rdfs:isDefinedBy : .
-:Template a rdfs:Class ;
+:Template a rdfs:Class, owl:Class ;
rdfs:label "Resource template" ;
rdfs:comment "A class of RDF resources that share the same URI template and SPARQL query template" ;
rdfs:isDefinedBy : .
-:Query a rdfs:Class ;
+:Query a rdfs:Class, owl:Class ;
rdfs:subClassOf sp:Query, [ a owl:Class ;
owl:unionOf (sp:Describe sp:Construct) ;
rdfs:label "Graph query forms"
@@ -185,12 +185,12 @@
rdfs:label "Query" ;
rdfs:isDefinedBy : .
-:Update a rdfs:Class ;
+:Update a rdfs:Class, owl:Class ;
rdfs:subClassOf sp:Update ;
rdfs:label "Update" ;
rdfs:isDefinedBy : .
-:Parameter a rdfs:Class ;
+:Parameter a rdfs:Class, owl:Class ;
rdfs:subClassOf spl:Argument ;
rdfs:label "Parameter" ;
rdfs:comment "Represents a query parameter that has predicate, value type, default value etc." ;
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
index a4321e573d..14afcb0cf6 100644
--- a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
@@ -53,11 +53,11 @@ public void testLoadOntologyFlattensClosureWithMaterializedRDFSInference()
Resource b = ResourceFactory.createResource(NS + "B");
Resource x = ResourceFactory.createResource(NS + "x");
- // imported ontology: A, B declared as rdfs:Class (as in dh.ttl, NOT owl:Class); B rdfs:subClassOf A; individual x a B
+ // imported ontology: A, B declared as owl:Class (as in dh.ttl since the OWL2 normalization); B rdfs:subClassOf A; individual x a B
Model imported = ModelFactory.createDefaultModel();
imported.add(imported.createResource(IMPORT_URI), RDF.type, OWL.Ontology);
- imported.add(a, RDF.type, RDFS.Class);
- imported.add(b, RDF.type, RDFS.Class);
+ imported.add(a, RDF.type, OWL.Class);
+ imported.add(b, RDF.type, OWL.Class);
imported.add(b, RDFS.subClassOf, a);
imported.add(x, RDF.type, b);
repository.put(IMPORT_URI, imported.getGraph());
@@ -78,11 +78,11 @@ public void testLoadOntologyFlattensClosureWithMaterializedRDFSInference()
assertTrue(result.contains(x, RDF.type, a), "RDFS-inferred 'x a A' should be materialized in the cached graph");
// (c) the import is also cached under its (fragment-stripped) document URI
assertTrue(repository.isCached(IMPORT_URI), "import should remain cached");
- // (d) REGRESSION GUARD: an rdfs:Class must be recognized as an OntClass by the model the pipeline returns.
- // Legacy OntModelSpec.OWL_MEM is OWL 1 Full and recognizes rdfs:Class; ontapi's OWL2_* profiles do NOT — so
- // the earlier OWL2_DL_MEM made GET /ns?forClass=...#Item return an empty graph (getOntClass -> null -> no SPIN construct).
- OntModel ontology = OntModelFactory.createModel(repository.get(BASE_URI), OntSpecification.OWL1_FULL_MEM);
- assertNotNull(ontology.getOntClass(NS + "B"), "rdfs:Class must be recognized as an OntClass (OWL1_FULL_MEM == legacy OWL_MEM)");
+ // (d) REGRESSION GUARD: an owl:Class must be recognized as an OntClass by the model the pipeline returns, so
+ // GET /ns?forClass=...#Item resolves the class and runs its SPIN constructor. The ontologies are normalized to
+ // owl:Class so OWL2_FULL_MEM recognizes them (bare rdfs:Class is NOT recognized by any OWL2 profile).
+ OntModel ontology = OntModelFactory.createModel(repository.get(BASE_URI), OntSpecification.OWL2_FULL_MEM);
+ assertNotNull(ontology.getOntClass(NS + "B"), "owl:Class must be recognized as an OntClass under OWL2_FULL_MEM");
}
}
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/util/SPINConstraintValidationTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/util/SPINConstraintValidationTest.java
index ac274f4d55..6d2062f9c1 100644
--- a/src/test/java/com/atomgraph/linkeddatahub/server/util/SPINConstraintValidationTest.java
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/util/SPINConstraintValidationTest.java
@@ -63,9 +63,9 @@ private OntModel loadOntology()
"com/atomgraph/linkeddatahub/ldh.ttl" })
RDFDataMgr.read(closure, classpath);
- // mirror OntologyFilter.loadOntology: RDFS-infer then materialize into a plain OWL1_FULL_MEM graph
- OntModel inferred = OntModelFactory.createModel(closure.getGraph(), OntSpecification.OWL1_FULL_MEM_RDFS_INF);
- OntModel materialized = OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM);
+ // mirror OntologyFilter.loadOntology: RDFS-infer then materialize into a plain OWL2_FULL_MEM graph
+ OntModel inferred = OntModelFactory.createModel(closure.getGraph(), OntSpecification.OWL2_FULL_MEM_RDFS_INF);
+ OntModel materialized = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
materialized.add(inferred);
return materialized;
}
diff --git a/src/test/java/com/atomgraph/linkeddatahub/vocabulary/VocabularyHolderTest.java b/src/test/java/com/atomgraph/linkeddatahub/vocabulary/VocabularyHolderTest.java
index 1bdf967335..95f10ddc6d 100644
--- a/src/test/java/com/atomgraph/linkeddatahub/vocabulary/VocabularyHolderTest.java
+++ b/src/test/java/com/atomgraph/linkeddatahub/vocabulary/VocabularyHolderTest.java
@@ -28,7 +28,7 @@
* All ~19 vocabulary classes follow the identical pattern — a static OntModel built with
* {@code ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null)} on which
* {@code createClass} / {@code createDatatypeProperty} mint typed terms. Phase A swaps the
- * factory to {@code OntModelFactory.createModel(OntSpecification.OWL1_FULL_MEM)} and renames
+ * factory to {@code OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM)} and renames
* {@code createClass}→{@code createOntClass}, {@code createDatatypeProperty}→{@code createDataProperty}.
*
* Asserted via the migration-stable {@link Resource} interface: the term URIs and the
From 4e52c177f2237f4e58501ab61e5cfb8b097728b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?=
Date: Fri, 19 Jun 2026 21:14:56 +0200
Subject: [PATCH 09/14] Add debug output to add-property-constraint and
GET-proxied-ontology-ns tests
Co-Authored-By: Claude Opus 4.8 (1M context)
---
.../admin/model/add-property-constraint.sh | 19 ++++++++++++++-----
http-tests/proxy/GET-proxied-ontology-ns.sh | 15 ++++++++++-----
2 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/http-tests/admin/model/add-property-constraint.sh b/http-tests/admin/model/add-property-constraint.sh
index c5e179841f..0c5ef907ce 100755
--- a/http-tests/admin/model/add-property-constraint.sh
+++ b/http-tests/admin/model/add-property-constraint.sh
@@ -22,6 +22,7 @@ add-property-constraint.sh \
--label "New constraint" \
--property "http://rdfs.org/sioc/ns#content" \
"$ontology_doc"
+echo "DEBUG: add-property-constraint.sh done"
# create a class with the constraint
@@ -34,21 +35,28 @@ add-class.sh \
--constraint "$constraint" \
--sub-class-of "https://www.w3.org/ns/ldt/document-hierarchy#Item" \
"$ontology_doc"
+echo "DEBUG: add-class.sh done"
# clear ontology from memory
-clear-ontology.sh \
+clear_output=$(clear-ontology.sh \
-f "$OWNER_CERT_FILE" \
-p "$OWNER_CERT_PWD" \
-b "$ADMIN_BASE_URL" \
- --ontology "$namespace"
+ --ontology "$namespace" 2>&1) && clear_exit=0 || clear_exit=$?
+echo "DEBUG: clear-ontology.sh exit=$clear_exit output=$clear_output"
+[ "$clear_exit" -eq 0 ] || exit "$clear_exit"
# check that the constraint is present in the ontology
-curl -k -f -s -N \
+ns_body=$(curl -k -f -s -N \
-H "Accept: application/n-triples" \
- "$namespace_doc" \
-| grep "$constraint" > /dev/null
+ "$namespace_doc" 2>&1) && ns_exit=0 || ns_exit=$?
+echo "DEBUG: namespace GET exit=$ns_exit"
+echo "DEBUG: namespace body (first 500 chars): ${ns_body:0:500}"
+[ "$ns_exit" -eq 0 ] || exit "$ns_exit"
+echo "$ns_body" | grep "$constraint" > /dev/null
+echo "DEBUG: constraint found in namespace doc"
# check that creating an instance of the class without sioc:content returns 422 Unprocessable Entity due to missing sioc:content
@@ -71,5 +79,6 @@ response=$(echo -e "$turtle" \
"$END_USER_BASE_URL" \
2>&1) # redirect output from stderr to stdout
+echo "DEBUG: PUT response (last 200 chars): ${response: -200}"
echo "$response" \
| grep "HTTP/1.1 422" > /dev/null
diff --git a/http-tests/proxy/GET-proxied-ontology-ns.sh b/http-tests/proxy/GET-proxied-ontology-ns.sh
index c97f48505a..e7ed016fb9 100755
--- a/http-tests/proxy/GET-proxied-ontology-ns.sh
+++ b/http-tests/proxy/GET-proxied-ontology-ns.sh
@@ -42,11 +42,13 @@ add-class.sh \
# clear the in-memory ontology so the new classes are present on next request
-clear-ontology.sh \
+clear_out=$(clear-ontology.sh \
-f "$OWNER_CERT_FILE" \
-p "$OWNER_CERT_PWD" \
-b "$ADMIN_BASE_URL" \
- --ontology "$namespace"
+ --ontology "$namespace" 2>&1) && clear_exit=0 || clear_exit=$?
+echo "DEBUG: clear-ontology.sh exit=$clear_exit output=$clear_out"
+[ "$clear_exit" -eq 0 ] || exit "$clear_exit"
# request the namespace document URI (without fragment) via ?uri= proxy.
# the namespace document is not DataManager-mapped and not a registered app,
@@ -58,9 +60,12 @@ response=$(curl -k -f -s \
-E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \
-H "Accept: application/n-triples" \
--data-urlencode "uri=${namespace_uri}" \
- "$END_USER_BASE_URL")
+ "$END_USER_BASE_URL" 2>&1) && proxy_exit=0 || proxy_exit=$?
+echo "DEBUG: proxy GET exit=$proxy_exit"
+echo "DEBUG: proxy response (first 500 chars): ${response:0:500}"
+[ "$proxy_exit" -eq 0 ] || exit "$proxy_exit"
# verify both class descriptions are present in the response
-echo "$response" | grep -q "$class1"
-echo "$response" | grep -q "$class2"
+echo "$response" | grep -q "$class1" && echo "DEBUG: class1 found" || { echo "DEBUG: class1 NOT found"; exit 1; }
+echo "$response" | grep -q "$class2" && echo "DEBUG: class2 found" || { echo "DEBUG: class2 NOT found"; exit 1; }
From 3cb48a41264b391a954adc3ebf2d14d080771dc5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?=
Date: Fri, 19 Jun 2026 21:58:59 +0200
Subject: [PATCH 10/14] Removed debug output
---
.../admin/model/add-property-constraint.sh | 19 +++++--------------
http-tests/proxy/GET-proxied-ontology-ns.sh | 15 +++++----------
2 files changed, 10 insertions(+), 24 deletions(-)
diff --git a/http-tests/admin/model/add-property-constraint.sh b/http-tests/admin/model/add-property-constraint.sh
index 0c5ef907ce..c5e179841f 100755
--- a/http-tests/admin/model/add-property-constraint.sh
+++ b/http-tests/admin/model/add-property-constraint.sh
@@ -22,7 +22,6 @@ add-property-constraint.sh \
--label "New constraint" \
--property "http://rdfs.org/sioc/ns#content" \
"$ontology_doc"
-echo "DEBUG: add-property-constraint.sh done"
# create a class with the constraint
@@ -35,28 +34,21 @@ add-class.sh \
--constraint "$constraint" \
--sub-class-of "https://www.w3.org/ns/ldt/document-hierarchy#Item" \
"$ontology_doc"
-echo "DEBUG: add-class.sh done"
# clear ontology from memory
-clear_output=$(clear-ontology.sh \
+clear-ontology.sh \
-f "$OWNER_CERT_FILE" \
-p "$OWNER_CERT_PWD" \
-b "$ADMIN_BASE_URL" \
- --ontology "$namespace" 2>&1) && clear_exit=0 || clear_exit=$?
-echo "DEBUG: clear-ontology.sh exit=$clear_exit output=$clear_output"
-[ "$clear_exit" -eq 0 ] || exit "$clear_exit"
+ --ontology "$namespace"
# check that the constraint is present in the ontology
-ns_body=$(curl -k -f -s -N \
+curl -k -f -s -N \
-H "Accept: application/n-triples" \
- "$namespace_doc" 2>&1) && ns_exit=0 || ns_exit=$?
-echo "DEBUG: namespace GET exit=$ns_exit"
-echo "DEBUG: namespace body (first 500 chars): ${ns_body:0:500}"
-[ "$ns_exit" -eq 0 ] || exit "$ns_exit"
-echo "$ns_body" | grep "$constraint" > /dev/null
-echo "DEBUG: constraint found in namespace doc"
+ "$namespace_doc" \
+| grep "$constraint" > /dev/null
# check that creating an instance of the class without sioc:content returns 422 Unprocessable Entity due to missing sioc:content
@@ -79,6 +71,5 @@ response=$(echo -e "$turtle" \
"$END_USER_BASE_URL" \
2>&1) # redirect output from stderr to stdout
-echo "DEBUG: PUT response (last 200 chars): ${response: -200}"
echo "$response" \
| grep "HTTP/1.1 422" > /dev/null
diff --git a/http-tests/proxy/GET-proxied-ontology-ns.sh b/http-tests/proxy/GET-proxied-ontology-ns.sh
index e7ed016fb9..c97f48505a 100755
--- a/http-tests/proxy/GET-proxied-ontology-ns.sh
+++ b/http-tests/proxy/GET-proxied-ontology-ns.sh
@@ -42,13 +42,11 @@ add-class.sh \
# clear the in-memory ontology so the new classes are present on next request
-clear_out=$(clear-ontology.sh \
+clear-ontology.sh \
-f "$OWNER_CERT_FILE" \
-p "$OWNER_CERT_PWD" \
-b "$ADMIN_BASE_URL" \
- --ontology "$namespace" 2>&1) && clear_exit=0 || clear_exit=$?
-echo "DEBUG: clear-ontology.sh exit=$clear_exit output=$clear_out"
-[ "$clear_exit" -eq 0 ] || exit "$clear_exit"
+ --ontology "$namespace"
# request the namespace document URI (without fragment) via ?uri= proxy.
# the namespace document is not DataManager-mapped and not a registered app,
@@ -60,12 +58,9 @@ response=$(curl -k -f -s \
-E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \
-H "Accept: application/n-triples" \
--data-urlencode "uri=${namespace_uri}" \
- "$END_USER_BASE_URL" 2>&1) && proxy_exit=0 || proxy_exit=$?
-echo "DEBUG: proxy GET exit=$proxy_exit"
-echo "DEBUG: proxy response (first 500 chars): ${response:0:500}"
-[ "$proxy_exit" -eq 0 ] || exit "$proxy_exit"
+ "$END_USER_BASE_URL")
# verify both class descriptions are present in the response
-echo "$response" | grep -q "$class1" && echo "DEBUG: class1 found" || { echo "DEBUG: class1 NOT found"; exit 1; }
-echo "$response" | grep -q "$class2" && echo "DEBUG: class2 found" || { echo "DEBUG: class2 NOT found"; exit 1; }
+echo "$response" | grep -q "$class1"
+echo "$response" | grep -q "$class2"
From ee9b15b1ccbfc61a94a333315ae7ce1e258c8af8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?=
Date: Fri, 19 Jun 2026 23:59:12 +0200
Subject: [PATCH 11/14] Tests for RDFS ontology imports
---
.../GET-namespace-forClass-rdfs.sh | 22 +++++++++++++++++++
.../OntologyImportsCharacterizationTest.java | 15 ++++++++-----
2 files changed, 31 insertions(+), 6 deletions(-)
create mode 100644 http-tests/document-hierarchy/GET-namespace-forClass-rdfs.sh
diff --git a/http-tests/document-hierarchy/GET-namespace-forClass-rdfs.sh b/http-tests/document-hierarchy/GET-namespace-forClass-rdfs.sh
new file mode 100644
index 0000000000..e363dfbcf4
--- /dev/null
+++ b/http-tests/document-hierarchy/GET-namespace-forClass-rdfs.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL"
+initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL"
+purge_cache "$END_USER_VARNISH_SERVICE"
+purge_cache "$ADMIN_VARNISH_SERVICE"
+purge_cache "$FRONTEND_VARNISH_SERVICE"
+
+# sp:Describe is declared only as rdfs:Class (not owl:Class) in sp.ttl.
+# OntologyFilter must promote rdfs:Class to owl:Class during materialization so
+# that OWL2 profiles recognise third-party vocab terms and return their SPIN constructors.
+
+response=$(curl -k -f -s \
+ -G \
+ -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \
+ -H "Accept: application/rdf+xml" \
+ --data-urlencode "forClass=http://spinrdf.org/sp#Describe" \
+ "${END_USER_BASE_URL}ns")
+
+# response must be non-empty: sp:Describe must be recognised as an OntClass
+echo "$response" | grep -q "http://spinrdf.org/sp#Describe"
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
index 14afcb0cf6..00e6f0c7ce 100644
--- a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
@@ -53,11 +53,12 @@ public void testLoadOntologyFlattensClosureWithMaterializedRDFSInference()
Resource b = ResourceFactory.createResource(NS + "B");
Resource x = ResourceFactory.createResource(NS + "x");
- // imported ontology: A, B declared as owl:Class (as in dh.ttl since the OWL2 normalization); B rdfs:subClassOf A; individual x a B
+ // imported ontology: A declared as owl:Class only; B declared as rdfs:Class only (mimicking third-party vocabs like sp.ttl);
+ // B rdfs:subClassOf A; individual x a B
Model imported = ModelFactory.createDefaultModel();
imported.add(imported.createResource(IMPORT_URI), RDF.type, OWL.Ontology);
imported.add(a, RDF.type, OWL.Class);
- imported.add(b, RDF.type, OWL.Class);
+ imported.add(b, RDF.type, RDFS.Class);
imported.add(b, RDFS.subClassOf, a);
imported.add(x, RDF.type, b);
repository.put(IMPORT_URI, imported.getGraph());
@@ -78,11 +79,13 @@ public void testLoadOntologyFlattensClosureWithMaterializedRDFSInference()
assertTrue(result.contains(x, RDF.type, a), "RDFS-inferred 'x a A' should be materialized in the cached graph");
// (c) the import is also cached under its (fragment-stripped) document URI
assertTrue(repository.isCached(IMPORT_URI), "import should remain cached");
- // (d) REGRESSION GUARD: an owl:Class must be recognized as an OntClass by the model the pipeline returns, so
- // GET /ns?forClass=...#Item resolves the class and runs its SPIN constructor. The ontologies are normalized to
- // owl:Class so OWL2_FULL_MEM recognizes them (bare rdfs:Class is NOT recognized by any OWL2 profile).
+ // (d) REGRESSION GUARD: both owl:Class and rdfs:Class-only terms must be recognized as OntClasses by the returned
+ // model, so GET /ns?forClass= resolves the class and runs its SPIN constructor.
+ // OntologyFilter promotes all rdfs:Class subjects to owl:Class so OWL2 profiles (which do not recognize bare
+ // rdfs:Class) can find third-party vocab terms like sp:Describe.
OntModel ontology = OntModelFactory.createModel(repository.get(BASE_URI), OntSpecification.OWL2_FULL_MEM);
- assertNotNull(ontology.getOntClass(NS + "B"), "owl:Class must be recognized as an OntClass under OWL2_FULL_MEM");
+ assertNotNull(ontology.getOntClass(NS + "A"), "owl:Class term must be recognized as an OntClass under OWL2_FULL_MEM");
+ assertNotNull(ontology.getOntClass(NS + "B"), "rdfs:Class-only term must be recognized as an OntClass after promotion");
}
}
From f27c423e0b384a470bcd614d8c8ae5d7a7996d85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?=
Date: Fri, 19 Jun 2026 23:59:37 +0200
Subject: [PATCH 12/14] Promote rdfs:Class to owl:Class during ontology
materialization
OWL2 profiles do not recognise bare rdfs:Class as OntClass, so third-party
vocab terms declared only as rdfs:Class (e.g. sp:Describe in sp.ttl) were
invisible to getOntClass() lookups, returning empty forClass constructor responses.
Co-Authored-By: Claude Opus 4.8 (1M context)
---
.../linkeddatahub/server/filter/request/OntologyFilter.java | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
index ea9befb2b6..86a49bb048 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
@@ -38,6 +38,8 @@
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.vocabulary.OWL;
+import org.apache.jena.vocabulary.RDF;
+import org.apache.jena.vocabulary.RDFS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -168,6 +170,8 @@ public static void loadOntology(PrefixGraphRepository repository, String uri)
OntModel inferred = OntModelFactory.createModel(union.getGraph(), OntSpecification.OWL2_FULL_MEM_RDFS_INF);
OntModel materialized = OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM);
materialized.add(inferred);
+ // promote rdfs:Class to owl:Class so OWL2 profiles recognise third-party vocab terms (e.g. sp:Describe in sp.ttl)
+ inferred.listSubjectsWithProperty(RDF.type, RDFS.Class).forEach(r -> materialized.add(r, RDF.type, OWL.Class));
repository.put(uri, materialized.getGraph());
// cache imported graphs under their fragment-stripped document URIs too
closure.stream().filter(closureURI -> !closureURI.equals(uri)).forEach(importURI -> addDocumentModel(repository, importURI));
From db8d966a1154bca8c975bb493d6bb683572adb4e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?=
Date: Sat, 20 Jun 2026 23:42:06 +0200
Subject: [PATCH 13/14] Repoint PrefixGraphRepository import to Web-Client;
replace deprecated Model.write with RDFWriter
- Update imports to com.atomgraph.client.util.jena.PrefixGraphRepository (moved out of Core):
Application, OntologyFilter, OntologyRepository, SourceResolverFactory, SameSiteSourceResolver + tests
- XSLTWriterBase: use RDFWriter instead of deprecated Model.write, keeping plain RDF/XML
Co-Authored-By: Claude Opus 4.8 (1M context)
---
.../java/com/atomgraph/linkeddatahub/Application.java | 2 +-
.../server/filter/request/OntologyFilter.java | 2 +-
.../linkeddatahub/server/util/OntologyRepository.java | 2 +-
.../atomgraph/linkeddatahub/writer/XSLTWriterBase.java | 8 ++++++--
.../writer/factory/SourceResolverFactory.java | 2 +-
.../linkeddatahub/writer/impl/SameSiteSourceResolver.java | 2 +-
.../server/filter/request/OntologyFilterTest.java | 2 +-
.../request/OntologyImportsCharacterizationTest.java | 2 +-
8 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/src/main/java/com/atomgraph/linkeddatahub/Application.java b/src/main/java/com/atomgraph/linkeddatahub/Application.java
index f294aea127..d10215d954 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/Application.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/Application.java
@@ -16,7 +16,7 @@
*/
package com.atomgraph.linkeddatahub;
-import com.atomgraph.core.util.jena.PrefixGraphRepository;
+import com.atomgraph.client.util.jena.PrefixGraphRepository;
import com.atomgraph.client.util.RDFSourceResolver;
import com.atomgraph.client.util.StylesheetResolver;
import com.atomgraph.linkeddatahub.writer.impl.SameSiteSourceResolver;
diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
index 86a49bb048..5312cc2e57 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilter.java
@@ -18,7 +18,7 @@
import com.atomgraph.linkeddatahub.apps.model.Application;
import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
-import com.atomgraph.core.util.jena.PrefixGraphRepository;
+import com.atomgraph.client.util.jena.PrefixGraphRepository;
import com.atomgraph.linkeddatahub.vocabulary.LAPP;
import com.atomgraph.server.exception.OntologyException;
import java.io.IOException;
diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/util/OntologyRepository.java b/src/main/java/com/atomgraph/linkeddatahub/server/util/OntologyRepository.java
index 2d6044a8e6..14a0ded159 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/server/util/OntologyRepository.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/server/util/OntologyRepository.java
@@ -18,7 +18,7 @@
import com.atomgraph.client.vocabulary.LDT;
import com.atomgraph.core.client.GraphStoreClient;
-import com.atomgraph.core.util.jena.PrefixGraphRepository;
+import com.atomgraph.client.util.jena.PrefixGraphRepository;
import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
diff --git a/src/main/java/com/atomgraph/linkeddatahub/writer/XSLTWriterBase.java b/src/main/java/com/atomgraph/linkeddatahub/writer/XSLTWriterBase.java
index 31eb596c4b..bbdaf3442c 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/writer/XSLTWriterBase.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/writer/XSLTWriterBase.java
@@ -60,7 +60,8 @@
import org.apache.http.HttpHeaders;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.Model;
-import org.apache.jena.riot.RDFLanguages;
+import org.apache.jena.riot.RDFFormat;
+import org.apache.jena.riot.RDFWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -229,7 +230,10 @@ public StreamSource getSource(Model model) throws IOException
try (ByteArrayOutputStream stream = new ByteArrayOutputStream())
{
- model.write(stream, RDFLanguages.RDFXML.getName(), null);
+ RDFWriter.create().
+ format(RDFFormat.RDFXML_PLAIN).
+ source(model).
+ output(stream);
return new StreamSource(new ByteArrayInputStream(stream.toByteArray()));
}
}
diff --git a/src/main/java/com/atomgraph/linkeddatahub/writer/factory/SourceResolverFactory.java b/src/main/java/com/atomgraph/linkeddatahub/writer/factory/SourceResolverFactory.java
index a405a7ca23..daca9faeb5 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/writer/factory/SourceResolverFactory.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/writer/factory/SourceResolverFactory.java
@@ -19,7 +19,7 @@
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.ext.Provider;
import com.atomgraph.client.util.RDFSourceResolver;
-import com.atomgraph.core.util.jena.PrefixGraphRepository;
+import com.atomgraph.client.util.jena.PrefixGraphRepository;
import com.atomgraph.linkeddatahub.apps.model.Application;
import com.atomgraph.linkeddatahub.apps.model.EndUserApplication;
import com.atomgraph.linkeddatahub.client.GraphStoreClient;
diff --git a/src/main/java/com/atomgraph/linkeddatahub/writer/impl/SameSiteSourceResolver.java b/src/main/java/com/atomgraph/linkeddatahub/writer/impl/SameSiteSourceResolver.java
index 3449bd2b3e..72134d5afc 100644
--- a/src/main/java/com/atomgraph/linkeddatahub/writer/impl/SameSiteSourceResolver.java
+++ b/src/main/java/com/atomgraph/linkeddatahub/writer/impl/SameSiteSourceResolver.java
@@ -18,7 +18,7 @@
import com.atomgraph.client.util.RDFSourceResolver;
import com.atomgraph.core.client.GraphStoreClient;
-import com.atomgraph.core.util.jena.PrefixGraphRepository;
+import com.atomgraph.client.util.jena.PrefixGraphRepository;
import com.google.common.net.InternetDomainName;
import java.net.URI;
import org.slf4j.Logger;
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilterTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilterTest.java
index aa6b7ac80a..9478f75d2d 100644
--- a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilterTest.java
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyFilterTest.java
@@ -16,7 +16,7 @@
*/
package com.atomgraph.linkeddatahub.server.filter.request;
-import com.atomgraph.core.util.jena.PrefixGraphRepository;
+import com.atomgraph.client.util.jena.PrefixGraphRepository;
import org.apache.jena.graph.Graph;
import org.apache.jena.rdf.model.ModelFactory;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
index 00e6f0c7ce..312a614151 100644
--- a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
+++ b/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/OntologyImportsCharacterizationTest.java
@@ -16,7 +16,7 @@
*/
package com.atomgraph.linkeddatahub.server.filter.request;
-import com.atomgraph.core.util.jena.PrefixGraphRepository;
+import com.atomgraph.client.util.jena.PrefixGraphRepository;
import org.apache.jena.ontapi.OntModelFactory;
import org.apache.jena.ontapi.OntSpecification;
import org.apache.jena.ontapi.model.OntModel;
From 9fc5bb321f532df6bf0e232cc05d7674a0203158 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?=
Date: Sun, 21 Jun 2026 11:11:41 +0200
Subject: [PATCH 14/14] SNAPSHOT bump
---
pom.xml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/pom.xml b/pom.xml
index 2f436e4f87..f8fb120864 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
com.atomgraph
linkeddatahub
- 5.5.4-SNAPSHOT
+ 5.6.0-SNAPSHOT
${packaging.type}
AtomGraph LinkedDataHub
@@ -163,13 +163,13 @@
${project.groupId}
client
- 4.3.1-SNAPSHOT
+ 4.4.0-SNAPSHOT
classes
${project.groupId}
client
- 4.3.1-SNAPSHOT
+ 4.4.0-SNAPSHOT
war