Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trillian updates #46

Merged
merged 49 commits into from
Oct 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
29dd88c
Allow predicates and objects to be Java objects. Store IRIs correctly…
twalmsley Jul 17, 2022
d4720d4
Fix problem with spaces at the end of an IRI String
twalmsley Jul 21, 2022
c72567e
Checkpoint
twalmsley Jul 17, 2022
fd76e98
Update after MC bug fix.
twalmsley Jul 18, 2022
72b6b67
Remove debugging code
twalmsley Jul 18, 2022
eaad266
Improved unit tests
twalmsley Jul 18, 2022
6273b95
Fix bug in Predicates.java
twalmsley Jul 22, 2022
5d4ce72
Add method for finding participant details in associations between tw…
twalmsley Jul 19, 2022
f3c724b
Add method for finding participant details in associations between tw…
twalmsley Jul 19, 2022
e992071
Fix DynamicObjects and HqdmObject.equals
twalmsley Jul 19, 2022
92215c0
Fix HqdmObject.hashCode because it wasn't working for HashSets
twalmsley Jul 19, 2022
877f562
Add unit test for findParticipantDetails and fix the code to match.
twalmsley Jul 19, 2022
a93f541
Add unit test for findParticipantDetails and fix the code to match.
twalmsley Jul 19, 2022
031c670
Fix incorrect use of KIND_OF_ASSOCIATION
twalmsley Jul 20, 2022
ba300bf
Exposed a method on MagmaCoreServices to export a dataset as TTL.
twalmsley Jul 21, 2022
550dedb
MagmaCoreRemoteSparqlDatabase does not support READ_PROMOTE transacti…
twalmsley Jul 21, 2022
48725df
Bulk deletes and creates.
twalmsley Jul 29, 2022
d975f09
Bulk deletes and creates.
twalmsley Jul 29, 2022
79baac2
Allow predicates and objects to be Java objects. Store IRIs correctly…
twalmsley Jul 17, 2022
9c63c72
Use SPARQL for FindParticipantDetails
twalmsley Aug 1, 2022
e5d73b0
Improve FindBySign performance.
twalmsley Aug 2, 2022
2bcd080
Separate SPARQL queries from MagmaCoreService so they're not exported…
twalmsley Aug 2, 2022
171d52d
Add service findByTypeKindAndSign and unit test.
twalmsley Aug 3, 2022
203bf10
Add service findByTypeKindAndSign and unit test.
twalmsley Aug 3, 2022
b62d35a
Add FindByKindOfAssociation.
twalmsley Aug 4, 2022
bc10267
Add FindByKindOfAssociation.
twalmsley Aug 4, 2022
b57869b
Added a (failing) unit test for FindByKindOfAssociation - needs bette…
twalmsley Aug 5, 2022
56907b4
Added FindByKindOfAssociation, and DataIntegriryReport
twalmsley Aug 8, 2022
cb63446
Simplify an overcomplicated query.
twalmsley Aug 8, 2022
4430d28
Fix a problem with Data Integrity Checks against remote SPARQL endpoints
twalmsley Aug 10, 2022
dd1c41f
Add a new data integrity check
twalmsley Aug 10, 2022
7ec2627
Fix a data integrity query
twalmsley Aug 11, 2022
a9c4295
Added two new queries to support application clients.
twalmsley Aug 23, 2022
db9e292
Added a missing line from a SPARQL query.
twalmsley Aug 23, 2022
9d330a0
Fix a SPARQL query with bad use of OPTIONAL parts.
twalmsley Sep 2, 2022
b101199
Added some search queries to find entities with various parameters.
twalmsley Sep 5, 2022
0f539e7
Added some extra finder methods.
twalmsley Sep 7, 2022
c0282e2
Undeprecate ENTITY_NAME.
twalmsley Sep 9, 2022
800f436
Remove filter that wasn't in use.
twalmsley Sep 9, 2022
e559d5a
Added find by field value and class.
twalmsley Sep 14, 2022
8a7ba3a
Use Instant instead of LocalDateTime to prevent GMT/BST errors.
twalmsley Sep 15, 2022
4a0e81f
Added a data import feature. Useful for DB delta management.
twalmsley Sep 20, 2022
72d2b07
Merge pull request #42 from twalmsley/aosd-multiple-issue-fixes
GCHQDeveloper42 Sep 23, 2022
66e2071
Fixed Javadocs and formatting issues.
GCHQDeveloper42 Oct 3, 2022
38130b1
Removed ENTITY_ID from HQDM RDF definitions.
GCHQDeveloper42 Oct 3, 2022
4510f47
Fixed typo in DataIntegrityReport.java: CHECK_STATE_OF_SIGN_PRTICIPAN…
GCHQDeveloper42 Oct 3, 2022
4c67f7a
Renamed McAssistMultInheritFromDataApp.java > McAssistMultiInheritFro…
GCHQDeveloper42 Oct 3, 2022
b18c945
Remove unused Predicates class and its test.
GCHQDeveloper42 Oct 3, 2022
753fddb
Merge branch 'develop' into trillian-updates
GCHQDeveloper42 Oct 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion checkstyle-suppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<suppress checks="AbbreviationAsWordInName" files="UID\.java" />

