Chris@0: #!/usr/bin/python Chris@0: # -*- coding: utf8 -*- Chris@0: # Chris@0: # SpecGen v5, ontology specification generator tool Chris@0: # Chris@0: # Chris@0: # Copyright (c) 2003-2008 Christopher Schmidt Chris@0: # Copyright (c) 2005-2008 Uldis Bojars Chris@0: # Copyright (c) 2007-2008 Sergio Fernández Chris@0: # Chris@0: # Previous versions of SpecGen: Chris@0: # v1,2,3 by Christopher Schmidt Chris@0: # v4 by Uldis Bojars Chris@0: # Chris@0: # This software is licensed under the terms of the MIT License. Chris@0: # Chris@0: # Permission is hereby granted, free of charge, to any person obtaining a copy Chris@0: # of this software and associated documentation files (the "Software"), to deal Chris@0: # in the Software without restriction, including without limitation the rights Chris@0: # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell Chris@0: # copies of the Software, and to permit persons to whom the Software is Chris@0: # furnished to do so, subject to the following conditions: Chris@0: # Chris@0: # The above copyright notice and this permission notice shall be included in Chris@0: # all copies or substantial portions of the Software. Chris@0: # Chris@0: # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR Chris@0: # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, Chris@0: # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE Chris@0: # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER Chris@0: # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, Chris@0: # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN Chris@0: # THE SOFTWARE. Chris@0: Chris@0: __version__ = "5.4.2" Chris@0: __authors__ = "Christopher Schmidt, Uldis Bojars, Sergio Fernández" Chris@0: __license__ = "MIT License " Chris@0: __contact__ = "specgen-devel@lists.morfeo-project.org" Chris@0: __date__ = "2008-12-02" Chris@0: Chris@0: import os Chris@0: import sys Chris@0: import time Chris@0: import re Chris@0: import urllib Chris@0: Chris@0: try: Chris@0: import RDF Chris@0: except ImportError: Chris@0: version = sys.version.split(" ")[0] Chris@0: if version.startswith("2.5"): Chris@0: sys.path.append("/usr/lib/python2.4/site-packages/") Chris@0: else: Chris@0: sys.path.append("/usr/lib/python2.5/site-packages/") Chris@0: try: Chris@0: import RDF Chris@0: except: Chris@0: sys.exit("Error importing RedLand bindings for Python; check if it is installed correctly") Chris@0: Chris@0: #global vars Chris@0: classranges = {} Chris@0: classdomains = {} Chris@0: spec_url = None Chris@0: spec_ns = None Chris@0: spec_pre = None Chris@0: ns_list = { "http://www.w3.org/1999/02/22-rdf-syntax-ns#" : "rdf", Chris@0: "http://www.w3.org/2000/01/rdf-schema#" : "rdfs", Chris@0: "http://www.w3.org/2002/07/owl#" : "owl", Chris@0: "http://www.w3.org/2001/XMLSchema#" : "xsd", Chris@0: "http://rdfs.org/sioc/ns#" : "sioc", Chris@0: "http://xmlns.com/foaf/0.1/" : "foaf", Chris@0: "http://purl.org/dc/elements/1.1/" : "dc", Chris@0: "http://purl.org/dc/terms/" : "dct", Chris@0: "http://usefulinc.com/ns/doap#" : "doap", Chris@0: "http://www.w3.org/2003/06/sw-vocab-status/ns#" : "status", Chris@0: "http://purl.org/rss/1.0/modules/content/" : "content", Chris@0: "http://www.w3.org/2003/01/geo/wgs84_pos#" : "geo", Chris@0: "http://www.w3.org/2004/02/skos/core#" : "skos" Chris@0: } Chris@0: Chris@0: rdf = RDF.NS('http://www.w3.org/1999/02/22-rdf-syntax-ns#') Chris@0: rdfs = RDF.NS('http://www.w3.org/2000/01/rdf-schema#') Chris@0: owl = RDF.NS('http://www.w3.org/2002/07/owl#') Chris@0: vs = RDF.NS('http://www.w3.org/2003/06/sw-vocab-status/ns#') Chris@0: Chris@0: termdir = './doc' #TODO Chris@0: Chris@0: Chris@0: def niceName(uri): Chris@0: regexp = re.compile( "^(.*[/#])([^/#]+)$" ) Chris@0: rez = regexp.search( uri ) Chris@0: pref = rez.group(1) Chris@0: #return ns_list.get(pref, pref) + ":" + rez.group(2) Chris@0: if ns_list.has_key(pref): Chris@0: return ns_list.get(pref, pref) + ":" + rez.group(2) Chris@0: else: Chris@0: return uri Chris@0: Chris@0: Chris@0: def setTermDir(directory): Chris@0: global termdir Chris@0: termdir = directory Chris@0: Chris@0: Chris@0: def termlink(string): Chris@0: """FOAF specific: function which replaces foaf:* with a Chris@0: link to the term in the document.""" Chris@0: return re.sub(r"" + spec_pre + r":(\w+)", r"""""" + spec_pre + r""":\1""", string) Chris@0: Chris@0: Chris@0: def return_name(m, urinode): Chris@0: "Trims the FOAF namespace out of a term to give a name to the term." Chris@0: return str(urinode.uri).replace(spec_url, "") Chris@0: Chris@0: Chris@0: def get_rdfs(m, urinode): Chris@0: "Returns label and comment given an RDF.Node with a URI in it" Chris@0: comment = '' Chris@0: label = '' Chris@0: if (type(urinode)==str): Chris@0: urinode = RDF.Uri(urinode) Chris@0: l = m.find_statements(RDF.Statement(urinode, rdfs.label, None)) Chris@0: if l.current(): Chris@0: label = l.current().object.literal_value['string'] Chris@0: c = m.find_statements(RDF.Statement(urinode, rdfs.comment, None)) Chris@0: if c.current(): Chris@0: comment = c.current().object.literal_value['string'] Chris@0: return label, comment Chris@0: Chris@0: Chris@0: def get_status(m, urinode): Chris@0: "Returns the status text for a term." Chris@0: status = '' Chris@0: s = m.find_statements(RDF.Statement(urinode, vs.term_status, None)) Chris@0: if s.current(): Chris@0: return s.current().object.literal_value['string'] Chris@0: Chris@0: Chris@0: def htmlDocInfo( t ): Chris@0: """Opens a file based on the term name (t) and termdir directory (global). Chris@0: Reads in the file, and returns a linkified version of it.""" Chris@0: doc = "" Chris@0: try: Chris@0: f = open("%s/%s.en" % (termdir, t), "r") Chris@0: doc = f.read() Chris@0: doc = termlink(doc) Chris@0: except: Chris@0: return "" # "

