Coverage for heritrace/utils/draft_labels.py: 99%
69 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-13 22:01 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-13 22:01 +0000
1# SPDX-FileCopyrightText: 2026 Arcangelo Massari <arcangelo.massari@unibo.it>
2#
3# SPDX-License-Identifier: ISC
5from uuid import uuid4
7from rdflib import RDF, Graph, Literal, URIRef
9from heritrace.extensions import get_form_fields
10from heritrace.sparql import select_results
11from heritrace.utils.datatypes import determine_datatype
12from heritrace.utils.display_rules_utils import find_matching_rule
13from heritrace.utils.shacl_utils import find_matching_form_field
14from heritrace.utils.uri_utils import is_valid_url
17def add_draft_entity(graph: Graph, entity: dict) -> URIRef:
18 if entity.get("is_existing_entity"):
19 uri = URIRef(entity["entity_uri"])
20 if "properties" not in entity:
21 return uri
22 else:
23 uri = URIRef(f"urn:heritrace:draft:{uuid4()}")
24 graph.add((uri, RDF.type, URIRef(entity["entity_type"])))
25 form_fields = get_form_fields()
26 key = find_matching_form_field(
27 entity["entity_type"], entity["entity_shape"], form_fields
28 )
29 for predicate, raw_values in entity["properties"].items():
30 values = raw_values if isinstance(raw_values, list) else [raw_values]
31 for value in values:
32 if isinstance(value, dict):
33 node = add_draft_entity(graph, value)
34 elif is_valid_url(str(value)):
35 node = URIRef(value)
36 else:
37 datatypes = []
38 if key and predicate in form_fields[key]:
39 fields = form_fields[key][predicate]
40 if fields and "datatypes" in fields[0]:
41 datatypes = fields[0]["datatypes"]
42 node = Literal(
43 value, datatype=determine_datatype(str(value), datatypes)
44 )
45 graph.add((uri, URIRef(predicate), node))
46 return uri
49def relation_display_query(entry: dict) -> str | None:
50 parent_rule = find_matching_rule(entry["parent_class"], entry["parent_shape"])
51 if not parent_rule or "displayProperties" not in parent_rule:
52 return None
53 for prop in parent_rule["displayProperties"]:
54 if prop.get("property") != entry["predicate"]:
55 continue
56 candidates = [prop]
57 if "displayRules" in prop:
58 candidates = prop["displayRules"]
59 for rule in candidates:
60 if "shape" in rule and rule["shape"] != entry["entity"]["entity_shape"]:
61 continue
62 if "fetchValueFromQuery" in rule:
63 return rule["fetchValueFromQuery"]
64 return None
67def draft_label(entry: dict) -> str | None:
68 graph = Graph()
69 entity = entry["entity"]
70 uri = add_draft_entity(graph, entity)
71 parent = URIRef(f"urn:heritrace:draft:{uuid4()}")
72 graph.add((parent, RDF.type, URIRef(entry["parent_class"])))
73 graph.add((parent, URIRef(entry["predicate"]), uri))
74 query = relation_display_query(entry)
75 if query is None:
76 rule = find_matching_rule(entity["entity_type"], entity["entity_shape"])
77 if rule and "fetchUriDisplay" in rule:
78 query = rule["fetchUriDisplay"]
79 if query is None:
80 return None
81 query = (
82 query.replace("[[subject]]", parent.n3())
83 .replace("[[value]]", uri.n3())
84 .replace("[[uri]]", uri.n3())
85 )
86 for row in select_results(graph.query(query)):
87 if row[0] is not None:
88 label = str(row[0]).strip()
89 if label and "urn:heritrace:draft:" not in label:
90 return label
91 return None