<!-- examples suppressions -->
<suppress checks="LineLength" files="ExampleDataObjects.java|ExampleRdl.java|ExampleAssociations.java" />
<suppress checks="LineLength" files="ExampleDataObjects.java|ExampleRdl.java|ExampleAssociations.java|MagmaCoreService.java" />
<suppress checks="MethodLength" files="ExampleDataObjects.java" />

<!-- hqdm-core suppressions -->
Expand Down
1 change: 1 addition & 0 deletions core/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
requires transitive uk.gov.gchq.magmacore.hqdm.rdf;

exports uk.gov.gchq.magmacore.service;
exports uk.gov.gchq.magmacore.service.dto;
exports uk.gov.gchq.magmacore.service.transformation;
exports uk.gov.gchq.magmacore.exception;
exports uk.gov.gchq.magmacore.util;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,18 @@

package uk.gov.gchq.magmacore.database;

import java.io.InputStream;
import java.io.PrintStream;
import java.util.List;

import org.apache.jena.riot.Lang;

import uk.gov.gchq.magmacore.database.query.QueryResultList;
import uk.gov.gchq.magmacore.hqdm.model.Thing;
import uk.gov.gchq.magmacore.hqdm.rdf.iri.HqdmIri;
import uk.gov.gchq.magmacore.hqdm.rdf.iri.IRI;
import uk.gov.gchq.magmacore.service.transformation.DbCreateOperation;
import uk.gov.gchq.magmacore.service.transformation.DbDeleteOperation;

/**
* Interface defining CRUD operations and generic queries for Magma Core data collections.
Expand Down Expand Up @@ -63,6 +69,13 @@ public interface MagmaCoreDatabase {
*/
void create(Thing object);

/**
* Apply a set of creates to the database.
*
* @param creates a {@link List} of {@link DbDeleteOperation}
*/
void create(List<DbCreateOperation> creates);

/**
* Update an existing entity within the collection.
*
Expand All @@ -77,6 +90,13 @@ public interface MagmaCoreDatabase {
*/
void delete(Thing object);

/**
* Apply a set of deletes to the database.
*
* @param deletes a {@link List} of {@link DbDeleteOperation}
*/
void delete(List<DbDeleteOperation> deletes);

/**
* Find object(s) that have a specific object associated with them.
*
Expand Down Expand Up @@ -118,4 +138,44 @@ public interface MagmaCoreDatabase {
* @param out Output stream to dump to.
*/
void dump(PrintStream out);

/**
* 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}
*/
void dump(final PrintStream out, final Lang language);

/**
* Import data into the model.
*
* @param in {@link InputStream} to read from.
* @param language RDF language syntax to output data as.
*/
void load(final InputStream in, final Lang language);

/**
* Perform a SPARQL query on the dataset.
*
* @param sparqlQueryString SPARQL query to execute.
* @return Results of the query.
*/
QueryResultList executeQuery(final String sparqlQueryString);

