Skip to content

Commit

Permalink
Merge pull request #163 from gchq/161-case-insensitive-find-entity-by…
Browse files Browse the repository at this point in the history
…-partial-sign-community-and-pattern

#161 case insensitive find entity by partial sign community and pattern
  • Loading branch information
GCHQDeveloper42 authored Jan 18, 2024
2 parents b232647 + aea6d61 commit b07f2e2
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 5 deletions.
4 changes: 0 additions & 4 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@
</properties>

<dependencies>
<dependency>
<groupId>uk.gov.gchq.magma-core</groupId>
<artifactId>hqdm</artifactId>
</dependency>
<dependency>
<groupId>uk.gov.gchq.magma-core</groupId>
<artifactId>hqdm</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,47 @@ public List<? extends Thing> findBySignValue(
return database.toTopObjects(queryResults);
}

/**
* Find the Set of {@link Thing} represented by the given partial sign value.
*
* <p>
* The search is case-insensitive.
* This could probably be replaced with a (rather complex) SPARQL query if {@link MagmaCoreDatabase}
* allowed the execution of such queries.
* </p>
*
* @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.
* @return {@link List} of {@link Thing} represented by the value.
* @throws MagmaCoreException if the number of {@link RepresentationByPattern} found is not 1.
*/
public List<? extends Thing> findByPartialSignValue(
final RecognizingLanguageCommunity community,
final Pattern pattern,
final String value,
final PointInTime pointInTime) throws MagmaCoreException {

final Set<Object> pointInTimeValues = pointInTime.value(HQDM.ENTITY_NAME);
if (pointInTimeValues == null || pointInTimeValues.isEmpty()) {
return List.of();
}

final Instant when = Instant.parse(pointInTimeValues.iterator().next().toString());

final QueryResultList queryResultList = database
.executeQuery(String.format(MagmaCoreServiceQueries.FIND_BY_PARTIAL_SIGN_VALUE_CASE_INSENSITIVE_QUERY,
value,
community.getId(),
pattern.getId()));

// Filter by the pointInTime
final QueryResultList queryResults = filterByPointInTime(when, queryResultList);

return database.toTopObjects(queryResults);
}

/**
* Find Things of a giver rdf:type and Class and their signs that are of a particular pattern.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,50 @@ public class MagmaCoreServiceQueries {
}
""";

/**
* This query is used to find the Things represented by a given partial sign value for a particular
* {@link uk.gov.gchq.magmacore.hqdm.model.RecognizingLanguageCommunity} and
* {@link uk.gov.gchq.magmacore.hqdm.model.Pattern}.
* <p>
* It needs three parameters provided using String.format() - the partial sign value {@link String}, the
* {@link uk.gov.gchq.magmacore.hqdm.model.RecognizingLanguageCommunity} IRI {@link String}, and the
* {@link uk.gov.gchq.magmacore.hqdm.model.Pattern} IRI String.
* </p>
* <p>
* The Things are likely to be states of some individual.
* </p>
*/
public static final String FIND_BY_PARTIAL_SIGN_VALUE_CASE_INSENSITIVE_QUERY = """
PREFIX hqdm: <https://hqdmtop.github.io/hqdm#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?s ?p ?o ?start ?finish
WHERE {
BIND("%s" as ?text)
BIND(<%s> as ?rlc)
BIND(<%s> as ?pattern)
?sign hqdm:value_ ?signvalue;
hqdm:member_of_ ?pattern.
FILTER(CONTAINS(lcase(str(?signvalue)), lcase(?text)))
?sos hqdm:temporal_part_of ?sign;
hqdm:participant_in ?repBySign.
?rlc hqdm:participant_in ?repBySign.
?repBySign hqdm:represents ?s.
?s ?p ?o.
OPTIONAL {
?repBySign hqdm:beginning ?begin.
?begin hqdm:data_EntityName ?start.
}
OPTIONAL {
?repBySign hqdm:ending ?end.
?end hqdm:data_EntityName ?finish.
}
}
""";

