import sys
import re
import urllib
import RDF
foaf = RDF.NS("http://xmlns.com/foaf/0.1/")
dc = RDF.NS('http://purl.org/dc/elements/1.1/')
rdf = RDF.NS('http://www.w3.org/1999/02/22-rdf-syntax-ns#')
rdfs = RDF.NS('http://www.w3.org/2000/01/rdf-schema#')
owl = RDF.NS('http://www.w3.org/2002/07/owl#')
vs = RDF.NS('http://www.w3.org/2003/06/sw-vocab-status/ns#')
classranges = {}
classdomains = {}
def termlink(string):
"""FOAF specific: function which replaces foaf:*
with a
link to the term in the document."""
return re.sub(r"foaf:(\w+)
", r"""foaf:\1
""", string)
def return_name(m, urinode):
"Trims the FOAF namespace out of a term to give a name to the term."
return str(urinode.uri).replace("http://xmlns.com/foaf/0.1/", "")
def get_rdfs(m, urinode):
"Returns label and comment given an RDF.Node with a URI in it"
l = m.find_statements(RDF.Statement(urinode, rdfs.label, None))
label = l.current().object.literal_value['string']
c = m.find_statements(RDF.Statement(urinode, rdfs.comment, None))
comment = c.current().object.literal_value['string']
return label, comment
def get_status(m, urinode):
"Returns the status text for a term."
s = m.find_statements(RDF.Statement(urinode, vs.term_status, None))
return s.current().object.literal_value['string']
def htmlDocInfo( t, termdir="../doc" ):
"""Opens a file based on the term name (t) and termdir (defaults to
current directory. Reads in the file, and returns a linkified
version of it."""
doc = ""
try:
f = open("%s/%s.en" % (termdir, t), "r")
doc = f.read()
doc = termlink(doc)
except:
return "
No detailed documentation for this term.
"
return doc
def rdfsPropertyInfo(term,m):
"""Generate HTML for properties: Domain, range, status."""
doc = ""
range = ""
domain = ""
# domain and range stuff (properties only)
d = m.find_statements(RDF.Statement(term, rdfs.domain, None))
if d.current():
domain = d.current().object.uri
domain = str(domain)
else:
domain = ""
r = m.find_statements(RDF.Statement(term, rdfs.range, None))
if r.current():
range = r.current().object.uri
range = str(range)
if domain:
if ("http://xmlns.com/foaf/0.1/" in domain):
domain = domain.replace("http://xmlns.com/foaf/0.1/", "")
domain = """foaf:%s""" % (domain, domain)
doc += "\tDomain: | \n\t%s |
\n" % domain
if range:
if ("http://xmlns.com/foaf/0.1/" in range):
range = range.replace("http://xmlns.com/foaf/0.1/", "")
range = """foaf:%s""" % (range, range)
doc += "\tRange: | \n\t%s |
\n" % range
return doc
def rdfsClassInfo(term,m):
"""Generate rdfs-type information for Classes: ranges, and domains."""
global classranges
global classdomains
doc = ""
# Find out about properties which have rdfs:range of t
r = classranges.get(str(term.uri), "")
if r:
rlist = ''
for k in r:
kname = k
if ("http://xmlns.com/foaf/0.1/" in k):
k = k.replace("http://xmlns.com/foaf/0.1/", "")
k = """foaf:%s""" % (k, k)
rlist += "%s " % k
doc += "in-range-of: | "+rlist+" |
"
# Find out about properties which have rdfs:domain of t
d = classdomains.get(str(term.uri), "")
if d:
dlist = ''
for k in d:
kname = k
if ("http://xmlns.com/foaf/0.1/" in k):
k = k.replace("http://xmlns.com/foaf/0.1/", "")
k = """foaf:%s""" % (k, k)
dlist += "%s " % k
doc += "in-domain-of: | "+dlist+" |
"
return doc
def owlInfo(term,m):
"""Returns an extra table row if the term (an RDF.Node()) is an IFP."""
o = m.find_statements(RDF.Statement(term, rdf.type, owl.InverseFunctionalProperty))
if o.current():
return("\tOWL Type: | \n\tAn InverseFunctionalProperty (uniquely identifying property) |
\n")
return ''
def docTerms(category, list, m):
"""A wrapper class for listing all the terms in a specific class (either
Properties, or Classes. Category is 'Property' or 'Class', list is a
list of term names (strings), return value is a chunk of HTML."""
doc = ""
nspre = "foaf"
for t in list:
term = foaf[t]
doc += """
\n
%s: %s:%s
\n""" % (t, category, nspre, t)
label, comment = get_rdfs(m, term)
status = get_status(m, term)
doc += "
%s - %s
" % (label, comment)
doc += """
\n\tStatus: | \n\t%s |
\n""" % status
doc += owlInfo(term,m)
if category=='Property': doc += rdfsPropertyInfo(term,m)
if category=='Class': doc += rdfsClassInfo(term,m)
doc += "
\n"
doc += htmlDocInfo(t)
#danbri
doc += "
[#]
\n\n" % (return_name(m,term))
doc += "
[back to top]
\n\n"
doc += "\n
\n
\n\n"
return doc
def buildazlist(classlist, proplist):
"""Builds the A-Z list of terms. Args are a list of classes (strings) and
a list of props (strings)"""
azlist = """"""
azlist = """%s\n
Classes: |""" % azlist
classlist.sort()
for c in classlist:
azlist = """%s %s | """ % (azlist, c.replace(" ", ""), c)
azlist = """%s\n
""" % azlist
azlist = """%s\n
Properties: |""" % azlist
proplist.sort()
for p in proplist:
azlist = """%s %s | """ % (azlist, p.replace(" ", ""), p)
azlist = """%s\n
""" % azlist
azlist = """%s\n
""" % azlist
return azlist
def specInformation(m):
"""Read through the spec (provided as a Redland model) and return classlist
and proplist. Global variables classranges and classdomains are also filled
as appropriate."""
global classranges
global classdomains
# Find the class information: Ranges, domains, and list of all names.
classlist = []
for classStatement in m.find_statements(RDF.Statement(None, rdf.type, rdfs.Class)):
for range in m.find_statements(RDF.Statement(None, rdfs.range, classStatement.subject)):
classranges.setdefault(str(classStatement.subject.uri), []).append(str(range.subject.uri))
for domain in m.find_statements(RDF.Statement(None, rdfs.domain, classStatement.subject)):
classdomains.setdefault(str(classStatement.subject.uri), []).append(str(domain.subject.uri))
classlist.append(return_name(m, classStatement.subject))
# Create a list of properties in the schema.
proplist = []
for propertyStatement in m.find_statements(RDF.Statement(None, rdf.type, rdf.Property)):
proplist.append(return_name(m, propertyStatement.subject))
return classlist, proplist
def main(specloc = "file:index.rdf"):
"""The meat and potatoes: Everything starts here."""
m = RDF.Model()
p = RDF.Parser()
p.parse_into_model(m, specloc)
classlist, proplist = specInformation(m)
# Build HTML list of terms.
azlist = buildazlist(classlist, proplist)
# Generate Term HTML
termlist = "Classes and Properties (full detail)
"
termlist += ""
termlist += docTerms('Class',classlist,m)
termlist += docTerms('Property',proplist,m)
termlist += "
"
# Generate RDF from original namespace.
u = urllib.urlopen(specloc)
rdfdata = u.read()
rdfdata.replace("""""", "")
# wip.template is a template file for the spec, python-style % escapes
# for replaced sections.
f = open("../0.1/template.html", "r")
template = f.read()
print template % (azlist.encode("utf-8"), termlist.encode("utf-8"), rdfdata)
if __name__ == "__main__":
"""Specification generator tool, created for FOAF schema maintenance."""
if (len(sys.argv) >= 2):
main(sys.argv[1])
else:
main()