/**
* Convert a {@link QueryResultList} to a {@link List} of {@link Thing}.
*
* @param queryResultsList {@link QueryResultList}
* @return a {@link List} of {@link Thing}
*/
List<Thing> toTopObjects(final QueryResultList queryResultsList);

/**
* Execute a CONSTRUCT query.
*
* @param query a CONSTRUCT query {@link String}
* @return a {@link List} of {@link Thing}
*/
List<Thing> executeConstruct(final String query);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package uk.gov.gchq.magmacore.database;

import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
Expand All @@ -29,7 +30,10 @@
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.Statement;
Expand All @@ -51,6 +55,8 @@
import uk.gov.gchq.magmacore.hqdm.rdf.iri.IRI;
import uk.gov.gchq.magmacore.hqdm.rdf.iri.IriBase;
import uk.gov.gchq.magmacore.hqdm.rdf.util.Pair;
import uk.gov.gchq.magmacore.service.transformation.DbCreateOperation;
import uk.gov.gchq.magmacore.service.transformation.DbDeleteOperation;

/**
* Apache Jena triplestore to store HQDM objects as RDF triples either as an in-memory Jena dataset
Expand Down Expand Up @@ -165,10 +171,44 @@ public Thing get(final IRI iri) {
*/
@Override
public void create(final Thing object) {
final Resource resource = dataset.getDefaultModel().createResource(object.getId());
final Model defaultModel = dataset.getDefaultModel();

object.getPredicates().forEach((iri, predicates) -> predicates.forEach(predicate -> resource
.addProperty(dataset.getDefaultModel().createProperty(iri.toString()), predicate.toString())));
final Resource resource = defaultModel.createResource(object.getId());

object.getPredicates().forEach((iri, predicates) -> predicates.forEach(value -> {
if (value instanceof IRI) {
final Resource valueResource = defaultModel.createResource(value.toString());
resource.addProperty(defaultModel.createProperty(iri.toString()), valueResource);
} else {
resource.addProperty(defaultModel.createProperty(iri.toString()), value.toString());
}
}));
}

/**
* {@inheritDoc}
*/
@Override
public void create(final List<DbCreateOperation> creates) {
final Model forCreation = ModelFactory.createDefaultModel();

creates.forEach(create -> {
final Resource s = forCreation.createResource(create.subject.getIri());
final Property p = forCreation.createProperty(create.predicate.getIri());
final Object value = create.object;

final RDFNode o;
if (value instanceof IRI) {
o = forCreation.createResource(value.toString());
} else {
o = forCreation.createLiteral(value.toString());
}
forCreation.add(forCreation.createStatement(s, p, o));
});

final Model model = dataset.getDefaultModel();

model.add(forCreation);
}

/**
Expand All @@ -188,6 +228,33 @@ public void delete(final Thing object) {
executeUpdate(String.format("delete {<%s> ?p ?o} WHERE {<%s> ?p ?o}", object.getId(), object.getId()));
}

/**
* {@inheritDoc}
*/
@Override
public void delete(final List<DbDeleteOperation> deletes) {
final Model forDeletion = ModelFactory.createDefaultModel();

deletes.forEach(delete -> {
final Resource s = forDeletion.createResource(delete.subject.getIri());
final Property p = forDeletion.createProperty(delete.predicate.getIri());
final Object value = delete.object;

final RDFNode o;
if (value instanceof IRI) {
o = forDeletion.createResource(value.toString());
} else {
o = forDeletion.createLiteral(value.toString());
}

forDeletion.add(forDeletion.createStatement(s, p, o));
});

final Model model = dataset.getDefaultModel();

model.remove(forDeletion);
}

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -233,6 +300,22 @@ public List<Thing> findByPredicateIriAndStringCaseInsensitive(final IRI predicat
return toTopObjects(list);
}

