From d7759fd5188338bf41534b0efc7843bf03c439f7 Mon Sep 17 00:00:00 2001 From: Pinto Pasquale Date: Fri, 11 Oct 2024 17:17:54 +0200 Subject: [PATCH] CVN-143 Add recursive removal of empty triples (#739) * CVN-143 Add recursive removal of empty triples * Fix typo in comment --------- Co-authored-by: Pasquale Pinto Co-authored-by: Rob van den Bogaard --- .../mod_ginger_rdf/models/m_rdf_triple.erl | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/modules/mod_ginger_rdf/models/m_rdf_triple.erl b/modules/mod_ginger_rdf/models/m_rdf_triple.erl index 2c05d3a4..b99ba957 100644 --- a/modules/mod_ginger_rdf/models/m_rdf_triple.erl +++ b/modules/mod_ginger_rdf/models/m_rdf_triple.erl @@ -7,7 +7,9 @@ insert/2, m_find_value/3, m_to_list/2, - m_value/2 + m_value/2, + + remove_empty/1 ]). -include_lib("zotonic.hrl"). @@ -127,3 +129,41 @@ create_predicate(Uri, Context) -> {error, Reason} -> {error, Reason} end. + + +% Removes all empty triples, recursively, from an 'rdf_resource', a 'triple' or +% a list of either; returns any other value unaltered. +% Note: the type of the output is always the same as the input's. +remove_empty(List) when is_list(List) -> + % First remove the empty triples from the resources/triples in the list: + NewList = lists:map(fun remove_empty/1, List), + % Then filter the items in the list themselves: + [Item || Item <- NewList, not is_empty(Item)]; +remove_empty(Triple) when is_record(Triple, triple) -> + NewObject = remove_empty(Triple#triple.object), + Triple#triple{object=NewObject}; +remove_empty(Resource) when is_record(Resource, rdf_resource) -> + NewTriples = remove_empty(Resource#rdf_resource.triples), + Resource#rdf_resource{triples=NewTriples}; +remove_empty(Other) -> + Other. + +% A triple is considered empty if it doesn't add any new information, aka iff: +% 1. its object is empty (see 'is_empty_object') +% 2. there are no 'subject_props' nor 'object_props' +-spec is_empty(rdf:triple()) -> boolean(). +is_empty(#triple{object = Object, subject_props = [], object_props = []}) -> + is_empty_object(Object); +is_empty(_) -> + false. + +% A triple's object is considered empty if it doesn't add any new information, aka iff: +% 1. it's an empty URI/binary value +% 2. it's an 'rdf_value' whose 'value' is itself an empty object +-spec is_empty_object(ginger_uri:uri() | #rdf_value{} | #rdf_resource{}) -> boolean(). +is_empty_object(Value) when is_binary(Value) -> + z_utils:is_empty(Value); +is_empty_object(#rdf_value{value = Value}) -> + is_empty_object(Value); +is_empty_object(_) -> + false.