From 092d1eee88f7b1c0e083a0a4b9b5039d67e2ebfc Mon Sep 17 00:00:00 2001 From: Sam Thursfield Date: Tue, 7 Jul 2015 12:34:38 +0100 Subject: schema: Improve handling of command lists, again Now they are represented by rdf:Seq, which is the most practical way I think. Each list object has its own URI in a separate namespace, which is way more readable than having blank nodes with URIs like N101340613. Change-Id: I8d0f16ab43ba3d7144a4e76a01295c269156f92f --- schema/parse.py | 89 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 33 deletions(-) diff --git a/schema/parse.py b/schema/parse.py index b9c0fec8..ed520e73 100644 --- a/schema/parse.py +++ b/schema/parse.py @@ -92,6 +92,15 @@ class DefinitionsNamespace(rdflib.Namespace): def cluster(self, cluster_name): return self.term('clusters/' + cluster_name) + def command_sequence(self, chunk_uriref, sequence_name): + # We use '-' rather than '/' between chunk name and sequence name, + # mainly because the rdflib_web browser tool goes nuts if you have + # many resources with the same 'basename'. If we used '/' then there + # would be hundreds of URIs ending with '.../install-commands', + # '.../build-commands' etc. + chunk_name = os.path.basename(chunk_uriref) + return self.term('commands/' + chunk_name + '-' + sequence_name) + def stratum(self, stratum_name): return self.term('strata/' + stratum_name) @@ -119,21 +128,47 @@ def new_resource(graph, uriref, rdf_type): return entity -def ordered(graph, value_list, node=None): +def ordered(graph, value_list, list_uriref=None): '''Create an ordered RDF collection from a list of values. + This uses the rdf:Seq class to represent the ordered list. The rdf:Seq + class is apparently deprecated. However, the alternatives (rdf:List, or + the Ordered List Ontology) are more verbose. + + Further reading: + - http://www.w3.org/2011/rdf-wg/track/issues/77 + - http://purl.org/ontology/olo/core + To define an ordered list in RDF, you need an identifier for the list itself. By default this function will create a 'blank node', which will end up with a random unique URI when serialised. To make serialised data more - readable you can create your own rdflib.URIRef term to identify the list. + readable you can pass in your own rdflib.URIRef term to identify the list. ''' - node = node or rdflib.BNode() - collection = rdflib.collection.Collection( - graph, node, [rdflib.Literal(v) for v in value_list]) + node = list_uriref or rdflib.BNode() + graph.add((node, RDF.type, RDF.Seq)) + for i, value in enumerate(value_list): + index = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#_%i' % (i + 1) + graph.add((node, rdflib.URIRef(index), rdflib.Literal(value))) return node +def to_property(name): + '''Convert a normal property name to stupidCamelCase.''' + property_name = [] + hyphen = False + for char in name: + if char == '-': + hyphen = True + else: + if hyphen: + property_name.append(char.upper()) + else: + property_name.append(char) + hyphen = False + return ''.join(property_name) + + def load_all_morphologies(path='.'): '''Load Baserock Definitions serialisation format V5 as an RDFLib 'graph'. @@ -144,7 +179,6 @@ def load_all_morphologies(path='.'): toplevel_path = path graph = rdflib.Graph() - def load_morph(toplevel_path, filename): try: contents = parse_morph_file(filename) @@ -161,33 +195,22 @@ def load_all_morphologies(path='.'): chunk_uriref = ns.chunk(contents['name']) entity = chunk = new_resource(graph, chunk_uriref, BASEROCK.Chunk) - if 'pre-configure-commands' in contents: - chunk.set(BASEROCK.preConfigureCommands, - ordered(graph, contents['pre-configure-commands'])) - if 'configure-commands' in contents: - chunk.set(BASEROCK.configureCommands, - ordered(graph, contents['configure-commands'])) - if 'post-configure-commands' in contents: - chunk.set(BASEROCK.postConfigureCommands, - ordered(graph, contents['post-configure-commands'])) - if 'pre-build-commands' in contents: - chunk.set(BASEROCK.preBuildCommands, - ordered(graph, contents['pre-build-commands'])) - if 'build-commands' in contents: - chunk.set(BASEROCK.buildCommands, - ordered(graph, contents['build-commands'])) - if 'post-build-commands' in contents: - chunk.set(BASEROCK.postBuildCommands, - ordered(graph, contents['post-build-commands'])) - if 'pre-install-commands' in contents: - chunk.set(BASEROCK.preInstallCommands, - ordered(graph, contents['pre-install-commands'])) - if 'install-commands' in contents: - chunk.set(BASEROCK.installCommands, - ordered(graph, contents['install-commands'])) - if 'post-install-commands' in contents: - chunk.set(BASEROCK.postInstallCommands, - ordered(graph, contents['post-install-commands'])) + def set_command_sequence(resource, name): + if name in contents: + property = BASEROCK.term(to_property(name)) + list_node = ns.command_sequence(resource.identifier, name) + resource.set(property, + ordered(graph, contents[name], list_node)) + + set_command_sequence(chunk, 'pre-configure-commands') + set_command_sequence(chunk, 'configure-commands') + set_command_sequence(chunk, 'post-configure-commands') + set_command_sequence(chunk, 'pre-build-commands') + set_command_sequence(chunk, 'build-commands') + set_command_sequence(chunk, 'post-build-commands') + set_command_sequence(chunk, 'pre-install-commands') + set_command_sequence(chunk, 'install-commands') + set_command_sequence(chunk, 'post-install-commands') elif contents['kind'] == 'stratum': stratum_uriref = ns.stratum(contents['name']) -- cgit v1.2.1