/**
* Execute a CONSTRUCT query.
*
* @param sparqlQueryString a CONSTRUCT query {@link String}
* @return a {@link List} of {@link Thing}
*/
public List<Thing> executeConstruct(final String sparqlQueryString) {
final Query query = QueryFactory.create(sparqlQueryString);
final QueryExecution queryExec = QueryExecutionFactory.create(query, dataset);

final Model model = queryExec.execConstruct();
final Query selectAllQuery = QueryFactory.create("select ?s ?p ?o where { ?s ?p ?o. }");
final QueryExecution selectAllQueryExec = QueryExecutionFactory.create(selectAllQuery, model);
return toTopObjects(getQueryResultList(selectAllQueryExec));
}

/**
* Perform an update query on the dataset.
*
Expand All @@ -250,7 +333,7 @@ protected void executeUpdate(final String statement) {
* @param sparqlQueryString SPARQL query to execute.
* @return Results of the query.
*/
protected QueryResultList executeQuery(final String sparqlQueryString) {
public QueryResultList executeQuery(final String sparqlQueryString) {
final Query query = QueryFactory.create(sparqlQueryString);
final QueryExecution queryExec = QueryExecutionFactory.create(query, dataset);
return getQueryResultList(queryExec);
Expand Down Expand Up @@ -282,28 +365,45 @@ private final QueryResultList getQueryResultList(final QueryExecution queryExec)
return queryResultList;
}

private final List<Thing> toTopObjects(final QueryResultList queryResultsList) {
final Map<String, List<Pair<String, String>>> objectMap = new HashMap<>();
final String subjectVarName = ((List<String>) queryResultsList.getVarNames()).get(0);
final String predicateVarName = ((List<String>) queryResultsList.getVarNames()).get(1);
final String objectVarName = ((List<String>) queryResultsList.getVarNames()).get(2);
/**
* Convert a {@link QueryResultList} to a {@link List} of {@link Thing}.
*
* @param queryResultsList {@link QueryResultList}
* @return a {@link List} of {@link Thing}
*/
public final List<Thing> toTopObjects(final QueryResultList queryResultsList) {
final Map<RDFNode, List<Pair<Object, Object>>> objectMap = new HashMap<>();
final List<String> varNames = (List<String>) queryResultsList.getVarNames();

final String subjectVarName = varNames.get(0);
final String predicateVarName = varNames.get(1);
final String objectVarName = varNames.get(2);

// Create a map of the triples for each unique subject IRI
final List<QueryResult> queryResults = queryResultsList.getQueryResults();
queryResults.forEach(queryResult -> {
final String subjectValue = queryResult.get(subjectVarName).toString();
final String predicateValue = queryResult.get(predicateVarName).toString();
final String objectValue = queryResult.get(objectVarName).toString();
final RDFNode subjectValue = queryResult.get(subjectVarName);
final RDFNode predicateValue = queryResult.get(predicateVarName);
final RDFNode objectValue = queryResult.get(objectVarName);

List<Pair<String, String>> dataModelObject = objectMap.get(subjectValue);
List<Pair<Object, Object>> dataModelObject = objectMap.get(subjectValue);
if (dataModelObject == null) {
dataModelObject = new ArrayList<>();
objectMap.put(subjectValue, dataModelObject);
}
dataModelObject.add(new Pair<>(predicateValue, objectValue));
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())));
} else {
throw new RuntimeException("objectValue is of unknown type: " + objectValue.getClass());
}
});

return objectMap.entrySet().stream().map(entry -> HqdmObjectFactory.create(entry.getKey(), entry.getValue()))
return objectMap
.entrySet()
.stream()
.map(entry -> HqdmObjectFactory.create(new IRI(entry.getKey().toString()), entry.getValue()))
.collect(Collectors.toList());
}

Expand Down Expand Up @@ -334,4 +434,17 @@ public final void dump(final PrintStream out, final Lang language) {
RDFDataMgr.write(out, dataset.getDefaultModel(), language);
abort();
}

/**
* Import data into the model.
*
* @param in {@link InputStream} to read from.
* @param language RDF language syntax to output data as.
*/
public final void load(final InputStream in, final Lang language) {
begin();
final Model model = dataset.getDefaultModel();
RDFDataMgr.read(model, in, language);
commit();
}
}
Loading