/**
* This query finds PARTICIPANTS in associations of a specified kind between two individuals.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,43 @@ public void testFindBySignSuccess() throws MagmaCoreException {
assertEquals(SignPatternTestData.person2.getId(), ((IRI) parent2.iterator().next()));
}

/**
* 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
* given
* {@link uk.gov.gchq.magmacore.hqdm.model.PointInTime}.
*/
@Test
public void testFindByPartialSignSuccess() throws MagmaCoreException {

// 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);

// Create the PointInTime we're looking for
final PointInTime now = SpatioTemporalExtentServices.createPointInTime(new IRI(TEST_BASE, "now"));
now.addValue(HQDM.ENTITY_NAME, Instant.now().toString());

// Find the required Things by sign in a transaction.
db.beginWrite();
final List<? extends Thing> found1 = service.findByPartialSignValue(SignPatternTestData.community1,
SignPatternTestData.pattern1, "son1", now);
final List<? extends Thing> found2 = service.findByPartialSignValue(SignPatternTestData.community2,
SignPatternTestData.pattern2, "ERSON", now);
db.commit();

// Assert the results are correct.
assertNotNull(found1);
assertNotNull(found2);
assertEquals(1, found1.size());
assertEquals(2, found2.size());
}

/**
* Check that we get an empty result if the sign value is null.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ public class SignPatternTestData {
static Pattern pattern2;
static Person person1;
static Person person2;
static Person person3;
static StateOfPerson stateOfPerson1;
static StateOfPerson stateOfPerson2;
static StateOfPerson stateOfPerson3;
static IRI kindOfPersonIri;
static IRI classOfPersonIri;

Expand Down Expand Up @@ -92,13 +94,18 @@ static void createSignPattern(final MagmaCoreDatabase db) {
.createRepresentationByPattern(new IRI(TEST_BASE, "repByPattern2"));
repByPattern2.addValue(RDFS.RDF_TYPE, HQDM.REPRESENTATION_BY_PATTERN);

// Add the relationships for the patterns and communities.
final RepresentationByPattern repByPattern3 = ClassServices
.createRepresentationByPattern(new IRI(TEST_BASE, "repByPattern3"));
repByPattern3.addValue(RDFS.RDF_TYPE, HQDM.REPRESENTATION_BY_PATTERN);

// Add the relationships for the patterns and communities.
repByPattern1.addValue(HQDM.CONSISTS_OF_IN_MEMBERS, community1.getId());
repByPattern2.addValue(HQDM.CONSISTS_OF_IN_MEMBERS, community2.getId());
repByPattern3.addValue(HQDM.CONSISTS_OF_IN_MEMBERS, community2.getId());

repByPattern1.addValue(HQDM.CONSISTS_OF_BY_CLASS, pattern1.getId());
repByPattern2.addValue(HQDM.CONSISTS_OF_BY_CLASS, pattern2.getId());
repByPattern3.addValue(HQDM.CONSISTS_OF_BY_CLASS, pattern2.getId());

// Create KindOfPerson
kindOfPersonIri = new IRI(TEST_BASE, "kindOfPerson1");
Expand All @@ -117,6 +124,11 @@ static void createSignPattern(final MagmaCoreDatabase db) {
person2.addValue(HQDM.MEMBER_OF_KIND, kindOfPersonIri);
person2.addValue(HQDM.MEMBER_OF, classOfPersonIri);

person3 = SpatioTemporalExtentServices.createPerson(new IRI(TEST_BASE, "person3"));
person3.addValue(RDFS.RDF_TYPE, HQDM.PERSON);
person3.addValue(HQDM.MEMBER_OF_KIND, kindOfPersonIri);
person3.addValue(HQDM.MEMBER_OF, classOfPersonIri);

// Create States for the People
stateOfPerson1 = SpatioTemporalExtentServices
.createStateOfPerson(new IRI(TEST_BASE, "stateOfPerson1"));
Expand All @@ -128,6 +140,11 @@ static void createSignPattern(final MagmaCoreDatabase db) {
stateOfPerson2.addValue(RDFS.RDF_TYPE, HQDM.STATE_OF_PERSON);
stateOfPerson2.addValue(HQDM.TEMPORAL_PART_OF, person2.getId());

stateOfPerson3 = SpatioTemporalExtentServices
.createStateOfPerson(new IRI(TEST_BASE, "stateOfPerson3"));
stateOfPerson3.addValue(RDFS.RDF_TYPE, HQDM.STATE_OF_PERSON);
stateOfPerson3.addValue(HQDM.TEMPORAL_PART_OF, person3.getId());

// Create signs
final Sign sign1 = SpatioTemporalExtentServices.createSign(new IRI(TEST_BASE, "sign1"));
sign1.addValue(RDFS.RDF_TYPE, HQDM.SIGN);
Expand All @@ -139,6 +156,11 @@ static void createSignPattern(final MagmaCoreDatabase db) {
sign2.addValue(HQDM.MEMBER_OF_, pattern2Iri);
sign2.addValue(HQDM.VALUE_, "person2");

final Sign sign3 = SpatioTemporalExtentServices.createSign(new IRI(TEST_BASE, "sign3"));
sign3.addValue(RDFS.RDF_TYPE, HQDM.SIGN);
sign3.addValue(HQDM.MEMBER_OF_, pattern2Iri);
sign3.addValue(HQDM.VALUE_, "person3");

// Create states for the Signs
final StateOfSign stateOfSign1 = SpatioTemporalExtentServices
.createStateOfSign(new IRI(TEST_BASE, "stateOfSign1"));
Expand All @@ -150,6 +172,11 @@ static void createSignPattern(final MagmaCoreDatabase db) {
stateOfSign2.addValue(RDFS.RDF_TYPE, HQDM.STATE_OF_SIGN);
stateOfSign2.addValue(HQDM.TEMPORAL_PART_OF, sign2.getId());

final StateOfSign stateOfSign3 = SpatioTemporalExtentServices
.createStateOfSign(new IRI(TEST_BASE, "stateOfSign3"));
stateOfSign3.addValue(RDFS.RDF_TYPE, HQDM.STATE_OF_SIGN);
stateOfSign3.addValue(HQDM.TEMPORAL_PART_OF, sign3.getId());

// Create Events for the BEGINNING and ENDING of the RepresentationBySigns
final PointInTime begin = SpatioTemporalExtentServices.createPointInTime(new IRI(TEST_BASE, "begin"));
final PointInTime end = SpatioTemporalExtentServices.createPointInTime(new IRI(TEST_BASE, "end"));
Expand Down Expand Up @@ -184,6 +211,16 @@ static void createSignPattern(final MagmaCoreDatabase db) {
community2.addValue(HQDM.PARTICIPANT_IN, repBySign2.getId());
stateOfSign2.addValue(HQDM.PARTICIPANT_IN, repBySign2.getId());

final RepresentationBySign repBySign3 = SpatioTemporalExtentServices
.createRepresentationBySign(new IRI(TEST_BASE, "repBySign3"));
repBySign3.addValue(RDFS.RDF_TYPE, HQDM.REPRESENTATION_BY_SIGN);
repBySign3.addValue(HQDM.REPRESENTS, stateOfPerson3.getId());
repBySign3.addValue(HQDM.MEMBER_OF_, repByPattern2.getId());
repBySign3.addValue(HQDM.BEGINNING, objectId);
repBySign3.addValue(HQDM.ENDING, objectId2);
community2.addValue(HQDM.PARTICIPANT_IN, repBySign3.getId());
stateOfSign3.addValue(HQDM.PARTICIPANT_IN, repBySign3.getId());

// Persist all objects
db.beginWrite();

Expand All @@ -193,18 +230,24 @@ static void createSignPattern(final MagmaCoreDatabase db) {
db.create(pattern2);
db.create(repByPattern1);
db.create(repByPattern2);
db.create(repByPattern3);
db.create(person1);
db.create(person2);
db.create(person3);
db.create(stateOfPerson1);
db.create(stateOfPerson2);
db.create(stateOfPerson3);
db.create(sign1);
db.create(sign2);
db.create(sign3);
db.create(stateOfSign1);
db.create(stateOfSign2);
db.create(stateOfSign3);
db.create(begin);
db.create(end);
db.create(repBySign1);
db.create(repBySign2);
db.create(repBySign3);

db.commit();
}
Expand Down

0 comments on commit b07f2e2

Please sign in to comment.