66from typing import Any , Dict , Tuple
77
88from pyshacl import validate
9- from rdflib import BNode , Graph , Literal
9+ from rdflib import BNode , Graph , Literal , Node
1010from rdflib .collection import Collection
11- from rdflib .namespace import RDF
11+ from rdflib .namespace import RDF , RDFS , XSD
1212
13+ from sc_validate .data_model import Parameter
1314from sc_validate .namespaces import PREFIXES , SC
1415
16+ # TODO: Add debug messages to all asserts.
17+
18+
19+ _ALLOWED_INNER_TYPES = (
20+ XSD .string ,
21+ XSD .boolean ,
22+ XSD .integer ,
23+ XSD .int ,
24+ XSD .decimal ,
25+ XSD .float ,
26+ XSD .double ,
27+ XSD .anyURI ,
28+ )
29+
1530
1631def read_rdf_resource (source : pathlib .Path | str ) -> Graph :
1732 graph = Graph ()
@@ -21,51 +36,80 @@ def read_rdf_resource(source: pathlib.Path | str) -> Graph:
2136 return graph
2237
2338
39+ def _create_rdf_list_parameter (
40+ parameter : Parameter , graph : Graph , config_parameter : Any
41+ ) -> Node :
42+ assert parameter .outer_type == RDF .List
43+ # assert (parameter.default_value, RDF.type, RDF.List) in graph
44+ assert (parameter .default_value , RDF .first , None ) in graph
45+ assert (parameter .default_value , RDF .rest , None ) in graph
46+
47+ if config_parameter is None :
48+ return Collection (graph , parameter .default_value ).uri
49+
50+ # TODO: What happens if `parameter_value` is empty list?
51+ assert isinstance (config_parameter , list )
52+ return Collection (
53+ graph , BNode (), seq = [Literal (value ) for value in config_parameter ]
54+ ).uri
55+
56+
57+ def _create_sc_scalar_parameter (
58+ parameter : Parameter , graph : Graph , config_parameter : Any
59+ ) -> Node :
60+ assert parameter .outer_type == SC .Scalar
61+
62+ assert isinstance (config_parameter , (str , int , float , type (None )))
63+
64+ if config_parameter :
65+ return Literal (config_parameter )
66+
67+ return graph .value (parameter .uri , SC .parameterDefaultValue , None )
68+
69+
2470# TODO: Is it safe to modify the graph while iterating over it?
2571def parameterize_graph (graph : Graph , config_parameters : Dict [str , Any ]) -> Graph :
2672 # iterate over all declared parameters of type `sc:Parameter`
27- for parameter in graph .subjects (RDF .type , SC .Parameter ):
28- # get config name for the parameter
29- parameter_name = str (graph .value (parameter , SC .parameterConfigPath , None ))
30- is_list = graph .value (parameter , SC .parameterType , None ) == RDF .List
31-
32- # get default value for the parameter
33- default_value = graph .value (parameter , SC .parameterDefaultValue , None )
34-
35- if is_list :
36- assert (default_value , RDF .first , None ) in graph
37- assert (default_value , RDF .rest , None ) in graph
38- default_value = Collection (graph , default_value )
39-
40- # load parameter from config by its name
41- parameter_value = config_parameters .get (parameter_name , [])
42- assert isinstance (parameter_value , list )
43-
44- o = default_value .uri
45- if parameter_value :
46- parameter_value = Collection (
47- graph , BNode (), seq = [Literal (value ) for value in parameter_value ]
48- )
49- o = parameter_value .uri
50-
51- # empty the list of the unused default value while the variable is still
52- # in scope
53- default_value .clear ()
73+ for parameter_ref in graph .subjects (RDF .type , SC .Parameter ):
74+ parameter = Parameter .from_graph (parameter_ref , graph )
75+
76+ inner_type_is_primitive = parameter .inner_type in _ALLOWED_INNER_TYPES
77+
78+ config_parameter = config_parameters .get (parameter .config_path )
79+
80+ if not inner_type_is_primitive and parameter .inner_type != RDFS .Resource :
81+ raise ValueError (
82+ f"Parameter '{ parameter .uri } ' has unknown inner type "
83+ f"'{ parameter .inner_type } '"
84+ )
85+
86+ if parameter .outer_type == RDF .List :
87+ o = _create_rdf_list_parameter (parameter , graph , config_parameter )
88+
89+ elif parameter .outer_type in (RDF .Seq , RDF .Bag , RDF .Alt ):
90+ raise NotImplementedError (
91+ f"Parameter '{ parameter .uri } ' has outer type "
92+ f"'{ parameter .outer_type } ', the handling of which "
93+ "is currently not implemented"
94+ )
95+
96+ elif parameter .outer_type == SC .Scalar :
97+ o = _create_sc_scalar_parameter (parameter , graph , config_parameter )
5498
5599 else :
56- # load parameter from config by its name
57- parameter_value = config_parameters . get ( parameter_name )
58- assert isinstance ( parameter_value , ( str , int , float , type ( None )))
59- o = Literal ( parameter_value ) if parameter_value else default_value
100+ raise ValueError (
101+ f"'Parameter { parameter . uri } ' has unknown outer type "
102+ f"' { parameter . outer_type } '"
103+ )
60104
61105 # add replacements for all occurences of the parameter
62- for s , p in graph .subject_predicates (parameter ):
106+ for s , p in graph .subject_predicates (parameter . uri ):
63107 graph .add ((s , p , o ))
64108
65109 # remove all references to the parameter from the graph
66- # TODO: Keep all `(parameter, None, None)` for debugging purposes?
67- graph .remove ((parameter , None , None ))
68- graph .remove ((None , None , parameter ))
110+ # TODO: Keep all `(parameter.uri , None, None)` for debugging purposes?
111+ graph .remove ((parameter . uri , None , None ))
112+ graph .remove ((None , None , parameter . uri ))
69113
70114 return graph
71115
0 commit comments