From 55e32d4a03269b35f308018a830e63de2cdba7be Mon Sep 17 00:00:00 2001 From: Tony Date: Sun, 4 Feb 2024 16:18:53 +0000 Subject: [PATCH 01/10] Added support for inferencing using the MagmaCoreService. --- .../magmacore/database/MagmaCoreDatabase.java | 12 +++ .../database/MagmaCoreJenaDatabase.java | 27 ++++++ .../MagmaCoreRemoteSparqlDatabase.java | 73 +++++++++++---- .../magmacore/service/MagmaCoreService.java | 15 ++++ .../MagmaCoreServiceInferencingTest.java | 90 +++++++++++++++++++ .../service/SignPatternTestData.java | 2 +- 6 files changed, 202 insertions(+), 17 deletions(-) create mode 100644 core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceInferencingTest.java diff --git a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreDatabase.java b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreDatabase.java index 1797b1fd..90c4ee1d 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreDatabase.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreDatabase.java @@ -181,4 +181,16 @@ public interface MagmaCoreDatabase { * @return a {@link List} of {@link Thing} */ List executeConstruct(final String query); + + /** + * Apply a set of inference rules to a subset of the model and return a MagmaCoreService attached to + * the resulting inference model for further use by the caller. + * + * @param query a SPARQL query String to extract a subset of the model for inferencing. + * @param rules a set of inference rules to be applied to the model subset. + * @param includeRdfsRules boolean true if inferencing should include the standard RDFS entailments. + * @return an in-memory MagmaCoreDatabase attached to the inferencing results which is + * independent of the source dataset. + */ + MagmaCoreDatabase applyInferenceRules(final String query, final String rules, final boolean includeRdfsRules); } diff --git a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java index b50bb1ad..e0555849 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java @@ -40,6 +40,8 @@ import org.apache.jena.rdf.model.Resource; import org.apache.jena.rdf.model.Statement; import org.apache.jena.rdf.model.StmtIterator; +import org.apache.jena.reasoner.rulesys.GenericRuleReasoner; +import org.apache.jena.reasoner.rulesys.Rule; import org.apache.jena.riot.Lang; import org.apache.jena.riot.RDFDataMgr; import org.apache.jena.tdb2.TDB2Factory; @@ -474,4 +476,29 @@ public final void load(final InputStream in, final Lang language) { RDFDataMgr.read(model, in, language); commit(); } + + /** + * {@inheritDoc} + */ + @Override + public MagmaCoreDatabase applyInferenceRules( + final String constructQuery, + final String rules, + final boolean includeRdfsRules) { + // Execute the query to get a subset of the data model. + final QueryExecution queryExec = QueryExecutionFactory.create(constructQuery, dataset); + final Model subset = queryExec.execConstruct(); + + // Parse the rules and create a reasoner using the rules and the sunset Model. + final List ruleSet = Rule.parseRules(rules); + final GenericRuleReasoner reasoner = new GenericRuleReasoner(ruleSet); + + // Create an Inference Model which will run the rules. + final Model model = ModelFactory.createInfModel(reasoner, subset); + + // Convert the inference model to a dataset and return it wrapped as + // an in-memory MagmaCoreDatabase. + final Dataset inferenceDataset = DatasetFactory.create(model); + return new MagmaCoreJenaDatabase(inferenceDataset); + } } diff --git a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreRemoteSparqlDatabase.java b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreRemoteSparqlDatabase.java index cbad7c1a..99e97f9d 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreRemoteSparqlDatabase.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreRemoteSparqlDatabase.java @@ -24,6 +24,7 @@ import java.util.stream.Collectors; import org.apache.jena.query.Dataset; +import org.apache.jena.query.DatasetFactory; import org.apache.jena.query.Query; import org.apache.jena.query.QueryExecution; import org.apache.jena.query.QueryExecutionFactory; @@ -41,6 +42,8 @@ import org.apache.jena.rdf.model.StmtIterator; import org.apache.jena.rdfconnection.RDFConnection; import org.apache.jena.rdfconnection.RDFConnectionRemote; +import org.apache.jena.reasoner.rulesys.GenericRuleReasoner; +import org.apache.jena.reasoner.rulesys.Rule; import org.apache.jena.riot.Lang; import org.apache.jena.riot.RDFDataMgr; import org.apache.jena.riot.RDFFormat; @@ -69,7 +72,7 @@ public class MagmaCoreRemoteSparqlDatabase implements MagmaCoreDatabase { */ public MagmaCoreRemoteSparqlDatabase(final String serviceUrl) { connection = RDFConnectionRemote.newBuilder().destination(serviceUrl).queryEndpoint("query") - .updateEndpoint("update").triplesFormat(RDFFormat.RDFJSON).build(); + .updateEndpoint("update").triplesFormat(RDFFormat.RDFJSON).build(); } /** @@ -143,7 +146,8 @@ public final void commit() { @Override public Thing get(final IRI iri) { - final String query = String.format("SELECT (<%1$s> as ?s) ?p ?o WHERE {<%1$s> ?p ?o.}", iri.toString()); + final String query = String.format("SELECT (<%1$s> as ?s) ?p ?o WHERE {<%1$s> ?p ?o.}", + iri.toString()); final QueryResultList list = executeQuery(query); final List objects = toTopObjects(list); @@ -189,6 +193,7 @@ public void create(final List creates) { final Object value = create.object; final RDFNode o; + if (value instanceof IRI) { o = forCreation.createResource(value.toString()); } else { @@ -214,7 +219,8 @@ public void update(final Thing object) { */ @Override public void delete(final Thing object) { - executeUpdate(String.format("delete {<%s> ?p ?o} WHERE {<%s> ?p ?o}", object.getId(), object.getId())); + executeUpdate(String.format("delete {<%s> ?p ?o} WHERE {<%s> ?p ?o}", object.getId(), + object.getId())); } /** @@ -258,7 +264,7 @@ public void delete(final List deletes) { @Override public List findByPredicateIri(final IRI predicateIri, final IRI objectIri) { final String query = "SELECT ?s ?p ?o WHERE {?s ?p ?o. ?s <" + predicateIri.toString() + "> <" - + objectIri.toString() + ">.}"; + + objectIri.toString() + ">.}"; final QueryResultList list = executeQuery(query); return toTopObjects(list); } @@ -268,8 +274,9 @@ public List findByPredicateIri(final IRI predicateIri, final IRI objectIr */ @Override public List findByPredicateIriOnly(final IRI predicateIri) { - final String query = "SELECT ?s ?p ?o WHERE {{select ?s ?p ?o where { ?s ?p ?o.}}{select ?s where {?s <" - + predicateIri.toString() + "> ?o.}}}"; + final String query = + "SELECT ?s ?p ?o WHERE {{select ?s ?p ?o where { ?s ?p ?o.}}{select ?s where {?s <" + + predicateIri.toString() + "> ?o.}}}"; final QueryResultList list = executeQuery(query); return toTopObjects(list); } @@ -288,6 +295,7 @@ public List findByPredicateIriAndValue(final IRI predicateIri, final Obje query = "SELECT ?s ?p ?o WHERE { ?s ?p ?o. ?s <" + predicateIri.toString() + "> \"\"\"" + value + "\"\"\".}"; } + final QueryResultList list = executeQuery(query); return toTopObjects(list); } @@ -296,10 +304,12 @@ public List findByPredicateIriAndValue(final IRI predicateIri, final Obje * {@inheritDoc} */ @Override - public List findByPredicateIriAndStringCaseInsensitive(final IRI predicateIri, final String value) { - final String query = "SELECT ?s ?p ?o WHERE {{ SELECT ?s ?p ?o where { ?s ?p ?o.}}{select ?s where {?s <" - + predicateIri.toString() + "> ?o. BIND(LCASE(?o) AS ?lcase) FILTER(?lcase= \"\"\"" + value - + "\"\"\")}}}"; + public List findByPredicateIriAndStringCaseInsensitive(final IRI predicateIri, + final String value) { + final String query = + "SELECT ?s ?p ?o WHERE {{ SELECT ?s ?p ?o where { ?s ?p ?o.}}{select ?s where {?s <" + + predicateIri.toString() + "> ?o. BIND(LCASE(?o) AS ?lcase) FILTER(?lcase= \"\"\"" + value + + "\"\"\")}}}"; final QueryResultList list = executeQuery(query); return toTopObjects(list); } @@ -350,7 +360,9 @@ public QueryResultList executeQuery(final String sparqlQueryString) { private final QueryResultList getQueryResultList(final QueryExecution queryExec) { final ResultSet resultSet = queryExec.execSelect(); final List queryResults = new ArrayList<>(); - final QueryResultList queryResultList = new QueryResultList(resultSet.getResultVars(), queryResults); + final QueryResultList queryResultList = new QueryResultList(resultSet.getResultVars(), + queryResults); + while (resultSet.hasNext()) { final QuerySolution querySolution = resultSet.next(); final Iterator varNames = querySolution.varNames(); @@ -361,8 +373,10 @@ private final QueryResultList getQueryResultList(final QueryExecution queryExec) final RDFNode node = querySolution.get(varName); queryResult.set(varName, node); } + queryResults.add(queryResult); } + queryExec.close(); return queryResultList; } @@ -388,6 +402,7 @@ public final List toTopObjects(final QueryResultList queryResultsList) { final RDFNode objectValue = queryResult.get(objectVarName); List> dataModelObject = objectMap.get(subjectValue); + if (dataModelObject == null) { dataModelObject = new ArrayList<>(); objectMap.put(subjectValue, dataModelObject); @@ -395,17 +410,18 @@ public final List toTopObjects(final QueryResultList queryResultsList) { if (objectValue instanceof Literal) { dataModelObject.add(new Pair<>(new IRI(predicateValue.toString()), objectValue.toString())); } else if (objectValue instanceof Resource) { - dataModelObject.add(new Pair<>(new IRI(predicateValue.toString()), new IRI(objectValue.toString()))); + dataModelObject.add(new Pair<>(new IRI(predicateValue.toString()), + new IRI(objectValue.toString()))); } else { throw new RuntimeException("objectValue is of unknown type: " + objectValue.getClass()); } }); return objectMap - .entrySet() - .stream() - .map(entry -> HqdmObjectFactory.create(new IRI(entry.getKey().toString()), entry.getValue())) - .collect(Collectors.toList()); + .entrySet() + .stream() + .map(entry -> HqdmObjectFactory.create(new IRI(entry.getKey().toString()), entry.getValue())) + .collect(Collectors.toList()); } /** @@ -448,4 +464,29 @@ public final void load(final InputStream in, final Lang language) { connection.load(model); commit(); } + + /** + * {@inheritDoc} + */ + @Override + public MagmaCoreDatabase applyInferenceRules( + final String constructQuery, + final String rules, + final boolean includeRdfsRules) { + // Execute the query to get a subset of the data model. + final QueryExecution queryExec = connection.query(constructQuery); + final Model subset = queryExec.execConstruct(); + + // Parse the rules and create a reasoner using the rules and the sunset Model. + final List ruleSet = Rule.parseRules(rules); + final GenericRuleReasoner reasoner = new GenericRuleReasoner(ruleSet); + + // Create an Inference Model which will run the rules. + final Model model = ModelFactory.createInfModel(reasoner, subset); + + // Convert the inference model to a dataset and return it wrapped as + // an in-memory MagmaCoreDatabase. + final Dataset inferenceDataset = DatasetFactory.create(model); + return new MagmaCoreJenaDatabase(inferenceDataset); + } } diff --git a/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java b/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java index f68e5d61..b7a38ab4 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java @@ -915,4 +915,19 @@ public void abort() { public QueryResultList executeQuery(final String query) { return database.executeQuery(query); } + + /** + * Apply a set of inference rules to a subset of the model and return a MagmaCoreService attached to + * the resulting inference model for further use by the caller. + * + * @param query a SPARQL query String to extract a subset of the model for inferencing. + * @param rules a set of inference rules to be applied to the model subset. + * @param includeRdfsRules boolean true if inferencing should include the standard RDFS entailments. + * @return an in-memory MagmaCoreService attached to the inferencing results which is independent of the source dataset. + */ + public MagmaCoreService applyInferenceRules(final String query, final String rules, final boolean includeRdfsRules) { + // This functionality is likely to be database-implementation-specific, so delegate. + final MagmaCoreDatabase db = database.applyInferenceRules(query, rules, includeRdfsRules); + return new MagmaCoreService(db); + } } diff --git a/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceInferencingTest.java b/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceInferencingTest.java new file mode 100644 index 00000000..fbc2c437 --- /dev/null +++ b/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceInferencingTest.java @@ -0,0 +1,90 @@ +/* + * Copyright 2021 Crown Copyright + * + * 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 uk.gov.gchq.magmacore.service; + +import static org.junit.Assert.assertEquals; + +import java.io.FileNotFoundException; +import java.util.List; + +import org.junit.Test; + +import uk.gov.gchq.magmacore.database.MagmaCoreDatabase; +import uk.gov.gchq.magmacore.database.MagmaCoreJenaDatabase; +import uk.gov.gchq.magmacore.exception.MagmaCoreException; +import uk.gov.gchq.magmacore.hqdm.rdf.iri.IRI; +import uk.gov.gchq.magmacore.hqdm.rdf.iri.IriBase; +import uk.gov.gchq.magmacore.service.transformation.DbChangeSet; +import uk.gov.gchq.magmacore.service.transformation.DbCreateOperation; +import uk.gov.gchq.magmacore.service.transformation.DbTransformation; + +/** + * Check that {@link MagmaCoreService} works correctly. + */ +public class MagmaCoreServiceInferencingTest { + private static final String RULE_SET = """ + +@prefix ex: . + +[transitiveDependencies: + (?x ex:depends_on ?y) (?y ex:depends_on ?z) + -> + (?x ex:depends_on ?z) +] + """; + private static final IriBase TEST_BASE = new IriBase("test", "http://example.com/test#"); + private static final IRI DEPENDS_ON = new IRI(TEST_BASE, "depends_on"); + + /** + * Test that inferencing can be performed using the MagmaCoreService. + * + * @throws FileNotFoundException if the file cannot be accessed. + */ + @Test + public void test() throws MagmaCoreException, FileNotFoundException { + + // Create and populate an in-memory database. + final MagmaCoreDatabase db = new MagmaCoreJenaDatabase(); + SignPatternTestData.createSignPattern(db); + + // Use it to create the services + final MagmaCoreService service = new MagmaCoreService(db); + + // Add some data. + final var a = new IRI(TEST_BASE, "a"); + final var b = new IRI(TEST_BASE, "b"); + final var c = new IRI(TEST_BASE, "c"); + + final var changes = List.of(new DbChangeSet( + List.of(), + List.of( + new DbCreateOperation(a, DEPENDS_ON, b), + new DbCreateOperation(b, DEPENDS_ON, c) + ) + )); + final var transform = new DbTransformation(changes); + service.runInWriteTransaction(transform); + + // Use a CONSTRUCT query to subselect from the model. + final String query = "CONSTRUCT {?s ?p ?o} WHERE {?s ?p ?o}"; + final MagmaCoreService inferencingSvc = service.applyInferenceRules(query, RULE_SET, false); + + // Query the database to check the result. + final var result = inferencingSvc.executeQuery("PREFIX ex: SELECT * WHERE {?s ex:depends_on ?o.}"); + + // The result should be 3 since " a depends_on c" is inferred. + assertEquals(3, result.getQueryResults().size()); + } +} diff --git a/core/src/test/java/uk/gov/gchq/magmacore/service/SignPatternTestData.java b/core/src/test/java/uk/gov/gchq/magmacore/service/SignPatternTestData.java index b6cc51c6..4d55e13a 100644 --- a/core/src/test/java/uk/gov/gchq/magmacore/service/SignPatternTestData.java +++ b/core/src/test/java/uk/gov/gchq/magmacore/service/SignPatternTestData.java @@ -39,7 +39,7 @@ */ public class SignPatternTestData { - static final IriBase TEST_BASE = new IriBase("test", "http://example.com/test#"); + public static final IriBase TEST_BASE = new IriBase("test", "http://example.com/test#"); static RecognizingLanguageCommunity community1; static RecognizingLanguageCommunity community2; static Pattern pattern1; From d725c3818fa22677b33694421432db56110c3e34 Mon Sep 17 00:00:00 2001 From: Tony Date: Mon, 5 Feb 2024 12:15:44 +0000 Subject: [PATCH 02/10] Added a validation service and a simple unit test. --- core/src/main/java/module-info.java | 1 + .../magmacore/database/MagmaCoreDatabase.java | 23 +++++- .../database/MagmaCoreJenaDatabase.java | 65 +++++++++++++-- .../MagmaCoreRemoteSparqlDatabase.java | 65 +++++++++++++-- .../validation/ValidationReportEntry.java | 7 ++ .../magmacore/service/MagmaCoreService.java | 14 ++++ .../MagmaCoreServiceInferencingTest.java | 79 ++++++++++++++++--- 7 files changed, 231 insertions(+), 23 deletions(-) create mode 100644 core/src/main/java/uk/gov/gchq/magmacore/database/validation/ValidationReportEntry.java diff --git a/core/src/main/java/module-info.java b/core/src/main/java/module-info.java index 7978739f..e55e2a31 100644 --- a/core/src/main/java/module-info.java +++ b/core/src/main/java/module-info.java @@ -29,6 +29,7 @@ requires transitive uk.gov.gchq.magmacore.hqdm; exports uk.gov.gchq.magmacore.database.query; + exports uk.gov.gchq.magmacore.database.validation; exports uk.gov.gchq.magmacore.exception; exports uk.gov.gchq.magmacore.service.dto; exports uk.gov.gchq.magmacore.service.transformation; diff --git a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreDatabase.java b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreDatabase.java index 90c4ee1d..8207f52d 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreDatabase.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreDatabase.java @@ -21,6 +21,7 @@ import org.apache.jena.riot.Lang; import uk.gov.gchq.magmacore.database.query.QueryResultList; +import uk.gov.gchq.magmacore.database.validation.ValidationReportEntry; import uk.gov.gchq.magmacore.hqdm.model.Thing; import uk.gov.gchq.magmacore.hqdm.rdf.iri.IRI; import uk.gov.gchq.magmacore.service.transformation.DbCreateOperation; @@ -186,11 +187,29 @@ public interface MagmaCoreDatabase { * Apply a set of inference rules to a subset of the model and return a MagmaCoreService attached to * the resulting inference model for further use by the caller. * - * @param query a SPARQL query String to extract a subset of the model for inferencing. + * @param constructQuery a SPARQL query String to extract a subset of the model for inferencing. * @param rules a set of inference rules to be applied to the model subset. * @param includeRdfsRules boolean true if inferencing should include the standard RDFS entailments. * @return an in-memory MagmaCoreDatabase attached to the inferencing results which is * independent of the source dataset. */ - MagmaCoreDatabase applyInferenceRules(final String query, final String rules, final boolean includeRdfsRules); + MagmaCoreDatabase applyInferenceRules( + final String constructQuery, + final String rules, + final boolean includeRdfsRules); + + /** + * Run a validation report. This is only valid for databases obtained from + * the {@link MagmaCoreDatabase.applyInferenceRules} method. + * + * @param constructQuery a SPARQL query String to extract a subset of the model for inferencing. + * @param rules a set of inference rules to be applied to the model subset. + * @param includeRdfsRules boolean true if inferencing should include the standard RDFS entailments. + * @return A {@link List} of {@link ValidationReportEntry} objects. + * It will be Optional.empty if the underlying database is not an inference model. + */ + List validate( + final String constructQuery, + final String rules, + final boolean includeRdfsRules); } diff --git a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java index e0555849..bfe182c0 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java @@ -32,6 +32,7 @@ import org.apache.jena.query.QuerySolution; import org.apache.jena.query.ResultSet; import org.apache.jena.query.TxnType; +import org.apache.jena.rdf.model.InfModel; import org.apache.jena.rdf.model.Literal; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.ModelFactory; @@ -40,6 +41,8 @@ import org.apache.jena.rdf.model.Resource; import org.apache.jena.rdf.model.Statement; import org.apache.jena.rdf.model.StmtIterator; +import org.apache.jena.reasoner.ValidityReport; +import org.apache.jena.reasoner.ValidityReport.Report; import org.apache.jena.reasoner.rulesys.GenericRuleReasoner; import org.apache.jena.reasoner.rulesys.Rule; import org.apache.jena.riot.Lang; @@ -53,6 +56,7 @@ import uk.gov.gchq.magmacore.database.query.QueryResult; import uk.gov.gchq.magmacore.database.query.QueryResultList; +import uk.gov.gchq.magmacore.database.validation.ValidationReportEntry; import uk.gov.gchq.magmacore.hqdm.model.Thing; import uk.gov.gchq.magmacore.hqdm.rdf.HqdmObjectFactory; import uk.gov.gchq.magmacore.hqdm.rdf.iri.IRI; @@ -485,6 +489,60 @@ public MagmaCoreDatabase applyInferenceRules( final String constructQuery, final String rules, final boolean includeRdfsRules) { + // Create an Inference Model which will run the rules. + final InfModel model = getInferenceModel(constructQuery, rules, includeRdfsRules); + + // Convert the inference model to a dataset and return it wrapped as + // an in-memory MagmaCoreDatabase. + final Dataset inferenceDataset = DatasetFactory.create(); + inferenceDataset.getDefaultModel().add(model); + return new MagmaCoreJenaDatabase(inferenceDataset); + } + + /** + * {@inheritDoc} + */ + @Override + public List validate(final String constructQuery, + final String rules, + final boolean includeRdfsRules) { + // + // Create an Inference Model which will run the rules. + final InfModel model = getInferenceModel(constructQuery, rules, includeRdfsRules); + + // Run the validation. + final ValidityReport validityReport = model.validate(); + + // Convert the result to be non-Jena-specific. + final List entries = new ArrayList<>(); + final Iterator reports = validityReport.getReports(); + + while (reports.hasNext()) { + final Report report = reports.next(); + + entries.add(new ValidationReportEntry( + report.getType(), + report.getExtension(), + report.getDescription() + )); + } + + return entries; + } + + /** + * Create an in-memory model for inferencing. + * + * @param constructQuery {@link String} + * @param rules {@link String} + * @param includeRdfsRules boolean + * @return {@link InfModel} + */ + private InfModel getInferenceModel( + final String constructQuery, + final String rules, + final boolean includeRdfsRules) { + // Get the default Model // Execute the query to get a subset of the data model. final QueryExecution queryExec = QueryExecutionFactory.create(constructQuery, dataset); final Model subset = queryExec.execConstruct(); @@ -494,11 +552,6 @@ public MagmaCoreDatabase applyInferenceRules( final GenericRuleReasoner reasoner = new GenericRuleReasoner(ruleSet); // Create an Inference Model which will run the rules. - final Model model = ModelFactory.createInfModel(reasoner, subset); - - // Convert the inference model to a dataset and return it wrapped as - // an in-memory MagmaCoreDatabase. - final Dataset inferenceDataset = DatasetFactory.create(model); - return new MagmaCoreJenaDatabase(inferenceDataset); + return ModelFactory.createInfModel(reasoner, subset); } } diff --git a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreRemoteSparqlDatabase.java b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreRemoteSparqlDatabase.java index 99e97f9d..130c7f6a 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreRemoteSparqlDatabase.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreRemoteSparqlDatabase.java @@ -32,6 +32,7 @@ import org.apache.jena.query.QuerySolution; import org.apache.jena.query.ResultSet; import org.apache.jena.query.TxnType; +import org.apache.jena.rdf.model.InfModel; import org.apache.jena.rdf.model.Literal; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.ModelFactory; @@ -42,6 +43,8 @@ import org.apache.jena.rdf.model.StmtIterator; import org.apache.jena.rdfconnection.RDFConnection; import org.apache.jena.rdfconnection.RDFConnectionRemote; +import org.apache.jena.reasoner.ValidityReport; +import org.apache.jena.reasoner.ValidityReport.Report; import org.apache.jena.reasoner.rulesys.GenericRuleReasoner; import org.apache.jena.reasoner.rulesys.Rule; import org.apache.jena.riot.Lang; @@ -51,6 +54,7 @@ import uk.gov.gchq.magmacore.database.query.QueryResult; import uk.gov.gchq.magmacore.database.query.QueryResultList; +import uk.gov.gchq.magmacore.database.validation.ValidationReportEntry; import uk.gov.gchq.magmacore.hqdm.model.Thing; import uk.gov.gchq.magmacore.hqdm.rdf.HqdmObjectFactory; import uk.gov.gchq.magmacore.hqdm.rdf.iri.IRI; @@ -473,6 +477,60 @@ public MagmaCoreDatabase applyInferenceRules( final String constructQuery, final String rules, final boolean includeRdfsRules) { + + // Create an Inference Model which will run the rules. + final InfModel model = getInferenceModel(constructQuery, rules, includeRdfsRules); + + // Convert the inference model to a dataset and return it wrapped as + // an in-memory MagmaCoreDatabase. + final Dataset inferenceDataset = DatasetFactory.create(model); + return new MagmaCoreJenaDatabase(inferenceDataset); + } + + /** + * {@inheritDoc} + */ + @Override + public List validate( + final String constructQuery, + final String rules, + final boolean includeRdfsRules) { + // + // Create an Inference Model which will run the rules. + final InfModel model = getInferenceModel(constructQuery, rules, includeRdfsRules); + + // Run the validation. + final ValidityReport validityReport = model.validate(); + + // Convert the result to be non-Jena-specific. + final List entries = new ArrayList<>(); + final Iterator reports = validityReport.getReports(); + + while (reports.hasNext()) { + final Report report = reports.next(); + + entries.add(new ValidationReportEntry( + report.getType(), + report.getExtension(), + report.getDescription() + )); + } + + return entries; + } + + /** + * Create an in-memory model for inferencing. + * + * @param constructQuery {@link String} + * @param rules {@link String} + * @param includeRdfsRules boolean + * @return {@link InfModel} + */ + private InfModel getInferenceModel( + final String constructQuery, + final String rules, + final boolean includeRdfsRules) { // Execute the query to get a subset of the data model. final QueryExecution queryExec = connection.query(constructQuery); final Model subset = queryExec.execConstruct(); @@ -482,11 +540,6 @@ public MagmaCoreDatabase applyInferenceRules( final GenericRuleReasoner reasoner = new GenericRuleReasoner(ruleSet); // Create an Inference Model which will run the rules. - final Model model = ModelFactory.createInfModel(reasoner, subset); - - // Convert the inference model to a dataset and return it wrapped as - // an in-memory MagmaCoreDatabase. - final Dataset inferenceDataset = DatasetFactory.create(model); - return new MagmaCoreJenaDatabase(inferenceDataset); + return ModelFactory.createInfModel(reasoner, subset); } } diff --git a/core/src/main/java/uk/gov/gchq/magmacore/database/validation/ValidationReportEntry.java b/core/src/main/java/uk/gov/gchq/magmacore/database/validation/ValidationReportEntry.java new file mode 100644 index 00000000..43198dc8 --- /dev/null +++ b/core/src/main/java/uk/gov/gchq/magmacore/database/validation/ValidationReportEntry.java @@ -0,0 +1,7 @@ +package uk.gov.gchq.magmacore.database.validation; + +/** + * An implementation agnostic model validation report entry. + */ +public record ValidationReportEntry(String type, Object additionalInformation, String description) {} + diff --git a/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java b/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java index b7a38ab4..0790d5db 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java @@ -31,6 +31,7 @@ import uk.gov.gchq.magmacore.database.MagmaCoreDatabase; import uk.gov.gchq.magmacore.database.query.QueryResult; import uk.gov.gchq.magmacore.database.query.QueryResultList; +import uk.gov.gchq.magmacore.database.validation.ValidationReportEntry; import uk.gov.gchq.magmacore.exception.MagmaCoreException; import uk.gov.gchq.magmacore.hqdm.model.Individual; import uk.gov.gchq.magmacore.hqdm.model.KindOfAssociation; @@ -930,4 +931,17 @@ public MagmaCoreService applyInferenceRules(final String query, final String rul final MagmaCoreDatabase db = database.applyInferenceRules(query, rules, includeRdfsRules); return new MagmaCoreService(db); } + + /** + * Apply a set of inference rules to a subset of the model and return a List of ValidationReportEntry objects. + * + * @param query a SPARQL query String to extract a subset of the model for inferencing. + * @param rules a set of inference rules to be applied to the model subset. + * @param includeRdfsRules boolean true if inferencing should include the standard RDFS entailments. + * @return A {@link List} of {@link ValidationReportEntry} objects. + * It will be Optional.empty if the underlying database is not an inference model. + */ + public List validate(final String query, final String rules, final boolean includeRdfsRules) { + return database.validate(query, rules, includeRdfsRules); + } } diff --git a/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceInferencingTest.java b/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceInferencingTest.java index fbc2c437..e0bdf028 100644 --- a/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceInferencingTest.java +++ b/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceInferencingTest.java @@ -15,14 +15,19 @@ package uk.gov.gchq.magmacore.service; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.io.FileNotFoundException; import java.util.List; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.impl.ResourceImpl; import org.junit.Test; import uk.gov.gchq.magmacore.database.MagmaCoreDatabase; import uk.gov.gchq.magmacore.database.MagmaCoreJenaDatabase; +import uk.gov.gchq.magmacore.database.query.QueryResultList; +import uk.gov.gchq.magmacore.database.validation.ValidationReportEntry; import uk.gov.gchq.magmacore.exception.MagmaCoreException; import uk.gov.gchq.magmacore.hqdm.rdf.iri.IRI; import uk.gov.gchq.magmacore.hqdm.rdf.iri.IriBase; @@ -43,17 +48,22 @@ public class MagmaCoreServiceInferencingTest { -> (?x ex:depends_on ?z) ] + +[validationRule1: + (?y rb:violation error('Object has ex:some_predicate', 'No objects should have ex:some_predicate', ?s)) + <- + (?s ex:some_predicate ?value) +] """; private static final IriBase TEST_BASE = new IriBase("test", "http://example.com/test#"); private static final IRI DEPENDS_ON = new IRI(TEST_BASE, "depends_on"); + private static final IRI SOME_PREDICATE = new IRI(TEST_BASE, "some_predicate"); /** * Test that inferencing can be performed using the MagmaCoreService. - * - * @throws FileNotFoundException if the file cannot be accessed. */ @Test - public void test() throws MagmaCoreException, FileNotFoundException { + public void testInferencingSuccess() throws MagmaCoreException, FileNotFoundException { // Create and populate an in-memory database. final MagmaCoreDatabase db = new MagmaCoreJenaDatabase(); @@ -63,18 +73,18 @@ public void test() throws MagmaCoreException, FileNotFoundException { final MagmaCoreService service = new MagmaCoreService(db); // Add some data. - final var a = new IRI(TEST_BASE, "a"); - final var b = new IRI(TEST_BASE, "b"); - final var c = new IRI(TEST_BASE, "c"); + final IRI a = new IRI(TEST_BASE, "a"); + final IRI b = new IRI(TEST_BASE, "b"); + final IRI c = new IRI(TEST_BASE, "c"); - final var changes = List.of(new DbChangeSet( + final List changes = List.of(new DbChangeSet( List.of(), List.of( new DbCreateOperation(a, DEPENDS_ON, b), new DbCreateOperation(b, DEPENDS_ON, c) ) )); - final var transform = new DbTransformation(changes); + final DbTransformation transform = new DbTransformation(changes); service.runInWriteTransaction(transform); // Use a CONSTRUCT query to subselect from the model. @@ -82,9 +92,60 @@ public void test() throws MagmaCoreException, FileNotFoundException { final MagmaCoreService inferencingSvc = service.applyInferenceRules(query, RULE_SET, false); // Query the database to check the result. - final var result = inferencingSvc.executeQuery("PREFIX ex: SELECT * WHERE {?s ex:depends_on ?o.}"); + final QueryResultList result = inferencingSvc.executeQuery("PREFIX ex: SELECT * WHERE {?s ex:depends_on ?o.}"); // The result should be 3 since " a depends_on c" is inferred. assertEquals(3, result.getQueryResults().size()); + + // Make sure there are no validation errors. + final List entries = inferencingSvc.validate(query, RULE_SET, true); + assertEquals(0, entries.size()); + } + + /** + * Test that inferencing can be performed using the MagmaCoreService. + */ + @Test + public void testInferencingValidationFail() throws MagmaCoreException, FileNotFoundException { + + // Create and populate an in-memory database. + final MagmaCoreDatabase db = new MagmaCoreJenaDatabase(); + SignPatternTestData.createSignPattern(db); + + // Use it to create the services + final MagmaCoreService service = new MagmaCoreService(db); + + // Add some data. + final IRI a = new IRI(TEST_BASE, "a"); + final IRI b = new IRI(TEST_BASE, "b"); + final IRI c = new IRI(TEST_BASE, "c"); + + final List changes = List.of(new DbChangeSet( + List.of(), + List.of( + new DbCreateOperation(a, DEPENDS_ON, b), + new DbCreateOperation(b, DEPENDS_ON, c), + new DbCreateOperation(b, SOME_PREDICATE, "This predicate is invalid") + ) + )); + final DbTransformation transform = new DbTransformation(changes); + service.runInWriteTransaction(transform); + + // Use a CONSTRUCT query to subselect from the model. + final String query = "CONSTRUCT {?s ?p ?o} WHERE {?s ?p ?o}"; + + // Make sure there are no validation errors. + final List entries = service.validate(query, RULE_SET, false); + + assertEquals(1, entries.size()); + + final ValidationReportEntry entry = entries.get(0); + + assertEquals("\"Object has ex:some_predicate\"", entry.type()); + assertEquals("\"No objects should have ex:some_predicate\"\nCulprit = *\nImplicated node: \n", entry.description()); + assertTrue(entry.additionalInformation() instanceof ResourceImpl); + + final Resource resource = (Resource) entry.additionalInformation(); + assertEquals("*", resource.toString()); } } From 3c9a3d1ef9d2d365270ffbe1d83d0e6c9b861171 Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 7 Feb 2024 12:29:25 +0000 Subject: [PATCH 03/10] Started an example for data integrity checking. --- .gitignore | 1 - .../magmacore/service/MagmaCoreService.java | 9 + .../verify/DataIntegrityChecksTest.java | 67 + .../src/test/resources/hqdm-0.0.1-alpha.ttl | 1100 +++++++++++++++++ examples/src/test/resources/validation.rules | 16 + 5 files changed, 1192 insertions(+), 1 deletion(-) create mode 100644 examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java create mode 100644 examples/src/test/resources/hqdm-0.0.1-alpha.ttl create mode 100644 examples/src/test/resources/validation.rules diff --git a/.gitignore b/.gitignore index a93a114f..81695d52 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,6 @@ tdb/ out *.code-workspace *.iml -*.ttl .DS_Store .factorypath .devcontainer diff --git a/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java b/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java index 1d3836c6..c5a0bead 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java @@ -966,4 +966,13 @@ public MagmaCoreService applyInferenceRules(final String query, final String rul public List validate(final String query, final String rules, final boolean includeRdfsRules) { return database.validate(query, rules, includeRdfsRules); } + + /** + * Load some TTL from an InputStream. + * + * @param stream {@link InputStream} + */ + public void loadTtl(final InputStream stream) { + database.load(stream, Lang.TTL); + } } diff --git a/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java b/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java new file mode 100644 index 00000000..c131478b --- /dev/null +++ b/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java @@ -0,0 +1,67 @@ +package uk.gov.gchq.magmacore.examples.verify; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; +import java.util.UUID; + +import org.junit.Test; + +import uk.gov.gchq.magmacore.database.validation.ValidationReportEntry; +import uk.gov.gchq.magmacore.hqdm.model.Thing; +import uk.gov.gchq.magmacore.hqdm.rdf.iri.IRI; +import uk.gov.gchq.magmacore.hqdm.rdf.iri.IriBase; +import uk.gov.gchq.magmacore.hqdm.services.ClassServices; +import uk.gov.gchq.magmacore.service.MagmaCoreService; +import uk.gov.gchq.magmacore.service.MagmaCoreServiceFactory; + +/** + * An example of how to use Jena rules for Data Integrity Checking. + */ +public class DataIntegrityChecksTest { + + private static final boolean INCLUDE_RDFS = true; + private static final IriBase TEST_BASE = new IriBase("test", "http://example.com/test#"); + + /** + * Run some data integrity checks. + * + * @throws URISyntaxException if the URI is invalid. + * @throws IOException if the rules file can't be read. + */ + @Test + public void test() throws IOException, URISyntaxException { + + // Create the in-memory MagmaCoreService object. + final MagmaCoreService service = MagmaCoreServiceFactory.createWithJenaDatabase(); + + // Load the HQDM data model. + service.loadTtl(getClass().getResourceAsStream("/hqdm-0.0.1-alpha.ttl")); + + // Populate some data to prove that the rules are applied. + service.runInWriteTransaction(svc -> { + + // Create a kind without an ENTITY_NAME. + final Thing kind = ClassServices.createKindOfOrganization(new IRI(TEST_BASE, UUID.randomUUID().toString())); + svc.create(kind); + return svc; + }); + + // Create the construct query and load the validation rules. + final String query = "CONSTRUCT {?s ?p ?o} WHERE {?s ?p ?o}"; + final String rules = Files.readString(Paths.get(getClass().getResource("/validation.rules").toURI())); + + // Validate the model. + final List validationResult = service.validate(query, rules, INCLUDE_RDFS); + + if (validationResult.size() > 0) { + System.out.println(validationResult); + } + assertEquals(1, validationResult.size()); + } + +} diff --git a/examples/src/test/resources/hqdm-0.0.1-alpha.ttl b/examples/src/test/resources/hqdm-0.0.1-alpha.ttl new file mode 100644 index 00000000..c9df2316 --- /dev/null +++ b/examples/src/test/resources/hqdm-0.0.1-alpha.ttl @@ -0,0 +1,1100 @@ + +@prefix hqdm: . +@prefix rdfs: . +@prefix rdf: . +@prefix xsd: . + +hqdm:abstract_object rdf:type rdfs:Class . +hqdm:abstract_object rdfs:subClassOf hqdm:thing . +hqdm:acceptance_of_offer rdf:type rdfs:Class . +hqdm:acceptance_of_offer rdfs:subClassOf hqdm:socially_constructed_activity . +hqdm:acceptance_of_offer_for_goods rdf:type rdfs:Class . +hqdm:acceptance_of_offer_for_goods rdfs:subClassOf hqdm:acceptance_of_offer . +hqdm:acceptance_of_offer_for_goods_part_of rdfs:domain hqdm:acceptance_of_offer_for_goods . +hqdm:acceptance_of_offer_for_goods_part_of rdfs:range hqdm:offer_and_acceptance_for_goods . +hqdm:acceptance_of_offer_for_goods_references rdfs:domain hqdm:acceptance_of_offer_for_goods . +hqdm:acceptance_of_offer_for_goods_references rdfs:range hqdm:offer_for_goods . +hqdm:acceptance_of_offer_part_of rdfs:domain hqdm:acceptance_of_offer . +hqdm:acceptance_of_offer_part_of rdfs:range hqdm:agree_contract . +hqdm:acceptance_of_offer_references rdfs:domain hqdm:acceptance_of_offer . +hqdm:acceptance_of_offer_references rdfs:range hqdm:offer . +hqdm:activity rdf:type rdfs:Class . +hqdm:activity rdfs:subClassOf hqdm:individual . +hqdm:activity rdfs:subClassOf hqdm:state_of_activity . +hqdm:activity_causes rdfs:domain hqdm:activity . +hqdm:activity_causes rdfs:range hqdm:event . +hqdm:activity_consists_of rdfs:domain hqdm:activity . +hqdm:activity_consists_of rdfs:range hqdm:activity . +hqdm:activity_consists_of_participant rdfs:domain hqdm:activity . +hqdm:activity_consists_of_participant rdfs:range hqdm:participant . +hqdm:activity_determines rdfs:domain hqdm:activity . +hqdm:activity_determines rdfs:range hqdm:thing . +hqdm:activity_member_of rdfs:domain hqdm:activity . +hqdm:activity_member_of rdfs:range hqdm:class_of_activity . +hqdm:activity_member_of_kind rdfs:domain hqdm:activity . +hqdm:activity_member_of_kind rdfs:range hqdm:kind_of_activity . +hqdm:activity_part_of rdfs:domain hqdm:activity . +hqdm:activity_part_of rdfs:range hqdm:activity . +hqdm:activity_references rdfs:domain hqdm:activity . +hqdm:activity_references rdfs:range hqdm:thing . +hqdm:aggregation rdf:type rdfs:Class . +hqdm:aggregation rdfs:subClassOf hqdm:relationship . +hqdm:aggregation_part rdfs:domain hqdm:aggregation . +hqdm:aggregation_part rdfs:range hqdm:spatio_temporal_extent . +hqdm:aggregation_whole rdfs:domain hqdm:aggregation . +hqdm:aggregation_whole rdfs:range hqdm:spatio_temporal_extent . +hqdm:agree_contract rdf:type rdfs:Class . +hqdm:agree_contract rdfs:subClassOf hqdm:reaching_agreement . +hqdm:agree_contract_agree_contract_part_of rdfs:domain hqdm:agree_contract . +hqdm:agree_contract_agree_contract_part_of rdfs:range hqdm:contract_process . +hqdm:agree_contract_consists_of rdfs:domain hqdm:agree_contract . +hqdm:agree_contract_consists_of rdfs:range hqdm:part_of . +hqdm:agree_contract_member_of rdfs:domain hqdm:agree_contract . +hqdm:agree_contract_member_of rdfs:range hqdm:class_of_agree_contract . +hqdm:agreement_execution rdf:type rdfs:Class . +hqdm:agreement_execution rdfs:subClassOf hqdm:socially_constructed_activity . +hqdm:agreement_execution_member_of rdfs:domain hqdm:agreement_execution . +hqdm:agreement_execution_member_of rdfs:range hqdm:class_of_agreement_execution . +hqdm:agreement_execution_part_of rdfs:domain hqdm:agreement_execution . +hqdm:agreement_execution_part_of rdfs:range hqdm:agreement_process . +hqdm:agreement_process rdf:type rdfs:Class . +hqdm:agreement_process rdfs:subClassOf hqdm:socially_constructed_activity . +hqdm:agreement_process_consists_of rdfs:domain hqdm:agreement_process . +hqdm:agreement_process_consists_of rdfs:range hqdm:part_of . +hqdm:agreement_process_consists_of_ rdfs:domain hqdm:agreement_process . +hqdm:agreement_process_consists_of_ rdfs:range hqdm:agreement_execution . +hqdm:agreement_process_member_of rdfs:domain hqdm:agreement_process . +hqdm:agreement_process_member_of rdfs:range hqdm:class_of_agreement_process . +hqdm:amount_of_money rdf:type rdfs:Class . +hqdm:amount_of_money rdfs:subClassOf hqdm:physical_object . +hqdm:amount_of_money rdfs:subClassOf hqdm:socially_constructed_object . +hqdm:amount_of_money rdfs:subClassOf hqdm:state_of_amount_of_money . +hqdm:amount_of_money_member_of rdfs:domain hqdm:amount_of_money . +hqdm:amount_of_money_member_of rdfs:range hqdm:class_of_amount_of_money . +hqdm:amount_of_money_member_of_currency rdfs:domain hqdm:amount_of_money . +hqdm:amount_of_money_member_of_currency rdfs:range hqdm:currency . +hqdm:asset rdf:type rdfs:Class . +hqdm:asset rdfs:subClassOf hqdm:participant . +hqdm:asset_participant_in rdfs:domain hqdm:asset . +hqdm:asset_participant_in rdfs:range hqdm:ownership . +hqdm:association rdf:type rdfs:Class . +hqdm:association rdfs:subClassOf hqdm:individual . +hqdm:association rdfs:subClassOf hqdm:state_of_association . +hqdm:association_consists_of_participant rdfs:domain hqdm:association . +hqdm:association_consists_of_participant rdfs:range hqdm:participant . +hqdm:association_member_of rdfs:domain hqdm:association . +hqdm:association_member_of rdfs:range hqdm:class_of_association . +hqdm:association_member_of_kind rdfs:domain hqdm:association . +hqdm:association_member_of_kind rdfs:range hqdm:kind_of_association . +hqdm:beginning_of_ownership rdf:type rdfs:Class . +hqdm:beginning_of_ownership rdfs:subClassOf hqdm:event . +hqdm:biological_object rdf:type rdfs:Class . +hqdm:biological_object rdfs:subClassOf hqdm:physical_object . +hqdm:biological_object rdfs:subClassOf hqdm:state_of_biological_object . +hqdm:biological_object_member_of rdfs:domain hqdm:biological_object . +hqdm:biological_object_member_of rdfs:range hqdm:class_of_biological_object . +hqdm:biological_object_member_of_kind rdfs:domain hqdm:biological_object . +hqdm:biological_object_member_of_kind rdfs:range hqdm:kind_of_biological_object . +hqdm:biological_system rdf:type rdfs:Class . +hqdm:biological_system rdfs:subClassOf hqdm:ordinary_biological_object . +hqdm:biological_system rdfs:subClassOf hqdm:state_of_biological_system . +hqdm:biological_system rdfs:subClassOf hqdm:system . +hqdm:biological_system_component rdf:type rdfs:Class . +hqdm:biological_system_component rdfs:subClassOf hqdm:state_of_biological_system_component . +hqdm:biological_system_component rdfs:subClassOf hqdm:system_component . +hqdm:biological_system_component_component_of rdfs:domain hqdm:biological_system_component . +hqdm:biological_system_component_component_of rdfs:range hqdm:biological_system . +hqdm:biological_system_component_member_of rdfs:domain hqdm:biological_system_component . +hqdm:biological_system_component_member_of rdfs:range hqdm:class_of_biological_system_component . +hqdm:biological_system_member_of rdfs:domain hqdm:biological_system . +hqdm:biological_system_member_of rdfs:range hqdm:class_of_biological_system . +hqdm:biological_system_member_of_kind rdfs:domain hqdm:biological_system . +hqdm:biological_system_member_of_kind rdfs:range hqdm:kind_of_biological_system . +hqdm:biological_system_natural_role rdfs:domain hqdm:biological_system . +hqdm:biological_system_natural_role rdfs:range hqdm:role . +hqdm:class rdf:type rdfs:Class . +hqdm:class rdfs:subClassOf hqdm:abstract_object . +hqdm:class_has_superclass rdfs:domain hqdm:class . +hqdm:class_has_superclass rdfs:range hqdm:class . +hqdm:class_member_of rdfs:domain hqdm:class . +hqdm:class_member_of rdfs:range hqdm:class_of_class . +hqdm:class_of_abstract_object rdf:type rdfs:Class . +hqdm:class_of_abstract_object rdfs:subClassOf hqdm:class . +hqdm:class_of_abstract_objectenumerated_class rdf:type rdfs:Class . +hqdm:class_of_activity rdf:type rdfs:Class . +hqdm:class_of_activity rdfs:subClassOf hqdm:class_of_individual . +hqdm:class_of_activity rdfs:subClassOf hqdm:class_of_state_of_activity . +hqdm:class_of_agree_contract rdf:type rdfs:Class . +hqdm:class_of_agree_contract rdfs:subClassOf hqdm:class_of_reaching_agreement . +hqdm:class_of_agree_contract_part_of_by_class rdfs:domain hqdm:class_of_agree_contract . +hqdm:class_of_agree_contract_part_of_by_class rdfs:range hqdm:class_of_contract_process . +hqdm:class_of_agreement_execution rdf:type rdfs:Class . +hqdm:class_of_agreement_execution rdfs:subClassOf hqdm:class_of_socially_constructed_activity . +hqdm:class_of_agreement_execution_part_of_by_class rdfs:domain hqdm:class_of_agreement_execution . +hqdm:class_of_agreement_execution_part_of_by_class rdfs:range hqdm:class_of_agreement_process . +hqdm:class_of_agreement_process rdf:type rdfs:Class . +hqdm:class_of_agreement_process rdfs:subClassOf hqdm:class_of_socially_constructed_activity . +hqdm:class_of_amount_of_money rdf:type rdfs:Class . +hqdm:class_of_amount_of_money rdfs:subClassOf hqdm:class_of_physical_object . +hqdm:class_of_amount_of_money rdfs:subClassOf hqdm:class_of_socially_contructed_object . +hqdm:class_of_amount_of_money rdfs:subClassOf hqdm:class_of_state_of_amount_of_money . +hqdm:class_of_association rdf:type rdfs:Class . +hqdm:class_of_association rdfs:subClassOf hqdm:class_of_individual . +hqdm:class_of_association rdfs:subClassOf hqdm:class_of_state_of_association . +hqdm:class_of_biological_object rdf:type rdfs:Class . +hqdm:class_of_biological_object rdfs:subClassOf hqdm:class_of_physical_object . +hqdm:class_of_biological_object rdfs:subClassOf hqdm:class_of_state_of_biological_object . +hqdm:class_of_biological_system rdf:type rdfs:Class . +hqdm:class_of_biological_system rdfs:subClassOf hqdm:class_of_ordinary_biological_object . +hqdm:class_of_biological_system rdfs:subClassOf hqdm:class_of_state_of_biological_system . +hqdm:class_of_biological_system rdfs:subClassOf hqdm:class_of_system . +hqdm:class_of_biological_system_component rdf:type rdfs:Class . +hqdm:class_of_biological_system_component rdfs:subClassOf hqdm:class_of_biological_object . +hqdm:class_of_biological_system_component rdfs:subClassOf hqdm:class_of_state_of_biological_system_component . +hqdm:class_of_biological_system_component rdfs:subClassOf hqdm:class_of_system_component . +hqdm:class_of_class rdf:type rdfs:Class . +hqdm:class_of_class rdfs:subClassOf hqdm:class_of_abstract_object . +hqdm:class_of_class_of_spatio_temporal_extent rdf:type rdfs:Class . +hqdm:class_of_class_of_spatio_temporal_extent rdfs:subClassOf hqdm:class_of_class . +hqdm:class_of_contract_execution rdf:type rdfs:Class . +hqdm:class_of_contract_execution rdfs:subClassOf hqdm:class_of_agreement_execution . +hqdm:class_of_contract_execution_part_of_by_class rdfs:domain hqdm:class_of_contract_execution . +hqdm:class_of_contract_execution_part_of_by_class rdfs:range hqdm:class_of_contract_process . +hqdm:class_of_contract_process rdfs:subClassOf hqdm:class_of_agreement_process . +hqdm:class_of_event rdf:type rdfs:Class . +hqdm:class_of_event rdfs:subClassOf hqdm:class_of_spatio_temporal_extent . +hqdm:class_of_functional_object rdf:type rdfs:Class . +hqdm:class_of_functional_object rdfs:subClassOf hqdm:class_of_intentionally_constructed_object . +hqdm:class_of_functional_object rdfs:subClassOf hqdm:class_of_physical_object . +hqdm:class_of_functional_object rdfs:subClassOf hqdm:class_of_state_of_functional_object . +hqdm:class_of_functional_system rdf:type rdfs:Class . +hqdm:class_of_functional_system rdfs:subClassOf hqdm:class_of_ordinary_functional_object . +hqdm:class_of_functional_system rdfs:subClassOf hqdm:class_of_state_of_functional_system . +hqdm:class_of_functional_system rdfs:subClassOf hqdm:class_of_system . +hqdm:class_of_functional_system_component rdf:type rdfs:Class . +hqdm:class_of_functional_system_component rdfs:subClassOf hqdm:class_of_state_of_functional_system_component . +hqdm:class_of_functional_system_component rdfs:subClassOf hqdm:class_of_system_component . +hqdm:class_of_in_place_biological_component rdf:type rdfs:Class . +hqdm:class_of_in_place_biological_component rdfs:subClassOf hqdm:class_of_installed_object . +hqdm:class_of_in_place_biological_component rdfs:subClassOf hqdm:class_of_state_of_biological_system_component . +hqdm:class_of_in_place_biological_component rdfs:subClassOf hqdm:class_of_state_of_ordinary_biological_object . +hqdm:class_of_individual rdf:type rdfs:Class . +hqdm:class_of_individual rdfs:subClassOf hqdm:class_of_state . +hqdm:class_of_installed_functional_system_component rdf:type rdfs:Class . +hqdm:class_of_installed_functional_system_component rdfs:subClassOf hqdm:class_of_installed_object . +hqdm:class_of_installed_functional_system_component rdfs:subClassOf hqdm:class_of_state_of_functional_system_component . +hqdm:class_of_installed_object rdf:type rdfs:Class . +hqdm:class_of_installed_object rdfs:subClassOf hqdm:class_of_state_of_ordinary_physical_object . +hqdm:class_of_installed_object rdfs:subClassOf hqdm:class_of_state_of_system_component . +hqdm:class_of_intentionally_constructed_object rdf:type rdfs:Class . +hqdm:class_of_intentionally_constructed_object rdfs:subClassOf hqdm:class_of_individual . +hqdm:class_of_intentionally_constructed_object rdfs:subClassOf hqdm:class_of_state_of_intentionally_constructed_object . +hqdm:class_of_offer rdf:type rdfs:Class . +hqdm:class_of_offer rdfs:subClassOf hqdm:class_of_socially_constructed_activity . +hqdm:class_of_ordinary_biological_object rdf:type rdfs:Class . +hqdm:class_of_ordinary_biological_object rdfs:subClassOf hqdm:class_of_biological_object . +hqdm:class_of_ordinary_biological_object rdfs:subClassOf hqdm:class_of_ordinary_physical_object . +hqdm:class_of_ordinary_biological_object rdfs:subClassOf hqdm:class_of_state_of_ordinary_biological_object . +hqdm:class_of_ordinary_functional_object rdf:type rdfs:Class . +hqdm:class_of_ordinary_functional_object rdfs:subClassOf hqdm:class_of_functional_object . +hqdm:class_of_ordinary_functional_object rdfs:subClassOf hqdm:class_of_ordinary_physical_object . +hqdm:class_of_ordinary_functional_object rdfs:subClassOf hqdm:class_of_state_of_ordinary_functional_object . +hqdm:class_of_ordinary_physical_object rdf:type rdfs:Class . +hqdm:class_of_ordinary_physical_object rdfs:subClassOf hqdm:class_of_physical_object . +hqdm:class_of_ordinary_physical_object rdfs:subClassOf hqdm:class_of_state_of_ordinary_physical_object . +hqdm:class_of_organization rdfs:subClassOf hqdm:class_of_party . +hqdm:class_of_organization rdfs:subClassOf hqdm:class_of_socially_contructed_object . +hqdm:class_of_organization rdfs:subClassOf hqdm:class_of_state_of_organization . +hqdm:class_of_organization_component rdf:type rdfs:Class . +hqdm:class_of_organization_component rdfs:subClassOf hqdm:class_of_socially_contructed_object . +hqdm:class_of_organization_component rdfs:subClassOf hqdm:class_of_state_of_organization_component . +hqdm:class_of_organization_component rdfs:subClassOf hqdm:class_of_system_component . +hqdm:class_of_participant rdf:type rdfs:Class . +hqdm:class_of_participant rdfs:subClassOf hqdm:class_of_state_of_physical_object . +hqdm:class_of_party rdf:type rdfs:Class . +hqdm:class_of_party rdfs:subClassOf hqdm:class_of_state_of_party . +hqdm:class_of_party rdfs:subClassOf hqdm:class_of_system . +hqdm:class_of_period_of_time rdf:type rdfs:Class . +hqdm:class_of_period_of_time rdfs:subClassOf hqdm:class_of_state . +hqdm:class_of_person rdf:type rdfs:Class . +hqdm:class_of_person rdfs:subClassOf hqdm:class_of_biological_system . +hqdm:class_of_person rdfs:subClassOf hqdm:class_of_party . +hqdm:class_of_person rdfs:subClassOf hqdm:class_of_state_of_person . +hqdm:class_of_person_in_position rdf:type rdfs:Class . +hqdm:class_of_person_in_position rdfs:subClassOf hqdm:class_of_installed_object . +hqdm:class_of_person_in_position rdfs:subClassOf hqdm:class_of_state_of_position . +hqdm:class_of_physical_object rdf:type rdfs:Class . +hqdm:class_of_physical_object rdfs:subClassOf hqdm:class_of_individual . +hqdm:class_of_physical_object rdfs:subClassOf hqdm:class_of_state_of_physical_object . +hqdm:class_of_physical_property rdf:type rdfs:Class . +hqdm:class_of_physical_property rdfs:subClassOf hqdm:class_of_class_of_spatio_temporal_extent . +hqdm:class_of_physical_quantity rdf:type rdfs:Class . +hqdm:class_of_physical_quantity rdfs:subClassOf hqdm:class_of_physical_property . +hqdm:class_of_point_in_time rdfs:subClassOf hqdm:class_of_event . +hqdm:class_of_position rdf:type rdfs:Class . +hqdm:class_of_position rdfs:subClassOf hqdm:class_of_organization_component . +hqdm:class_of_position rdfs:subClassOf hqdm:class_of_state_of_position . +hqdm:class_of_possible_world rdfs:subClassOf hqdm:class_of_individual . +hqdm:class_of_possible_world rdfs:subClassOf hqdm:class_of_period_of_time . +hqdm:class_of_reaching_agreement rdf:type rdfs:Class . +hqdm:class_of_reaching_agreement rdfs:subClassOf hqdm:class_of_socially_constructed_activity . +hqdm:class_of_reaching_agreement_part_of_by_class rdfs:domain hqdm:class_of_reaching_agreement . +hqdm:class_of_reaching_agreement_part_of_by_class rdfs:range hqdm:class_of_agreement_process . +hqdm:class_of_relationship rdf:type rdfs:Class . +hqdm:class_of_relationship rdfs:subClassOf hqdm:class_of_abstract_object . +hqdm:class_of_representation rdf:type rdfs:Class . +hqdm:class_of_representation rdfs:subClassOf hqdm:class_of_association . +hqdm:class_of_sales_product_instance rdf:type rdfs:Class . +hqdm:class_of_sales_product_instance rdfs:subClassOf hqdm:class_of_ordinary_functional_object . +hqdm:class_of_sales_product_instance rdfs:subClassOf hqdm:class_of_state_of_sales_product_instance . +hqdm:class_of_sign rdfs:subClassOf hqdm:class_of_socially_contructed_object . +hqdm:class_of_sign rdfs:subClassOf hqdm:class_of_state_of_sign . +hqdm:class_of_socially_constructed_activity rdf:type rdfs:Class . +hqdm:class_of_socially_constructed_activity rdfs:subClassOf hqdm:class_of_activity . +hqdm:class_of_socially_constructed_activity rdfs:subClassOf hqdm:class_of_socially_contructed_object . +hqdm:class_of_socially_constructed_activity_part_of_by_class rdfs:domain hqdm:class_of_socially_constructed_activity . +hqdm:class_of_socially_constructed_activity_part_of_by_class rdfs:range hqdm:class_of_reaching_agreement . +hqdm:class_of_socially_constructed_activity_part_of_by_class_ rdfs:domain hqdm:class_of_socially_constructed_activity . +hqdm:class_of_socially_constructed_activity_part_of_by_class_ rdfs:range hqdm:class_of_agreement_execution . +hqdm:class_of_socially_contructed_object rdf:type rdfs:Class . +hqdm:class_of_socially_contructed_object rdfs:subClassOf hqdm:class_of_intentionally_constructed_object . +hqdm:class_of_socially_contructed_object rdfs:subClassOf hqdm:class_of_state_of_socially_constructed_object . +hqdm:class_of_spatio_temporal_extent rdf:type rdfs:Class . +hqdm:class_of_spatio_temporal_extent rdfs:subClassOf hqdm:class . +hqdm:class_of_spatio_temporal_extent_consists__of_by_class rdfs:domain hqdm:class_of_spatio_temporal_extent . +hqdm:class_of_spatio_temporal_extent_consists__of_by_class rdfs:range hqdm:class_of_spatio_temporal_extent . +hqdm:class_of_spatio_temporal_extent_member_of_ rdfs:domain hqdm:class_of_spatio_temporal_extent . +hqdm:class_of_spatio_temporal_extent_member_of_ rdfs:range hqdm:class_of_class_of_spatio_temporal_extent . +hqdm:class_of_spatio_temporal_extent_part__of_by_class rdfs:domain hqdm:class_of_spatio_temporal_extent . +hqdm:class_of_spatio_temporal_extent_part__of_by_class rdfs:range hqdm:class_of_spatio_temporal_extent . +hqdm:class_of_state rdf:type rdfs:Class . +hqdm:class_of_state rdfs:subClassOf hqdm:class_of_spatio_temporal_extent . +hqdm:class_of_state_of_activity rdf:type rdfs:Class . +hqdm:class_of_state_of_activity rdfs:subClassOf hqdm:class_of_state . +hqdm:class_of_state_of_amount_of_money rdf:type rdfs:Class . +hqdm:class_of_state_of_amount_of_money rdfs:subClassOf hqdm:class_of_state_of_physical_object . +hqdm:class_of_state_of_amount_of_money rdfs:subClassOf hqdm:class_of_state_of_socially_constructed_object . +hqdm:class_of_state_of_association rdf:type rdfs:Class . +hqdm:class_of_state_of_association rdfs:subClassOf hqdm:class_of_state . +hqdm:class_of_state_of_biological_object rdf:type rdfs:Class . +hqdm:class_of_state_of_biological_object rdfs:subClassOf hqdm:class_of_state_of_physical_object . +hqdm:class_of_state_of_biological_system rdf:type rdfs:Class . +hqdm:class_of_state_of_biological_system rdfs:subClassOf hqdm:class_of_state_of_ordinary_biological_object . +hqdm:class_of_state_of_biological_system rdfs:subClassOf hqdm:class_of_state_of_system . +hqdm:class_of_state_of_biological_system_component rdf:type rdfs:Class . +hqdm:class_of_state_of_biological_system_component rdfs:subClassOf hqdm:class_of_state_of_biological_object . +hqdm:class_of_state_of_biological_system_component rdfs:subClassOf hqdm:class_of_state_of_system_component . +hqdm:class_of_state_of_functional_object rdf:type rdfs:Class . +hqdm:class_of_state_of_functional_object rdfs:subClassOf hqdm:class_of_state_of_intentionally_constructed_object . +hqdm:class_of_state_of_functional_object rdfs:subClassOf hqdm:class_of_state_of_physical_object . +hqdm:class_of_state_of_functional_system rdf:type rdfs:Class . +hqdm:class_of_state_of_functional_system rdfs:subClassOf hqdm:class_of_state_of_ordinary_functional_object . +hqdm:class_of_state_of_functional_system rdfs:subClassOf hqdm:class_of_state_of_system . +hqdm:class_of_state_of_functional_system_component rdf:type rdfs:Class . +hqdm:class_of_state_of_functional_system_component rdfs:subClassOf hqdm:class_of_state_of_ordinary_functional_object . +hqdm:class_of_state_of_functional_system_component rdfs:subClassOf hqdm:class_of_state_of_system_component . +hqdm:class_of_state_of_intentionally_constructed_object rdf:type rdfs:Class . +hqdm:class_of_state_of_intentionally_constructed_object rdfs:subClassOf hqdm:class_of_state . +hqdm:class_of_state_of_ordinary_biological_object rdf:type rdfs:Class . +hqdm:class_of_state_of_ordinary_biological_object rdfs:subClassOf hqdm:class_of_state_of_biological_object . +hqdm:class_of_state_of_ordinary_biological_object rdfs:subClassOf hqdm:class_of_state_of_ordinary_physical_object . +hqdm:class_of_state_of_ordinary_functional_object rdf:type rdfs:Class . +hqdm:class_of_state_of_ordinary_functional_object rdfs:subClassOf hqdm:class_of_state_of_functional_object . +hqdm:class_of_state_of_ordinary_functional_object rdfs:subClassOf hqdm:class_of_state_of_ordinary_physical_object . +hqdm:class_of_state_of_ordinary_physical_object rdf:type rdfs:Class . +hqdm:class_of_state_of_ordinary_physical_object rdfs:subClassOf hqdm:class_of_state_of_physical_object . +hqdm:class_of_state_of_organization rdf:type rdfs:Class . +hqdm:class_of_state_of_organization rdfs:subClassOf hqdm:class_of_state_of_party . +hqdm:class_of_state_of_organization rdfs:subClassOf hqdm:class_of_state_of_socially_constructed_object . +hqdm:class_of_state_of_organization_component rdf:type rdfs:Class . +hqdm:class_of_state_of_organization_component rdfs:subClassOf hqdm:class_of_state_of_socially_constructed_object . +hqdm:class_of_state_of_organization_component rdfs:subClassOf hqdm:class_of_state_of_system_component . +hqdm:class_of_state_of_party rdf:type rdfs:Class . +hqdm:class_of_state_of_party rdfs:subClassOf hqdm:class_of_state_of_system . +hqdm:class_of_state_of_person rdf:type rdfs:Class . +hqdm:class_of_state_of_person rdfs:subClassOf hqdm:class_of_state_of_biological_system . +hqdm:class_of_state_of_person rdfs:subClassOf hqdm:class_of_state_of_party . +hqdm:class_of_state_of_physical_object rdf:type rdfs:Class . +hqdm:class_of_state_of_physical_object rdfs:subClassOf hqdm:class_of_state . +hqdm:class_of_state_of_position rdf:type rdfs:Class . +hqdm:class_of_state_of_position rdfs:subClassOf hqdm:class_of_state_of_organization_component . +hqdm:class_of_state_of_sales_product_instance rdf:type rdfs:Class . +hqdm:class_of_state_of_sales_product_instance rdfs:subClassOf hqdm:class_of_state_of_ordinary_functional_object . +hqdm:class_of_state_of_sign rdf:type rdfs:Class . +hqdm:class_of_state_of_sign rdfs:subClassOf hqdm:class_of_state_of_socially_constructed_object . +hqdm:class_of_state_of_socially_constructed_activity rdf:type rdfs:Class . +hqdm:class_of_state_of_socially_constructed_activity rdfs:subClassOf hqdm:class_of_state_of_activity . +hqdm:class_of_state_of_socially_constructed_activity rdfs:subClassOf hqdm:class_of_state_of_socially_constructed_object . +hqdm:class_of_state_of_socially_constructed_object rdf:type rdfs:Class . +hqdm:class_of_state_of_socially_constructed_object rdfs:subClassOf hqdm:class_of_state_of_intentionally_constructed_object . +hqdm:class_of_state_of_system rdf:type rdfs:Class . +hqdm:class_of_state_of_system rdfs:subClassOf hqdm:class_of_state_of_ordinary_physical_object . +hqdm:class_of_state_of_system_component rdf:type rdfs:Class . +hqdm:class_of_state_of_system_component rdfs:subClassOf hqdm:class_of_state_of_physical_object . +hqdm:class_of_system rdf:type rdfs:Class . +hqdm:class_of_system rdfs:subClassOf hqdm:class_of_ordinary_physical_object . +hqdm:class_of_system rdfs:subClassOf hqdm:class_of_state_of_system . +hqdm:class_of_system_component rdf:type rdfs:Class . +hqdm:class_of_system_component rdfs:subClassOf hqdm:class_of_physical_object . +hqdm:class_of_system_component rdfs:subClassOf hqdm:class_of_state_of_system_component . +hqdm:classification rdf:type rdfs:Class . +hqdm:classification rdfs:subClassOf hqdm:relationship . +hqdm:classification_classifier rdfs:domain hqdm:classification . +hqdm:classification_classifier rdfs:range hqdm:class . +hqdm:classification_member rdfs:domain hqdm:classification . +hqdm:classification_member rdfs:range hqdm:thing . +hqdm:composition rdf:type rdfs:Class . +hqdm:composition rdfs:subClassOf hqdm:aggregation . +hqdm:contract_execution rdf:type rdfs:Class . +hqdm:contract_execution rdfs:subClassOf hqdm:agreement_execution . +hqdm:contract_execution_member_of rdfs:domain hqdm:contract_execution . +hqdm:contract_execution_member_of rdfs:range hqdm:class_of_contract_execution . +hqdm:contract_execution_part_of rdfs:domain hqdm:contract_execution . +hqdm:contract_execution_part_of rdfs:range hqdm:contract_process . +hqdm:contract_process rdf:type rdfs:Class . +hqdm:contract_process rdfs:subClassOf hqdm:agreement_process . +hqdm:contract_process_consists_of rdfs:domain hqdm:contract_process . +hqdm:contract_process_consists_of rdfs:range hqdm:part_of . +hqdm:contract_process_consists_of_ rdfs:domain hqdm:contract_process . +hqdm:contract_process_consists_of_ rdfs:range hqdm:part_of . +hqdm:contract_process_member_of rdfs:domain hqdm:contract_process . +hqdm:contract_process_member_of rdfs:range hqdm:class_of_contract_process . +hqdm:currency rdfs:subClassOf hqdm:class_of_amount_of_money . +hqdm:defined_relationship rdf:type rdfs:Class . +hqdm:defined_relationship rdfs:subClassOf hqdm:relationship . +hqdm:defined_relationship_involves rdfs:domain hqdm:defined_relationship . +hqdm:defined_relationship_involves rdfs:range hqdm:classification . +hqdm:defined_relationship_member_of_kind rdfs:domain hqdm:defined_relationship . +hqdm:defined_relationship_member_of_kind rdfs:range hqdm:kind_of_relationship_with_signature . +hqdm:definition rdfs:subClassOf hqdm:representation_by_pattern . +hqdm:definition_represented rdfs:domain hqdm:definition . +hqdm:definition_represented rdfs:range hqdm:class . +hqdm:description rdf:type rdfs:Class . +hqdm:description rdfs:subClassOf hqdm:representation_by_pattern . +hqdm:employee rdf:type rdfs:Class . +hqdm:employee rdfs:subClassOf hqdm:participant . +hqdm:employee rdfs:subClassOf hqdm:state_of_person . +hqdm:employee_participant_in rdfs:domain hqdm:employee . +hqdm:employee_participant_in rdfs:range hqdm:employment . +hqdm:employer rdf:type rdfs:Class . +hqdm:employer rdfs:subClassOf hqdm:participant . +hqdm:employer rdfs:subClassOf hqdm:state_of_party . +hqdm:employer_participant_in rdfs:domain hqdm:employer . +hqdm:employer_participant_in rdfs:range hqdm:employment . +hqdm:employment rdf:type rdfs:Class . +hqdm:employment rdfs:subClassOf hqdm:association . +hqdm:employment_consists_of_participant rdfs:domain hqdm:employment . +hqdm:employment_consists_of_participant rdfs:range hqdm:participant_in . +hqdm:employment_consists_of_participant_ rdfs:domain hqdm:employment . +hqdm:employment_consists_of_participant_ rdfs:range hqdm:employee . +hqdm:ending_of_ownership rdf:type rdfs:Class . +hqdm:ending_of_ownership rdfs:subClassOf hqdm:event . +hqdm:enumerated_class rdfs:subClassOf hqdm:class . +hqdm:event rdf:type rdfs:Class . +hqdm:event rdfs:subClassOf hqdm:spatio_temporal_extent . +hqdm:event_member_of rdfs:domain hqdm:event . +hqdm:event_member_of rdfs:range hqdm:class_of_event . +hqdm:exchange_of_goods_and_money rdf:type rdfs:Class . +hqdm:exchange_of_goods_and_money rdfs:subClassOf hqdm:contract_execution . +hqdm:exchange_of_goods_and_money_consists_of rdfs:domain hqdm:exchange_of_goods_and_money . +hqdm:exchange_of_goods_and_money_consists_of rdfs:range hqdm:part_of . +hqdm:exchange_of_goods_and_money_consists_of_ rdfs:domain hqdm:exchange_of_goods_and_money . +hqdm:exchange_of_goods_and_money_consists_of_ rdfs:range hqdm:transfer_of_ownership_of_money . +hqdm:exchange_of_goods_and_money_part_of rdfs:domain hqdm:exchange_of_goods_and_money . +hqdm:exchange_of_goods_and_money_part_of rdfs:range hqdm:sale_of_goods . +hqdm:function_ rdf:type rdfs:Class . +hqdm:function_ rdfs:subClassOf hqdm:relationship . +hqdm:functional_object rdf:type rdfs:Class . +hqdm:functional_object rdfs:subClassOf hqdm:intentionally_constructed_object . +hqdm:functional_object rdfs:subClassOf hqdm:physical_object . +hqdm:functional_object rdfs:subClassOf hqdm:state_of_functional_object . +hqdm:functional_object_intended_role rdfs:domain hqdm:functional_object . +hqdm:functional_object_intended_role rdfs:range hqdm:role . +hqdm:functional_object_member_of rdfs:domain hqdm:functional_object . +hqdm:functional_object_member_of rdfs:range hqdm:class_of_functional_object . +hqdm:functional_object_member_of_kind rdfs:domain hqdm:functional_object . +hqdm:functional_object_member_of_kind rdfs:range hqdm:kind_of_functional_object . +hqdm:functional_system rdf:type rdfs:Class . +hqdm:functional_system rdfs:subClassOf hqdm:ordinary_functional_object . +hqdm:functional_system rdfs:subClassOf hqdm:state_of_functional_system . +hqdm:functional_system rdfs:subClassOf hqdm:system . +hqdm:functional_system_component rdf:type rdfs:Class . +hqdm:functional_system_component rdfs:subClassOf hqdm:functional_object . +hqdm:functional_system_component rdfs:subClassOf hqdm:state_of_functional_system_component . +hqdm:functional_system_component rdfs:subClassOf hqdm:system_component . +hqdm:functional_system_component_component_of rdfs:domain hqdm:functional_system_component . +hqdm:functional_system_component_component_of rdfs:range hqdm:functional_system . +hqdm:functional_system_component_member_of rdfs:domain hqdm:functional_system_component . +hqdm:functional_system_component_member_of rdfs:range hqdm:class_of_functional_system_component . +hqdm:functional_system_component_member_of_kind rdfs:domain hqdm:functional_system_component . +hqdm:functional_system_component_member_of_kind rdfs:range hqdm:kind_of_functional_system_component . +hqdm:functional_system_member_of rdfs:domain hqdm:functional_system . +hqdm:functional_system_member_of rdfs:range hqdm:class_of_functional_system . +hqdm:functional_system_member_of_kind rdfs:domain hqdm:functional_system . +hqdm:functional_system_member_of_kind rdfs:range hqdm:kind_of_functional_system . +hqdm:identification rdf:type rdfs:Class . +hqdm:identification rdfs:subClassOf hqdm:representation_by_pattern . +hqdm:identification_of_physical_quantity rdfs:subClassOf hqdm:identification . +hqdm:identification_of_physical_quantity_consists_of_by_class rdfs:domain hqdm:identification_of_physical_quantity . +hqdm:identification_of_physical_quantity_consists_of_by_class rdfs:range xsd:double . +hqdm:identification_of_physical_quantity_represented rdfs:domain hqdm:identification_of_physical_quantity . +hqdm:identification_of_physical_quantity_represented rdfs:range hqdm:physical_quantity . +hqdm:identification_of_physical_quantity_uses rdfs:domain hqdm:identification_of_physical_quantity . +hqdm:identification_of_physical_quantity_uses rdfs:range hqdm:scale . +hqdm:in_place_biological_component rdf:type rdfs:Class . +hqdm:in_place_biological_component rdfs:subClassOf hqdm:installed_object . +hqdm:in_place_biological_component rdfs:subClassOf hqdm:state_of_biological_system_component . +hqdm:in_place_biological_component rdfs:subClassOf hqdm:state_of_ordinary_biological_object . +hqdm:in_place_biological_component_member_of rdfs:domain hqdm:in_place_biological_component . +hqdm:in_place_biological_component_member_of rdfs:range hqdm:class_of_in_place_biological_component . +hqdm:individual rdf:type rdfs:Class . +hqdm:individual rdfs:subClassOf hqdm:state . +hqdm:individual_member_of rdfs:domain hqdm:individual . +hqdm:individual_member_of rdfs:range hqdm:class_of_individual . +hqdm:individual_member_of_kind rdfs:domain hqdm:individual . +hqdm:individual_member_of_kind rdfs:range hqdm:kind_of_individual . +hqdm:installed_functional_system_component rdf:type rdfs:Class . +hqdm:installed_functional_system_component rdfs:subClassOf hqdm:installed_object . +hqdm:installed_functional_system_component rdfs:subClassOf hqdm:state_of_functional_system_component . +hqdm:installed_functional_system_component rdfs:subClassOf hqdm:state_of_ordinary_functional_object . +hqdm:installed_functional_system_component_member_of rdfs:domain hqdm:installed_functional_system_component . +hqdm:installed_functional_system_component_member_of rdfs:range hqdm:class_of_installed_functional_system_component . +hqdm:installed_object rdf:type rdfs:Class . +hqdm:installed_object rdfs:subClassOf hqdm:state_of_ordinary_physical_object . +hqdm:installed_object rdfs:subClassOf hqdm:state_of_system_component . +hqdm:installed_object_member_of rdfs:domain hqdm:installed_object . +hqdm:installed_object_member_of rdfs:range hqdm:class_of_installed_object . +hqdm:intentionally_constructed_object rdf:type rdfs:Class . +hqdm:intentionally_constructed_object rdfs:subClassOf hqdm:individual . +hqdm:intentionally_constructed_object rdfs:subClassOf hqdm:state_of_intentionally_constructed_object . +hqdm:intentionally_constructed_object_member_of rdfs:domain hqdm:intentionally_constructed_object . +hqdm:intentionally_constructed_object_member_of rdfs:range hqdm:class_of_intentionally_constructed_object . +hqdm:intentionally_constructed_object_member_of_kind rdfs:domain hqdm:intentionally_constructed_object . +hqdm:intentionally_constructed_object_member_of_kind rdfs:range hqdm:kind_of_intentionally_constructed_object . +hqdm:kind_of_activity rdfs:subClassOf hqdm:class_of_activity . +hqdm:kind_of_activity_causes_by_class rdfs:domain hqdm:kind_of_activity . +hqdm:kind_of_activity_causes_by_class rdfs:range hqdm:class_of_event . +hqdm:kind_of_activity_consists_of_by_class rdfs:domain hqdm:kind_of_activity . +hqdm:kind_of_activity_consists_of_by_class rdfs:range hqdm:role . +hqdm:kind_of_activity_determines_by_class rdfs:domain hqdm:kind_of_activity . +hqdm:kind_of_activity_determines_by_class rdfs:range hqdm:class . +hqdm:kind_of_activity_references_by_class rdfs:domain hqdm:kind_of_activity . +hqdm:kind_of_activity_references_by_class rdfs:range hqdm:class . +hqdm:kind_of_association rdfs:subClassOf hqdm:class_of_association . +hqdm:kind_of_association_consists_of_by_class rdfs:domain hqdm:kind_of_association . +hqdm:kind_of_association_consists_of_by_class rdfs:range hqdm:role . +hqdm:kind_of_biological_object rdf:type rdfs:Class . +hqdm:kind_of_biological_object rdfs:subClassOf hqdm:class_of_biological_object . +hqdm:kind_of_biological_object rdfs:subClassOf hqdm:kind_of_physical_object . +hqdm:kind_of_biological_system rdf:type rdfs:Class . +hqdm:kind_of_biological_system rdfs:subClassOf hqdm:class_of_biological_system . +hqdm:kind_of_biological_system rdfs:subClassOf hqdm:kind_of_system . +hqdm:kind_of_biological_system_component rdfs:subClassOf hqdm:class_of_biological_system_component . +hqdm:kind_of_biological_system_component rdfs:subClassOf hqdm:kind_of_system_component . +hqdm:kind_of_biological_system_has_component_by_class rdfs:domain hqdm:kind_of_biological_system . +hqdm:kind_of_biological_system_has_component_by_class rdfs:range hqdm:kind_of_biological_system_component . +hqdm:kind_of_biological_system_natural_role_by_class rdfs:domain hqdm:kind_of_biological_system . +hqdm:kind_of_biological_system_natural_role_by_class rdfs:range hqdm:role . +hqdm:kind_of_functional_object rdf:type rdfs:Class . +hqdm:kind_of_functional_object rdfs:subClassOf hqdm:class_of_functional_object . +hqdm:kind_of_functional_object rdfs:subClassOf hqdm:kind_of_intentionally_constructed_object . +hqdm:kind_of_functional_object rdfs:subClassOf hqdm:kind_of_physical_object . +hqdm:kind_of_functional_object_intended_role_by_class rdfs:domain hqdm:kind_of_functional_object . +hqdm:kind_of_functional_object_intended_role_by_class rdfs:range hqdm:role . +hqdm:kind_of_functional_system rdf:type rdfs:Class . +hqdm:kind_of_functional_system rdfs:subClassOf hqdm:class_of_functional_system . +hqdm:kind_of_functional_system rdfs:subClassOf hqdm:kind_of_system . +hqdm:kind_of_functional_system_component rdfs:subClassOf hqdm:class_of_functional_system_component . +hqdm:kind_of_functional_system_component rdfs:subClassOf hqdm:kind_of_system_component . +hqdm:kind_of_functional_system_has_component_by_class rdfs:domain hqdm:kind_of_functional_system . +hqdm:kind_of_functional_system_has_component_by_class rdfs:range hqdm:kind_of_functional_system_component . +hqdm:kind_of_individual rdf:type rdfs:Class . +hqdm:kind_of_individual rdfs:subClassOf hqdm:class_of_individual . +hqdm:kind_of_intentionally_constructed_object rdf:type rdfs:Class . +hqdm:kind_of_intentionally_constructed_object rdfs:subClassOf hqdm:class_of_intentionally_constructed_object . +hqdm:kind_of_intentionally_constructed_object rdfs:subClassOf hqdm:kind_of_individual . +hqdm:kind_of_ordinary_biological_object rdfs:subClassOf hqdm:class_of_ordinary_biological_object . +hqdm:kind_of_ordinary_biological_object rdfs:subClassOf hqdm:kind_of_biological_object . +hqdm:kind_of_ordinary_biological_object rdfs:subClassOf hqdm:kind_of_ordinary_physical_object . +hqdm:kind_of_ordinary_functional_object rdf:type rdfs:Class . +hqdm:kind_of_ordinary_functional_object rdfs:subClassOf hqdm:class_of_ordinary_functional_object . +hqdm:kind_of_ordinary_functional_object rdfs:subClassOf hqdm:kind_of_functional_object . +hqdm:kind_of_ordinary_functional_object rdfs:subClassOf hqdm:kind_of_ordinary_physical_object . +hqdm:kind_of_ordinary_physical_object rdf:type rdfs:Class . +hqdm:kind_of_ordinary_physical_object rdfs:subClassOf hqdm:class_of_ordinary_physical_object . +hqdm:kind_of_ordinary_physical_object rdfs:subClassOf hqdm:kind_of_physical_object . +hqdm:kind_of_organization rdfs:subClassOf hqdm:class_of_organization . +hqdm:kind_of_organization rdfs:subClassOf hqdm:kind_of_party . +hqdm:kind_of_organization rdfs:subClassOf hqdm:kind_of_socially_constructed_object . +hqdm:kind_of_organization_component rdf:type rdfs:Class . +hqdm:kind_of_organization_component rdfs:subClassOf hqdm:class_of_organization_component . +hqdm:kind_of_organization_component rdfs:subClassOf hqdm:kind_of_socially_constructed_object . +hqdm:kind_of_organization_component rdfs:subClassOf hqdm:kind_of_system_component . +hqdm:kind_of_organization_component_by_class rdfs:domain hqdm:kind_of_organization . +hqdm:kind_of_organization_component_by_class rdfs:range hqdm:kind_of_organization_component . +hqdm:kind_of_party rdf:type rdfs:Class . +hqdm:kind_of_party rdfs:subClassOf hqdm:class_of_party . +hqdm:kind_of_party rdfs:subClassOf hqdm:kind_of_system . +hqdm:kind_of_person rdf:type rdfs:Class . +hqdm:kind_of_person rdfs:subClassOf hqdm:class_of_person . +hqdm:kind_of_person rdfs:subClassOf hqdm:kind_of_party . +hqdm:kind_of_physical_object rdf:type rdfs:Class . +hqdm:kind_of_physical_object rdfs:subClassOf hqdm:class_of_physical_object . +hqdm:kind_of_physical_object rdfs:subClassOf hqdm:kind_of_individual . +hqdm:kind_of_physical_property rdf:type rdfs:Class . +hqdm:kind_of_physical_property rdfs:subClassOf hqdm:class_of_physical_property . +hqdm:kind_of_physical_quantity rdf:type rdfs:Class . +hqdm:kind_of_physical_quantity rdfs:subClassOf hqdm:class_of_physical_quantity . +hqdm:kind_of_physical_quantity rdfs:subClassOf hqdm:kind_of_physical_property . +hqdm:kind_of_position rdf:type rdfs:Class . +hqdm:kind_of_position rdfs:subClassOf hqdm:class_of_position . +hqdm:kind_of_position rdfs:subClassOf hqdm:kind_of_organization_component . +hqdm:kind_of_relationship_with_restriction rdf:type rdfs:Class . +hqdm:kind_of_relationship_with_restriction rdfs:subClassOf hqdm:kind_of_relationship_with_signature . +hqdm:kind_of_relationship_with_restriction_required_role_player rdfs:domain hqdm:kind_of_relationship_with_restriction . +hqdm:kind_of_relationship_with_restriction_required_role_player rdfs:range hqdm:classification . +hqdm:kind_of_relationship_with_signature rdf:type rdfs:Class . +hqdm:kind_of_relationship_with_signature rdfs:subClassOf hqdm:class_of_relationship . +hqdm:kind_of_relationship_with_signature_roles rdfs:domain hqdm:kind_of_relationship_with_signature . +hqdm:kind_of_relationship_with_signature_roles rdfs:range hqdm:class . +hqdm:kind_of_socially_constructed_object rdf:type rdfs:Class . +hqdm:kind_of_socially_constructed_object rdfs:subClassOf hqdm:class_of_state_of_socially_constructed_object . +hqdm:kind_of_socially_constructed_object rdfs:subClassOf hqdm:kind_of_intentionally_constructed_object . +hqdm:kind_of_system rdf:type rdfs:Class . +hqdm:kind_of_system rdfs:subClassOf hqdm:class_of_system . +hqdm:kind_of_system rdfs:subClassOf hqdm:kind_of_ordinary_physical_object . +hqdm:kind_of_system_component rdf:type rdfs:Class . +hqdm:kind_of_system_component rdfs:subClassOf hqdm:class_of_system_component . +hqdm:kind_of_system_component rdfs:subClassOf hqdm:kind_of_physical_object . +hqdm:kind_of_system_has_component_by_class rdfs:domain hqdm:kind_of_system . +hqdm:kind_of_system_has_component_by_class rdfs:range hqdm:kind_of_system_component . +hqdm:language_community rdf:type rdfs:Class . +hqdm:language_community rdfs:subClassOf hqdm:organization . +hqdm:language_community rdfs:subClassOf hqdm:state_of_language_community . +hqdm:money_asset rdf:type rdfs:Class . +hqdm:money_asset rdfs:subClassOf hqdm:asset . +hqdm:money_asset rdfs:subClassOf hqdm:state_of_amount_of_money . +hqdm:offer rdf:type rdfs:Class . +hqdm:offer rdfs:subClassOf hqdm:socially_constructed_activity . +hqdm:offer_and_acceptance_for_goods rdf:type rdfs:Class . +hqdm:offer_and_acceptance_for_goods rdfs:subClassOf hqdm:agree_contract . +hqdm:offer_and_acceptance_for_goods_consists_of rdfs:domain hqdm:offer_and_acceptance_for_goods . +hqdm:offer_and_acceptance_for_goods_consists_of rdfs:range hqdm:part_of . +hqdm:offer_and_acceptance_for_goods_consists_of_ rdfs:domain hqdm:offer_and_acceptance_for_goods . +hqdm:offer_and_acceptance_for_goods_consists_of_ rdfs:range hqdm:part_of . +hqdm:offer_and_acceptance_for_goods_part_of rdfs:domain hqdm:offer_and_acceptance_for_goods . +hqdm:offer_and_acceptance_for_goods_part_of rdfs:range hqdm:sale_of_goods . +hqdm:offer_for_goods rdf:type rdfs:Class . +hqdm:offer_for_goods rdfs:subClassOf hqdm:offer . +hqdm:offer_for_goods_part_of rdfs:domain hqdm:offer_for_goods . +hqdm:offer_for_goods_part_of rdfs:range hqdm:offer_and_acceptance_for_goods . +hqdm:offer_for_goods_references rdfs:domain hqdm:offer_for_goods . +hqdm:offer_for_goods_references rdfs:range hqdm:exchange_of_goods_and_money . +hqdm:offer_member_of rdfs:domain hqdm:offer . +hqdm:offer_member_of rdfs:range hqdm:class_of_offer . +hqdm:offer_part_of rdfs:domain hqdm:offer . +hqdm:offer_part_of rdfs:range hqdm:agree_contract . +hqdm:offering rdf:type rdfs:Class . +hqdm:offering rdfs:subClassOf hqdm:class_of_offer . +hqdm:offering_class_of_offered rdfs:domain hqdm:offering . +hqdm:offering_class_of_offered rdfs:range hqdm:class_of_individual . +hqdm:offering_consideration_by_class rdfs:domain hqdm:offering . +hqdm:offering_consideration_by_class rdfs:range hqdm:price . +hqdm:offering_offeror rdfs:domain hqdm:offering . +hqdm:offering_offeror rdfs:range hqdm:party . +hqdm:offering_period_offered rdfs:domain hqdm:offering . +hqdm:offering_period_offered rdfs:range hqdm:period_of_time . +hqdm:ordinary_biological_object rdf:type rdfs:Class . +hqdm:ordinary_biological_object rdfs:subClassOf hqdm:biological_object . +hqdm:ordinary_biological_object rdfs:subClassOf hqdm:ordinary_physical_object . +hqdm:ordinary_biological_object rdfs:subClassOf hqdm:state_of_ordinary_biological_object . +hqdm:ordinary_biological_object_member_of rdfs:domain hqdm:ordinary_biological_object . +hqdm:ordinary_biological_object_member_of rdfs:range hqdm:class_of_ordinary_biological_object . +hqdm:ordinary_biological_object_member_of_kind rdfs:domain hqdm:ordinary_biological_object . +hqdm:ordinary_biological_object_member_of_kind rdfs:range hqdm:kind_of_ordinary_biological_object . +hqdm:ordinary_functional_object rdf:type rdfs:Class . +hqdm:ordinary_functional_object rdfs:subClassOf hqdm:functional_object . +hqdm:ordinary_functional_object rdfs:subClassOf hqdm:ordinary_physical_object . +hqdm:ordinary_functional_object rdfs:subClassOf hqdm:state_of_ordinary_functional_object . +hqdm:ordinary_functional_object_member_of rdfs:domain hqdm:ordinary_functional_object . +hqdm:ordinary_functional_object_member_of rdfs:range hqdm:class_of_ordinary_functional_object . +hqdm:ordinary_functional_object_member_of_kind rdfs:domain hqdm:ordinary_functional_object . +hqdm:ordinary_functional_object_member_of_kind rdfs:range hqdm:kind_of_ordinary_functional_object . +hqdm:ordinary_physical_object rdf:type rdfs:Class . +hqdm:ordinary_physical_object rdfs:subClassOf hqdm:physical_object . +hqdm:ordinary_physical_object rdfs:subClassOf hqdm:state_of_ordinary_physical_object . +hqdm:ordinary_physical_object_member_of rdfs:domain hqdm:ordinary_physical_object . +hqdm:ordinary_physical_object_member_of rdfs:range hqdm:class_of_ordinary_physical_object . +hqdm:ordinary_physical_object_member_of_kind rdfs:domain hqdm:ordinary_physical_object . +hqdm:ordinary_physical_object_member_of_kind rdfs:range hqdm:kind_of_ordinary_physical_object . +hqdm:organization rdf:type rdfs:Class . +hqdm:organization rdfs:subClassOf hqdm:party . +hqdm:organization rdfs:subClassOf hqdm:socially_constructed_object . +hqdm:organization rdfs:subClassOf hqdm:state_of_organization . +hqdm:organization_component rdf:type rdfs:Class . +hqdm:organization_component rdfs:subClassOf hqdm:socially_constructed_object . +hqdm:organization_component rdfs:subClassOf hqdm:state_of_organization_component . +hqdm:organization_component rdfs:subClassOf hqdm:system_component . +hqdm:organization_component_component_of rdfs:domain hqdm:organization_component . +hqdm:organization_component_component_of rdfs:range hqdm:organization . +hqdm:organization_component_member_of rdfs:domain hqdm:organization_component . +hqdm:organization_component_member_of rdfs:domain hqdm:class_of_organization_component . +hqdm:organization_component_member_of_kind rdfs:domain hqdm:organization_component . +hqdm:organization_component_member_of_kind rdfs:range hqdm:kind_of_organization_component . +hqdm:organization_member_of rdfs:domain hqdm:organization . +hqdm:organization_member_of rdfs:range hqdm:class_of_organization . +hqdm:organization_member_of_kind rdfs:domain hqdm:organization . +hqdm:organization_member_of_kind rdfs:range hqdm:kind_of_organization . +hqdm:owner rdf:type rdfs:Class . +hqdm:owner rdfs:subClassOf hqdm:participant . +hqdm:owner rdfs:subClassOf hqdm:state_of_party . +hqdm:owner_participant_in rdfs:domain hqdm:owner . +hqdm:owner_participant_in rdfs:range hqdm:ownership . +hqdm:ownership rdf:type rdfs:Class . +hqdm:ownership rdfs:subClassOf hqdm:association . +hqdm:ownership_consists_of_participant rdfs:domain hqdm:ownership . +hqdm:ownership_consists_of_participant rdfs:range hqdm:owner . +hqdm:ownership_consists_of_participant_ rdfs:domain hqdm:ownership . +hqdm:ownership_consists_of_participant_ rdfs:range hqdm:asset . +hqdm:ownership_ending rdfs:domain hqdm:ownership . +hqdm:ownership_ending rdfs:range hqdm:ending_of_ownership . +hqdm:ownership_beginning rdfs:domain hqdm:ownership . +hqdm:ownership_beginning rdfs:range hqdm:beginning_of_ownership . +hqdm:participant rdf:type rdfs:Class . +hqdm:participant rdfs:subClassOf hqdm:state_of_physical_object . +hqdm:participant_member_of rdfs:domain hqdm:participant . +hqdm:participant_member_of rdfs:range hqdm:class_of_participant . +hqdm:participant_member_of_kind rdfs:domain hqdm:participant . +hqdm:participant_member_of_kind rdfs:range hqdm:role . +hqdm:participant_participant_in rdfs:domain hqdm:participant . +hqdm:participant_participant_in rdfs:range hqdm:participant_in_activity_or_association . +hqdm:participant_in_activity_or_association rdf:type rdfs:Class . +hqdm:participant_in_activity_or_association rdfs:subClassOf hqdm:activity . +hqdm:participant_in_activity_or_association rdfs:subClassOf hqdm:association . +hqdm:party rdf:type rdfs:Class . +hqdm:party rdfs:subClassOf hqdm:state_of_party . +hqdm:party rdfs:subClassOf hqdm:system . +hqdm:party_member_of rdfs:domain hqdm:party . +hqdm:party_member_of rdfs:range hqdm:class_of_party . +hqdm:party_member_of_kind rdfs:domain hqdm:party . +hqdm:party_member_of_kind rdfs:range hqdm:kind_of_party . +hqdm:pattern rdfs:subClassOf hqdm:class_of_sign . +hqdm:period_of_time rdf:type rdfs:Class . +hqdm:period_of_time rdfs:subClassOf hqdm:state . +hqdm:period_of_time_member_of rdfs:domain hqdm:period_of_time . +hqdm:period_of_time_member_of rdfs:range hqdm:class_of_period_of_time . +hqdm:period_of_time_temporal_part_of_ rdfs:domain hqdm:period_of_time . +hqdm:period_of_time_temporal_part_of_ rdfs:range hqdm:possible_world . +hqdm:person rdf:type rdfs:Class . +hqdm:person rdfs:subClassOf hqdm:biological_system . +hqdm:person rdfs:subClassOf hqdm:party . +hqdm:person rdfs:subClassOf hqdm:state_of_person . +hqdm:person_in_position rdf:type rdfs:Class . +hqdm:person_in_position rdfs:subClassOf hqdm:installed_object . +hqdm:person_in_position rdfs:subClassOf hqdm:state_of_person . +hqdm:person_in_position rdfs:subClassOf hqdm:state_of_position . +hqdm:person_in_position_member_of rdfs:domain hqdm:person_in_position . +hqdm:person_in_position_member_of rdfs:range hqdm:class_of_person_in_position . +hqdm:person_member_of rdfs:domain hqdm:person . +hqdm:person_member_of rdfs:range hqdm:class_of_person . +hqdm:person_member_of_kind rdfs:domain hqdm:person . +hqdm:person_member_of_kind rdfs:range hqdm:kind_of_person . +hqdm:physical_object rdf:type rdfs:Class . +hqdm:physical_object rdfs:subClassOf hqdm:individual . +hqdm:physical_object rdfs:subClassOf hqdm:state_of_physical_object . +hqdm:physical_object_member_of rdfs:domain hqdm:physical_object . +hqdm:physical_object_member_of rdfs:range hqdm:class_of_physical_object . +hqdm:physical_object_member_of_kind rdfs:domain hqdm:physical_object . +hqdm:physical_object_member_of_kind rdfs:range hqdm:kind_of_physical_object . +hqdm:physical_property rdf:type rdfs:Class . +hqdm:physical_property rdfs:subClassOf hqdm:class_of_state . +hqdm:physical_property_member_of rdfs:domain hqdm:physical_property . +hqdm:physical_property_member_of rdfs:range hqdm:class_of_physical_property . +hqdm:physical_property_member_of_kind rdfs:domain hqdm:physical_property . +hqdm:physical_property_member_of_kind rdfs:range hqdm:kind_of_physical_property . +hqdm:physical_property_range rdf:type rdfs:Class . +hqdm:physical_property_range rdfs:subClassOf hqdm:class_of_state . +hqdm:physical_property_range_ranges_over rdfs:domain hqdm:physical_property_range . +hqdm:physical_property_range_ranges_over rdfs:range hqdm:physical_property . +hqdm:physical_quantity rdf:type rdfs:Class . +hqdm:physical_quantity rdfs:subClassOf hqdm:physical_property . +hqdm:physical_quantity_member_of rdfs:domain hqdm:physical_quantity . +hqdm:physical_quantity_member_of rdfs:range hqdm:class_of_physical_quantity . +hqdm:physical_quantity_member_of_kind rdfs:domain hqdm:physical_quantity . +hqdm:physical_quantity_member_of_kind rdfs:range hqdm:kind_of_physical_quantity . +hqdm:physical_quantity_range rdf:type rdfs:Class . +hqdm:physical_quantity_range rdfs:subClassOf hqdm:physical_property_range . +hqdm:physical_quantity_range_lower_bound rdfs:domain hqdm:physical_quantity_range . +hqdm:physical_quantity_range_lower_bound rdfs:range hqdm:physical_quantity . +hqdm:physical_quantity_range_upper_bound rdfs:domain hqdm:physical_quantity_range . +hqdm:physical_quantity_range_upper_bound rdfs:range hqdm:physical_quantity . +hqdm:plan rdf:type rdfs:Class . +hqdm:plan rdfs:subClassOf hqdm:possible_world . +hqdm:point_in_time rdf:type rdfs:Class . +hqdm:point_in_time rdfs:subClassOf hqdm:event . +hqdm:point_in_time_member_of rdfs:domain hqdm:point_in_time . +hqdm:point_in_time_member_of rdfs:range hqdm:class_of_point_in_time . +hqdm:position rdf:type rdfs:Class . +hqdm:position rdfs:subClassOf hqdm:organization_component . +hqdm:position rdfs:subClassOf hqdm:state_of_position . +hqdm:position_member_of rdfs:domain hqdm:position . +hqdm:position_member_of rdfs:range hqdm:class_of_position . +hqdm:position_member_of_kind rdfs:domain hqdm:position . +hqdm:position_member_of_kind rdfs:range hqdm:kind_of_position . +hqdm:possible_world rdf:type rdfs:Class . +hqdm:possible_world rdfs:subClassOf hqdm:individual . +hqdm:possible_world rdfs:subClassOf hqdm:period_of_time . +hqdm:possible_world_member_of rdfs:domain hqdm:possible_world . +hqdm:possible_world_member_of rdfs:range hqdm:class_of_possible_world . +hqdm:price rdf:type rdfs:Class . +hqdm:price rdfs:subClassOf hqdm:class_of_amount_of_money . +hqdm:product_brand rdf:type rdfs:Class . +hqdm:product_brand rdfs:subClassOf hqdm:class_of_sales_product_instance . +hqdm:product_offering rdf:type rdfs:Class . +hqdm:product_offering rdfs:subClassOf hqdm:offering . +hqdm:product_offering_class_of_offered rdfs:domain hqdm:product_offering . +hqdm:product_offering_class_of_offered rdfs:range hqdm:sales_product . +hqdm:reaching_agreement rdf:type rdfs:Class . +hqdm:reaching_agreement rdfs:subClassOf hqdm:socially_constructed_activity . +hqdm:reaching_agreement_member_of rdfs:domain hqdm:reaching_agreement . +hqdm:reaching_agreement_member_of rdfs:range hqdm:class_of_reaching_agreement . +hqdm:reaching_agreement_part_of rdfs:domain hqdm:reaching_agreement . +hqdm:reaching_agreement_part_of rdfs:range hqdm:agreement_process . +hqdm:recognizing_language_community rdf:type rdfs:Class . +hqdm:recognizing_language_community rdfs:subClassOf hqdm:participant . +hqdm:recognizing_language_community rdfs:subClassOf hqdm:state_of_language_community . +hqdm:recognizing_language_community_participant_in rdfs:domain hqdm:recognizing_language_community . +hqdm:recognizing_language_community_participant_in rdfs:range hqdm:representation_by_sign . +hqdm:relationship rdf:type rdfs:Class . +hqdm:relationship rdfs:subClassOf hqdm:abstract_object . +hqdm:relationship_member_of rdfs:domain hqdm:relationship . +hqdm:relationship_member_of rdfs:range hqdm:class_of_relationship . +hqdm:representation_by_pattern rdf:type rdfs:Class . +hqdm:representation_by_pattern rdfs:subClassOf hqdm:class_of_representation . +hqdm:representation_by_pattern_consists_of_by_class rdfs:domain hqdm:representation_by_pattern . +hqdm:representation_by_pattern_consists_of_by_class rdfs:range hqdm:pattern . +hqdm:representation_by_pattern_consists_of_in_members rdfs:domain hqdm:representation_by_pattern . +hqdm:representation_by_pattern_consists_of_in_members rdfs:range hqdm:recognizing_language_community . +hqdm:representation_by_pattern_represented rdfs:domain hqdm:representation_by_pattern . +hqdm:representation_by_pattern_represented rdfs:range hqdm:thing . +hqdm:representation_by_sign rdf:type rdfs:Class . +hqdm:representation_by_sign rdfs:subClassOf hqdm:association . +hqdm:representation_by_sign_consists_of rdfs:domain hqdm:representation_by_sign . +hqdm:representation_by_sign_consists_of rdfs:range hqdm:participant_in . +hqdm:representation_by_sign_consists_of_ rdfs:domain hqdm:representation_by_sign . +hqdm:representation_by_sign_consists_of_ rdfs:range hqdm:recognizing_language_community . +hqdm:representation_by_sign_member_of rdfs:domain hqdm:representation_by_sign . +hqdm:representation_by_sign_member_of rdfs:range hqdm:class_of_representation . +hqdm:representation_by_sign_member_of_ rdfs:domain hqdm:representation_by_sign . +hqdm:representation_by_sign_member_of_ rdfs:range hqdm:representation_by_pattern . +hqdm:representation_by_sign_represents rdfs:domain hqdm:representation_by_sign . +hqdm:representation_by_sign_represents rdfs:range hqdm:thing . +hqdm:requirement rdf:type rdfs:Class . +hqdm:requirement rdfs:subClassOf hqdm:spatio_temporal_extent . +hqdm:requirement_defined_by rdfs:domain hqdm:requirement . +hqdm:requirement_defined_by rdfs:range hqdm:requirement_specification . +hqdm:requirement_part_of_plan rdfs:domain hqdm:requirement . +hqdm:requirement_part_of_plan rdfs:range hqdm:plan . +hqdm:requirement_specification rdf:type rdfs:Class . +hqdm:requirement_specification rdfs:subClassOf hqdm:class_of_spatio_temporal_extent . +hqdm:requirement_specification_intersection_of rdfs:domain hqdm:requirement_specification . +hqdm:requirement_specification_intersection_of rdfs:range hqdm:class_of_state . +hqdm:role rdf:type rdfs:Class . +hqdm:role rdfs:subClassOf hqdm:class_of_participant . +hqdm:role_part_of_by_class rdfs:domain hqdm:role . +hqdm:role_part_of_by_class rdfs:range hqdm:kind_of_activity . +hqdm:role_part_of_by_class_ rdfs:domain hqdm:role . +hqdm:role_part_of_by_class_ rdfs:range hqdm:kind_of_association . +hqdm:sale_of_goods rdf:type rdfs:Class . +hqdm:sale_of_goods rdfs:subClassOf hqdm:contract_process . +hqdm:sale_of_goods_consists_of rdfs:domain hqdm:sale_of_goods . +hqdm:sale_of_goods_consists_of rdfs:range hqdm:part_of . +hqdm:sale_of_goods_consists_of_ rdfs:domain hqdm:sale_of_goods . +hqdm:sale_of_goods_consists_of_ rdfs:range hqdm:part_of . +hqdm:sales_product rdf:type rdfs:Class . +hqdm:sales_product rdfs:subClassOf hqdm:class_of_sales_product_instance . +hqdm:sales_product_instance rdf:type rdfs:Class . +hqdm:sales_product_instance rdfs:subClassOf hqdm:ordinary_functional_object . +hqdm:sales_product_instance rdfs:subClassOf hqdm:state_of_sales_product_instance . +hqdm:sales_product_instance_member_of rdfs:domain hqdm:sales_product_instance . +hqdm:sales_product_instance_member_of rdfs:range hqdm:class_of_sales_product_instance . +hqdm:sales_product_meets_specification rdfs:domain hqdm:sales_product . +hqdm:sales_product_meets_specification rdfs:range hqdm:requirement_specification . +hqdm:sales_product_sold_under rdfs:domain hqdm:sales_product . +hqdm:sales_product_sold_under rdfs:range hqdm:product_brand . +hqdm:sales_product_version rdfs:subClassOf hqdm:class_of_sales_product_instance . +hqdm:sales_product_version_sold_as rdfs:domain hqdm:sales_product_version . +hqdm:sales_product_version_sold_as rdfs:range hqdm:sales_product . +hqdm:sales_product_version_successor rdfs:domain hqdm:sales_product_version . +hqdm:sales_product_version_successor rdfs:range hqdm:sales_product_version . +hqdm:scale rdfs:subClassOf hqdm:function_ . +hqdm:scale_domain rdfs:domain hqdm:scale . +hqdm:scale_domain rdfs:range hqdm:kind_of_physical_quantity . +hqdm:scale_unit rdfs:domain hqdm:scale . +hqdm:scale_unit rdfs:range hqdm:unit_of_measure . +hqdm:sign rdfs:subClassOf hqdm:participant . +hqdm:sign rdfs:subClassOf hqdm:socially_constructed_object . +hqdm:sign rdfs:subClassOf hqdm:state_of_sign . +hqdm:sign_member_of rdfs:domain hqdm:sign . +hqdm:sign_member_of rdfs:range hqdm:class_of_sign . +hqdm:sign_member_of_ rdfs:domain hqdm:sign . +hqdm:sign_member_of_ rdfs:range hqdm:pattern . +hqdm:sign_participant_in rdfs:domain hqdm:sign . +hqdm:sign_participant_in rdfs:range hqdm:representation_by_sign . +hqdm:socially_constructed_activity rdf:type rdfs:Class . +hqdm:socially_constructed_activity rdfs:subClassOf hqdm:activity . +hqdm:socially_constructed_activity rdfs:subClassOf hqdm:socially_constructed_object . +hqdm:socially_constructed_activity_member_of rdfs:domain hqdm:socially_constructed_activity . +hqdm:socially_constructed_activity_member_of rdfs:range hqdm:class_of_socially_constructed_activity . +hqdm:socially_constructed_activity_part_of rdfs:domain hqdm:socially_constructed_activity . +hqdm:socially_constructed_activity_part_of rdfs:range hqdm:reaching_agreement . +hqdm:socially_constructed_activity_part_of_ rdfs:domain hqdm:socially_constructed_activity . +hqdm:socially_constructed_activity_part_of_ rdfs:range hqdm:agreement_execution . +hqdm:socially_constructed_object rdf:type rdfs:Class . +hqdm:socially_constructed_object rdfs:subClassOf hqdm:intentionally_constructed_object . +hqdm:socially_constructed_object rdfs:subClassOf hqdm:state_of_socially_constructed_object . +hqdm:socially_constructed_object_member_of rdfs:domain hqdm:socially_constructed_object . +hqdm:socially_constructed_object_member_of rdfs:range hqdm:class_of_socially_contructed_object . +hqdm:socially_constructed_object_member_of_kind rdfs:domain hqdm:socially_constructed_object . +hqdm:socially_constructed_object_member_of_kind rdfs:range hqdm:kind_of_socially_constructed_object . +hqdm:spatio_temporal_extent rdf:type rdfs:Class . +hqdm:spatio_temporal_extent rdfs:subClassOf hqdm:thing . +hqdm:spatio_temporal_extent_aggregated_into rdfs:domain hqdm:spatio_temporal_extent . +hqdm:spatio_temporal_extent_aggregated_into rdfs:range hqdm:spatio_temporal_extent . +hqdm:spatio_temporal_extent_beginning rdfs:domain hqdm:spatio_temporal_extent . +hqdm:spatio_temporal_extent_beginning rdfs:range hqdm:event . +hqdm:spatio_temporal_extent_consists__of rdfs:domain hqdm:spatio_temporal_extent . +hqdm:spatio_temporal_extent_consists__of rdfs:range hqdm:spatio_temporal_extent . +hqdm:spatio_temporal_extent_ending rdfs:domain hqdm:spatio_temporal_extent . +hqdm:spatio_temporal_extent_ending rdfs:range hqdm:event . +hqdm:spatio_temporal_extent_member_of rdfs:domain hqdm:spatio_temporal_extent . +hqdm:spatio_temporal_extent_member_of rdfs:range hqdm:class_of_spatio_temporal_extent . +hqdm:spatio_temporal_extent_part__of rdfs:domain hqdm:spatio_temporal_extent . +hqdm:spatio_temporal_extent_part__of rdfs:range hqdm:spatio_temporal_extent . +hqdm:spatio_temporal_extent_part_of_possible_world rdfs:domain hqdm:spatio_temporal_extent . +hqdm:spatio_temporal_extent_part_of_possible_world rdfs:range hqdm:possible_world . +hqdm:spatio_temporal_extent_temporal__part_of rdfs:domain hqdm:spatio_temporal_extent . +hqdm:spatio_temporal_extent_temporal__part_of rdfs:range hqdm:spatio_temporal_extent . +hqdm:specialization rdf:type rdfs:Class . +hqdm:specialization rdfs:subClassOf hqdm:relationship . +hqdm:specialization_subclass rdfs:domain hqdm:specialization . +hqdm:specialization_subclass rdfs:range hqdm:class . +hqdm:specialization_superclass rdfs:domain hqdm:specialization . +hqdm:specialization_superclass rdfs:range hqdm:class . +hqdm:state rdf:type rdfs:Class . +hqdm:state rdfs:subClassOf hqdm:spatio_temporal_extent . +hqdm:state_member_of rdfs:domain hqdm:state . +hqdm:state_member_of rdfs:range hqdm:class_of_state . +hqdm:state_of_activity rdf:type rdfs:Class . +hqdm:state_of_activity rdfs:subClassOf hqdm:state . +hqdm:state_of_activity_member_of rdfs:domain hqdm:state_of_activity . +hqdm:state_of_activity_member_of rdfs:range hqdm:class_of_state_of_activity . +hqdm:state_of_activity_temporal_part_of rdfs:domain hqdm:state_of_activity . +hqdm:state_of_activity_temporal_part_of rdfs:range hqdm:activity . +hqdm:state_of_amount_of_money rdf:type rdfs:Class . +hqdm:state_of_amount_of_money rdfs:subClassOf hqdm:state_of_physical_object . +hqdm:state_of_amount_of_money rdfs:subClassOf hqdm:state_of_socially_constructed_object . +hqdm:state_of_amount_of_money_member_of rdfs:domain hqdm:state_of_amount_of_money . +hqdm:state_of_amount_of_money_member_of rdfs:range hqdm:class_of_state_of_amount_of_money . +hqdm:state_of_amount_of_money_temporal_part_of rdfs:domain hqdm:state_of_amount_of_money . +hqdm:state_of_amount_of_money_temporal_part_of rdfs:range hqdm:amount_of_money . +hqdm:state_of_association rdf:type rdfs:Class . +hqdm:state_of_association rdfs:subClassOf hqdm:state . +hqdm:state_of_association_member_of rdfs:domain hqdm:state_of_association . +hqdm:state_of_association_member_of rdfs:range hqdm:class_of_state_of_association . +hqdm:state_of_association_temporal_part_of rdfs:domain hqdm:state_of_association . +hqdm:state_of_association_temporal_part_of rdfs:range hqdm:association . +hqdm:state_of_biological_object rdf:type rdfs:Class . +hqdm:state_of_biological_object rdfs:subClassOf hqdm:state_of_physical_object . +hqdm:state_of_biological_object_member_of rdfs:domain hqdm:state_of_biological_object . +hqdm:state_of_biological_object_member_of rdfs:range hqdm:class_of_state_of_biological_object . +hqdm:state_of_biological_object_temporal_part_of rdfs:domain hqdm:state_of_biological_object . +hqdm:state_of_biological_object_temporal_part_of rdfs:range hqdm:biological_object . +hqdm:state_of_biological_system rdf:type rdfs:Class . +hqdm:state_of_biological_system rdfs:subClassOf hqdm:state_of_ordinary_biological_object . +hqdm:state_of_biological_system rdfs:subClassOf hqdm:state_of_system . +hqdm:state_of_biological_system_component rdf:type rdfs:Class . +hqdm:state_of_biological_system_component rdfs:subClassOf hqdm:state_of_biological_object . +hqdm:state_of_biological_system_component rdfs:subClassOf hqdm:state_of_system_component . +hqdm:state_of_biological_system_component_member_of rdfs:domain hqdm:state_of_biological_system_component . +hqdm:state_of_biological_system_component_member_of rdfs:range hqdm:class_of_state_of_biological_system_component . +hqdm:state_of_biological_system_component_temporal_part_of rdfs:domain hqdm:state_of_biological_system_component . +hqdm:state_of_biological_system_component_temporal_part_of rdfs:range hqdm:biological_system_component . +hqdm:state_of_biological_system_member_of rdfs:domain hqdm:state_of_biological_system . +hqdm:state_of_biological_system_member_of rdfs:range hqdm:class_of_state_of_biological_system . +hqdm:state_of_biological_system_temporal_part_of rdfs:domain hqdm:state_of_biological_system . +hqdm:state_of_biological_system_temporal_part_of rdfs:range hqdm:biological_system . +hqdm:state_of_functional_object rdf:type rdfs:Class . +hqdm:state_of_functional_object rdfs:subClassOf hqdm:state_of_intentionally_constructed_object . +hqdm:state_of_functional_object rdfs:subClassOf hqdm:state_of_physical_object . +hqdm:state_of_functional_object_member_of rdfs:domain hqdm:state_of_functional_object . +hqdm:state_of_functional_object_member_of rdfs:range hqdm:class_of_state_of_functional_object . +hqdm:state_of_functional_object_temporal_part_of rdfs:domain hqdm:state_of_functional_object . +hqdm:state_of_functional_object_temporal_part_of rdfs:range hqdm:functional_object . +hqdm:state_of_functional_system rdf:type rdfs:Class . +hqdm:state_of_functional_system rdfs:subClassOf hqdm:state_of_ordinary_functional_object . +hqdm:state_of_functional_system rdfs:subClassOf hqdm:state_of_system . +hqdm:state_of_functional_system_component rdf:type rdfs:Class . +hqdm:state_of_functional_system_component rdfs:subClassOf hqdm:state_of_functional_object . +hqdm:state_of_functional_system_component rdfs:subClassOf hqdm:state_of_system_component . +hqdm:state_of_functional_system_component_member_of rdfs:domain hqdm:state_of_functional_system_component . +hqdm:state_of_functional_system_component_member_of rdfs:range hqdm:class_of_state_of_functional_system_component . +hqdm:state_of_functional_system_component_temporal_part_of rdfs:domain hqdm:state_of_functional_system_component . +hqdm:state_of_functional_system_component_temporal_part_of rdfs:range hqdm:functional_system_component . +hqdm:state_of_functional_system_member_of rdfs:domain hqdm:state_of_functional_system . +hqdm:state_of_functional_system_member_of rdfs:range hqdm:class_of_state_of_functional_system . +hqdm:state_of_functional_system_temporal_part_of rdfs:domain hqdm:state_of_functional_system . +hqdm:state_of_functional_system_temporal_part_of rdfs:range hqdm:functional_system . +hqdm:state_of_intentionally_constructed_object rdf:type rdfs:Class . +hqdm:state_of_intentionally_constructed_object rdfs:subClassOf hqdm:state . +hqdm:state_of_intentionally_constructed_object_member_of rdfs:domain hqdm:state_of_intentionally_constructed_object . +hqdm:state_of_intentionally_constructed_object_member_of rdfs:range hqdm:class_of_state_of_intentionally_constructed_object . +hqdm:state_of_intentionally_constructed_object_temporal_part_of rdfs:domain hqdm:state_of_intentionally_constructed_object . +hqdm:state_of_intentionally_constructed_object_temporal_part_of rdfs:range hqdm:intentionally_constructed_object . +hqdm:state_of_language_community rdf:type rdfs:Class . +hqdm:state_of_language_community rdfs:subClassOf hqdm:state_of_organization . +hqdm:state_of_language_community_temporal_part_of rdfs:domain hqdm:state_of_language_community . +hqdm:state_of_language_community_temporal_part_of rdfs:range hqdm:language_community . +hqdm:state_of_ordinary_biological_object rdf:type rdfs:Class . +hqdm:state_of_ordinary_biological_object rdfs:subClassOf hqdm:state_of_biological_object . +hqdm:state_of_ordinary_biological_object rdfs:subClassOf hqdm:state_of_ordinary_physical_object . +hqdm:state_of_ordinary_biological_object_member_of rdfs:domain hqdm:state_of_ordinary_biological_object . +hqdm:state_of_ordinary_biological_object_member_of rdfs:range hqdm:class_of_state_of_ordinary_biological_object . +hqdm:state_of_ordinary_biological_object_temporal_part_of rdfs:domain hqdm:state_of_ordinary_biological_object . +hqdm:state_of_ordinary_biological_object_temporal_part_of rdfs:range hqdm:ordinary_biological_object . +hqdm:state_of_ordinary_functional_object rdf:type rdfs:Class . +hqdm:state_of_ordinary_functional_object rdfs:subClassOf hqdm:state_of_functional_object . +hqdm:state_of_ordinary_functional_object rdfs:subClassOf hqdm:state_of_ordinary_physical_object . +hqdm:state_of_ordinary_functional_object_member_of rdfs:domain hqdm:state_of_ordinary_functional_object . +hqdm:state_of_ordinary_functional_object_member_of rdfs:range hqdm:class_of_state_of_ordinary_functional_object . +hqdm:state_of_ordinary_functional_object_temporal_part_of rdfs:domain hqdm:state_of_ordinary_functional_object . +hqdm:state_of_ordinary_functional_object_temporal_part_of rdfs:range hqdm:ordinary_functional_object . +hqdm:state_of_ordinary_physical_object rdf:type rdfs:Class . +hqdm:state_of_ordinary_physical_object rdfs:subClassOf hqdm:state_of_physical_object . +hqdm:state_of_ordinary_physical_object_member_of rdfs:domain hqdm:state_of_ordinary_physical_object . +hqdm:state_of_ordinary_physical_object_member_of rdfs:range hqdm:class_of_state_of_ordinary_physical_object . +hqdm:state_of_ordinary_physical_object_temporal_part_of rdfs:domain hqdm:state_of_ordinary_physical_object . +hqdm:state_of_ordinary_physical_object_temporal_part_of rdfs:range hqdm:ordinary_physical_object . +hqdm:state_of_organization rdf:type rdfs:Class . +hqdm:state_of_organization rdfs:subClassOf hqdm:state_of_party . +hqdm:state_of_organization rdfs:subClassOf hqdm:state_of_socially_constructed_object . +hqdm:state_of_organization_component rdf:type rdfs:Class . +hqdm:state_of_organization_component rdfs:subClassOf hqdm:state_of_socially_constructed_object . +hqdm:state_of_organization_component rdfs:subClassOf hqdm:state_of_system_component . +hqdm:state_of_organization_component_member_of rdfs:domain hqdm:state_of_organization_component . +hqdm:state_of_organization_component_member_of rdfs:range hqdm:class_of_state_of_organization_component . +hqdm:state_of_organization_component_temporal_part_of rdfs:domain hqdm:state_of_organization_component . +hqdm:state_of_organization_component_temporal_part_of rdfs:range hqdm:organization_component . +hqdm:state_of_organization_member_of rdfs:domain hqdm:state_of_organization . +hqdm:state_of_organization_member_of rdfs:range hqdm:class_of_state_of_organization . +hqdm:state_of_organization_temporal_part_of rdfs:domain hqdm:state_of_organization . +hqdm:state_of_organization_temporal_part_of rdfs:range hqdm:organization . +hqdm:state_of_party rdf:type rdfs:Class . +hqdm:state_of_party rdfs:subClassOf hqdm:state_of_system . +hqdm:state_of_party_member_of rdfs:domain hqdm:state_of_party . +hqdm:state_of_party_member_of rdfs:range hqdm:class_of_state_of_party . +hqdm:state_of_party_temporal_part_of rdfs:domain hqdm:state_of_party . +hqdm:state_of_party_temporal_part_of rdfs:range hqdm:party . +hqdm:state_of_person rdf:type rdfs:Class . +hqdm:state_of_person rdfs:subClassOf hqdm:state_of_biological_system . +hqdm:state_of_person rdfs:subClassOf hqdm:state_of_party . +hqdm:state_of_person_member_of rdfs:domain hqdm:state_of_person . +hqdm:state_of_person_member_of rdfs:range hqdm:class_of_state_of_person . +hqdm:state_of_person_temporal_part_of rdfs:domain hqdm:state_of_person . +hqdm:state_of_person_temporal_part_of rdfs:range hqdm:person . +hqdm:state_of_physical_object rdf:type rdfs:Class . +hqdm:state_of_physical_object rdfs:subClassOf hqdm:state . +hqdm:state_of_physical_object_member_of rdfs:domain hqdm:state_of_physical_object . +hqdm:state_of_physical_object_member_of rdfs:range hqdm:class_of_state_of_physical_object . +hqdm:state_of_physical_object_temporal_part_of rdfs:domain hqdm:state_of_physical_object . +hqdm:state_of_physical_object_temporal_part_of rdfs:range hqdm:physical_object . +hqdm:state_of_position rdf:type rdfs:Class . +hqdm:state_of_position rdfs:subClassOf hqdm:state_of_organization_component . +hqdm:state_of_position_member_of rdfs:domain hqdm:state_of_position . +hqdm:state_of_position_member_of rdfs:range hqdm:class_of_state_of_position . +hqdm:state_of_position_temporal_part_of rdfs:domain hqdm:state_of_position . +hqdm:state_of_position_temporal_part_of rdfs:range hqdm:position . +hqdm:state_of_sales_product_instance rdf:type rdfs:Class . +hqdm:state_of_sales_product_instance rdfs:subClassOf hqdm:state_of_ordinary_functional_object . +hqdm:state_of_sales_product_instance_member_of rdfs:domain hqdm:state_of_sales_product_instance . +hqdm:state_of_sales_product_instance_member_of rdfs:range hqdm:class_of_state_of_sales_product_instance . +hqdm:state_of_sales_product_instance_temporal_part_of rdfs:domain hqdm:state_of_sales_product_instance . +hqdm:state_of_sales_product_instance_temporal_part_of rdfs:range hqdm:sales_product_instance . +hqdm:state_of_sign rdf:type rdfs:Class . +hqdm:state_of_sign rdfs:subClassOf hqdm:state_of_socially_constructed_object . +hqdm:state_of_sign_member_of rdfs:domain hqdm:state_of_sign . +hqdm:state_of_sign_member_of rdfs:range hqdm:class_of_state_of_sign . +hqdm:state_of_sign_temporal_part_of rdfs:domain hqdm:state_of_sign . +hqdm:state_of_sign_temporal_part_of rdfs:range hqdm:sign . +hqdm:state_of_socially_constructed_activity rdf:type rdfs:Class . +hqdm:state_of_socially_constructed_activity rdfs:subClassOf hqdm:state_of_activity . +hqdm:state_of_socially_constructed_activity rdfs:subClassOf hqdm:state_of_socially_constructed_object . +hqdm:state_of_socially_constructed_object rdf:type rdfs:Class . +hqdm:state_of_socially_constructed_object rdfs:subClassOf hqdm:state_of_intentionally_constructed_object . +hqdm:state_of_socially_constructed_object_member_of rdfs:domain hqdm:state_of_socially_constructed_object . +hqdm:state_of_socially_constructed_object_member_of rdfs:range hqdm:class_of_state_of_socially_constructed_object . +hqdm:state_of_socially_constructed_object_temporal_part_of rdfs:domain hqdm:state_of_socially_constructed_object . +hqdm:state_of_socially_constructed_object_temporal_part_of rdfs:range hqdm:socially_constructed_object . +hqdm:state_of_system rdf:type rdfs:Class . +hqdm:state_of_system rdfs:subClassOf hqdm:state_of_ordinary_physical_object . +hqdm:state_of_system_component rdf:type rdfs:Class . +hqdm:state_of_system_component rdfs:subClassOf hqdm:state_of_physical_object . +hqdm:state_of_system_component_member_of rdfs:domain hqdm:state_of_system_component . +hqdm:state_of_system_component_member_of rdfs:range hqdm:class_of_state_of_system_component . +hqdm:state_of_system_component_temporal_part_of rdfs:domain hqdm:state_of_system_component . +hqdm:state_of_system_component_temporal_part_of rdfs:range hqdm:system_component . +hqdm:state_of_system_member_of rdfs:domain hqdm:state_of_system . +hqdm:state_of_system_member_of rdfs:range hqdm:class_of_state_of_system . +hqdm:state_of_system_temporal_part_of rdfs:domain hqdm:state_of_system . +hqdm:state_of_system_temporal_part_of rdfs:range hqdm:system . +hqdm:state_temporal_part_of rdfs:domain hqdm:state . +hqdm:state_temporal_part_of rdfs:range hqdm:individual . +hqdm:system rdf:type rdfs:Class . +hqdm:system rdfs:subClassOf hqdm:ordinary_physical_object . +hqdm:system rdfs:subClassOf hqdm:state_of_system . +hqdm:system_component rdf:type rdfs:Class . +hqdm:system_component rdfs:subClassOf hqdm:physical_object . +hqdm:system_component rdfs:subClassOf hqdm:state_of_system_component . +hqdm:system_component_component_of rdfs:domain hqdm:system_component . +hqdm:system_component_component_of rdfs:range hqdm:system . +hqdm:system_component_member_of rdfs:domain hqdm:system_component . +hqdm:system_component_member_of rdfs:range hqdm:class_of_system_component . +hqdm:system_member_of rdfs:domain hqdm:system . +hqdm:system_member_of rdfs:range hqdm:class_of_system . +hqdm:system_member_of_kind rdfs:domain hqdm:system . +hqdm:system_member_of_kind rdfs:range hqdm:kind_of_system . +hqdm:temporal_composition rdfs:subClassOf hqdm:composition . +hqdm:thing rdf:type rdfs:Class . +hqdm:thing_member__of rdfs:domain hqdm:thing . +hqdm:thing_member__of rdfs:range hqdm:class . +hqdm:transfer_of_ownership rdf:type rdfs:Class . +hqdm:transfer_of_ownership rdfs:subClassOf hqdm:socially_constructed_activity . +hqdm:transfer_of_ownership_causes_beginning rdfs:domain hqdm:transfer_of_ownership . +hqdm:transfer_of_ownership_causes_beginning rdfs:range hqdm:beginning_of_ownership . +hqdm:transfer_of_ownership_causes_ending rdfs:domain hqdm:transfer_of_ownership . +hqdm:transfer_of_ownership_causes_ending rdfs:range hqdm:ending_of_ownership . +hqdm:transfer_of_ownership_consists_of_participant rdfs:domain hqdm:transfer_of_ownership . +hqdm:transfer_of_ownership_consists_of_participant rdfs:range hqdm:participant_in . +hqdm:transfer_of_ownership_of_money rdf:type rdfs:Class . +hqdm:transfer_of_ownership_of_money rdfs:subClassOf hqdm:transfer_of_ownership . +hqdm:transfer_of_ownership_of_money_part_of rdfs:domain hqdm:transfer_of_ownership_of_money . +hqdm:transfer_of_ownership_of_money_part_of rdfs:range hqdm:exchange_of_goods_and_money . +hqdm:transfer_of_ownership_of_money_references rdfs:domain hqdm:transfer_of_ownership_of_money . +hqdm:transfer_of_ownership_of_money_references rdfs:range hqdm:money_asset . +hqdm:transfer_of_ownership_references rdfs:domain hqdm:transfer_of_ownership . +hqdm:transfer_of_ownership_references rdfs:range hqdm:asset . +hqdm:transfer_of_ownership_transfer_of_ownership_part_of rdfs:domain hqdm:transfer_of_ownership . +hqdm:transfer_of_ownership_transfer_of_ownership_part_of rdfs:range hqdm:exchange_of_goods_and_money . +hqdm:transferee rdfs:subClassOf hqdm:participant . +hqdm:transferee rdfs:subClassOf hqdm:state_of_party . +hqdm:transferee_participant_in rdfs:domain hqdm:transferee . +hqdm:transferee_participant_in rdfs:range hqdm:transfer_of_ownership . +hqdm:transferor rdf:type rdfs:Class . +hqdm:transferor rdfs:subClassOf hqdm:participant . +hqdm:transferor rdfs:subClassOf hqdm:state_of_party . +hqdm:transferor_participant_in rdfs:domain hqdm:transferor . +hqdm:transferor_participant_in rdfs:range hqdm:transfer_of_ownership . +hqdm:transferor_temporal_part_of rdfs:domain hqdm:transferor . +hqdm:transferor_temporal_part_of rdfs:range hqdm:owner . +hqdm:unit_of_measure rdf:type rdfs:Class . +hqdm:unit_of_measure rdfs:subClassOf hqdm:function_ . diff --git a/examples/src/test/resources/validation.rules b/examples/src/test/resources/validation.rules new file mode 100644 index 00000000..a9fe5595 --- /dev/null +++ b/examples/src/test/resources/validation.rules @@ -0,0 +1,16 @@ +@prefix rdfs: . +@prefix rdf: . +@prefix xsd: . +@prefix hqdm: . + +@include . + +# +# Check that all classes have a data_EntityName predicate. +# +[checkForDataEntityName: + (?y rb:violation error('Mising Entity Name', 'Entity should have predicate data_EntityName', ?s)) + <- + (?s rdf:type hqdm:class) + noValue(?s hqdm:data_EntityName) +] From 5e15f42b65928f008259ec2786cf81c9ba99e3de Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 7 Feb 2024 16:20:29 +0000 Subject: [PATCH 04/10] Use DatasetFactory.wrap() to hold the InfModel. --- .../uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java index bfe182c0..5e750e79 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java @@ -494,8 +494,7 @@ public MagmaCoreDatabase applyInferenceRules( // Convert the inference model to a dataset and return it wrapped as // an in-memory MagmaCoreDatabase. - final Dataset inferenceDataset = DatasetFactory.create(); - inferenceDataset.getDefaultModel().add(model); + final Dataset inferenceDataset = DatasetFactory.wrap(model); return new MagmaCoreJenaDatabase(inferenceDataset); } From 885412681bf4949937026eecd9ab63f9b0ad111b Mon Sep 17 00:00:00 2001 From: Tony Date: Thu, 8 Feb 2024 11:20:11 +0000 Subject: [PATCH 05/10] Checkpoint - added some validation rules. Not finished yet. --- .../verify/DataIntegrityChecksTest.java | 50 ++++++++++++++++-- examples/src/test/resources/validation.rules | 52 +++++++++++++++++++ 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java b/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java index c131478b..4be9c2c9 100644 --- a/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java +++ b/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java @@ -12,10 +12,17 @@ import org.junit.Test; import uk.gov.gchq.magmacore.database.validation.ValidationReportEntry; +import uk.gov.gchq.magmacore.hqdm.model.Organization; +import uk.gov.gchq.magmacore.hqdm.model.Person; +import uk.gov.gchq.magmacore.hqdm.model.PossibleWorld; +import uk.gov.gchq.magmacore.hqdm.model.Role; +import uk.gov.gchq.magmacore.hqdm.model.Sign; import uk.gov.gchq.magmacore.hqdm.model.Thing; +import uk.gov.gchq.magmacore.hqdm.rdf.iri.HQDM; import uk.gov.gchq.magmacore.hqdm.rdf.iri.IRI; import uk.gov.gchq.magmacore.hqdm.rdf.iri.IriBase; import uk.gov.gchq.magmacore.hqdm.services.ClassServices; +import uk.gov.gchq.magmacore.hqdm.services.SpatioTemporalExtentServices; import uk.gov.gchq.magmacore.service.MagmaCoreService; import uk.gov.gchq.magmacore.service.MagmaCoreServiceFactory; @@ -44,10 +51,39 @@ public void test() throws IOException, URISyntaxException { // Populate some data to prove that the rules are applied. service.runInWriteTransaction(svc -> { - // Create a kind without an ENTITY_NAME. - final Thing kind = ClassServices.createKindOfOrganization(new IRI(TEST_BASE, UUID.randomUUID().toString())); + final Thing kind = ClassServices.createKindOfOrganization(randomIri()); svc.create(kind); + + // Create a participant that isn't a member_of_kind of a role. + // Also, as a SpatioTemporalExtent it should have a part_of_possible_world predicate. + final Thing participant = SpatioTemporalExtentServices.createParticipant(randomIri()); + svc.create(participant); + + // Create an entity with invalid temporal parthood. + final PossibleWorld possibleWorld = SpatioTemporalExtentServices.createPossibleWorld(randomIri()); + possibleWorld.addValue(HQDM.PART_OF_POSSIBLE_WORLD, possibleWorld.getId()); + + final Person person = SpatioTemporalExtentServices.createPerson(randomIri()); + person.addValue(HQDM.PART_OF_POSSIBLE_WORLD, possibleWorld.getId()); + + final Organization organization = SpatioTemporalExtentServices.createOrganization(randomIri()); + organization.addValue(HQDM.PART_OF_POSSIBLE_WORLD, possibleWorld.getId()); + + person.addValue(HQDM.TEMPORAL_PART_OF, organization.getId()); + + svc.create(possibleWorld); + svc.create(person); + svc.create(organization); + + // Create a sign without a value_ predicate. + final Sign sign = SpatioTemporalExtentServices.createSign(randomIri()); + sign.addValue(HQDM.PART_OF_POSSIBLE_WORLD, possibleWorld.getId()); + final Role signRole = ClassServices.createRole(randomIri()); + signRole.addValue(HQDM.ENTITY_NAME, "A role for a sign"); + sign.addValue(HQDM.MEMBER_OF_KIND, signRole.getId()); + svc.create(sign); + svc.create(signRole); return svc; }); @@ -61,7 +97,15 @@ public void test() throws IOException, URISyntaxException { if (validationResult.size() > 0) { System.out.println(validationResult); } - assertEquals(1, validationResult.size()); + assertEquals(5, validationResult.size()); } + /** + * Make random IRIs. + * + * @return a random {@link IRI} + */ + private static IRI randomIri() { + return new IRI(TEST_BASE, UUID.randomUUID().toString()); + } } diff --git a/examples/src/test/resources/validation.rules b/examples/src/test/resources/validation.rules index a9fe5595..46aa1a49 100644 --- a/examples/src/test/resources/validation.rules +++ b/examples/src/test/resources/validation.rules @@ -14,3 +14,55 @@ (?s rdf:type hqdm:class) noValue(?s hqdm:data_EntityName) ] + +# +# Check that participants have roles. +# +[checkParticipantRoles: + (?y rb:violation error('Missing Participant Role', 'All participants should be a member_of_kind of a Role', ?s)) + <- + (?s rdf:type hqdm:participant) + noValue(?s hqdm:member_of_kind) +] + +# +# Check that SpatioTemporalExtents are part of some PossibleWorld +# +[checkPartOfPossibleWorld: + (?y rb:violation error('Missing PossibleWorld', 'All SpatioTemporalExtents should be a part of a PossibleWorld', ?s)) + <- + (?s rdf:type hqdm:spatio_temporal_extent) + noValue(?s hqdm:part_of_possible_world) +] + +# +# Check that temporal parts are a part of a subtype. +# +[checkTemporalPartsPartOfSubtype: + (?y rb:violation error('Invalid temporal parthood', 'All temporal parts must be temporal parts of a subtype.', ?s, ?t)) + <- + (?s hqdm:temporal_part_of ?t) + noValue(?t rdfs:subClassOf ?s) +] +[checkTemporalPartsPartOfSubtype2: + (?y rb:violation error('Invalid temporal parthood', 'All temporal parts must be temporal parts of a subtype.', ?s, ?t)) + <- + (?s hqdm:temporal_part_of_ ?t) + noValue(?t rdfs:subClassOf ?s) +] +[checkTemporalPartsPartOfSubtype3: + (?y rb:violation error('Invalid temporal parthood', 'All temporal parts must be temporal parts of a subtype.', ?s, ?t)) + <- + (?s hqdm:temporal__part_of ?t) + noValue(?t rdfs:subClassOf ?s) +] + +# +# Check that all signs have a value_ +# +[checkAllSignsHaveAValue: + (?y rb:violation error('Sign has no value', 'All signs should have a value_ predicate.', ?s)) + <- + (?s rdf:type hqdm:sign) + noValue(?t hqdm:value_ ?v) +] From ce33a2ce607d0080b943726be10e7129e8661790 Mon Sep 17 00:00:00 2001 From: Tony Date: Mon, 12 Feb 2024 12:12:53 +0000 Subject: [PATCH 06/10] Checkpoint: Added some validateion rules and a better unit test - needs fixing. --- .../verify/DataIntegrityChecksTest.java | 64 ++++++++++++++- examples/src/test/resources/validation.rules | 79 ++++++++++++++++++- 2 files changed, 137 insertions(+), 6 deletions(-) diff --git a/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java b/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java index 4be9c2c9..d1834e7c 100644 --- a/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java +++ b/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java @@ -1,20 +1,26 @@ package uk.gov.gchq.magmacore.examples.verify; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.List; import java.util.UUID; +import org.junit.BeforeClass; import org.junit.Test; import uk.gov.gchq.magmacore.database.validation.ValidationReportEntry; import uk.gov.gchq.magmacore.hqdm.model.Organization; +import uk.gov.gchq.magmacore.hqdm.model.Pattern; import uk.gov.gchq.magmacore.hqdm.model.Person; import uk.gov.gchq.magmacore.hqdm.model.PossibleWorld; +import uk.gov.gchq.magmacore.hqdm.model.RepresentationByPattern; +import uk.gov.gchq.magmacore.hqdm.model.RepresentationBySign; import uk.gov.gchq.magmacore.hqdm.model.Role; import uk.gov.gchq.magmacore.hqdm.model.Sign; import uk.gov.gchq.magmacore.hqdm.model.Thing; @@ -34,6 +40,25 @@ public class DataIntegrityChecksTest { private static final boolean INCLUDE_RDFS = true; private static final IriBase TEST_BASE = new IriBase("test", "http://example.com/test#"); + private static List expectedErrors = null; + + /** + * Get all the errors we expect to see. + * + * @throws IOException on error. + * @throws URISyntaxException on error. + */ + @BeforeClass + public static void beforeClass() throws IOException, URISyntaxException { + final var rulesUri = DataIntegrityChecksTest.class.getResource("/validation.rules").toURI(); + expectedErrors = Files.readAllLines(Paths.get(rulesUri)) + .stream() + .filter(line -> line.contains("error")) + .map(line -> line.split("'")[1]) + .map(s -> "\"" + s + "\"") + .toList(); + } + /** * Run some data integrity checks. * @@ -77,6 +102,8 @@ public void test() throws IOException, URISyntaxException { svc.create(organization); // Create a sign without a value_ predicate. + // Also tests the member_of_ for pattern since that is also missing. + // final Sign sign = SpatioTemporalExtentServices.createSign(randomIri()); sign.addValue(HQDM.PART_OF_POSSIBLE_WORLD, possibleWorld.getId()); final Role signRole = ClassServices.createRole(randomIri()); @@ -84,6 +111,27 @@ public void test() throws IOException, URISyntaxException { sign.addValue(HQDM.MEMBER_OF_KIND, signRole.getId()); svc.create(sign); svc.create(signRole); + + // Create a RepresentationByPattern without a pattern and a pattern without a + // RepresentationByPattern. The RepresentationByPattern also has no community, + // and no sign. + // + final RepresentationByPattern rbp = ClassServices.createRepresentationByPattern(randomIri()); + rbp.addValue(HQDM.ENTITY_NAME, "A RepresentationByPattern with no pattern"); + svc.create(rbp); + + final Pattern pattern = ClassServices.createPattern(randomIri()); + pattern.addValue(HQDM.ENTITY_NAME, "A Pattern with no RepresentationByPattern"); + svc.create(pattern); + + // Create a RepresentationBySign with no community, and no sign, and does not + // represent a thing. + // + final RepresentationBySign rbs = SpatioTemporalExtentServices.createRepresentationBySign(randomIri()); + rbs.addValue(HQDM.PART_OF_POSSIBLE_WORLD, possibleWorld.getId()); + rbs.addValue(HQDM.ENTITY_NAME, "A RepresentationBySign with no community and no sign and no thing"); + svc.create(rbs); + return svc; }); @@ -94,10 +142,22 @@ public void test() throws IOException, URISyntaxException { // Validate the model. final List validationResult = service.validate(query, rules, INCLUDE_RDFS); + final List actualErrors = new ArrayList<>(); + if (validationResult.size() > 0) { - System.out.println(validationResult); + validationResult.forEach(result -> { + actualErrors.add(result.type()); + System.out.println(result.type()); + System.out.println(result.description()); + System.out.println(result.additionalInformation()); + System.out.println(); + }); } - assertEquals(5, validationResult.size()); + // Check that each rule has fired. + expectedErrors.forEach(e -> { + assertTrue(e + " was expected but not present.", actualErrors.contains(e)); + }); + assertEquals(expectedErrors.size(), actualErrors.size()); } /** diff --git a/examples/src/test/resources/validation.rules b/examples/src/test/resources/validation.rules index 46aa1a49..925fdb8b 100644 --- a/examples/src/test/resources/validation.rules +++ b/examples/src/test/resources/validation.rules @@ -9,7 +9,7 @@ # Check that all classes have a data_EntityName predicate. # [checkForDataEntityName: - (?y rb:violation error('Mising Entity Name', 'Entity should have predicate data_EntityName', ?s)) + (?y rb:violation error('Missing Entity Name', 'Entity should have predicate data_EntityName', ?s)) <- (?s rdf:type hqdm:class) noValue(?s hqdm:data_EntityName) @@ -39,19 +39,19 @@ # Check that temporal parts are a part of a subtype. # [checkTemporalPartsPartOfSubtype: - (?y rb:violation error('Invalid temporal parthood', 'All temporal parts must be temporal parts of a subtype.', ?s, ?t)) + (?y rb:violation error('Invalid temporal_part_of parthood', 'All temporal parts must be temporal parts of a subtype.', ?s, ?t)) <- (?s hqdm:temporal_part_of ?t) noValue(?t rdfs:subClassOf ?s) ] [checkTemporalPartsPartOfSubtype2: - (?y rb:violation error('Invalid temporal parthood', 'All temporal parts must be temporal parts of a subtype.', ?s, ?t)) + (?y rb:violation error('Invalid temporal_part_of_ parthood', 'All temporal parts must be temporal parts of a subtype.', ?s, ?t)) <- (?s hqdm:temporal_part_of_ ?t) noValue(?t rdfs:subClassOf ?s) ] [checkTemporalPartsPartOfSubtype3: - (?y rb:violation error('Invalid temporal parthood', 'All temporal parts must be temporal parts of a subtype.', ?s, ?t)) + (?y rb:violation error('Invalid temporal__part_of parthood', 'All temporal parts must be temporal parts of a subtype.', ?s, ?t)) <- (?s hqdm:temporal__part_of ?t) noValue(?t rdfs:subClassOf ?s) @@ -66,3 +66,74 @@ (?s rdf:type hqdm:sign) noValue(?t hqdm:value_ ?v) ] + +# +# Check that all signs are member_of_ a pattern. +# +[checkSignsMemberOfPattern: + (?y rb:violation error('Sign has no pattern', 'All signs should be member_of_ a pattern.', ?s)) + <- + (?s rdf:type hqdm:sign) + noValue(?t hqdm:member_of_ ?pattern) +] + +# +# Check that all representation_by_pattern consists_of_by_class a pattern. +# +[checkAllRepByPatternConsistOfPattern: + (?y rb:violation error('representation_by_pattern has no pattern', 'All representation_by_pattern should consists_of_by_class a pattern.', ?s)) + <- + (?r rdf:type hqdm:representation_by_pattern) + noValue(?r hqdm:consists_of_by_class ?pattern) +] + +# +# Check that all representation_by_pattern consists_of_in_members a community. +# +[checkAllRepByPatternConsistOfCommunity: + (?y rb:violation error('representation_by_pattern has no community', 'All representation_by_pattern should consists_of_in_members a community.', ?s)) + <- + (?r rdf:type hqdm:representation_by_pattern) + noValue(?r hqdm:consists_of_in_members ?community) +] + +# +# Check that all patterns have a representation_by_pattern. +# +[checkAllRepByPatternConsistOfPattern: + (?y rb:violation error('pattern has no representation_by_pattern', 'All patterns should have representation_by_patterns', ?s)) + <- + (?pattern rdf:type hqdm:pattern) + noValue(?r hqdm:consists_of_by_class ?pattern) +] + +# +# Check that all representation_by_sign consists_of_ a community. +# +[checkAllRepBySignConsistOfCommunity: + (?y rb:violation error('representation_by_sign has no community', 'All representation_by_sign should consists_of_ a community.', ?s)) + <- + (?r rdf:type hqdm:representation_by_sign) + noValue(?r hqdm:consists_of_ ?community) +] + +# +# Check that all representation_by_sign consists_of_ a sign. +# +[checkAllRepBySignConsistOfSign: + (?y rb:violation error('representation_by_sign has no sign', 'All representation_by_sign should consists_of a sign.', ?s)) + <- + (?r rdf:type hqdm:representation_by_sign) + noValue(?r hqdm:consists_of ?sign) +] + +# +# Check that all representation_by_sign represent some thing. +# +[checkAllRepBySignRepresentThing: + (?y rb:violation error('representation_by_sign represents nothing', 'All representation_by_sign should represent a thing.', ?s)) + <- + (?r rdf:type hqdm:representation_by_sign) + noValue(?r hqdm:represents ?thing) +] + From 1a59be179c8d46a6aaca8a7f83abd6b4227eab39 Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 21 Feb 2024 11:06:28 +0000 Subject: [PATCH 07/10] Added some validation rules and improved the unit test. --- .../verify/DataIntegrityChecksTest.java | 38 +++++++----- examples/src/test/resources/validation.rules | 60 +++++++++++++------ 2 files changed, 65 insertions(+), 33 deletions(-) diff --git a/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java b/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java index d1834e7c..11ea90a0 100644 --- a/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java +++ b/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java @@ -7,8 +7,9 @@ import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.UUID; import org.junit.BeforeClass; @@ -23,6 +24,7 @@ import uk.gov.gchq.magmacore.hqdm.model.RepresentationBySign; import uk.gov.gchq.magmacore.hqdm.model.Role; import uk.gov.gchq.magmacore.hqdm.model.Sign; +import uk.gov.gchq.magmacore.hqdm.model.StateOfSign; import uk.gov.gchq.magmacore.hqdm.model.Thing; import uk.gov.gchq.magmacore.hqdm.rdf.iri.HQDM; import uk.gov.gchq.magmacore.hqdm.rdf.iri.IRI; @@ -57,6 +59,8 @@ public static void beforeClass() throws IOException, URISyntaxException { .map(line -> line.split("'")[1]) .map(s -> "\"" + s + "\"") .toList(); + final Set deduped = Set.copyOf(expectedErrors); + assertEquals("Posible duplicate errors in validation rules file.", deduped.size(), expectedErrors.size()); } /** @@ -132,6 +136,11 @@ public void test() throws IOException, URISyntaxException { rbs.addValue(HQDM.ENTITY_NAME, "A RepresentationBySign with no community and no sign and no thing"); svc.create(rbs); + // Create a state_of_sign with no participant_in relation. + final StateOfSign stateOfSign = SpatioTemporalExtentServices.createStateOfSign(randomIri()); + stateOfSign.addValue(HQDM.PART_OF_POSSIBLE_WORLD, possibleWorld.getId()); + svc.create(stateOfSign); + return svc; }); @@ -142,21 +151,20 @@ public void test() throws IOException, URISyntaxException { // Validate the model. final List validationResult = service.validate(query, rules, INCLUDE_RDFS); - final List actualErrors = new ArrayList<>(); - - if (validationResult.size() > 0) { - validationResult.forEach(result -> { - actualErrors.add(result.type()); - System.out.println(result.type()); - System.out.println(result.description()); - System.out.println(result.additionalInformation()); - System.out.println(); - }); - } - // Check that each rule has fired. - expectedErrors.forEach(e -> { - assertTrue(e + " was expected but not present.", actualErrors.contains(e)); + final Set actualErrors = new HashSet<>(); + + validationResult.forEach(result -> { + actualErrors.add(result.type()); }); + + // Check that each rule has fired. + final List missing = expectedErrors.stream() + .filter(e -> !actualErrors.contains(e)) + .map(e -> e + " was expected but not present.") + .toList(); + + missing.forEach(System.err::println); + assertTrue("Not all rules fired - see log for details", missing.isEmpty()); assertEquals(expectedErrors.size(), actualErrors.size()); } diff --git a/examples/src/test/resources/validation.rules b/examples/src/test/resources/validation.rules index 925fdb8b..b140473e 100644 --- a/examples/src/test/resources/validation.rules +++ b/examples/src/test/resources/validation.rules @@ -5,6 +5,11 @@ @include . +# +# NOTE that these rules are not as strict as they should be since they are 'for all' rules and we actually +# need 'there exists' rules. +# + # # Check that all classes have a data_EntityName predicate. # @@ -44,18 +49,6 @@ (?s hqdm:temporal_part_of ?t) noValue(?t rdfs:subClassOf ?s) ] -[checkTemporalPartsPartOfSubtype2: - (?y rb:violation error('Invalid temporal_part_of_ parthood', 'All temporal parts must be temporal parts of a subtype.', ?s, ?t)) - <- - (?s hqdm:temporal_part_of_ ?t) - noValue(?t rdfs:subClassOf ?s) -] -[checkTemporalPartsPartOfSubtype3: - (?y rb:violation error('Invalid temporal__part_of parthood', 'All temporal parts must be temporal parts of a subtype.', ?s, ?t)) - <- - (?s hqdm:temporal__part_of ?t) - noValue(?t rdfs:subClassOf ?s) -] # # Check that all signs have a value_ @@ -81,7 +74,7 @@ # Check that all representation_by_pattern consists_of_by_class a pattern. # [checkAllRepByPatternConsistOfPattern: - (?y rb:violation error('representation_by_pattern has no pattern', 'All representation_by_pattern should consists_of_by_class a pattern.', ?s)) + (?y rb:violation error('representation_by_pattern has no pattern', 'All representation_by_pattern should consists_of_by_class a pattern.', ?r)) <- (?r rdf:type hqdm:representation_by_pattern) noValue(?r hqdm:consists_of_by_class ?pattern) @@ -91,7 +84,7 @@ # Check that all representation_by_pattern consists_of_in_members a community. # [checkAllRepByPatternConsistOfCommunity: - (?y rb:violation error('representation_by_pattern has no community', 'All representation_by_pattern should consists_of_in_members a community.', ?s)) + (?y rb:violation error('representation_by_pattern has no community', 'All representation_by_pattern should consists_of_in_members a community.', ?r)) <- (?r rdf:type hqdm:representation_by_pattern) noValue(?r hqdm:consists_of_in_members ?community) @@ -101,7 +94,7 @@ # Check that all patterns have a representation_by_pattern. # [checkAllRepByPatternConsistOfPattern: - (?y rb:violation error('pattern has no representation_by_pattern', 'All patterns should have representation_by_patterns', ?s)) + (?y rb:violation error('pattern has no representation_by_pattern', 'All patterns should have representation_by_patterns', ?pattern)) <- (?pattern rdf:type hqdm:pattern) noValue(?r hqdm:consists_of_by_class ?pattern) @@ -111,7 +104,7 @@ # Check that all representation_by_sign consists_of_ a community. # [checkAllRepBySignConsistOfCommunity: - (?y rb:violation error('representation_by_sign has no community', 'All representation_by_sign should consists_of_ a community.', ?s)) + (?y rb:violation error('representation_by_sign has no community', 'All representation_by_sign should consists_of_ a community.', ?r)) <- (?r rdf:type hqdm:representation_by_sign) noValue(?r hqdm:consists_of_ ?community) @@ -121,7 +114,7 @@ # Check that all representation_by_sign consists_of_ a sign. # [checkAllRepBySignConsistOfSign: - (?y rb:violation error('representation_by_sign has no sign', 'All representation_by_sign should consists_of a sign.', ?s)) + (?y rb:violation error('representation_by_sign has no sign', 'All representation_by_sign should consists_of a sign.', ?r)) <- (?r rdf:type hqdm:representation_by_sign) noValue(?r hqdm:consists_of ?sign) @@ -131,9 +124,40 @@ # Check that all representation_by_sign represent some thing. # [checkAllRepBySignRepresentThing: - (?y rb:violation error('representation_by_sign represents nothing', 'All representation_by_sign should represent a thing.', ?s)) + (?y rb:violation error('representation_by_sign represents nothing', 'All representation_by_sign should represent a thing.', ?r)) <- (?r rdf:type hqdm:representation_by_sign) noValue(?r hqdm:represents ?thing) ] +# +# Check that all state_of_sign are participants in representation_by_sign +# +[checkAllStateOfSignParticipantInRepBySign: + (?y rb:violation error('state_of_sign not participant_in representation_by_sign', 'All state_of_sign should be participant_in a representation_by_sign', ?r)) + <- + (?r rdf:type hqdm:state_of_sign) + noValue(?r hqdm:participant_in ?thing) +] + +# +# Check that all representation_by_sign have a state_of_sign as a participant +# +[checkAllRepBySignHaveStateOfSignParticipant: + (?y rb:violation error('representation_by_sign missing a state_of_sign', 'All representation_by_sign should have state_of_sign as a participant', ?r)) + <- + (?r rdf:type hqdm:representation_by_sign) + noValue(?s hqdm:participant_in ?r) +] + +# +# Check that all representation_by_sign have a recognizing_language_community as a participant +# +[checkAllRepBySignHaveACommunityParticipant: + (?y rb:violation error('representation_by_sign missing a recognizing_language_community', 'All representation_by_sign should have recognizing_language_community as a participant', ?r)) + <- + (?r rdf:type hqdm:representation_by_sign) + noValue(?s hqdm:participant_in ?r) + noValue(?s rdf:type hqdm:recognizing_language_community) +] + From 905018a1c5bf659ab10f4afe5f55155010bd4500 Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 21 Feb 2024 11:13:00 +0000 Subject: [PATCH 08/10] Minor tweaks to the validation rules tests. --- .../verify/DataIntegrityChecksTest.java | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java b/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java index 11ea90a0..e379cd4e 100644 --- a/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java +++ b/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java @@ -39,9 +39,10 @@ */ public class DataIntegrityChecksTest { - private static final boolean INCLUDE_RDFS = true; + private static final boolean INCLUDE_RDFS_YES = true; private static final IriBase TEST_BASE = new IriBase("test", "http://example.com/test#"); + private static MagmaCoreService service = null; private static List expectedErrors = null; /** @@ -61,22 +62,12 @@ public static void beforeClass() throws IOException, URISyntaxException { .toList(); final Set deduped = Set.copyOf(expectedErrors); assertEquals("Posible duplicate errors in validation rules file.", deduped.size(), expectedErrors.size()); - } - - /** - * Run some data integrity checks. - * - * @throws URISyntaxException if the URI is invalid. - * @throws IOException if the rules file can't be read. - */ - @Test - public void test() throws IOException, URISyntaxException { // Create the in-memory MagmaCoreService object. - final MagmaCoreService service = MagmaCoreServiceFactory.createWithJenaDatabase(); + service = MagmaCoreServiceFactory.createWithJenaDatabase(); // Load the HQDM data model. - service.loadTtl(getClass().getResourceAsStream("/hqdm-0.0.1-alpha.ttl")); + service.loadTtl(DataIntegrityChecksTest.class.getResourceAsStream("/hqdm-0.0.1-alpha.ttl")); // Populate some data to prove that the rules are applied. service.runInWriteTransaction(svc -> { @@ -144,27 +135,39 @@ public void test() throws IOException, URISyntaxException { return svc; }); + } + + /** + * Run some data integrity checks. + * + * @throws URISyntaxException if the URI is invalid. + * @throws IOException if the rules file can't be read. + */ + @Test + public void test() throws IOException, URISyntaxException { // Create the construct query and load the validation rules. final String query = "CONSTRUCT {?s ?p ?o} WHERE {?s ?p ?o}"; final String rules = Files.readString(Paths.get(getClass().getResource("/validation.rules").toURI())); // Validate the model. - final List validationResult = service.validate(query, rules, INCLUDE_RDFS); + final List validationResult = service.validate(query, rules, INCLUDE_RDFS_YES); + // Create a Set of the actual errors found. final Set actualErrors = new HashSet<>(); - validationResult.forEach(result -> { actualErrors.add(result.type()); }); // Check that each rule has fired. final List missing = expectedErrors.stream() - .filter(e -> !actualErrors.contains(e)) + .filter(e -> !actualErrors.contains(e)) // Find the missing errors .map(e -> e + " was expected but not present.") .toList(); missing.forEach(System.err::println); assertTrue("Not all rules fired - see log for details", missing.isEmpty()); + + // Make sure that the actual number of errors found matches the expected number. assertEquals(expectedErrors.size(), actualErrors.size()); } From 3f5404e19fe5c6ee3fbd1a6459c361343a2328f6 Mon Sep 17 00:00:00 2001 From: Tony Date: Fri, 1 Mar 2024 14:16:25 +0000 Subject: [PATCH 09/10] Spelling correction for 'contructed'. --- .../src/test/resources/hqdm-0.0.1-alpha.ttl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/src/test/resources/hqdm-0.0.1-alpha.ttl b/examples/src/test/resources/hqdm-0.0.1-alpha.ttl index c9df2316..8c6dc97a 100644 --- a/examples/src/test/resources/hqdm-0.0.1-alpha.ttl +++ b/examples/src/test/resources/hqdm-0.0.1-alpha.ttl @@ -136,7 +136,7 @@ hqdm:class_of_agreement_process rdf:type rdfs:Class . hqdm:class_of_agreement_process rdfs:subClassOf hqdm:class_of_socially_constructed_activity . hqdm:class_of_amount_of_money rdf:type rdfs:Class . hqdm:class_of_amount_of_money rdfs:subClassOf hqdm:class_of_physical_object . -hqdm:class_of_amount_of_money rdfs:subClassOf hqdm:class_of_socially_contructed_object . +hqdm:class_of_amount_of_money rdfs:subClassOf hqdm:class_of_socially_constructed_object . hqdm:class_of_amount_of_money rdfs:subClassOf hqdm:class_of_state_of_amount_of_money . hqdm:class_of_association rdf:type rdfs:Class . hqdm:class_of_association rdfs:subClassOf hqdm:class_of_individual . @@ -203,10 +203,10 @@ hqdm:class_of_ordinary_physical_object rdf:type rdfs:Class . hqdm:class_of_ordinary_physical_object rdfs:subClassOf hqdm:class_of_physical_object . hqdm:class_of_ordinary_physical_object rdfs:subClassOf hqdm:class_of_state_of_ordinary_physical_object . hqdm:class_of_organization rdfs:subClassOf hqdm:class_of_party . -hqdm:class_of_organization rdfs:subClassOf hqdm:class_of_socially_contructed_object . +hqdm:class_of_organization rdfs:subClassOf hqdm:class_of_socially_constructed_object . hqdm:class_of_organization rdfs:subClassOf hqdm:class_of_state_of_organization . hqdm:class_of_organization_component rdf:type rdfs:Class . -hqdm:class_of_organization_component rdfs:subClassOf hqdm:class_of_socially_contructed_object . +hqdm:class_of_organization_component rdfs:subClassOf hqdm:class_of_socially_constructed_object . hqdm:class_of_organization_component rdfs:subClassOf hqdm:class_of_state_of_organization_component . hqdm:class_of_organization_component rdfs:subClassOf hqdm:class_of_system_component . hqdm:class_of_participant rdf:type rdfs:Class . @@ -247,18 +247,18 @@ hqdm:class_of_representation rdfs:subClassOf hqdm:class_of_association . hqdm:class_of_sales_product_instance rdf:type rdfs:Class . hqdm:class_of_sales_product_instance rdfs:subClassOf hqdm:class_of_ordinary_functional_object . hqdm:class_of_sales_product_instance rdfs:subClassOf hqdm:class_of_state_of_sales_product_instance . -hqdm:class_of_sign rdfs:subClassOf hqdm:class_of_socially_contructed_object . +hqdm:class_of_sign rdfs:subClassOf hqdm:class_of_socially_constructed_object . hqdm:class_of_sign rdfs:subClassOf hqdm:class_of_state_of_sign . hqdm:class_of_socially_constructed_activity rdf:type rdfs:Class . hqdm:class_of_socially_constructed_activity rdfs:subClassOf hqdm:class_of_activity . -hqdm:class_of_socially_constructed_activity rdfs:subClassOf hqdm:class_of_socially_contructed_object . +hqdm:class_of_socially_constructed_activity rdfs:subClassOf hqdm:class_of_socially_constructed_object . hqdm:class_of_socially_constructed_activity_part_of_by_class rdfs:domain hqdm:class_of_socially_constructed_activity . hqdm:class_of_socially_constructed_activity_part_of_by_class rdfs:range hqdm:class_of_reaching_agreement . hqdm:class_of_socially_constructed_activity_part_of_by_class_ rdfs:domain hqdm:class_of_socially_constructed_activity . hqdm:class_of_socially_constructed_activity_part_of_by_class_ rdfs:range hqdm:class_of_agreement_execution . -hqdm:class_of_socially_contructed_object rdf:type rdfs:Class . -hqdm:class_of_socially_contructed_object rdfs:subClassOf hqdm:class_of_intentionally_constructed_object . -hqdm:class_of_socially_contructed_object rdfs:subClassOf hqdm:class_of_state_of_socially_constructed_object . +hqdm:class_of_socially_constructed_object rdf:type rdfs:Class . +hqdm:class_of_socially_constructed_object rdfs:subClassOf hqdm:class_of_intentionally_constructed_object . +hqdm:class_of_socially_constructed_object rdfs:subClassOf hqdm:class_of_state_of_socially_constructed_object . hqdm:class_of_spatio_temporal_extent rdf:type rdfs:Class . hqdm:class_of_spatio_temporal_extent rdfs:subClassOf hqdm:class . hqdm:class_of_spatio_temporal_extent_consists__of_by_class rdfs:domain hqdm:class_of_spatio_temporal_extent . @@ -854,7 +854,7 @@ hqdm:socially_constructed_object rdf:type rdfs:Class . hqdm:socially_constructed_object rdfs:subClassOf hqdm:intentionally_constructed_object . hqdm:socially_constructed_object rdfs:subClassOf hqdm:state_of_socially_constructed_object . hqdm:socially_constructed_object_member_of rdfs:domain hqdm:socially_constructed_object . -hqdm:socially_constructed_object_member_of rdfs:range hqdm:class_of_socially_contructed_object . +hqdm:socially_constructed_object_member_of rdfs:range hqdm:class_of_socially_constructed_object . hqdm:socially_constructed_object_member_of_kind rdfs:domain hqdm:socially_constructed_object . hqdm:socially_constructed_object_member_of_kind rdfs:range hqdm:kind_of_socially_constructed_object . hqdm:spatio_temporal_extent rdf:type rdfs:Class . From 7c48d3ff27e5eb715c530c7406c6c3386c7050b1 Mon Sep 17 00:00:00 2001 From: GCHQDeveloper42 <70384549+GCHQDeveloper42@users.noreply.github.com> Date: Fri, 22 Mar 2024 15:05:18 +0000 Subject: [PATCH 10/10] Linting. --- .../magmacore/database/MagmaCoreDatabase.java | 56 ++++--- .../database/MagmaCoreJenaDatabase.java | 28 ++-- .../MagmaCoreRemoteSparqlDatabase.java | 69 ++++---- .../validation/ValidationReportEntry.java | 4 +- .../magmacore/service/MagmaCoreService.java | 158 ++++++++++++------ .../MagmaCoreServiceInferencingTest.java | 51 +++--- .../service/MagmaCoreServiceTest.java | 38 +++-- .../service/SignPatternTestData.java | 3 +- .../verify/DataIntegrityChecksTest.java | 31 ++-- 9 files changed, 249 insertions(+), 189 deletions(-) diff --git a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreDatabase.java b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreDatabase.java index 8207f52d..9147a483 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreDatabase.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreDatabase.java @@ -28,7 +28,8 @@ import uk.gov.gchq.magmacore.service.transformation.DbDeleteOperation; /** - * Interface defining CRUD operations and generic queries for Magma Core data collections. + * Interface defining CRUD operations and generic queries for Magma Core data + * collections. */ public interface MagmaCoreDatabase { @@ -43,13 +44,15 @@ public interface MagmaCoreDatabase { void beginWrite(); /** - * Commit a transaction - Finish the current transaction and make any changes permanent (if a + * Commit a transaction - Finish the current transaction and make any changes + * permanent (if a * "write" transaction). */ void commit(); /** - * Abort a transaction - Finish the transaction and undo any changes (if a "write" transaction). + * Abort a transaction - Finish the transaction and undo any changes (if a + * "write" transaction). */ void abort(); @@ -128,7 +131,8 @@ public interface MagmaCoreDatabase { List findByPredicateIriAndValue(IRI predicateIri, Object value); /** - * Find object(s) that have a specific string-value attribute associated with them. + * Find object(s) that have a specific string-value attribute associated with + * them. * * @param predicateIri IRI of the predicate being queried. * @param value Case-insensitive string to match. @@ -144,7 +148,8 @@ public interface MagmaCoreDatabase { void dump(PrintStream out); /** - * Write the database as TTL using the {@link PrintStream} and {@link org.apache.jena.riot.Lang}. + * Write the database as TTL using the {@link PrintStream} and + * {@link org.apache.jena.riot.Lang}. * * @param out a {@link PrintStream} * @param language a {@link Lang} @@ -184,32 +189,41 @@ public interface MagmaCoreDatabase { List executeConstruct(final String query); /** - * Apply a set of inference rules to a subset of the model and return a MagmaCoreService attached to + * Apply a set of inference rules to a subset of the model and return a + * MagmaCoreService attached to * the resulting inference model for further use by the caller. * - * @param constructQuery a SPARQL query String to extract a subset of the model for inferencing. - * @param rules a set of inference rules to be applied to the model subset. - * @param includeRdfsRules boolean true if inferencing should include the standard RDFS entailments. - * @return an in-memory MagmaCoreDatabase attached to the inferencing results which is - * independent of the source dataset. + * @param constructQuery a SPARQL query String to extract a subset of the + * model for inferencing. + * @param rules a set of inference rules to be applied to the model + * subset. + * @param includeRdfsRules boolean true if inferencing should include the + * standard RDFS entailments. + * @return an in-memory MagmaCoreDatabase attached to the inferencing results + * which is + * independent of the source dataset. */ MagmaCoreDatabase applyInferenceRules( - final String constructQuery, - final String rules, + final String constructQuery, + final String rules, final boolean includeRdfsRules); /** - * Run a validation report. This is only valid for databases obtained from - * the {@link MagmaCoreDatabase.applyInferenceRules} method. + * Run a validation report. This is only valid for databases obtained from + * the {@link MagmaCoreDatabase.applyInferenceRules} method. * - * @param constructQuery a SPARQL query String to extract a subset of the model for inferencing. - * @param rules a set of inference rules to be applied to the model subset. - * @param includeRdfsRules boolean true if inferencing should include the standard RDFS entailments. + * @param constructQuery a SPARQL query String to extract a subset of the + * model for inferencing. + * @param rules a set of inference rules to be applied to the model + * subset. + * @param includeRdfsRules boolean true if inferencing should include the + * standard RDFS entailments. * @return A {@link List} of {@link ValidationReportEntry} objects. - * It will be Optional.empty if the underlying database is not an inference model. + * It will be Optional.empty if the underlying database is not an + * inference model. */ List validate( - final String constructQuery, - final String rules, + final String constructQuery, + final String rules, final boolean includeRdfsRules); } diff --git a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java index 50ff25f8..dd9191a4 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreJenaDatabase.java @@ -486,13 +486,13 @@ public final void load(final InputStream in, final Lang language) { */ @Override public MagmaCoreDatabase applyInferenceRules( - final String constructQuery, - final String rules, + final String constructQuery, + final String rules, final boolean includeRdfsRules) { // Create an Inference Model which will run the rules. final InfModel model = getInferenceModel(constructQuery, rules, includeRdfsRules); - // Convert the inference model to a dataset and return it wrapped as + // Convert the inference model to a dataset and return it wrapped as // an in-memory MagmaCoreDatabase. final Dataset inferenceDataset = DatasetFactory.wrap(model); return new MagmaCoreJenaDatabase(inferenceDataset); @@ -502,10 +502,9 @@ public MagmaCoreDatabase applyInferenceRules( * {@inheritDoc} */ @Override - public List validate(final String constructQuery, - final String rules, + public List validate(final String constructQuery, + final String rules, final boolean includeRdfsRules) { - // // Create an Inference Model which will run the rules. final InfModel model = getInferenceModel(constructQuery, rules, includeRdfsRules); @@ -520,26 +519,25 @@ public List validate(final String constructQuery, final Report report = reports.next(); entries.add(new ValidationReportEntry( - report.getType(), - report.getExtension(), - report.getDescription() - )); + report.getType(), + report.getExtension(), + report.getDescription())); } - + return entries; } /** * Create an in-memory model for inferencing. * - * @param constructQuery {@link String} - * @param rules {@link String} + * @param constructQuery {@link String} + * @param rules {@link String} * @param includeRdfsRules boolean * @return {@link InfModel} */ private InfModel getInferenceModel( - final String constructQuery, - final String rules, + final String constructQuery, + final String rules, final boolean includeRdfsRules) { // Get the default Model // Execute the query to get a subset of the data model. diff --git a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreRemoteSparqlDatabase.java b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreRemoteSparqlDatabase.java index 95b333eb..ee93cf11 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreRemoteSparqlDatabase.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/database/MagmaCoreRemoteSparqlDatabase.java @@ -76,11 +76,12 @@ public class MagmaCoreRemoteSparqlDatabase implements MagmaCoreDatabase { */ public MagmaCoreRemoteSparqlDatabase(final String serviceUrl) { connection = RDFConnectionRemote.newBuilder().destination(serviceUrl).queryEndpoint("query") - .updateEndpoint("update").triplesFormat(RDFFormat.RDFJSON).build(); + .updateEndpoint("update").triplesFormat(RDFFormat.RDFJSON).build(); } /** - * Constructs a MagmaCoreRemoteSparqlDatabase connection to a SPARQL server and populates it with + * Constructs a MagmaCoreRemoteSparqlDatabase connection to a SPARQL server and + * populates it with * the dataset. * * @param serviceUrl The URL String of the SPARQL update endpoint. @@ -151,7 +152,7 @@ public final void commit() { public Thing get(final IRI iri) { final String query = String.format("SELECT (<%1$s> as ?s) ?p ?o WHERE {<%1$s> ?p ?o.}", - iri.toString()); + iri.toString()); final QueryResultList list = executeQuery(query); final List objects = toTopObjects(list); @@ -224,7 +225,7 @@ public void update(final Thing object) { @Override public void delete(final Thing object) { executeUpdate(String.format("delete {<%s> ?p ?o} WHERE {<%s> ?p ?o}", object.getId(), - object.getId())); + object.getId())); } /** @@ -268,7 +269,7 @@ public void delete(final List deletes) { @Override public List findByPredicateIri(final IRI predicateIri, final IRI objectIri) { final String query = "SELECT ?s ?p ?o WHERE {?s ?p ?o. ?s <" + predicateIri.toString() + "> <" - + objectIri.toString() + ">.}"; + + objectIri.toString() + ">.}"; final QueryResultList list = executeQuery(query); return toTopObjects(list); } @@ -278,9 +279,8 @@ public List findByPredicateIri(final IRI predicateIri, final IRI objectIr */ @Override public List findByPredicateIriOnly(final IRI predicateIri) { - final String query = - "SELECT ?s ?p ?o WHERE {{select ?s ?p ?o where { ?s ?p ?o.}}{select ?s where {?s <" - + predicateIri.toString() + "> ?o.}}}"; + final String query = "SELECT ?s ?p ?o WHERE {{select ?s ?p ?o where { ?s ?p ?o.}}{select ?s where {?s <" + + predicateIri.toString() + "> ?o.}}}"; final QueryResultList list = executeQuery(query); return toTopObjects(list); } @@ -310,10 +310,9 @@ public List findByPredicateIriAndValue(final IRI predicateIri, final Obje @Override public List findByPredicateIriAndStringCaseInsensitive(final IRI predicateIri, final String value) { - final String query = - "SELECT ?s ?p ?o WHERE {{ SELECT ?s ?p ?o where { ?s ?p ?o.}}{select ?s where {?s <" - + predicateIri.toString() + "> ?o. BIND(LCASE(?o) AS ?lcase) FILTER(?lcase= \"\"\"" + value - + "\"\"\")}}}"; + final String query = "SELECT ?s ?p ?o WHERE {{ SELECT ?s ?p ?o where { ?s ?p ?o.}}{select ?s where {?s <" + + predicateIri.toString() + "> ?o. BIND(LCASE(?o) AS ?lcase) FILTER(?lcase= \"\"\"" + value + + "\"\"\")}}}"; final QueryResultList list = executeQuery(query); return toTopObjects(list); } @@ -356,7 +355,8 @@ public QueryResultList executeQuery(final String sparqlQueryString) { } /** - * Execute a SPARQL query and construct a list of HQDM objects from the resulting RDF triples. + * Execute a SPARQL query and construct a list of HQDM objects from the + * resulting RDF triples. * * @param queryExec SPARQL query to execute. * @return Results of the query. @@ -365,7 +365,7 @@ private final QueryResultList getQueryResultList(final QueryExecution queryExec) final ResultSet resultSet = queryExec.execSelect(); final List queryResults = new ArrayList<>(); final QueryResultList queryResultList = new QueryResultList(resultSet.getResultVars(), - queryResults); + queryResults); while (resultSet.hasNext()) { final QuerySolution querySolution = resultSet.next(); @@ -414,17 +414,17 @@ public final List toTopObjects(final QueryResultList queryResultsList) { dataModelObject.add(new Pair<>(new IRI(predicateValue.toString()), objectValue.toString())); } else if (objectValue instanceof Resource) { dataModelObject.add(new Pair<>(new IRI(predicateValue.toString()), - new IRI(objectValue.toString()))); + new IRI(objectValue.toString()))); } else { throw new RuntimeException("objectValue is of unknown type: " + objectValue.getClass()); } }); return objectMap - .entrySet() - .stream() - .map(entry -> HqdmObjectFactory.create(new IRI(entry.getKey().toString()), entry.getValue())) - .collect(Collectors.toList()); + .entrySet() + .stream() + .map(entry -> HqdmObjectFactory.create(new IRI(entry.getKey().toString()), entry.getValue())) + .collect(Collectors.toList()); } /** @@ -473,9 +473,9 @@ public final void load(final InputStream in, final Lang language) { */ @Override public MagmaCoreDatabase applyInferenceRules( - final String constructQuery, - final String rules, - final boolean includeRdfsRules) { + final String constructQuery, + final String rules, + final boolean includeRdfsRules) { // Create an Inference Model which will run the rules. final InfModel model = getInferenceModel(constructQuery, rules, includeRdfsRules); @@ -491,10 +491,10 @@ public MagmaCoreDatabase applyInferenceRules( */ @Override public List validate( - final String constructQuery, - final String rules, - final boolean includeRdfsRules) { - // + final String constructQuery, + final String rules, + final boolean includeRdfsRules) { + // Create an Inference Model which will run the rules. final InfModel model = getInferenceModel(constructQuery, rules, includeRdfsRules); @@ -509,26 +509,25 @@ public List validate( final Report report = reports.next(); entries.add(new ValidationReportEntry( - report.getType(), - report.getExtension(), - report.getDescription() - )); + report.getType(), + report.getExtension(), + report.getDescription())); } - + return entries; } /** * Create an in-memory model for inferencing. * - * @param constructQuery {@link String} - * @param rules {@link String} + * @param constructQuery {@link String} + * @param rules {@link String} * @param includeRdfsRules boolean * @return {@link InfModel} */ private InfModel getInferenceModel( - final String constructQuery, - final String rules, + final String constructQuery, + final String rules, final boolean includeRdfsRules) { // Execute the query to get a subset of the data model. final QueryExecution queryExec = connection.query(constructQuery); diff --git a/core/src/main/java/uk/gov/gchq/magmacore/database/validation/ValidationReportEntry.java b/core/src/main/java/uk/gov/gchq/magmacore/database/validation/ValidationReportEntry.java index 43198dc8..51fbc59c 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/database/validation/ValidationReportEntry.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/database/validation/ValidationReportEntry.java @@ -3,5 +3,5 @@ /** * An implementation agnostic model validation report entry. */ -public record ValidationReportEntry(String type, Object additionalInformation, String description) {} - +public record ValidationReportEntry(String type, Object additionalInformation, String description) { +} diff --git a/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java b/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java index c42617bb..580fedb3 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/service/MagmaCoreService.java @@ -68,7 +68,8 @@ *
  • verifyModel()
  • * *

    - * Nested transactions are not supported so ensure that no transaction is in progress before + * Nested transactions are not supported so ensure that no transaction is in + * progress before * using any of the above methods. *

    */ @@ -86,13 +87,15 @@ public class MagmaCoreService { } /** - * Find the details of participants in associations of a specific kind between two + * Find the details of participants in associations of a specific kind between + * two * {@link Individual} objects at a point in time. * * @param individual1 The first {@link Individual}. * @param individual2 The second {@link Individual}. * @param kind The {@link KindOfAssociation}. - * @param pointInTime The {@link PointInTime} that the associations should exist. + * @param pointInTime The {@link PointInTime} that the associations should + * exist. * @return A {@link Set} of {@link ParticipantDetails}. */ public Set findParticipantDetails(final Individual individual1, final Individual individual2, @@ -126,7 +129,8 @@ public Set findParticipantDetails(final Individual individua } /** - * Filter a {@link QueryResultList} by a {@link PointInTime}. The {@link QueryResultList} should + * Filter a {@link QueryResultList} by a {@link PointInTime}. The + * {@link QueryResultList} should * have `start` and `finish` columns to allow filtering. * * @param when {@link Instant}. @@ -155,16 +159,20 @@ private QueryResultList filterByPointInTime(final Instant when, final QueryResul * Find the Set of {@link Thing} represented by the given sign value. * *

    - * This could probably be replaced with a (rather complex) SPARQL query if {@link MagmaCoreDatabase} + * This could probably be replaced with a (rather complex) SPARQL query if + * {@link MagmaCoreDatabase} * allowed the execution of such queries. *

    * - * @param community The {@link RecognizingLanguageCommunity} that recognizes the sign value. + * @param community The {@link RecognizingLanguageCommunity} that recognizes + * the sign value. * @param pattern The {@link Pattern} the sign conforms to. * @param value {@link String} the sign value to look for. - * @param pointInTime {@link PointInTime} the point in time we are interested in. + * @param pointInTime {@link PointInTime} the point in time we are interested + * in. * @return {@link List} of {@link Thing} represented by the value. - * @throws MagmaCoreException if the number of {@link RepresentationByPattern} found is not 1. + * @throws MagmaCoreException if the number of {@link RepresentationByPattern} + * found is not 1. */ public List findBySignValue( final RecognizingLanguageCommunity community, @@ -196,16 +204,20 @@ public List findBySignValue( * *

    * The search is case-insensitive. - * This could probably be replaced with a (rather complex) SPARQL query if {@link MagmaCoreDatabase} + * This could probably be replaced with a (rather complex) SPARQL query if + * {@link MagmaCoreDatabase} * allowed the execution of such queries. *

    * - * @param community The {@link RecognizingLanguageCommunity} that recognizes the sign value. + * @param community The {@link RecognizingLanguageCommunity} that recognizes + * the sign value. * @param pattern The {@link Pattern} the sign conforms to. * @param value {@link String} the partial sign value to look for. - * @param pointInTime {@link PointInTime} the point in time we are interested in. + * @param pointInTime {@link PointInTime} the point in time we are interested + * in. * @return {@link List} of {@link Thing} represented by the value. - * @throws MagmaCoreException if the number of {@link RepresentationByPattern} found is not 1. + * @throws MagmaCoreException if the number of {@link RepresentationByPattern} + * found is not 1. */ public List findByPartialSignValue( final RecognizingLanguageCommunity community, @@ -233,7 +245,8 @@ public List findByPartialSignValue( } /** - * Find Things of a giver rdf:type and Class and their signs that are of a particular pattern. + * Find Things of a giver rdf:type and Class and their signs that are of a + * particular pattern. * * @param type IRI. * @param clazz IRI. @@ -265,7 +278,8 @@ public List findByTypeClassAndSignPattern( } /** - * Find Things of a giver rdf:type and Kind and their signs that are of a particular pattern. + * Find Things of a giver rdf:type and Kind and their signs that are of a + * particular pattern. * * @param type IRI. * @param kind IRI. @@ -297,7 +311,8 @@ public List findByTypeKindAndSignPattern( } /** - * Find Individuals with states participating in associations of a specified kind, their roles and + * Find Individuals with states participating in associations of a specified + * kind, their roles and * signs. * * @param kindOfAssociation {@link IRI}. @@ -344,14 +359,16 @@ public List findAssociated(final IRI item, final IRI kindOfAsso } /** - * Find the items associated to an item by an association of a specified kind that are valid at a PointInTime. + * Find the items associated to an item by an association of a specified kind + * that are valid at a PointInTime. * * @param item IRI * @param kindOfAssociation IRI - * @param pointInTime {@link PointInTime} + * @param pointInTime {@link PointInTime} * @return {@link List} of {@link Thing} */ - public List findAssociated(final IRI item, final IRI kindOfAssociation, final PointInTime pointInTime) { + public List findAssociated(final IRI item, final IRI kindOfAssociation, + final PointInTime pointInTime) { final String pointInTimeValue = pointInTime.oneValue(HQDM.ENTITY_NAME); if (pointInTimeValue == null) { @@ -372,10 +389,12 @@ public List findAssociated(final IRI item, final IRI kindOfAsso } /** - * A case-sensitive search for entities in a specified class with a sign containing the given text. + * A case-sensitive search for entities in a specified class with a sign + * containing the given text. * * @param text The String to search for. - * @param classIri The IRI of the class that the entities should be a member_of. + * @param classIri The IRI of the class that the entities should be a + * member_of. * @param pointInTime When the entities should have the matching sign. * @return A {@link List} of {@link Thing}. */ @@ -404,10 +423,12 @@ public List findByPartialSignAndClassCaseSensitive(final String } /** - * A case-insensitive search for entities in a specified class with a sign containing the given text. + * A case-insensitive search for entities in a specified class with a sign + * containing the given text. * * @param text The String to search for. - * @param classIri The IRI of the class that the entities should be a member_of. + * @param classIri The IRI of the class that the entities should be a + * member_of. * @param pointInTime When the entities should have the matching sign. * @return A {@link List} of {@link Thing}. */ @@ -436,12 +457,14 @@ public List findByPartialSignAndClass(final String text, final } /** - * A case-insensitive search for entities in a specified class with a sign containing the given text + * A case-insensitive search for entities in a specified class with a sign + * containing the given text * that are referenced by an activity. * * @param wholeIri The object that the required entities are composed into. * @param text The String to search for. - * @param classIri The IRI of the class that the entities should be a member_of. + * @param classIri The IRI of the class that the entities should be a + * member_of. * @param pointInTime When the entities should have the matching sign. * @return A {@link List} of {@link Thing}. */ @@ -470,12 +493,14 @@ public List findByPartialSignByActivityReferenceAndClass(final } /** - * A case-sensitive search for entities in a specified class with a sign containing the given text + * A case-sensitive search for entities in a specified class with a sign + * containing the given text * that are referenced by an activity. * * @param wholeIri The object that the required entities are composed into. * @param text The String to search for. - * @param classIri The IRI of the class that the entities should be a member_of. + * @param classIri The IRI of the class that the entities should be a + * member_of. * @param pointInTime When the entities should have the matching sign. * @return A {@link List} of {@link Thing}. */ @@ -504,12 +529,14 @@ public List findByPartialSignByActivityReferenceAndClassCaseSen } /** - * A case-sensitive search for entities in a specified class with a sign containing the given text + * A case-sensitive search for entities in a specified class with a sign + * containing the given text * that are parts of a given whole. * * @param wholeIri The object that the required entities are composed into. * @param text The String to search for. - * @param classIri The IRI of the class that the entities should be a member_of. + * @param classIri The IRI of the class that the entities should be a + * member_of. * @param pointInTime When the entities should have the matching sign. * @return A {@link List} of {@link Thing}. */ @@ -538,12 +565,14 @@ public List findByPartialSignCompositionAndClassCaseSensitive(f } /** - * A case-insensitive search for entities in a specified class with a sign containing the given text + * A case-insensitive search for entities in a specified class with a sign + * containing the given text * that are parts of a given whole. * * @param wholeIri The object that the required entities are composed into. * @param text The String to search for. - * @param classIri The IRI of the class that the entities should be a member_of. + * @param classIri The IRI of the class that the entities should be a + * member_of. * @param pointInTime When the entities should have the matching sign. * @return A {@link List} of {@link Thing}. */ @@ -599,10 +628,12 @@ public List findSignsForEntity(final IRI entityIri, final PointI } /** - * Find the Thing referenced by a field value where the thing is a member of the given class. + * Find the Thing referenced by a field value where the thing is a member of the + * given class. * * @param fieldIri The HQDM predicate IRI. - * @param fieldValue The field value - typically a {@link String} or {@link IRI}. + * @param fieldValue The field value - typically a {@link String} or + * {@link IRI}. * @param classIri The class {@link IRI}. * @return A {@link List} of {@link Thing}. */ @@ -711,8 +742,10 @@ void delete(final List deletes) { } /** - * Convert a {@link Collection} of {@link Thing} objects to a {@link DbTransformation} that can be - * used to persist them. Typically this should be followed by a call to `runInTransaction`. + * Convert a {@link Collection} of {@link Thing} objects to a + * {@link DbTransformation} that can be + * used to persist them. Typically this should be followed by a call to + * `runInTransaction`. * * @param things a {@link Collection} of {@link Thing} objects to be persisted. * @return {@link DbTransformation} @@ -724,7 +757,8 @@ public DbTransformation createDbTransformation(final Collection } /** - * Convert a {@link Thing} to a {@link DbChangeSet} by creating a {@link DbCreateOperation} for each + * Convert a {@link Thing} to a {@link DbChangeSet} by creating a + * {@link DbCreateOperation} for each * of its predicate valiues. * * @param thing a {@link Thing} @@ -893,7 +927,8 @@ public void beginWrite() { } /** - * Commit a transaction - Finish the current transaction and make any changes permanent (if a + * Commit a transaction - Finish the current transaction and make any changes + * permanent (if a * "write" transaction). */ public void commit() { @@ -901,7 +936,8 @@ public void commit() { } /** - * Abort a transaction - Finish the transaction and undo any changes (if a "write" transaction). + * Abort a transaction - Finish the transaction and undo any changes (if a + * "write" transaction). */ public void abort() { database.abort(); @@ -918,7 +954,8 @@ public QueryResultList executeQuery(final String query) { } /** - * SPARQL queries restricted to having 3 columns for the subject, predicate, and object, with any names but they must be in that order. E.g. + * SPARQL queries restricted to having 3 columns for the subject, predicate, and + * object, with any names but they must be in that order. E.g. * SELECT ?s ?p ?o WHERE {...} order by ?s ?p ?o * The first column must contain entity IDs. * The second column must contain predicates. @@ -929,41 +966,54 @@ public QueryResultList executeQuery(final String query) { */ public Map executeQueryForThings(final String query) { final QueryResultList resultsList = database.executeQuery(query); - + final List things = database.toTopObjects(resultsList); - + final Map result = new HashMap<>(); - + things.forEach(t -> result.put(t.getId(), t)); return result; } /** - * Apply a set of inference rules to a subset of the model and return a MagmaCoreService attached to + * Apply a set of inference rules to a subset of the model and return a + * MagmaCoreService attached to * the resulting inference model for further use by the caller. * - * @param query a SPARQL query String to extract a subset of the model for inferencing. - * @param rules a set of inference rules to be applied to the model subset. - * @param includeRdfsRules boolean true if inferencing should include the standard RDFS entailments. - * @return an in-memory MagmaCoreService attached to the inferencing results which is independent of the source dataset. + * @param query a SPARQL query String to extract a subset of the + * model for inferencing. + * @param rules a set of inference rules to be applied to the model + * subset. + * @param includeRdfsRules boolean true if inferencing should include the + * standard RDFS entailments. + * @return an in-memory MagmaCoreService attached to the inferencing results + * which is independent of the source dataset. */ - public MagmaCoreService applyInferenceRules(final String query, final String rules, final boolean includeRdfsRules) { - // This functionality is likely to be database-implementation-specific, so delegate. + public MagmaCoreService applyInferenceRules(final String query, final String rules, + final boolean includeRdfsRules) { + // This functionality is likely to be database-implementation-specific, so + // delegate. final MagmaCoreDatabase db = database.applyInferenceRules(query, rules, includeRdfsRules); return new MagmaCoreService(db); } /** - * Apply a set of inference rules to a subset of the model and return a List of ValidationReportEntry objects. + * Apply a set of inference rules to a subset of the model and return a List of + * ValidationReportEntry objects. * - * @param query a SPARQL query String to extract a subset of the model for inferencing. - * @param rules a set of inference rules to be applied to the model subset. - * @param includeRdfsRules boolean true if inferencing should include the standard RDFS entailments. + * @param query a SPARQL query String to extract a subset of the + * model for inferencing. + * @param rules a set of inference rules to be applied to the model + * subset. + * @param includeRdfsRules boolean true if inferencing should include the + * standard RDFS entailments. * @return A {@link List} of {@link ValidationReportEntry} objects. - * It will be Optional.empty if the underlying database is not an inference model. + * It will be Optional.empty if the underlying database is not an + * inference model. */ - public List validate(final String query, final String rules, final boolean includeRdfsRules) { + public List validate(final String query, final String rules, + final boolean includeRdfsRules) { return database.validate(query, rules, includeRdfsRules); } diff --git a/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceInferencingTest.java b/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceInferencingTest.java index e0bdf028..176d1547 100644 --- a/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceInferencingTest.java +++ b/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceInferencingTest.java @@ -41,20 +41,20 @@ public class MagmaCoreServiceInferencingTest { private static final String RULE_SET = """ -@prefix ex: . - -[transitiveDependencies: - (?x ex:depends_on ?y) (?y ex:depends_on ?z) - -> - (?x ex:depends_on ?z) -] - -[validationRule1: - (?y rb:violation error('Object has ex:some_predicate', 'No objects should have ex:some_predicate', ?s)) - <- - (?s ex:some_predicate ?value) -] - """; + @prefix ex: . + + [transitiveDependencies: + (?x ex:depends_on ?y) (?y ex:depends_on ?z) + -> + (?x ex:depends_on ?z) + ] + + [validationRule1: + (?y rb:violation error('Object has ex:some_predicate', 'No objects should have ex:some_predicate', ?s)) + <- + (?s ex:some_predicate ?value) + ] + """; private static final IriBase TEST_BASE = new IriBase("test", "http://example.com/test#"); private static final IRI DEPENDS_ON = new IRI(TEST_BASE, "depends_on"); private static final IRI SOME_PREDICATE = new IRI(TEST_BASE, "some_predicate"); @@ -80,10 +80,8 @@ public void testInferencingSuccess() throws MagmaCoreException, FileNotFoundExce final List changes = List.of(new DbChangeSet( List.of(), List.of( - new DbCreateOperation(a, DEPENDS_ON, b), - new DbCreateOperation(b, DEPENDS_ON, c) - ) - )); + new DbCreateOperation(a, DEPENDS_ON, b), + new DbCreateOperation(b, DEPENDS_ON, c)))); final DbTransformation transform = new DbTransformation(changes); service.runInWriteTransaction(transform); @@ -92,7 +90,8 @@ public void testInferencingSuccess() throws MagmaCoreException, FileNotFoundExce final MagmaCoreService inferencingSvc = service.applyInferenceRules(query, RULE_SET, false); // Query the database to check the result. - final QueryResultList result = inferencingSvc.executeQuery("PREFIX ex: SELECT * WHERE {?s ex:depends_on ?o.}"); + final QueryResultList result = inferencingSvc + .executeQuery("PREFIX ex: SELECT * WHERE {?s ex:depends_on ?o.}"); // The result should be 3 since " a depends_on c" is inferred. assertEquals(3, result.getQueryResults().size()); @@ -123,11 +122,9 @@ public void testInferencingValidationFail() throws MagmaCoreException, FileNotFo final List changes = List.of(new DbChangeSet( List.of(), List.of( - new DbCreateOperation(a, DEPENDS_ON, b), - new DbCreateOperation(b, DEPENDS_ON, c), - new DbCreateOperation(b, SOME_PREDICATE, "This predicate is invalid") - ) - )); + new DbCreateOperation(a, DEPENDS_ON, b), + new DbCreateOperation(b, DEPENDS_ON, c), + new DbCreateOperation(b, SOME_PREDICATE, "This predicate is invalid")))); final DbTransformation transform = new DbTransformation(changes); service.runInWriteTransaction(transform); @@ -136,13 +133,15 @@ public void testInferencingValidationFail() throws MagmaCoreException, FileNotFo // Make sure there are no validation errors. final List entries = service.validate(query, RULE_SET, false); - + assertEquals(1, entries.size()); final ValidationReportEntry entry = entries.get(0); assertEquals("\"Object has ex:some_predicate\"", entry.type()); - assertEquals("\"No objects should have ex:some_predicate\"\nCulprit = *\nImplicated node: \n", entry.description()); + assertEquals( + "\"No objects should have ex:some_predicate\"\nCulprit = *\nImplicated node: \n", + entry.description()); assertTrue(entry.additionalInformation() instanceof ResourceImpl); final Resource resource = (Resource) entry.additionalInformation(); diff --git a/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceTest.java b/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceTest.java index 0050a620..8c412737 100644 --- a/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceTest.java +++ b/core/src/test/java/uk/gov/gchq/magmacore/service/MagmaCoreServiceTest.java @@ -98,7 +98,8 @@ public void testFindBySignSuccess() throws MagmaCoreException { final MagmaCoreService service = new MagmaCoreService(db); // Create the PointInTime we're looking for - final PointInTime now = SpatioTemporalExtentServices.createPointInTime(new IRI("http://example.com/entity#now")); + final PointInTime now = SpatioTemporalExtentServices + .createPointInTime(new IRI("http://example.com/entity#now")); now.addStringValue(HQDM.ENTITY_NAME, Instant.now().toString()); // Find the required Things by sign in a transaction. @@ -133,7 +134,8 @@ public void testFindBySignSuccess() throws MagmaCoreException { } /** - * Test that findByPartialSignValue can be used to find the right Things represented by + * Test that findByPartialSignValue can be used to find the right Things + * represented by * a sign value for * the given {@link uk.gov.gchq.magmacore.hqdm.model.Pattern} and * {@link uk.gov.gchq.magmacore.hqdm.model.RecognizingLanguageCommunity} at the @@ -183,7 +185,8 @@ public void testFindBySignWithNullSignValue() throws MagmaCoreException { final MagmaCoreService service = new MagmaCoreService(db); // Create the PointInTime we're looking for - final PointInTime now = SpatioTemporalExtentServices.createPointInTime(new IRI("http://example.com/entity#now")); + final PointInTime now = SpatioTemporalExtentServices + .createPointInTime(new IRI("http://example.com/entity#now")); now.addStringValue(HQDM.ENTITY_NAME, Instant.now().toString()); // Find the required Things by sign in a transaction. @@ -211,7 +214,8 @@ public void testFindBySignWithBadPointInTime() throws MagmaCoreException { final MagmaCoreService service = new MagmaCoreService(db); // Create the PointInTime we're looking for - final PointInTime now = SpatioTemporalExtentServices.createPointInTime(new IRI("http://example.com/entity#now")); + final PointInTime now = SpatioTemporalExtentServices + .createPointInTime(new IRI("http://example.com/entity#now")); // Find the required Things by sign in a transaction. db.beginRead(); @@ -270,7 +274,7 @@ public void testFindByPredicateOnly() { // Find individual1 by a String value svc.runInReadTransaction(mc -> { final List result = mc.findByPredicateIriAndValue( - HQDM.MEMBER_OF, + HQDM.MEMBER_OF, new IRI(TEST_BASE, "classOfIndividual")); assertEquals(1, result.size()); @@ -367,12 +371,11 @@ public void testSparqlQuery() { final IRI obj2 = new IRI(TEST_BASE, "obj2"); new DbChangeSet( - List.of(), // no deletes - List.of(// Two creates - new DbCreateOperation(subj1, pred1, obj1), - new DbCreateOperation(obj1, pred2, obj2) - ) - ).apply(service); + List.of(), // no deletes + List.of(// Two creates + new DbCreateOperation(subj1, pred1, obj1), + new DbCreateOperation(obj1, pred2, obj2))) + .apply(service); // Query the service by joining the two statements in a single result. final QueryResultList result = service.executeQuery("SELECT * WHERE { ?a ?b ?c. ?c ?d ?e}"); @@ -403,13 +406,12 @@ public void testQueryForThingsSuccess() { final IRI obj1 = new IRI(TEST_BASE, "obj1"); new DbChangeSet( - List.of(), // no deletes - List.of(// Two creates - new DbCreateOperation(subj1, HQDM.MEMBER_OF, obj1), - new DbCreateOperation(subj1, RDFS.RDF_TYPE, HQDM.PERSON), - new DbCreateOperation(obj1, RDFS.RDF_TYPE, HQDM.CLASS_OF_PERSON) - ) - ).apply(service); + List.of(), // no deletes + List.of(// Two creates + new DbCreateOperation(subj1, HQDM.MEMBER_OF, obj1), + new DbCreateOperation(subj1, RDFS.RDF_TYPE, HQDM.PERSON), + new DbCreateOperation(obj1, RDFS.RDF_TYPE, HQDM.CLASS_OF_PERSON))) + .apply(service); // Query the service by joining the two statements in a single result. final Map result = service.executeQueryForThings("SELECT ?s ?p ?o WHERE { ?s ?p ?o}"); diff --git a/core/src/test/java/uk/gov/gchq/magmacore/service/SignPatternTestData.java b/core/src/test/java/uk/gov/gchq/magmacore/service/SignPatternTestData.java index 06bba8b8..0143ec6d 100644 --- a/core/src/test/java/uk/gov/gchq/magmacore/service/SignPatternTestData.java +++ b/core/src/test/java/uk/gov/gchq/magmacore/service/SignPatternTestData.java @@ -57,7 +57,8 @@ public class SignPatternTestData { * Populate a {@link MagmaCoreDatabase} with an instance of the sign pattern. * *

    - * This will create two {@link RepresentationBySign} associations that each use a String to + * This will create two {@link RepresentationBySign} associations that each use + * a String to * represent a {@link StateOfPerson}, but for different {@link Pattern} and * {@link RecognizingLanguageCommunity} objects. *

    diff --git a/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java b/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java index 404e6f62..599f8e13 100644 --- a/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java +++ b/examples/src/test/java/uk/gov/gchq/magmacore/examples/verify/DataIntegrityChecksTest.java @@ -48,18 +48,18 @@ public class DataIntegrityChecksTest { /** * Get all the errors we expect to see. * - * @throws IOException on error. + * @throws IOException on error. * @throws URISyntaxException on error. */ @BeforeClass public static void beforeClass() throws IOException, URISyntaxException { final var rulesUri = DataIntegrityChecksTest.class.getResource("/validation.rules").toURI(); expectedErrors = Files.readAllLines(Paths.get(rulesUri)) - .stream() - .filter(line -> line.contains("error")) - .map(line -> line.split("'")[1]) - .map(s -> "\"" + s + "\"") - .toList(); + .stream() + .filter(line -> line.contains("error")) + .map(line -> line.split("'")[1]) + .map(s -> "\"" + s + "\"") + .toList(); final Set deduped = Set.copyOf(expectedErrors); assertEquals("Posible duplicate errors in validation rules file.", deduped.size(), expectedErrors.size()); @@ -76,7 +76,8 @@ public static void beforeClass() throws IOException, URISyntaxException { svc.create(kind); // Create a participant that isn't a member_of_kind of a role. - // Also, as a SpatioTemporalExtent it should have a part_of_possible_world predicate. + // Also, as a SpatioTemporalExtent it should have a part_of_possible_world + // predicate. final Thing participant = SpatioTemporalExtentServices.createParticipant(randomIri()); svc.create(participant); @@ -98,7 +99,6 @@ public static void beforeClass() throws IOException, URISyntaxException { // Create a sign without a value_ predicate. // Also tests the member_of_ for pattern since that is also missing. - // final Sign sign = SpatioTemporalExtentServices.createSign(randomIri()); sign.addValue(HQDM.PART_OF_POSSIBLE_WORLD, possibleWorld.getId()); final Role signRole = ClassServices.createRole(randomIri()); @@ -107,10 +107,9 @@ public static void beforeClass() throws IOException, URISyntaxException { svc.create(sign); svc.create(signRole); - // Create a RepresentationByPattern without a pattern and a pattern without a + // Create a RepresentationByPattern without a pattern and a pattern without a // RepresentationByPattern. The RepresentationByPattern also has no community, // and no sign. - // final RepresentationByPattern rbp = ClassServices.createRepresentationByPattern(randomIri()); rbp.addStringValue(HQDM.ENTITY_NAME, "A RepresentationByPattern with no pattern"); svc.create(rbp); @@ -121,7 +120,6 @@ public static void beforeClass() throws IOException, URISyntaxException { // Create a RepresentationBySign with no community, and no sign, and does not // represent a thing. - // final RepresentationBySign rbs = SpatioTemporalExtentServices.createRepresentationBySign(randomIri()); rbs.addValue(HQDM.PART_OF_POSSIBLE_WORLD, possibleWorld.getId()); rbs.addStringValue(HQDM.ENTITY_NAME, "A RepresentationBySign with no community and no sign and no thing"); @@ -134,20 +132,19 @@ public static void beforeClass() throws IOException, URISyntaxException { return svc; }); - } /** * Run some data integrity checks. * * @throws URISyntaxException if the URI is invalid. - * @throws IOException if the rules file can't be read. + * @throws IOException if the rules file can't be read. */ @Test public void test() throws IOException, URISyntaxException { // Create the construct query and load the validation rules. final String query = "CONSTRUCT {?s ?p ?o} WHERE {?s ?p ?o}"; - final String rules = Files.readString(Paths.get(getClass().getResource("/validation.rules").toURI())); + final String rules = Files.readString(Paths.get(getClass().getResource("/validation.rules").toURI())); // Validate the model. final List validationResult = service.validate(query, rules, INCLUDE_RDFS_YES); @@ -160,9 +157,9 @@ public void test() throws IOException, URISyntaxException { // Check that each rule has fired. final List missing = expectedErrors.stream() - .filter(e -> !actualErrors.contains(e)) // Find the missing errors - .map(e -> e + " was expected but not present.") - .toList(); + .filter(e -> !actualErrors.contains(e)) // Find the missing errors + .map(e -> e + " was expected but not present.") + .toList(); missing.forEach(System.err::println); assertTrue("Not all rules fired - see log for details", missing.isEmpty());