No detailed documentation for this term.

" Chris@0: return doc Chris@0: Chris@0: Chris@0: def owlVersionInfo(m): Chris@0: v = m.find_statements(RDF.Statement(None, owl.versionInfo, None)) Chris@0: if v.current(): Chris@0: return v.current().object.literal_value['string'] Chris@0: else: Chris@0: return "" Chris@0: Chris@0: Chris@0: def rdfsPropertyInfo(term,m): Chris@0: """Generate HTML for properties: Domain, range, status.""" Chris@0: global classranges Chris@0: global classdomains Chris@0: doc = "" Chris@0: range = "" Chris@0: domain = "" Chris@0: Chris@0: #find subPropertyOf information Chris@0: o = m.find_statements( RDF.Statement(term, rdfs.subPropertyOf, None) ) Chris@0: if o.current(): Chris@0: rlist = '' Chris@0: for st in o: Chris@0: k = getTermLink(str(st.object.uri)) Chris@0: rlist += "
%s
" % k Chris@0: doc += "
sub-property-of:
%s" % rlist Chris@0: Chris@0: #domain stuff Chris@0: domains = m.find_statements(RDF.Statement(term, rdfs.domain, None)) Chris@0: domainsdoc = "" Chris@0: for d in domains: Chris@0: collection = m.find_statements(RDF.Statement(d.object, owl.unionOf, None)) Chris@0: if collection.current(): Chris@0: uris = parseCollection(m, collection) Chris@0: for uri in uris: Chris@0: domainsdoc += "
%s
" % getTermLink(uri) Chris@0: add(classdomains, uri, term.uri) Chris@0: else: Chris@0: if not d.object.is_blank(): Chris@0: domainsdoc += "
%s
" % getTermLink(str(d.object.uri)) Chris@0: if (len(domainsdoc)>0): Chris@0: doc += "
Domain:
%s" % domainsdoc Chris@0: Chris@0: #range stuff Chris@0: ranges = m.find_statements(RDF.Statement(term, rdfs.range, None)) Chris@0: rangesdoc = "" Chris@0: for r in ranges: Chris@0: collection = m.find_statements(RDF.Statement(r.object, owl.unionOf, None)) Chris@0: if collection.current(): Chris@0: uris = parseCollection(m, collection) Chris@0: for uri in uris: Chris@0: rangesdoc += "
%s
" % getTermLink(uri) Chris@0: add(classranges, uri, term.uri) Chris@0: else: Chris@0: if not r.object.is_blank(): Chris@0: rangesdoc += "
%s
" % getTermLink(str(r.object.uri)) Chris@0: if (len(rangesdoc)>0): Chris@0: doc += "
Range:
%s" % rangesdoc Chris@0: Chris@0: return doc Chris@0: Chris@0: Chris@0: def parseCollection(model, collection): Chris@0: # #propertyA a rdf:Property ; Chris@0: # rdfs:domain [ Chris@0: # a owl:Class ; Chris@0: # owl:unionOf [ Chris@0: # rdf:parseType Collection ; Chris@0: # #Foo a owl:Class ; Chris@0: # #Bar a owl:Class Chris@0: # ] Chris@0: # ] Chris@0: # Chris@0: # seeAlso "Collections in RDF" Chris@0: Chris@0: uris = [] Chris@0: Chris@0: rdflist = model.find_statements(RDF.Statement(collection.current().object, None, None)) Chris@0: while rdflist and rdflist.current() and not rdflist.current().object.is_blank(): Chris@0: one = rdflist.current() Chris@0: if not one.object.is_blank(): Chris@0: uris.append(str(one.object.uri)) Chris@0: rdflist.next() Chris@0: one = rdflist.current() Chris@0: if one.predicate == rdf.rest: Chris@0: rdflist = model.find_statements(RDF.Statement(one.object, None, None)) Chris@0: Chris@0: return uris Chris@0: Chris@0: Chris@0: def getTermLink(uri): Chris@0: uri = str(uri) Chris@0: if (uri.startswith(spec_url)): Chris@0: return '%s' % (uri.replace(spec_url, ""), niceName(uri)) Chris@0: else: Chris@0: return '%s' % (uri, niceName(uri)) Chris@0: Chris@0: Chris@0: def rdfsClassInfo(term,m): Chris@0: """Generate rdfs-type information for Classes: ranges, and domains.""" Chris@0: global classranges Chris@0: global classdomains Chris@0: doc = "" Chris@0: Chris@0: #patch to control incoming strings (FIXME, why??? drop it!) Chris@0: try: Chris@0: term.uri Chris@0: except: Chris@0: term = RDF.Node(RDF.Uri(term)) Chris@0: Chris@0: # Find subClassOf information Chris@0: o = m.find_statements( RDF.Statement(term, rdfs.subClassOf, None) ) Chris@0: if o.current(): Chris@0: doc += "
sub-class-of:
" Chris@0: superclasses = [] Chris@0: for st in o: Chris@0: if not st.object.is_blank(): Chris@0: uri = str(st.object.uri) Chris@0: if (not uri in superclasses): Chris@0: superclasses.append(uri) Chris@0: for superclass in superclasses: Chris@0: doc += "
%s
" % getTermLink(superclass) Chris@0: Chris@0: # Find out about properties which have rdfs:domain of t Chris@0: d = classdomains.get(str(term.uri), "") Chris@0: if d: Chris@0: dlist = '' Chris@0: for k in d: Chris@0: dlist += "
%s
" % getTermLink(k) Chris@0: doc += "
in-domain-of:
" + dlist Chris@0: Chris@0: # Find out about properties which have rdfs:range of t Chris@0: r = classranges.get(str(term.uri), "") Chris@0: if r: Chris@0: rlist = '' Chris@0: for k in r: Chris@0: rlist += "
%s
" % getTermLink(k) Chris@0: doc += "
in-range-of:
" + rlist Chris@0: Chris@0: return doc Chris@0: Chris@0: def rdfsInstanceInfo(term,m): Chris@0: """Generate rdfs-type information for instances""" Chris@0: doc = "" Chris@0: Chris@0: t = m.find_statements( RDF.Statement(RDF.Node(RDF.Uri(term)), rdf.type, None) ) Chris@0: if t.current(): Chris@0: doc += "
RDF Type:
" Chris@0: while t.current(): Chris@0: doc += "
%s
" % getTermLink(str(t.current().object.uri)) Chris@0: t.next() Chris@0: Chris@0: return doc Chris@0: Chris@0: Chris@0: def owlInfo(term,m): Chris@0: """Returns an extra information that is defined about a term (an RDF.Node()) using OWL.""" Chris@0: res = '' Chris@0: Chris@0: # FIXME: refactor this code Chris@0: Chris@0: # Inverse properties ( owl:inverseOf ) Chris@0: o = m.find_statements( RDF.Statement(term, owl.inverseOf, None) ) Chris@0: if o.current(): Chris@0: res += "
Inverse:
" Chris@0: for st in o: Chris@0: res += "
%s
" % getTermLink(str(st.object.uri)) Chris@0: Chris@0: # Datatype Property ( owl.DatatypeProperty ) Chris@0: o = m.find_statements( RDF.Statement(term, rdf.type, owl.DatatypeProperty) ) Chris@0: if o.current(): Chris@0: res += "
OWL Type:
DatatypeProperty
\n" Chris@0: Chris@0: # Object Property ( owl.ObjectProperty ) Chris@0: o = m.find_statements( RDF.Statement(term, rdf.type, owl.ObjectProperty) ) Chris@0: if o.current(): Chris@0: res += "
OWL Type:
ObjectProperty
\n" Chris@0: Chris@0: # Annotation Property ( owl.AnnotationProperty ) Chris@0: o = m.find_statements( RDF.Statement(term, rdf.type, owl.AnnotationProperty) ) Chris@0: if o.current(): Chris@0: res += "
OWL Type:
AnnotationProperty
\n" Chris@0: Chris@0: # IFPs ( owl.InverseFunctionalProperty ) Chris@0: o = m.find_statements( RDF.Statement(term, rdf.type, owl.InverseFunctionalProperty) ) Chris@0: if o.current(): Chris@0: res += "
OWL Type:
InverseFunctionalProperty (uniquely identifying property)
\n" Chris@0: Chris@0: # Symmertic Property ( owl.SymmetricProperty ) Chris@0: o = m.find_statements( RDF.Statement(term, rdf.type, owl.SymmetricProperty) ) Chris@0: if o.current(): Chris@0: res += "
OWL Type:
SymmetricProperty
\n" Chris@0: Chris@0: return res Chris@0: Chris@0: Chris@0: def docTerms(category, list, m): Chris@0: """ Chris@0: A wrapper class for listing all the terms in a specific class (either Chris@0: Properties, or Classes. Category is 'Property' or 'Class', list is a Chris@0: list of term names (strings), return value is a chunk of HTML. Chris@0: """ Chris@0: doc = "" Chris@0: nspre = spec_pre Chris@0: for t in list: Chris@0: if (t.startswith(spec_url)) and (len(t[len(spec_url):].split("/"))<2): Chris@0: term = t Chris@0: t = t.split(spec_url[-1])[-1] Chris@0: curie = t#"%s:%s" % (nspre, t) Chris@0: else: Chris@0: if t.startswith("http://"): Chris@0: term = t Chris@0: curie = getShortName(t) Chris@0: t = getAnchor(t) Chris@0: else: Chris@0: term = spec_ns[t] Chris@0: curie = "%s:%s" % (nspre, t) Chris@0: Chris@0: doc += """
\n

%s: %s

\n""" % (t, category, curie) Chris@0: try: Chris@0: term_uri = term.uri Chris@0: except: Chris@0: term_uri = term Chris@0: doc += """

URI: %s

""" % (term_uri, term_uri) Chris@0: label, comment = get_rdfs(m, term) Chris@0: status = get_status(m, term) Chris@0: doc += "

%s - %s

" % (label, comment) Chris@0: terminfo = "" Chris@0: if category=='Property': Chris@0: terminfo += owlInfo(term,m) Chris@0: terminfo += rdfsPropertyInfo(term,m) Chris@0: if category=='Class': Chris@0: terminfo += rdfsClassInfo(term,m) Chris@0: if category=='Instance': Chris@0: terminfo += rdfsInstanceInfo(term,m) Chris@0: if (len(terminfo)>0): #to prevent empty list (bug #882) Chris@0: doc += "\n
%s
\n" % terminfo Chris@0: doc += htmlDocInfo(t) Chris@0: doc += "

[back to top]

\n\n" Chris@0: doc += "\n\n
\n\n" Chris@0: Chris@0: return doc Chris@0: Chris@0: Chris@0: def getShortName(uri): Chris@0: if ("#" in uri): Chris@0: return uri.split("#")[-1] Chris@0: else: Chris@0: return uri.split("/")[-1] Chris@0: Chris@0: Chris@0: def getAnchor(uri): Chris@0: if (uri.startswith(spec_url)): Chris@0: return uri[len(spec_url):].replace("/","_") Chris@0: else: Chris@0: return getShortName(uri) Chris@0: Chris@0: Chris@0: def buildazlist(classlist, proplist, instalist=None): Chris@0: """ Chris@0: Builds the A-Z list of terms. Args are a list of classes (strings) and Chris@0: a list of props (strings) Chris@0: """ Chris@0: azlist = '
' Chris@0: Chris@0: if (len(classlist)>0): Chris@0: azlist += "

Classes: " Chris@0: classlist.sort() Chris@0: for c in classlist: Chris@0: if c.startswith(spec_url): Chris@0: c = c.split(spec_url[-1])[1] Chris@0: azlist = """%s %s, """ % (azlist, c, c) Chris@0: azlist = """%s\n

""" % azlist Chris@0: Chris@0: if (len(proplist)>0): Chris@0: azlist += "

Properties: " Chris@0: proplist.sort() Chris@0: for p in proplist: Chris@0: if p.startswith(spec_url): Chris@0: p = p.split(spec_url[-1])[1] Chris@0: azlist = """%s %s, """ % (azlist, p, p) Chris@0: azlist = """%s\n

""" % azlist Chris@0: Chris@0: if (instalist!=None and len(instalist)>0): Chris@0: azlist += "

Instances: " Chris@0: for i in instalist: Chris@0: p = getShortName(i) Chris@0: anchor = getAnchor(i) Chris@0: azlist = """%s %s, """ % (azlist, anchor, p) Chris@0: azlist = """%s\n

""" % azlist Chris@0: Chris@0: azlist = """%s\n
""" % azlist Chris@0: return azlist Chris@0: Chris@0: Chris@0: def build_simple_list(classlist, proplist, instalist=None): Chris@0: """ Chris@0: Builds a simple
    A-Z list of terms. Args are a list of classes (strings) and Chris@0: a list of props (strings) Chris@0: """ Chris@0: Chris@0: azlist = """
    """ Chris@0: azlist = """%s\n

    Classes:""" % azlist Chris@0: azlist += """\n

      """ Chris@0: Chris@0: classlist.sort() Chris@0: for c in classlist: Chris@0: azlist += """\n
    • %s
    • """ % (c.replace(" ", ""), c) Chris@0: azlist = """%s\n

    """ % azlist Chris@0: Chris@0: azlist = """%s\n

    Properties:""" % azlist Chris@0: azlist += """\n

      """ Chris@0: proplist.sort() Chris@0: for p in proplist: Chris@0: azlist += """\n
    • %s
    • """ % (p.replace(" ", ""), p) Chris@0: azlist = """%s\n

    """ % azlist Chris@0: Chris@0: #FIXME: instances Chris@0: Chris@0: azlist = """%s\n
    """ % azlist Chris@0: return azlist Chris@0: Chris@0: Chris@0: def add(where, key, value): Chris@0: if not where.has_key(key): Chris@0: where[key] = [] Chris@0: if not value in where[key]: Chris@0: where[key].append(value) Chris@0: Chris@0: Chris@0: def specInformation(m, ns): Chris@0: """ Chris@0: Read through the spec (provided as a Redland model) and return classlist Chris@0: and proplist. Global variables classranges and classdomains are also filled Chris@0: as appropriate. Chris@0: """ Chris@0: global classranges Chris@0: global classdomains Chris@0: Chris@0: # Find the class information: Ranges, domains, and list of all names. Chris@0: classtypes = [rdfs.Class, owl.Class] Chris@0: classlist = [] Chris@0: for onetype in classtypes: Chris@0: for classStatement in m.find_statements(RDF.Statement(None, rdf.type, onetype)): Chris@0: for range in m.find_statements(RDF.Statement(None, rdfs.range, classStatement.subject)): Chris@0: if not m.contains_statement( RDF.Statement( range.subject, rdf.type, owl.DeprecatedProperty )): Chris@0: if not classStatement.subject.is_blank(): Chris@0: add(classranges, str(classStatement.subject.uri), str(range.subject.uri)) Chris@0: for domain in m.find_statements(RDF.Statement(None, rdfs.domain, classStatement.subject)): Chris@0: if not m.contains_statement( RDF.Statement( domain.subject, rdf.type, owl.DeprecatedProperty )): Chris@0: if not classStatement.subject.is_blank(): Chris@0: add(classdomains, str(classStatement.subject.uri), str(domain.subject.uri)) Chris@0: if not classStatement.subject.is_blank(): Chris@0: uri = str(classStatement.subject.uri) Chris@0: name = return_name(m, classStatement.subject) Chris@0: if name not in classlist and uri.startswith(spec_url): Chris@0: classlist.append(return_name(m, classStatement.subject)) Chris@0: Chris@0: # Create a list of properties in the schema. Chris@0: proptypes = [rdf.Property, owl.ObjectProperty, owl.DatatypeProperty, owl.AnnotationProperty] Chris@0: proplist = [] Chris@0: for onetype in proptypes: Chris@0: for propertyStatement in m.find_statements(RDF.Statement(None, rdf.type, onetype)): Chris@0: uri = str(propertyStatement.subject.uri) Chris@0: name = return_name(m, propertyStatement.subject) Chris@0: if uri.startswith(ns) and not name in proplist: Chris@0: proplist.append(name) Chris@0: Chris@0: return classlist, proplist Chris@0: Chris@0: def getInstances(model, classes, properties): Chris@0: """ Chris@0: Extract all resources instanced in the ontology Chris@0: (aka "everything that is not a class or a property") Chris@0: """ Chris@0: instances = [] Chris@0: for one in classes: Chris@0: for i in model.find_statements(RDF.Statement(None, rdf.type, spec_ns[one])): Chris@0: uri = str(i.subject.uri) Chris@0: if not uri in instances: Chris@0: instances.append(uri) Chris@0: for i in model.find_statements(RDF.Statement(None, rdfs.isDefinedBy, RDF.Uri(spec_url))): Chris@0: uri = str(i.subject.uri) Chris@0: if (uri.startswith(spec_url)): Chris@0: uri = uri[len(spec_url):] Chris@0: if ((not uri in instances) and (not uri in classes)): Chris@0: instances.append(uri) Chris@0: return instances Chris@0: Chris@0: Chris@0: def specgen(specloc, template, instances=False, mode="spec"): Chris@0: """The meat and potatoes: Everything starts here.""" Chris@0: Chris@0: global spec_url Chris@0: global spec_ns Chris@0: global ns_list Chris@0: Chris@0: m = RDF.Model() Chris@0: p = RDF.Parser() Chris@0: try: Chris@0: p.parse_into_model(m, specloc) Chris@0: except IOError, e: Chris@0: print "Error reading from ontology:", str(e) Chris@0: usage() Chris@0: except RDF.RedlandError, e: Chris@0: print "Error parsing the ontology" Chris@0: Chris@0: spec_url = getOntologyNS(m) Chris@0: spec_ns = RDF.NS(spec_url) Chris@0: ns_list[spec_url] = spec_pre Chris@0: Chris@0: classlist, proplist = specInformation(m, spec_url) Chris@0: classlist = sorted(classlist) Chris@0: proplist = sorted(proplist) Chris@0: Chris@0: instalist = None Chris@0: if instances: Chris@0: instalist = getInstances(m, classlist, proplist) Chris@0: instalist.sort(lambda x, y: cmp(getShortName(x).lower(), getShortName(y).lower())) Chris@0: Chris@0: if mode == "spec": Chris@0: # Build HTML list of terms. Chris@0: azlist = buildazlist(classlist, proplist, instalist) Chris@0: elif mode == "list": Chris@0: # Build simple
      list of terms. Chris@0: azlist = build_simple_list(classlist, proplist, instalist) Chris@0: Chris@0: # Generate Term HTML Chris@0: termlist = docTerms('Property', proplist, m) Chris@0: termlist = docTerms('Class', classlist, m) + termlist Chris@0: if instances: Chris@0: termlist += docTerms('Instance', instalist, m) Chris@0: Chris@0: # Generate RDF from original namespace. Chris@0: u = urllib.urlopen(specloc) Chris@0: rdfdata = u.read() Chris@0: rdfdata = re.sub(r"(<\?xml version.*\?>)", "", rdfdata) Chris@0: rdfdata = re.sub(r"()", "", rdfdata) Chris@0: #rdfdata.replace("""""", "") Chris@0: Chris@0: # print template % (azlist.encode("utf-8"), termlist.encode("utf-8"), rdfdata.encode("ISO-8859-1")) Chris@0: template = re.sub(r"^#format \w*\n", "", template) Chris@0: template = re.sub(r"\$VersionInfo\$", owlVersionInfo(m).encode("utf-8"), template) Chris@0: Chris@0: # NOTE: This works with the assumtpion that all "%" in the template are escaped to "%%" and it Chris@0: # contains the same number of "%s" as the number of parameters in % ( ...parameters here... ) Chris@0: template = template % (azlist, termlist.encode("utf-8")); Chris@0: template += "" Chris@0: Chris@0: return template Chris@0: Chris@0: Chris@0: def save(path, text): Chris@0: try: Chris@0: f = open(path, "w") Chris@0: f.write(text) Chris@0: f.flush() Chris@0: f.close() Chris@0: except Exception, e: Chris@0: print "Error writting in file \"" + path + "\": " + str(e) Chris@0: Chris@0: Chris@0: def getOntologyNS(m): Chris@0: ns = None Chris@0: o = m.find_statements(RDF.Statement(None, rdf.type, owl.Ontology)) Chris@0: if o.current(): Chris@0: s = o.current().subject Chris@0: if (not s.is_blank()): Chris@0: ns = str(s.uri) Chris@0: if (ns[-1]!="/" and ns[-1]!="#"): Chris@0: ns += "#" Chris@0: Chris@0: if (ns == None): Chris@0: sys.exit("Impossible to get ontology's namespace") Chris@0: else: Chris@0: return ns Chris@0: Chris@0: Chris@0: def __getScriptPath(): Chris@0: path = sys.argv[0] Chris@0: if path.startswith("./"): Chris@0: return path Chris@0: else: Chris@0: base = "/".join(path.split("/")[:-1]) Chris@0: for one in os.environ["PATH"].split(":"): Chris@0: if base == one: Chris@0: return path.split("/")[-1] Chris@0: return path Chris@0: Chris@0: Chris@0: def usage(): Chris@0: script = __getScriptPath() Chris@0: print """Usage: Chris@0: %s ontology prefix template destination [flags] Chris@0: Chris@0: ontology : path to ontology file Chris@0: prefix : prefix for CURIEs Chris@0: template : HTML template path Chris@0: destination : specification destination (by default) Chris@0: Chris@0: optional flags: Chris@0: -i : add instances on the specification (disabled by default) Chris@0: Chris@0: examples: Chris@0: %s example.owl ex template.html example.owl.html -i Chris@0: Chris@0: """ % (script, script) Chris@0: sys.exit(-1) Chris@0: Chris@0: if __name__ == "__main__": Chris@0: """Ontology specification generator tool""" Chris@0: Chris@0: args = sys.argv[1:] Chris@0: if (len(args) < 4): Chris@0: usage() Chris@0: else: Chris@0: Chris@0: #ontology Chris@0: specloc = "file:" + str(args[0]) Chris@0: spec_pre = args[1] Chris@0: Chris@0: #template Chris@0: temploc = args[2] Chris@0: template = None Chris@0: try: Chris@0: f = open(temploc, "r") Chris@0: template = f.read() Chris@0: except Exception, e: Chris@0: print "Error reading from template \"" + temploc + "\": " + str(e) Chris@0: usage() Chris@0: Chris@0: #destination Chris@0: dest = args[3] Chris@0: Chris@0: #flags Chris@0: instances = False Chris@0: if len(args) > 3: Chris@0: flags = args[3:] Chris@0: if '-i' in flags: Chris@0: instances = True Chris@0: Chris@0: save(dest, specgen(specloc, template, instances=instances)) Chris@0: