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 107ac972..80fa222a 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 @@ -285,6 +285,34 @@ 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. + * + * @param item IRI + * @param kindOfAssociation IRI + * @param pointInTime {@link PointInTime} + * @return {@link List} of {@link Thing} + */ + public List findAssociated(final IRI item, final IRI kindOfAssociation, final PointInTime pointInTime) { + + final Set 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_ASSOCIATED, + kindOfAssociation, item, item, + kindOfAssociation, item, item, + kindOfAssociation, item, item)); + + final QueryResultList queryResults = filterByPointInTime(when, queryResultList); + return database.toTopObjects(queryResults); + + } + /** * A case-sensitive search for entities in a specified class with a sign containing the given text. * diff --git a/core/src/main/java/uk/gov/gchq/magmacore/service/sparql/MagmaCoreServiceQueries.java b/core/src/main/java/uk/gov/gchq/magmacore/service/sparql/MagmaCoreServiceQueries.java index 3a6f2342..8088e1b1 100644 --- a/core/src/main/java/uk/gov/gchq/magmacore/service/sparql/MagmaCoreServiceQueries.java +++ b/core/src/main/java/uk/gov/gchq/magmacore/service/sparql/MagmaCoreServiceQueries.java @@ -362,66 +362,92 @@ public class MagmaCoreServiceQueries { """; /** - * TODO: Comment. + * Find things associated to a given thing by an association of a given kind. */ public static final String FIND_ASSOCIATED = """ PREFIX hqdm: - select ?s ?p ?o + + select ?s ?p ?o ?start ?finish where { { - select distinct ?s ?p ?o - WHERE { - BIND(<%s> as ?kind_of_association) - ?from hqdm:temporal_part_of <%s>; - hqdm:participant_in ?association. - ?association hqdm:member_of_kind ?kind_of_association. - ?participant hqdm:participant_in ?association; - hqdm:temporal_part_of ?s. - ?s ?p ?o. - FILTER(?s != <%s>) - } + select distinct ?s ?p ?o ?start ?finish + WHERE { + BIND(<%s> as ?kind_of_association) + ?from hqdm:temporal_part_of <%s>; + hqdm:participant_in ?association. + ?association hqdm:member_of_kind ?kind_of_association. + ?participant hqdm:participant_in ?association; + hqdm:temporal_part_of ?s. + ?s ?p ?o. + FILTER(?s != <%s>) + OPTIONAL { + ?association hqdm:beginning ?begin. + ?begin hqdm:data_EntityName ?start. + } + OPTIONAL { + ?association hqdm:ending ?end. + ?end hqdm:data_EntityName ?finish. + } } - UNION - { - select distinct ?s ?p ?o - WHERE { - BIND(<%s> as ?kind_of_association) - ?from hqdm:temporal_part_of <%s>; - hqdm:participant_in ?association. - ?association hqdm:member_of_kind ?kind_of_association. - ?participant hqdm:participant_in ?association; - hqdm:temporal_part_of ?s; - hqdm:member_of_kind ?role. - FILTER(?s != <%s>) - ?role hqdm:data_EntityName ?o; - ?p ?o. - } + } + UNION + { + select distinct ?s ?p ?o ?start ?finish + WHERE { + BIND(<%s> as ?kind_of_association) + ?from hqdm:temporal_part_of <%s>; + hqdm:participant_in ?association. + ?association hqdm:member_of_kind ?kind_of_association. + ?participant hqdm:participant_in ?association; + hqdm:temporal_part_of ?s; + hqdm:member_of_kind ?role. + FILTER(?s != <%s>) + OPTIONAL { + ?association hqdm:beginning ?begin. + ?begin hqdm:data_EntityName ?start. + } + OPTIONAL { + ?association hqdm:ending ?end. + ?end hqdm:data_EntityName ?finish. + } + ?role hqdm:data_EntityName ?o; + ?p ?o. } - UNION - { - select distinct ?s ?p ?o - WHERE { - BIND(<%s> as ?kind_of_association) - ?from hqdm:temporal_part_of <%s>; - hqdm:participant_in ?association. - ?association hqdm:member_of_kind ?kind_of_association. - ?participant hqdm:participant_in ?association; - hqdm:temporal_part_of ?s. - FILTER(?s != <%s>) - ?state_of_individual hqdm:temporal_part_of ?s. - ?repBySign hqdm:represents ?state_of_individual. - ?repBySign a hqdm:representation_by_sign. - ?state_of_sign hqdm:participant_in ?repBySign; - a hqdm:state_of_sign; - hqdm:temporal_part_of ?sign. - ?sign hqdm:value_ ?o; - ?p ?o. - } + } + UNION + { + select distinct ?s ?p ?o ?start ?finish + WHERE { + BIND(<%s> as ?kind_of_association) + ?from hqdm:temporal_part_of <%s>; + hqdm:participant_in ?association. + ?association hqdm:member_of_kind ?kind_of_association. + ?participant hqdm:participant_in ?association; + hqdm:temporal_part_of ?s. + FILTER(?s != <%s>) + ?state_of_individual hqdm:temporal_part_of ?s. + ?repBySign hqdm:represents ?state_of_individual. + ?repBySign a hqdm:representation_by_sign. + ?state_of_sign hqdm:participant_in ?repBySign; + a hqdm:state_of_sign; + hqdm:temporal_part_of ?sign. + OPTIONAL { + ?association hqdm:beginning ?begin. + ?begin hqdm:data_EntityName ?start. + } + OPTIONAL { + ?association hqdm:ending ?end. + ?end hqdm:data_EntityName ?finish. + } + ?sign hqdm:value_ ?o; + ?p ?o. } } - order by ?s ?p ?o + } + order by ?s ?p ?o + """; /**