merging specgen inclusions by domel
authorHenry Story <henry.story@bblfish.net>
Tue, 04 Oct 2011 18:05:11 +0200
changeset 164 8e287b5c7efc
parent 163 d657b2d4ddf1 (current diff)
parent 160 711cb645c543 (diff)
child 165 fa002be8029e
merging specgen inclusions by domel
ontologies/cert.owl
ontologies/rsa.owl
--- a/ontologies/rdfa/cert.html	Mon Oct 03 15:24:47 2011 +0200
+++ b/ontologies/rdfa/cert.html	Tue Oct 04 18:05:11 2011 +0200
@@ -182,8 +182,8 @@
   			<td><span property="vs:term_status" >unstable</span></td></tr>
   			
   			<tr><th>Has sub class</th>
- <td>  <a href="#PublicKey">Public Key</a>
- <a href="#PrivateKey">Private Key</a>
+ <td>  <a href="#PrivateKey">Private Key</a>
+ <a href="#PublicKey">Public Key</a>
  </td></tr><tr><th colspan="2">OWL Class</th>
  <td>  </td></tr>
   			</table>
@@ -268,7 +268,7 @@
 <h3>Properties</h3>
  
 
-<div class="specterm" id="hex" about="http://www.w3.org/ns/auth/cert#hex" typeof="owl:InverseFunctionalProperty">
+<div class="specterm" id="hex" about="http://www.w3.org/ns/auth/cert#hex" typeof="owl:DatatypeProperty">
   			<h4>Property: http://www.w3.org/ns/auth/cert#:hex</h4> 
   			<em property="rdfs:label" >hex</em> - <span property="rdfs:comment" >An encoding of a positive integer (from 0 to infinity) as a hexadecimal string that makes it easy to read and/or fun to present on the web. 
 The purpose of this way of representing hexadecimals is to enable users to copy and paste hexadecimal notations as shown by most browsers, keychains or tools such as opensso, into their rdf representation of choice.There are a wide variety of ways in which such strings can be presented. One finds the following e1 dc d5 e1 00 8f 21 5e d5 cc 7c 7e c4 9c ad 86 64 aa dc 29 f2 8d d9 56 7f 31 b6 bd 1b fd b8 ee 51 0d 3c 84 59 a2 45 d2 13 59 2a 14 82 1a 0f 6e d3 d1 4a 2d a9 4c 7e db 90 07 fc f1 8d a3 8e 38 25 21 0a 32 c1 95 31 3c ba 56 cc 17 45 87 e1 eb fd 9f 0f 82 16 67 9f 67 fa 91 e4 0d 55 4e 52 c0 66 64 2f fe 98 8f ae f8 96 21 5e ea 38 9e 5c 4f 27 e2 48 ca ca f2 90 23 ad 99 4b cc 38 32 6d bf Or the same as the above, with ':' instead of spaces. We can't guarantee that these are the only ways such tools will present hexadecimals, so we are very lax. The letters can be uppercase or lowercase, or mixed.
@@ -278,8 +278,8 @@
   			<td><span property="vs:term_status" >unstable</span></td></tr>
   			
   			<tr><th colspan="2">Datatype Property</th>
- <td> <span rel="rdf:type" href="http://www.w3.org/2002/07/owl#DatatypeProperty"></span> </td></tr><tr><th colspan="2">Inverse Functional Property</th>
- <td>  </td></tr>
+ <td>  </td></tr><tr><th colspan="2">Inverse Functional Property</th>
+ <td> <span rel="rdf:type" href="http://www.w3.org/2002/07/owl#InverseFunctionalProperty"></span> </td></tr>
   			</table>
   			
   			<p style="float: right; font-size: small;">[<a href="#hex">#</a>] <!-- hex --> [<a href="#glance">back to top</a>]</p>
@@ -329,7 +329,7 @@
   			<p style="float: right; font-size: small;">[<a href="#public_key">#</a>] <!-- public_key --> [<a href="#glance">back to top</a>]</p>
   			<br/>
   			</div>
-<div class="specterm" id="decimal" about="http://www.w3.org/ns/auth/cert#decimal" typeof="owl:InverseFunctionalProperty">
+<div class="specterm" id="decimal" about="http://www.w3.org/ns/auth/cert#decimal" typeof="owl:DatatypeProperty">
   			<h4>Property: http://www.w3.org/ns/auth/cert#:decimal</h4> 
   			<em property="rdfs:label" >decimal</em> - <span property="rdfs:comment" >An encoding of an integer in base 10 notation. Use cert:int instead.</span> <br /><table style="float: top;">
   			<tr><th>Status:</th>
@@ -340,8 +340,8 @@
   			<tr><th>Range:</th>
  <td>  <span rel="rdfs:range" href="http://www.w3.org/2001/XMLSchema#string"><a href="http://www.w3.org/2001/XMLSchema#string">xsd:string</a></span>
  </td></tr><tr><th colspan="2">Datatype Property</th>
- <td> <span rel="rdf:type" href="http://www.w3.org/2002/07/owl#DatatypeProperty"></span> </td></tr><tr><th colspan="2">Inverse Functional Property</th>
- <td>  </td></tr>
+ <td>  </td></tr><tr><th colspan="2">Inverse Functional Property</th>
+ <td> <span rel="rdf:type" href="http://www.w3.org/2002/07/owl#InverseFunctionalProperty"></span> </td></tr>
   			</table>
   			
   			<p style="float: right; font-size: small;">[<a href="#decimal">#</a>] <!-- decimal --> [<a href="#glance">back to top</a>]</p>
@@ -358,7 +358,7 @@
 </div>
 
 <!-- dirty hack for specgen -->
-<span about="http://www.w3.org/ns/auth/cert#PGPCertificate" rel="owl:equivalentClass" href="http://xmlns.com/wot/0.1/PubKey"></span>
+<div style="display: none"><span about="http://www.w3.org/ns/auth/cert#PGPCertificate" rel="owl:equivalentClass" href="http://xmlns.com/wot/0.1/PubKey"></span></div>
 
 
 <h2 id="sec-ack">Acknowledgments</h2>
--- a/ontologies/rdfa/rsa.html	Mon Oct 03 15:24:47 2011 +0200
+++ b/ontologies/rdfa/rsa.html	Tue Oct 04 18:05:11 2011 +0200
@@ -64,7 +64,7 @@
 <ul>
 <li><a href="#sec-glance">The RSA Ontology at a glance</a></li>
 <li><a href="#sec-example">Examples</a></li>
-<li><a href="#sec-crossref">Cross-reference for Cert classes and properties</a></li>
+<li><a href="#sec-crossref">Cross-reference for classes and properties</a></li>
 <li><a href="#sec-ack">Acknowledgments</a></li>
 </ul>
 
@@ -102,7 +102,7 @@
 </div>
 
 <h2 id="sec-example">Examples</h2>
-<pre>@prefix cert: &lt;http://www.w3.org/ns/auth/cert#&gt; .
+<pre> @prefix cert: &lt;http://www.w3.org/ns/auth/cert#&gt; .
  @prefix rsa: &lt;http://www.w3.org/ns/auth/rsa#&gt; .
  @prefix foaf: &lt;http://xmlns.com/foaf/0.1/&gt; .
  @prefix : &lt;https://joe.example/profile#&gt; .
@@ -152,14 +152,14 @@
 </div>
 
 <!-- and this is the bulk of the vocab descriptions -->
-<div class="termlist"><h3>Classes and Properties (full detail)</h3>
+<div class="termlist">
 <div class='termdetails'><br />
 
-<h2>Classes</h2>
+<h3>Classes</h3>
  
 
 <div class="specterm" id="RSAKey" about="http://www.w3.org/ns/auth/rsa#RSAKey" typeof="owl:Class">
-  			<h3>Class: http://www.w3.org/ns/auth/rsa#:RSAKey</h3> 
+  			<h4>Class: http://www.w3.org/ns/auth/rsa#:RSAKey</h4> 
   			<em property="rdfs:label" >RSA Key</em> - <span property="rdfs:comment" >The union of the public and private components of an RSAKey. Usually those pieces are not kept together.</span> <br /><table style="float: top;">
   			<tr><th>Status:</th>
   			<td><span property="vs:term_status" >unstable</span></td></tr>
@@ -169,8 +169,8 @@
   			<tr><th>Sub class of</th>
  <td>  <span rel="rdfs:subClassOf" href="http://www.w3.org/ns/auth/cert#Key"><a href="http://www.w3.org/ns/auth/cert#Key">http://www.w3.org/ns/auth/cert#:Key</a></span>
  </td></tr><tr><th>Has sub class</th>
- <td>  <a href="#RSAPublicKey">RSA Public Key</a>
- <a href="#RSAPrivateKey">RSA Private Key</a>
+ <td>  <a href="#RSAPrivateKey">RSA Private Key</a>
+ <a href="#RSAPublicKey">RSA Public Key</a>
  </td></tr><tr><th colspan="2">OWL Class</th>
  <td>  </td></tr>
   			</table>
@@ -178,7 +178,7 @@
   			<p style="float: right; font-size: small;">[<a href="#RSAKey">#</a>] <!-- RSAKey --> [<a href="#glance">back to top</a>]</p>
   			<br/>
   			</div><div class="specterm" id="RSAPrivateKey" about="http://www.w3.org/ns/auth/rsa#RSAPrivateKey" typeof="owl:Class">
-  			<h3>Class: http://www.w3.org/ns/auth/rsa#:RSAPrivateKey</h3> 
+  			<h4>Class: http://www.w3.org/ns/auth/rsa#:RSAPrivateKey</h4> 
   			<em property="rdfs:label" >RSA Private Key</em> - <span property="rdfs:comment" >A Private Key in the RSA framework</span> <br /><table style="float: top;">
   			<tr><th>Status:</th>
   			<td><span property="vs:term_status" >unstable</span></td></tr>
@@ -195,7 +195,7 @@
   			<p style="float: right; font-size: small;">[<a href="#RSAPrivateKey">#</a>] <!-- RSAPrivateKey --> [<a href="#glance">back to top</a>]</p>
   			<br/>
   			</div><div class="specterm" id="RSAPublicKey" about="http://www.w3.org/ns/auth/rsa#RSAPublicKey" typeof="owl:Class">
-  			<h3>Class: http://www.w3.org/ns/auth/rsa#:RSAPublicKey</h3> 
+  			<h4>Class: http://www.w3.org/ns/auth/rsa#:RSAPublicKey</h4> 
   			<em property="rdfs:label" >RSA Public Key</em> - <span property="rdfs:comment" >The RSA public key. Padded message m are encrypted by applying the function modulus(power(m,exponent),modulus).</span> <br /><table style="float: top;">
   			<tr><th>Status:</th>
   			<td><span property="vs:term_status" >unstable</span></td></tr>
@@ -212,11 +212,11 @@
   			<p style="float: right; font-size: small;">[<a href="#RSAPublicKey">#</a>] <!-- RSAPublicKey --> [<a href="#glance">back to top</a>]</p>
   			<br/>
   			</div>
-<h2>Properties</h2>
+<h3>Properties</h3>
  
 
 <div class="specterm" id="modulus" about="http://www.w3.org/ns/auth/rsa#modulus" typeof="owl:ObjectProperty">
-  			<h3>Property: http://www.w3.org/ns/auth/rsa#:modulus</h3> 
+  			<h4>Property: http://www.w3.org/ns/auth/rsa#:modulus</h4> 
   			<em property="rdfs:label" >modulus</em> - <span property="rdfs:comment" >The modulus of an RSA public and private key. This is defined as n = p*q.</span> <br /><table style="float: top;">
   			<tr><th>Status:</th>
   			<td><span property="vs:term_status" >unstable</span></td></tr>
@@ -232,7 +232,7 @@
   			<p style="float: right; font-size: small;">[<a href="#modulus">#</a>] <!-- modulus --> [<a href="#glance">back to top</a>]</p>
   			<br/>
   			</div><div class="specterm" id="private_exponent" about="http://www.w3.org/ns/auth/rsa#private_exponent" typeof="owl:ObjectProperty">
-  			<h3>Property: http://www.w3.org/ns/auth/rsa#:private_exponent</h3> 
+  			<h4>Property: http://www.w3.org/ns/auth/rsa#:private_exponent</h4> 
   			<em property="rdfs:label" >private exponent</em> - <span property="rdfs:comment" > The exponent used to decrypt the message calculated as public_exponent*private_exponent = 1 modulo totient(p*q). The private exponent is often named 'd'</span> <br /><table style="float: top;">
   			<tr><th>Status:</th>
   			<td><span property="vs:term_status" >unstable</span></td></tr>
@@ -248,7 +248,7 @@
   			<p style="float: right; font-size: small;">[<a href="#private_exponent">#</a>] <!-- private_exponent --> [<a href="#glance">back to top</a>]</p>
   			<br/>
   			</div><div class="specterm" id="public_exponent" about="http://www.w3.org/ns/auth/rsa#public_exponent" typeof="owl:ObjectProperty">
-  			<h3>Property: http://www.w3.org/ns/auth/rsa#:public_exponent</h3> 
+  			<h4>Property: http://www.w3.org/ns/auth/rsa#:public_exponent</h4> 
   			<em property="rdfs:label" >public exponent</em> - <span property="rdfs:comment" >The exponent used to encrypt the message. Number chosen between 1 and the totient(p*q). Often named 'e'.</span> <br /><table style="float: top;">
   			<tr><th>Status:</th>
   			<td><span property="vs:term_status" >unstable</span></td></tr>
@@ -272,9 +272,13 @@
 </div>
 
 <!-- other ns classes -->
-<span class="specterm" id="PrivateKey" about="http://www.w3.org/ns/auth/cert#PrivateKey" typeof="owl:Class"><span property="rdfs:label" content="Private Key"></span></span>
-<span class="specterm" id="PublicKey" about="http://www.w3.org/ns/auth/cert#PublicKey" typeof="owl:Class"><span property="rdfs:label" content="Public Key"></span></span>
-<h3 id="sec-ack">Acknowledgments</h3>
+<h3>Other vocabularies terms</h3>
+<ul>
+<li class="specterm" id="PrivateKey" about="http://www.w3.org/ns/auth/cert#PrivateKey" typeof="owl:Class"><em property="rdfs:label" content="Private Key"><a href="http://www.w3.org/ns/auth/cert.html#PrivateKey">Private Key</a></em></li>
+<li class="specterm" id="PublicKey" about="http://www.w3.org/ns/auth/cert#PublicKey" typeof="owl:Class"><em property="rdfs:label" content="Public Key"><a href="http://www.w3.org/ns/auth/cert.html#PublicKey">Public Key</a></em></li>
+</ul>
+
+<h2 id="sec-ack">Acknowledgments</h2>
 
 <p>The following people have been instrumental in providing thoughts, feedback,
 reviews, criticism and input in the creation of this specification:</p>
--- a/ontologies/rdfa/template_cert.html	Mon Oct 03 15:24:47 2011 +0200
+++ b/ontologies/rdfa/template_cert.html	Tue Oct 04 18:05:11 2011 +0200
@@ -145,7 +145,7 @@
 %s
 
 <!-- dirty hack for specgen -->
-<span about="http://www.w3.org/ns/auth/cert#PGPCertificate" rel="owl:equivalentClass" href="http://xmlns.com/wot/0.1/PubKey"></span>
+<div style="display: none"><span about="http://www.w3.org/ns/auth/cert#PGPCertificate" rel="owl:equivalentClass" href="http://xmlns.com/wot/0.1/PubKey"></span></div>
 
 
 <h2 id="sec-ack">Acknowledgments</h2>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ontologies/specgen/README.TXT	Tue Oct 04 18:05:11 2011 +0200
@@ -0,0 +1,61 @@
+This is an experimental new codebase for specgen tools based on danbri's
+specgen5 version (http://svn.foaf-project.org/foaftown/specgen/).
+
+		heavily updated by Bob Ferris, July 2010
+		<http://smiy.wordpress.com/author/zazi0815/>
+		
+It depends utterly upon rdflib. See http://rdflib.net/
+		+ http://code.google.com/p/rdfextras/
+		+ http://pyparsing.wikispaces.com/ (easy_install pyparsing)
+		(at I had to install these packages additionally ;) )
+
+If you're lucky, typing this is enough: 
+					easy_install rdflib
+
+and if you have problems there, update easy_install etc with: 
+
+					easy_install -U setuptools
+
+Inputs: RDF, HTML and OWL description(s) of an RDF vocabulary
+Output: an XHTML+RDFa specification designed for human users
+
+example: specgen6.py --indir=onto/co/ --ns=http://purl.org/ontology/co/core# 
+--prefix=co --ontofile=counterontology.owl --outdir=spec/co/ --templatedir=onto/co/ 
+--outfile=counterontology.html
+
+See libvocab.py and specgen6.py for details.
+
+Status:
+
+ - we load up and interpret the core RDFS/OWL 
+ - we populate Vocab, Term (Class or Property) instances
+ - able to generate a XHTML/RDFa ontology specification with common concepts and properties from OWL, RDFS, RDF
+
+TODO:
+ - enable more OWL features, especially an automated construction of owl:Ontology (currently this must be
+   done manually in the template)
+ - enable more support for other namespaces (super classes and super properties from other namespaces already possible)
+ - restructure the code !!!
+ - write a cool parser for the "\n"'s and "\t"'s etc. in the parsed comments (e.g. "\n" to <br/> ...)
+
+
+ISSUES
+
+1. librdf doesn't seem to like abbreviations in FILTER clauses.
+this worked:
+
+q= 'SELECT ?x ?l ?c ?type WHERE { ?x rdfs:label ?l . ?x rdfs:comment ?c . ?x a ?type .  FILTER (?type = <http://www.w3.org/2002/07/owl#ObjectProperty>)  } '
+
+while this failed:
+
+q= 'PREFIX owl: <http://www.w3.org/2002/07/owl#> SELECT ?x ?l ?c ?type WHERE { ?x rdfs:label ?l . ?x rdfs:comment ?c . ?x a ?type .  FILTER (?type = owl:ObjectProperty)  } '
+
+(even when passing in bindings)
+
+This forces us to be verbose, ie.
+q= 'SELECT distinct ?x ?l ?c WHERE { ?x rdfs:label ?l . ?x rdfs:comment ?c . ?x a ?type . FILTER (?type = <http://www.w3.org/2002/07/owl#ObjectProperty> || ?type = <http://www.w3.org/2002/07/owl#DatatypeProperty> || ?type = <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> || ?type = <http://www.w3.org/2002/07/owl#FunctionalProperty> || ?type = <http://www.w3.org/2002/07/owl#InverseFunctionalProperty>) } '
+
+2. TODO: work out how to do ".encode('UTF-8')" everywhere
+
+3. Be more explicit and careful re defaulting to English, and more robust when
+multilingual labels are found.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ontologies/specgen/libvocab.py	Tue Oct 04 18:05:11 2011 +0200
@@ -0,0 +1,1201 @@
+#!/usr/bin/env python
+
+# total rewrite. --danbri
+#
+# modifications and extensions: Bob Ferris, July 2010
+#		+ multiple property and class types 
+#		+ muttiple restrictions modelling
+#		+ rdfs:label, rdfs:comment
+#		+ classes and properties from other namespaces
+#		+ inverse properties (explicit and anonymous)
+#		+ sub properties
+#
+#		Copyright 2010 Bob Ferris <http://smiy.wordpress.com/author/zazi0815/>
+#
+# Usage:
+#
+# >>> from libvocab import Vocab, Term, Class, Property
+#
+# >>> from libvocab import Vocab, Term, Class, Property
+# >>> v = Vocab( f='examples/foaf/index.rdf', uri='http://xmlns.com/foaf/0.1/')
+# >>> dna = v.lookup('http://xmlns.com/foaf/0.1/dnaChecksum')
+# >>> dna.label
+#     'DNA checksum'
+# >>> dna.comment
+#     'A checksum for the DNA of some thing. Joke.'
+# >>> dna.id
+#     u'dnaChecksum'
+# >>> dna.uri
+#     'http://xmlns.com/foaf/0.1/dnaChecksum'
+#
+#
+# Python OO notes:
+# http://www.devshed.com/c/a/Python/Object-Oriented-Programming-With-Python-part-1/
+# http://www.daniweb.com/code/snippet354.html
+# http://docs.python.org/reference/datamodel.html#specialnames
+#
+# RDFlib:
+# http://www.science.uva.nl/research/air/wiki/RDFlib
+#
+# http://dowhatimean.net/2006/03/spellchecking-vocabularies-with-sparql
+#
+# We define basics, Vocab, Term, Property, Class
+# and populate them with data from RDF schemas, OWL, translations ... and nearby html files.
+
+import rdflib
+
+from rdflib import term
+
+from rdflib.namespace import Namespace
+from rdflib.graph import Graph, ConjunctiveGraph
+
+rdflib.plugin.register('sparql', rdflib.query.Processor,
+	'rdfextras.sparql.processor', 'Processor')
+rdflib.plugin.register('sparql', rdflib.query.Result,
+	'rdfextras.sparql.query', 'SPARQLQueryResult')
+
+# pre3: from rdflib.sparql.sparqlGraph  import SPARQLGraph
+#from rdflib.sparql.graphPattern import GraphPattern
+#from rdflib.sparql import Query 
+
+CO = Namespace('http://purl.org/ontology/co/core#')
+FOAF = Namespace('http://xmlns.com/foaf/0.1/')
+RDFS = Namespace('http://www.w3.org/2000/01/rdf-schema#')
+XFN = Namespace("http://gmpg.org/xfn/1#")
+RDF = Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
+OWL = Namespace('http://www.w3.org/2002/07/owl#')
+VS = Namespace('http://www.w3.org/2003/06/sw-vocab-status/ns#')
+DC = Namespace('http://purl.org/dc/elements/1.1/')
+DOAP = Namespace('http://usefulinc.com/ns/doap#')
+SIOC = Namespace('http://rdfs.org/sioc/ns#')
+SIOCTYPES = Namespace('http://rdfs.org/sioc/types#')
+SIOCSERVICES = Namespace('http://rdfs.org/sioc/services#')
+#
+# TODO: rationalise these two lists. or at least check they are same.
+
+
+import sys, time, re, urllib, getopt
+import logging
+import os.path
+import cgi
+import operator
+
+def speclog(str):
+	sys.stderr.write("LOG: " + str + "\n")
+
+# todo: shouldn't be foaf specific
+def termlink(text):
+	result = re.sub(r"<code>foaf:(\w+)<\/code>", r"<code><a href='#term_\g<1>'>\g<1></a></code>", text)
+	return result
+
+# a Term has... (intrinsically and via it's RDFS/OWL description)
+# uri - a (primary) URI, eg. 'http://xmlns.com/foaf/0.1/workplaceHomepage'
+# id - a local-to-spec ID, eg. 'workplaceHomepage'
+# ns - an ns URI (isDefinedBy, eg. 'http://xmlns.com/foaf/0.1/')
+# 
+# label  - an rdfs:label 
+# comment - an rdfs:comment
+#
+# Beyond this, properties vary. Some have vs:term_status. Some have owl Deprecated.
+# Some have OWL descriptions, and RDFS descriptions; eg. property range/domain
+# or class disjointness.
+
+def ns_split(uri):
+	regexp = re.compile("^(.*[/#])([^/#]+)$")
+	rez = regexp.search(uri)
+	return(rez.group(1), rez.group(2))
+
+
+
+class Term(object):
+
+	def __init__(self, uri = 'file://dev/null'):
+		self.uri = str(uri)
+		self.uri = self.uri.rstrip()
+
+	 	# speclog("Parsing URI " + uri)
+	 	a, b = ns_split(uri)
+	 	self.id = b
+	 	self.ns = a
+	 	# print "namspace ",a
+	 	if self.id == None:
+	 		speclog("Error parsing URI. " + uri)
+	 	if self.ns == None:
+	 		speclog("Error parsing URI. " + uri)
+	 	# print "self.id: "+ self.id + " self.ns: " + self.ns
+
+  	def uri(self):
+  		try:
+  			s = self.uri
+  		except NameError:
+  			self.uri = None
+  			s = '[NOURI]'
+  			speclog('No URI for' + self)
+  		return s
+
+  	def id(self):
+  		print "trying id"
+  		try:
+  			s = self.id
+  		except NameError:
+  			self.id = None
+  			s = '[NOID]'
+  			speclog('No ID for' + self)
+  		return str(s)
+
+  	def is_external(self, vocab):
+  		print "Comparing property URI ", self.uri, " with vocab uri: " + vocab.uri
+  		return(False)
+
+     #def __repr__(self):
+     #  return(self.__str__)
+
+  	def __str__(self):
+  		try:
+  			s = self.id
+  		except NameError:
+  			self.label = None
+  			speclog('No label for ' + self + ' todo: take from uri regex')
+  			s = (str(self))
+  		return(str(s))
+
+    # so we can treat this like a string 
+	def __add__(self, s):
+		return (s + str(self))
+
+  	def __radd__(self, s):
+  	 	return (s + str(self))
+
+  	def simple_report(self):
+  		t = self
+  		s = ''
+  		s += "default: \t\t" + t + "\n"
+  		s += "id:      \t\t" + t.id + "\n"
+  		s += "uri:     \t\t" + t.uri + "\n"
+  		s += "ns:   \t\t" + t.ns + "\n"
+  		s += "label:   \t\t" + t.label + "\n"
+  		s += "comment: \t\t" + t.comment + "\n"
+  		s += "status: \t\t" + t.status + "\n"
+  		s += "\n"
+  		return s
+
+
+  	def _get_status(self):
+  	 	try:
+  		  	return self._status
+  	  	except:
+  		  	return 'unknown'
+
+  	def _set_status(self, value):
+  	 	self._status = str(value)
+
+  	status = property(_get_status, _set_status)
+
+
+
+# a Python class representing an RDFS/OWL property.
+# 
+class Property(Term):
+
+	# OK OK but how are we SUPPOSED to do this stuff in Python OO?. Stopgap.
+	def is_property(self):
+		# print "Property.is_property called on "+self
+		return(True)
+
+  	def is_class(self):
+  	 	# print "Property.is_class called on "+self
+  	 	return(False)
+
+
+
+
+
+# A Python class representing an RDFS/OWL class
+#
+
+class Class(Term):
+
+	# OK OK but how are we SUPPOSED to do this stuff in Python OO?. Stopgap.
+	def is_property(self):
+		# print "Class.is_property called on "+self
+		return(False)
+
+  	def is_class(self):
+  		# print "Class.is_class called on "+self
+  		return(True)
+
+
+# A python class representing (a description of) some RDF vocabulary
+#
+class Vocab(object):
+
+	def __init__(self, dir, f = 'index.rdf', uri = None):
+		self.graph = ConjunctiveGraph()
+		self._uri = uri
+		self.dir = dir
+		self.filename = os.path.join(dir, f)
+		# print "ontology file name ", self.filename 
+		self.graph.parse(self.filename)
+		self.terms = []
+		self.uterms = []
+		# should also load translations here?
+		# and deal with a base-dir?
+
+		##if f != None:    
+		##  self.index()
+		self.ns_list = { "http://www.w3.org/1999/02/22-rdf-syntax-ns#"   : "rdf",
+					"http://www.w3.org/2000/01/rdf-schema#"         : "rdfs",
+					"http://www.w3.org/2002/07/owl#"                : "owl",
+					"http://www.w3.org/2001/XMLSchema#"             : "xsd",
+					"http://rdfs.org/sioc/ns#"                      : "sioc",
+					"http://xmlns.com/foaf/0.1/"                    : "foaf",
+					"http://purl.org/dc/elements/1.1/"              : "dc",
+					"http://purl.org/dc/terms/"                     : "dcterms",
+					"http://usefulinc.com/ns/doap#"                 : "doap",
+					"http://www.w3.org/2003/06/sw-vocab-status/ns#" : "vs",
+					"http://purl.org/rss/1.0/modules/content/"      : "content",
+					"http://www.w3.org/2003/01/geo/wgs84_pos#"      : "geo",
+					"http://www.w3.org/2004/02/skos/core#"          : "skos",
+					"http://purl.org/NET/c4dm/event.owl#"           : "event",
+					"http://purl.org/ontology/co/core#"             : "co",
+					"http://purl.org/ontology/olo/core#"            : "olo",
+					"http://purl.org/ontology/is/core#"             : "is"
+		}
+
+
+
+  	def addShortName(self, sn):
+  		self.ns_list[self._uri] = sn
+  		self.shortName = sn
+  		#print self.ns_list
+
+  	# not currently used
+  	def unique_terms(self):
+  		tmp = []
+  		for t in list(set(self.terms)):
+  			s = str(t)
+  			if (not s in tmp):
+  				self.uterms.append(t)
+  				tmp.append(s)
+
+  	# TODO: python question - can we skip needing getters? and only define setters. i tried/failed. --danbri
+  	def _get_uri(self):
+  	  	return self._uri
+
+  	def _set_uri(self, value):
+  		v = str(value) # we don't want Namespace() objects and suchlike, but we can use them without whining.
+  		if ':' not in v:
+  			speclog("Warning: this doesn't look like a URI: " + v)
+  			# raise Exception("This doesn't look like a URI.")
+  		self._uri = str(value)
+
+  		uri = property(_get_uri, _set_uri)
+
+  	def set_filename(self, filename):
+  		self.filename = filename
+
+  	# TODO: be explicit if/where we default to English
+  	# TODO: do we need a separate index(), versus just use __init__ ?
+  	def index(self):
+  		#    speclog("Indexing description of "+str(self))
+  		# blank down anything we learned already
+
+  		self.terms = []
+  		self.properties = []
+  		self.classes = []
+  		tmpclasses = []
+  		tmpproperties = []
+
+  		g = self.graph
+  		# extend query for different property types 
+  		query = 'SELECT ?x ?l ?c ?t WHERE { ?x rdfs:label ?l . ?x rdfs:comment ?c . ?x rdf:type ?t . ?x a ?type FILTER (?type = <http://www.w3.org/2002/07/owl#ObjectProperty> || ?type = <http://www.w3.org/2002/07/owl#DatatypeProperty> || ?type = <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> || ?type = <http://www.w3.org/2002/07/owl#FunctionalProperty> || ?type = <http://www.w3.org/2002/07/owl#InverseFunctionalProperty>) }'
+
+  		relations = g.query(query)
+  		for (term, label, comment, type) in relations:
+  			p = Property(term)
+  			# print "Made a property! "+str(p) + " using label: "+str(label)
+  			p.label = str(label)
+  			p.comment = str(comment)
+  			p.type = self.niceName(type)
+  			self.terms.append(p)
+  			if (not str(p) in tmpproperties):
+  				tmpproperties.append(str(p))
+  				self.properties.append(p)
+
+  		query = 'SELECT ?x ?l ?c ?t WHERE { ?x rdfs:label ?l . ?x rdfs:comment ?c . ?x rdf:type ?t . ?x a ?type  FILTER (?type = <http://www.w3.org/2002/07/owl#Class> || ?type = <http://www.w3.org/2000/01/rdf-schema#Class> ) }'
+  		relations = g.query(query)
+  		for (term, label, comment, type) in relations:
+  			c = Class(term)
+  			# print "Made a class! "+str(c) + " using comment: "+comment
+  			c.label = str(label)
+  			c.comment = str(comment)
+  			c.type = self.niceName(type)
+  			self.terms.append(c)
+  			if (not str(c) in tmpclasses):
+  				self.classes.append(c)
+  				tmpclasses.append(str(c))
+
+  		self.terms.sort(key = operator.attrgetter('id'))
+  		self.classes.sort(key = operator.attrgetter('id'))
+  		self.properties.sort(key = operator.attrgetter('id'))
+
+  		# http://www.w3.org/2003/06/sw-vocab-status/ns#"
+  		query = 'SELECT ?x ?vs WHERE { ?x <http://www.w3.org/2003/06/sw-vocab-status/ns#term_status> ?vs }'
+  		status = g.query(query)
+  		# print "status results: ",status.__len__()
+  		for x, vs in status:
+  			#print "STATUS: ",vs, " for ",x
+  			t = self.lookup(x)
+  			if t != None:
+  				t.status = vs
+  				# print "Set status.", t.status
+  			else:
+  				speclog("Couldn't lookup term: " + x)
+
+#    self.terms.sort()   # does this even do anything? 
+#    self.classes.sort()
+#    self.properties.sort()
+   	# todo, use a dictionary index instead. RTFM.
+   	def lookup(self, uri):
+   		uri = str(uri)
+   		for t in self.terms:
+   			# print "Lookup: comparing '"+t.uri+"' to '"+uri+"'"
+   			# print "type of t.uri is ",t.uri.__class__
+   			if t.uri == uri:
+   				# print "Matched."  # should we str here, to be more liberal?
+   				return t
+   			else:
+   				# print "Fail."
+   				''
+   		return None
+
+   	# print a raw debug summary, direct from the RDF
+   	def raw(self):
+   		g = self.graph
+   		query = 'SELECT ?x ?l ?c WHERE { ?x rdfs:label ?l . ?x rdfs:comment ?c  } '
+   		relations = g.query(query)
+   		print "Properties and Classes (%d terms)" % len(relations)
+   		print 40 * "-"
+   		for (term, label, comment) in relations:
+   			print "term %s l: %s \t\tc: %s " % (term, label, comment)
+   		print
+
+   		# TODO: work out how to do ".encode('UTF-8')" here
+
+   	# for debugging only
+   	def detect_types(self):
+   		self.properties = []
+   		self.classes = []
+   		for t in self.terms:
+   			# print "Doing t: "+t+" which is of type " + str(t.__class__)
+   			if t.is_property():
+   				# print "is_property."
+   				self.properties.append(t)
+   			if t.is_class():
+   				# print "is_class."
+   				self.classes.append(t)
+
+
+# CODE FROM ORIGINAL specgen:
+
+
+  	def niceName(self, uri = None):
+  		if uri is None:
+  			return
+  		# speclog("Nicing uri "+uri)
+  		regexp = re.compile("^(.*[/#])([^/#]+)$")
+  		rez = regexp.search(uri)
+  		if rez == None:
+  			#print "Failed to niceName. Returning the whole thing."
+  			return(uri)
+  		pref = rez.group(1)
+  		# print "...",self.ns_list.get(pref, pref),":",rez.group(2)
+  		# todo: make this work when uri doesn't match the regex --danbri
+  		# AttributeError: 'NoneType' object has no attribute 'group'
+  		return self.ns_list.get(pref, pref) + ":" + rez.group(2)
+
+
+  	# HTML stuff, should be a separate class
+
+  	def azlist(self):
+  		"""Builds the A-Z list of terms"""
+  		c_ids = []
+  		p_ids = []
+  		for p in self.properties:
+  			p_ids.append(str(p.id))
+  		for c in self.classes:
+  			c_ids.append(str(c.id))
+  		c_ids.sort()
+  		p_ids.sort()
+  		return (c_ids, p_ids)
+
+
+
+class VocabReport(object):
+
+	def __init__(self, vocab, basedir = './examples/', temploc = 'template.html', templatedir = './examples/'):
+		self.vocab = vocab
+		self.basedir = basedir
+		self.temploc = temploc
+		self.templatedir = templatedir
+
+		self._template = "no template loaded"
+
+	# text.gsub(/<code>foaf:(\w+)<\/code>/){ defurl($1) } return "<code><a href=\"#term_#{term}\">foaf:#{term}</a></code>"
+   	def codelink(self, s):
+   		reg1 = re.compile(r"""<code>foaf:(\w+)<\/code>""")
+   		return(re.sub(reg1, r"""<code><a href="#\1">foaf:\1</a></code>""", s))
+
+  	def _get_template(self):
+  		self._template = self.load_template() # should be conditional
+  		return self._template
+
+  	def _set_template(self, value):
+  		self._template = str(value)
+
+  	template = property(_get_template, _set_template)
+
+  	def load_template(self):
+  		filename = os.path.join(self.templatedir, self.temploc)
+
+  		f = open(filename, "r")
+  		template = f.read()
+  		return(template)
+
+  	def generate(self):
+  		tpl = self.template
+  		azlist = self.az()
+  		termlist = self.termlist()
+
+  		f = open (self.vocab.filename, "r")
+  		rdfdata = f.read()
+  		#   print "GENERATING >>>>>>>> "
+  		## having the rdf in there was making it invalid
+  		## removed in favour of RDFa
+  		##    tpl = tpl % (azlist.encode("utf-8"), termlist.encode("utf-8"), rdfdata)
+  		#
+  		# IMPORTANT: this is the code, which is responsible for write code fragments to the template
+  		tpl = tpl % (azlist.encode("utf-8"), azlist.encode("utf-8"), termlist.encode("utf-8"))
+  		#    tpl = tpl % (azlist.encode("utf-8"), termlist.encode("utf-8"))
+  		return(tpl)
+
+  	def az(self):
+  		"""AZ List for html doc"""
+  		c_ids, p_ids = self.vocab.azlist()
+  		az = """<div class="azlist">"""
+  		az = """%s\n<p>Classes: |""" % az
+  		# print c_ids, p_ids
+  		for c in c_ids:
+  			# speclog("Class "+c+" in az generation.")
+  			az = """%s <a href="#%s">%s</a> | """ % (az, str(c).replace(" ", ""), c)
+
+  		az = """%s\n</p>""" % az
+  		az = """%s\n<p>Properties: |""" % az
+  		for p in p_ids:
+  			# speclog("Property "+p+" in az generation.")
+  			az = """%s <a href="#%s">%s</a> | """ % (az, str(p).replace(" ", ""), p)
+  		az = """%s\n</p>""" % az
+  		az = """%s\n</div>""" % az
+  		return(az)
+
+  	def termlist(self):
+  		"""Term List for html doc"""
+  		stableTxt = ''
+  		testingTxt = ''
+  		unstableTxt = ''
+  		archaicTxt = ''
+
+  		queries = ''
+  		c_ids, p_ids = self.vocab.azlist()
+  		tl = """<div class="termlist">"""
+  		tl = """%s\n<div class='termdetails'><br />\n\n""" % tl
+
+
+  		# danbri hack 20100101 removed: href="http://www.w3.org/2003/06/sw-vocab-status/ns#%s" pending discussion w/ libby and leigh re URIs
+
+  		# first classes, then properties
+  		eg = """<div class="specterm" id="%s" about="%s" typeof="%s">
+  			<h4>%s: %s</h4> 
+  			<em property="rdfs:label" >%s</em> - <span property="rdfs:comment" >%s</span> <br /><table style="float: top;">
+  			<tr><th>Status:</th>
+  			<td><span property="vs:term_status" >%s</span></td></tr>
+  			%s
+  			%s
+  			</table>
+  			%s
+  			<p style="float: right; font-size: small;">[<a href="#%s">#</a>] <!-- %s --> [<a href="#glance">back to top</a>]</p>
+  			<br/>
+  			</div>"""
+
+  		# replace this if you want validation queries: xxx danbri
+  		#            <p style="float: right; font-size: small;">[<a href="#term_%s">permalink</a>] [<a href="#queries_%s">validation queries</a>] [<a href="#glance">back to top</a>]</p>
+
+  		# todo, push this into an api call (c_ids currently setup by az above)
+
+  		# classes
+  		for term in self.vocab.classes:
+  			# strings to use later
+  			domainsOfClass = ''
+  			rangesOfClass = ''
+
+  			#class in domain of -> only for classes included in this ontology specification
+  			g = self.vocab.graph
+
+  			q = 'SELECT ?d ?l WHERE {?d rdfs:domain <%s> . ?d rdfs:label ?l } ' % (term.uri)
+
+  			relations = g.query(q)
+  			startStr = '<tr><th>Properties include:</th>\n'
+
+  			contentStr = ''
+  			for (domain, label) in relations:
+  				dom = Term(domain)
+  				# danbri hack 20100101
+  				#          termStr = """<a href="#term_%s">%s</a>\n""" % (dom.id, label)
+  				termStr = """<a href="#%s">%s</a>\n""" % (dom.id, dom.id)
+  				contentStr = "%s %s" % (contentStr, termStr)
+
+  			if contentStr != "":
+  				domainsOfClass = "%s <td> %s </td></tr>" % (startStr, contentStr)
+
+
+  			# class in range of -> only for classes included in this ontology specification
+  			q2 = 'SELECT ?d ?l WHERE {?d rdfs:range <%s> . ?d rdfs:label ?l } ' % (term.uri)
+  			relations2 = g.query(q2)
+  			startStr = '<tr><th>Used with:</th>\n'
+
+  			contentStr = ''
+  			for (range, label) in relations2:
+  				ran = Term(range)
+  				#          termStr = """<a href="#term_%s">%s</a>\n""" % (ran.id, label)
+  				# danbri hack 20100101 better to use exact IDs here
+  				termStr = """<a href="#%s">%s</a>\n""" % (ran.id, ran.id)
+  				contentStr = "%s %s" % (contentStr, termStr)
+
+  			if contentStr != "":
+  				rangesOfClass = "%s <td> %s</td></tr> " % (startStr, contentStr)
+
+  			# class sub class of -> handles only "real" super classes
+  			subClassOf = ''
+  			restriction = ''
+
+  			q = 'SELECT ?sc ?l WHERE {<%s> rdfs:subClassOf ?sc . ?sc rdfs:label ?l } ' % (term.uri)
+
+  			relations = g.query(q)
+  			startStr = '<tr><th>Sub class of</th>\n'
+
+  			contentStr = ''
+  			contentStr2 = ''
+  			for (subclass, label) in relations:
+  				sub = Term(subclass)
+  				termStr = """<span rel="rdfs:subClassOf" href="%s"><a href="#%s">%s</a></span>\n""" % (subclass, sub.id, label)
+  				contentStr = "%s %s" % (contentStr, termStr)
+
+  			if contentStr != "":
+  				subClassOf = "%s <td> %s </td></tr>" % (startStr, contentStr)
+  			else:
+  				q1 = 'SELECT ?sc WHERE {<%s> rdfs:subClassOf ?sc } ' % (term.uri)
+
+  				relations = g.query(q1)
+  				ordone = False
+  				for (subclass) in relations:
+  					subclassnice = self.vocab.niceName(subclass)
+  					# print "subclass ",subclass
+  					# print "subclassnice ",subclassnice
+  					# check niceName result
+  					# TODO: handle other sub class types (...) currently owl:Restriction only
+  					colon = subclassnice.find(':')
+  					if colon > 0:
+  						termStr = """<span rel="rdfs:subClassOf" href="%s"><a href="%s">%s</a></span>\n""" % (subclass, subclass, subclassnice)
+  						contentStr = "%s %s" % (contentStr, termStr)
+  						print "must be super class from another ns"
+  					elif (ordone == False):
+  						# with that query I get all restrictions of a concept :\
+  						# TODO: enable a query with bnodes (_:bnode currently doesn't work :( )
+  						# that's why the following code isn't really nice
+  						q2 = 'SELECT ?orsc ?or ?orv WHERE { <%s> rdfs:subClassOf ?orsc . ?orsc rdf:type <http://www.w3.org/2002/07/owl#Restriction> . ?orsc ?or ?orv }' % (term.uri)
+
+  						print "try to fetch owl:Restrictions with query ", q2
+  						orrelations = g.query(q2)
+  						startStr2 = '<tr><th class="restrictions">Restriction(s):</th>\n'
+  						orpcounter = 0
+  						orsubclass = ''
+  						contentStr3 = ''
+  						termStr1 = ''
+  						termStr2 = ''
+  						prop = ''
+  						oronproperty = ''
+  						orproperty = ''
+  						orpropertyvalue = ''
+  						orscope = ''
+  						for (orsc, orp, orpv) in orrelations:
+  							orproperty2 = ''
+  							orpropertyvalue2 = ''
+  							orscope2 = ''
+  							if (orsubclass == ""):
+  								print "initialize orsubclass with ", orsc
+  								orsubclass = orsc
+  							if(orsubclass != orsc):
+  								termStr1 = """<span about="%s" rel="rdfs:subClassOf" resource="[_:%s]"></span>\n""" % (term.uri, orsubclass)
+  								termStr2 = """<span about="[_:%s]" typeof="owl:Restriction"></span>The property 
+  									<span about="[_:%s]" rel="owl:onProperty" href="%s"><a href="#%s">%s</a></span> must be set <em>%s</em> 
+  									<span about="[_:%s]" property="%s" datatype="xsd:nonNegativeInteger" >%s</span> time(s)""" % (orsubclass, orsubclass, oronproperty, prop.id, prop.type, orscope, orsubclass, orproperty, orpropertyvalue)
+
+  								contentStr2 = "%s %s %s %s<br/>" % (contentStr2, termStr1, termStr2, contentStr3)
+  								print "change orsubclass to", orsc
+  								orsubclass = orsc
+  								contentStr3 = ''
+  								orpcounter = 0
+  								termStr1 = ''
+  								termStr2 = ''
+  								prop = ''
+  								oronproperty = ''
+  								orproperty = ''
+  								orpropertyvalue = ''
+  								orscope = ''
+
+  							print "orp ", orp
+  							print "orpv", orpv
+  							if (str(orp) == "http://www.w3.org/2002/07/owl#onProperty"):
+  								oronproperty = orpv
+  								prop = Term(orpv)
+  								prop.type = self.vocab.niceName(orpv)
+  								print "found new owl:Restriction"
+  								print "write onproperty property"
+  							elif ((str(orp) != "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") & (str(orp) != "http://www.w3.org/2002/07/owl#onProperty")):
+  								if (orpcounter == 0):
+  									orproperty = self.vocab.niceName(orp)
+  									# <- that must be a specific cardinality restriction
+  									orpropertyvalue = orpv
+  									if (str(orp) == "http://www.w3.org/2002/07/owl#cardinality"):
+  										orscope = "exactly"
+  									if (str(orp) == "http://www.w3.org/2002/07/owl#minCardinality"):
+  										orscope = "at least"
+  									if (str(orp) == "http://www.w3.org/2002/07/owl#maxCardinality"):
+  										orscope = "at most"
+  									print "write 1st cardinality of restriction"
+  								else:
+  									orproperty2 = self.vocab.niceName(orp)
+  									# <- that must be another specific cardinality restriction
+  									orpropertyvalue2 = orpv
+  									if (str(orp) == "http://www.w3.org/2002/07/owl#cardinality"):
+  										orscope2 = "exactly"
+  									if (str(orp) == "http://www.w3.org/2002/07/owl#minCardinality"):
+  										orscope2 = "at least"
+  									if (str(orp) == "http://www.w3.org/2002/07/owl#maxCardinality"):
+  										orscope2 = "at most"
+  									print "write another cardinality of restriction"
+  								orpcounter = orpcounter + 1
+  							else:
+  								print "here I am with ", orp
+
+  							if (str(orproperty2) != ""):
+  								termStr3 = """ and <em>%s</em> 
+  										<span about="[_:%s]" property="%s" >%s</span> time(s)""" % (orscope2, orsubclass, orproperty2, orpropertyvalue2)
+  								contentStr3 = "%s %s" % (contentStr3, termStr3)
+
+  						# write also last/one restriction
+  						termStr1 = """<span about ="%s" rel="rdfs:subClassOf" resource="[_:%s]"></span>\n""" % (term.uri, orsubclass)
+  						termStr2 = """<span about="[_:%s]" typeof="owl:Restriction"></span>The property 
+  									<span about="[_:%s]" rel="owl:onProperty" href="%s"><a href="#%s">%s</a></span> must be set <em>%s</em> 
+  									<span about="[_:%s]" property="%s" datatype="xsd:nonNegativeInteger" >%s</span> time(s)""" % (orsubclass, orsubclass, oronproperty, prop.id, prop.type, orscope, orsubclass, orproperty, orpropertyvalue)
+
+  						contentStr2 = "%s %s %s %s\n" % (contentStr2, termStr1, termStr2, contentStr3)
+
+  						ordone = True
+  						print "owl restriction modelling done for", term.uri
+
+  				if contentStr != "":
+  					subClassOf = "%s <td> %s </td></tr>" % (startStr, contentStr)
+
+  				if contentStr2 != "":
+  					restriction = "%s <td> %s </td></tr>" % (startStr2, contentStr2)
+
+  			# class has sub class -> handles only "real" super classes
+  			hasSubClass = ''
+
+  			q = 'SELECT ?sc ?l WHERE {?sc rdfs:subClassOf <%s>. ?sc rdfs:label ?l } ' % (term.uri)
+  			relations = g.query(q)
+  			startStr = '<tr><th>Has sub class</th>\n'
+
+  			contentStr = ''
+  			for (subclass, label) in relations:
+  				sub = Term(subclass)
+  				termStr = """<a href="#%s">%s</a>\n""" % (sub.id, label)
+  				contentStr = "%s %s" % (contentStr, termStr)
+
+  			if contentStr != "":
+  				hasSubClass = "%s <td> %s </td></tr>" % (startStr, contentStr)
+  			else:
+  				q = 'SELECT ?sc WHERE {?sc rdfs:subClassOf <%s> } ' % (term.uri)
+
+  				relations = g.query(q)
+  				for (subclass) in relations:
+  					subclassnice = self.vocab.niceName(subclass)
+  					print "has subclass ", subclass
+  					print "has subclassnice ", subclassnice
+  					# check niceName result
+  					colon = subclassnice.find(':')
+  					if colon > 0:
+  						termStr = """<a href="%s">%s</a>\n""" % (subclass, subclassnice)
+  						contentStr = "%s %s" % (contentStr, termStr)
+
+  				if contentStr != "":
+  					hasSubClass = "%s <td> %s </td></tr>" % (startStr, contentStr)
+
+
+  			# is defined by
+  			classIsDefinedBy = ''
+
+  			q = 'SELECT ?idb WHERE { <%s> rdfs:isDefinedBy ?idb  } ' % (term.uri)
+  			relations = g.query(q)
+  			startStr	 = '\n'
+
+  			contentStr = ''
+  			for (isdefinedby) in relations:
+  				termStr = """<span rel="rdfs:isDefinedBy" href="%s"></span>\n""" % (isdefinedby)
+  				contentStr = "%s %s" % (contentStr, termStr)
+
+  			if contentStr != "":
+  				classIsDefinedBy = "%s <tr><td> %s </td></tr>" % (startStr, contentStr)
+
+
+  			# disjoint with
+  			isDisjointWith = ''
+
+  			q = 'SELECT ?dj ?l WHERE { <%s> <http://www.w3.org/2002/07/owl#disjointWith> ?dj . ?dj rdfs:label ?l } ' % (term.uri)
+  			relations = g.query(q)
+  			startStr = '<tr><th>Disjoint With:</th>\n'
+
+  			contentStr = ''
+  			for (disjointWith, label) in relations:
+  				termStr = """<span rel="owl:disjointWith" href="%s"><a href="#%s">%s</a></span>\n""" % (disjointWith, label, label)
+  				contentStr = "%s %s" % (contentStr, termStr)
+
+  			if contentStr != "":
+  				isDisjointWith = "%s <td> %s </td></tr>" % (startStr, contentStr)
+
+
+  			# owl class
+  			oc = ''
+  			termStr = ''
+
+  			q = 'SELECT * WHERE { <%s> rdf:type <http://www.w3.org/2002/07/owl#Class> } ' % (term.uri)
+  			relations = g.query(q)
+  			startStr = '<tr><th colspan="2">OWL Class</th>\n'
+
+  			if (len(relations) > 0):
+  				if (str(term.type) != "owl:Class"):
+  					termStr = """<span rel="rdf:type" href="http://www.w3.org/2002/07/owl#Class"></span>"""
+  				oc = "%s <td> %s </td></tr>" % (startStr, termStr)
+
+
+  			# rdfs class
+  			rc = ''
+  			termStr = ''
+
+  			q = 'SELECT * WHERE { <%s> rdf:type <http://www.w3.org/2000/01/rdf-schema#Class> } ' % (term.uri)
+  			relations = g.query(q)
+  			startStr = '<tr><th colspan="2">RDFS Class</th>\n'
+
+  			if (len(relations) > 0):
+  				if (str(term.type) != "rdfs:Class"):
+  					termStr = """<span rel="rdf:type" href="http://www.w3.org/2000/01/rdf-schema#Class"></span>"""
+  				rc = "%s <td> %s </td></tr>" % (startStr, termStr)
+
+  			# end
+
+  			dn = os.path.join(self.basedir, "doc")
+  			filename = os.path.join(dn, term.id + ".en")
+  			s = ''
+  			try:
+  				f = open (filename, "r")
+  				s = f.read()
+  			except:
+  				s = ''
+
+  			# if we want validation queries this is where it looks for them.
+  			filename = os.path.join(dn, term.id + ".sparql")
+  			fileStr = ''
+  			try:
+  				f = open (filename, "r")
+  				fileStr = f.read()
+  				fileStr = "<h4><a name=\"queries_" + term.id + "\"></a>" + term.id + " Validation Query</h4><pre>" + cgi.escape(ss) + "</pre>"
+  			except:
+  				fileStr = ''
+
+  			queries = queries + "\n" + fileStr
+  			sn = self.vocab.niceName(term.uri)
+  			s = termlink(s)
+
+  			# danbri added another term.id 20010101 and removed term.status
+  			zz = eg % (term.id, term.uri, term.type, "Class", sn, term.label, term.comment, term.status, domainsOfClass, rangesOfClass + subClassOf + restriction + hasSubClass + classIsDefinedBy + isDisjointWith + oc + rc, s, term.id, term.id)
+
+  			## we add to the relevant string - stable, unstable, testing or archaic
+  			if(term.status == "stable"):
+  				stableTxt = stableTxt + zz
+  			if(term.status == "testing"):
+  				testingTxt = testingTxt + zz
+  			if(term.status == "unstable"):
+  				unstableTxt = unstableTxt + zz
+  			if(term.status == "archaic"):
+  				archaicTxt = archaicTxt + zz
+  			if((term.status == None) or (term.status == "") or (term.status == "unknown")):
+  				archaicTxt = archaicTxt + zz
+
+  		## then add the whole thing to the main tl string
+  		tl = tl + "<h3>Classes</h3>\n"
+  		tl = "%s %s" % (tl, stableTxt + "\n" + testingTxt + "\n" + unstableTxt + "\n" + archaicTxt)
+  		tl = tl + "<h3>Properties</h3>\n"
+
+  		# properties
+  		stableTxt = ''
+  		testingTxt = ''
+  		unstableTxt = ''
+  		archaicTxt = ''
+
+  		for term in self.vocab.properties:
+  			domainsOfProperty = ''
+  			rangesOfProperty = ''
+
+  			# domain of properties -> handles only simple domains
+  			g = self.vocab.graph
+  			q = 'SELECT ?d ?l WHERE {<%s> rdfs:domain ?d . ?d rdfs:label ?l } ' % (term.uri)
+  			# print "term.uri before ", term.uri
+  			relations = g.query(q)
+  			startStr = '<tr><th>Domain:</th>\n'
+
+  			contentStr = ''
+  			for (domain, label) in relations:
+  				dom = Term(domain)
+  				termStr = """<span rel="rdfs:domain" href="%s"><a href="#%s">%s</a></span>\n""" % (domain, dom.id, label)
+  				contentStr = "%s %s" % (contentStr, termStr)
+
+  			if contentStr != "":
+  				domainsOfProperty = "%s <td>%s</td></tr>" % (startStr, contentStr)
+  			else:
+  				q = 'SELECT ?d WHERE {<%s> rdfs:domain ?d } ' % (term.uri)
+
+  				relations = g.query(q)
+  				for (domain) in relations:
+  					domainnice = self.vocab.niceName(domain)
+  					# print "domain ",domain
+  					# print "domainnice ",domainnice
+  					# check niceName result
+  					# TODO: handle other domain types (owl:Union, ...)
+  					colon = domainnice.find(':')
+  					if colon > 0:
+  						termStr = """<span rel="rdfs:domain" href="%s"><a href="%s">%s</a></span>\n""" % (domain, domain, domainnice)
+  						contentStr = "%s %s" % (contentStr, termStr)
+
+  				if contentStr != "":
+  					domainsOfProperty = "%s <td> %s </td></tr>" % (startStr, contentStr)
+
+
+  			# range of properties -> handles only simple ranges
+  			q2 = 'SELECT ?r ?l WHERE {<%s> rdfs:range ?r . ?r rdfs:label ?l } ' % (term.uri)
+  			relations2 = g.query(q2)
+  			startStr = '<tr><th>Range:</th>\n'
+  			contentStr = ''
+  			for (range, label) in relations2:
+  				ran = Term(range)
+  				termStr = """<span rel="rdfs:range" href="%s"><a href="#%s">%s</a></span>\n""" % (range, ran.id, label)
+  				contentStr = "%s %s" % (contentStr, termStr)
+
+  			if contentStr != "":
+  				rangesOfProperty = "%s <td>%s</td>	</tr>" % (startStr, contentStr)
+  			else:
+  				q = 'SELECT ?r WHERE {<%s> rdfs:range ?r } ' % (term.uri)
+
+  				relations = g.query(q)
+  				for (range) in relations:
+  					rangenice = self.vocab.niceName(range)
+  					# print "range ",range
+  					# print "rangenice ",rangenice
+  					# check niceName result
+  					# TODO: handle other range types (owl:Union, ...)
+  					colon = rangenice.find(':')
+  					if colon > 0:
+  						termStr = """<span rel="rdfs:range" href="%s"><a href="%s">%s</a></span>\n""" % (range, range, rangenice)
+  						contentStr = "%s %s" % (contentStr, termStr)
+
+  				if contentStr != "":
+  					rangesOfProperty = "%s <td> %s </td></tr>" % (startStr, contentStr)
+
+  			# property sub property of -> only for property included in this ontology specification
+  			subPropertyOf = ''
+
+  			q = 'SELECT ?sp ?l WHERE {<%s> rdfs:subPropertyOf ?sp . ?sp rdfs:label ?l } ' % (term.uri)
+  			# print "term.uri ", term.uri
+  			relations = g.query(q)
+  			startStr = '<tr><th>Sub property of</th>\n'
+
+  			contentStr = ''
+  			for (subproperty, label) in relations:
+  				sub = Term(subproperty)
+  				termStr = """<span rel="rdfs:subPropertyOf" href="%s"><a href="#%s">%s</a></span>\n""" % (subproperty, sub.id, label)
+  				contentStr = "%s %s" % (contentStr, termStr)
+
+  			if contentStr != "":
+  				subPropertyOf = "%s <td> %s </td></tr>" % (startStr, contentStr)
+  			else:
+  				q1 = 'SELECT ?sp WHERE {<%s> rdfs:subPropertyOf ?sp } ' % (term.uri)
+  				
+  				relations = g.query(q1)
+  				for (subproperty) in relations:
+  					subpropertynice = self.vocab.niceName(subproperty)
+  					# check niceName result
+  					colon = subpropertynice.find(':')
+  					if colon > 0:
+  						termStr = """<span rel="rdfs:subPropertyOf" href="%s"><a href="%s">%s</a></span>\n""" % (subproperty, subproperty, subpropertynice)
+  						contentStr = "%s %s" % (contentStr, termStr)
+  						print "must be super property from another ns"
+  				
+  				if contentStr != "":
+  					subPropertyOf = "%s <td> %s </td></tr>" % (startStr, contentStr)
+
+  			# property has sub property -> only for property included in this ontology specification
+  			hasSubProperty = ''
+
+  			q = 'SELECT ?sp ?l WHERE {?sp rdfs:subPropertyOf <%s>. ?sp rdfs:label ?l } ' % (term.uri)
+  			relations = g.query(q)
+  			startStr = '<tr><th>Has sub property</th>\n'
+
+  			contentStr = ''
+  			for (subproperty, label) in relations:
+  				sub = Term(subproperty)
+  				termStr = """<a href="#%s">%s</a>\n""" % (sub.id, label)
+  				contentStr = "%s %s" % (contentStr, termStr)
+
+  			if contentStr != "":
+  				hasSubProperty = "%s <td> %s </td></tr>" % (startStr, contentStr)
+
+
+  			# property inverse property of -> only for property included in this ontology specification
+  			inverseOf = ''
+
+  			q = 'SELECT ?ip ?l WHERE {<%s> <http://www.w3.org/2002/07/owl#inverseOf> ?ip . ?ip rdfs:label ?l } ' % (term.uri)
+  			# print "term.uri ", term.uri
+  			relations = g.query(q)
+  			startStr = '<tr><th>Inverse property of</th>\n'
+
+  			contentStr = ''
+  			for (inverseproperty, label) in relations:
+  				ipnice = self.vocab.niceName(inverseproperty)
+  				colon = ipnice.find(':')
+  				# check wether explicite defined inverse property or anonymous defined inverse property
+  				if colon > 0:
+  					inverse = Term(inverseproperty)
+  					termStr = """<span rel="owl:inverseOf" href="%s"><a href="#%s">%s</a></span>\n""" % (inverseproperty, inverse.id, label)
+  					print "inverse property must be explicitly defined"
+  				else:
+  					q2 = 'SELECT ?ipt WHERE {<%s> <http://www.w3.org/2002/07/owl#inverseOf> ?ip . ?ip rdfs:label ?l . ?ip rdf:type ?ipt } ' % (term.uri)
+  					relations2 = g.query(q2)
+
+  					contentStr2 = ''
+  					iptcounter = 0
+  					termStr2 = ''
+  					for (inversepropertytype) in relations2:
+  						print "inversepropertytype ", inversepropertytype
+  						iptype = ''
+  						termStr3 = ''
+  						iptypenice = self.vocab.niceName(inversepropertytype)
+  						if (str(inversepropertytype) == "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"):
+  							iptype = "RDF Property"
+  						if (str(inversepropertytype) == "http://www.w3.org/2002/07/owl#ObjectProperty"):
+  							iptype = "Object Property"
+  						if (str(inversepropertytype) == "http://www.w3.org/2002/07/owl#DatatypeProperty"):
+  							iptype = "Datatype Property"
+  						if (str(inversepropertytype) == "http://www.w3.org/2002/07/owl#InverseFunctionalProperty"):
+  							iptype = "Inverse Functional Property"
+  						if (str(inversepropertytype) == "http://www.w3.org/2002/07/owl#FunctionalProperty"):
+  							iptype = "Functional Property"
+  						if (iptype != ""):
+  							termStr3 = """<span about="[_:%s]" typeof="%s"><strong>%s</strong></span>""" % (inverseproperty, iptypenice, iptype)
+  							if (iptcounter > 0):
+  								termStr2 = "%s, %s" % (termStr2, termStr3)
+  							else:
+  								termStr2 = termStr3
+  							iptcounter = iptcounter + 1
+  					if (termStr2 != ""):
+  						contentStr2 = "(%s)" % (termStr2)
+  					termStr = """<span rel="owl:inverseOf" resource="[_:%s]">the anonymous defined property with the label
+  							 \'<em about="[_:%s]" property="rdfs:label">%s</em>\'</span>\n""" % (inverseproperty, inverseproperty, label)
+  					termStr = "%s %s" % (termStr, contentStr2)
+  					print "inverse property must be anonymous defined"
+  				contentStr = "%s %s" % (contentStr, termStr)
+
+  			if contentStr != "":
+  				inverseOf = "%s <td> %s </td></tr>" % (startStr, contentStr)
+  				# print "write inverse property"
+
+  			# property has inverse property -> only for property included in this ontology specification
+  			hasInverseProperty = ''
+
+  			q = 'SELECT ?ip ?l WHERE {?ip <http://www.w3.org/2002/07/owl#inverseOf> <%s>. ?ip rdfs:label ?l } ' % (term.uri)
+  			relations = g.query(q)
+  			startStr = '<tr><th>Has inverse property</th>\n'
+
+  			contentStr = ''
+  			for (inverseproperty, label) in relations:
+  				inverse = Term(inverseproperty)
+  				termStr = """<a href="#%s">%s</a>\n""" % (inverse.id, label)
+  				contentStr = "%s %s" % (contentStr, termStr)
+
+  			if contentStr != "":
+  				hasInverseProperty = "%s <td> %s </td></tr>" % (startStr, contentStr)
+  				# print "write has inverse property"
+
+
+  			# is defined by
+  			propertyIsDefinedBy = ''
+
+  			q = 'SELECT ?idb WHERE { <%s> rdfs:isDefinedBy ?idb  } ' % (term.uri)
+  			relations = g.query(q)
+  			startStr = '\n'
+
+  			contentStr = ''
+  			for (isdefinedby) in relations:
+  				termStr = """<span rel="rdfs:isDefinedBy" href="%s"></span>\n""" % (isdefinedby)
+  				contentStr = "%s %s" % (contentStr, termStr)
+
+  			if contentStr != "":
+  				propertyIsDefinedBy = "%s <tr><td> %s </td></tr>" % (startStr, contentStr)
+
+
+  			# rdf property
+  			rp = ''
+  			termStr = ''
+
+  			q = 'SELECT * WHERE { <%s> rdf:type <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> } ' % (term.uri)
+  			relations = g.query(q)
+  			startStr = '<tr><th colspan="2">RDF Property</th>\n'
+
+  			if (len(relations) > 0):
+  				if (str(term.type) != "rdf:Property"):
+  					termStr = """<span rel="rdf:type" href="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"></span>"""
+  				rp = "%s <td> %s </td></tr>" % (startStr, termStr)
+
+
+  			# object property
+  			op = ''
+  			termStr = ''
+
+  			q = 'SELECT * WHERE { <%s> rdf:type <http://www.w3.org/2002/07/owl#ObjectProperty> } ' % (term.uri)
+  			relations = g.query(q)
+  			startStr = '<tr><th colspan="2">Object Property</th>\n'
+
+  			if (len(relations) > 0):
+  				if (str(term.type) != "owl:ObjectProperty"):
+  					termStr = """<span rel="rdf:type" href="http://www.w3.org/2002/07/owl#ObjectProperty"></span>"""
+  				op = "%s <td> %s </td></tr>" % (startStr, termStr)
+
+
+  			# datatype property
+  			dp = ''
+  			termStr = ''
+
+  			q = 'SELECT * WHERE { <%s> rdf:type <http://www.w3.org/2002/07/owl#DatatypeProperty> } ' % (term.uri)
+  			relations = g.query(q)
+  			startStr = '<tr><th colspan="2">Datatype Property</th>\n'
+
+  			if (len(relations) > 0):
+  				if (str(term.type) != "owl:DatatypeProperty"):
+  					termStr = """<span rel="rdf:type" href="http://www.w3.org/2002/07/owl#DatatypeProperty"></span>"""
+  				dp = "%s <td> %s </td></tr>" % (startStr, termStr)
+
+
+  			# inverse functional property
+  			ifp = ''
+  			termStr = ''
+
+  			q = 'SELECT * WHERE { <%s> rdf:type <http://www.w3.org/2002/07/owl#InverseFunctionalProperty> } ' % (term.uri)
+  			relations = g.query(q)
+  			startStr = '<tr><th colspan="2">Inverse Functional Property</th>\n'
+
+  			if (len(relations) > 0):
+  				if (str(term.type) != "owl:InverseFunctionalProperty"):
+  					termStr = """<span rel="rdf:type" href="http://www.w3.org/2002/07/owl#InverseFunctionalProperty"></span>"""
+  				ifp = "%s <td> %s </td></tr>" % (startStr, termStr)
+
+
+  			# functonal property
+  			fp = ''
+
+  			q = 'SELECT * WHERE { <%s> rdf:type <http://www.w3.org/2002/07/owl#FunctionalProperty> } ' % (term.uri)
+  			relations = g.query(q)
+  			startStr = '<tr><th colspan="2">Functional Property</th>\n'
+
+  			if (len(relations) > 0):
+  				if (str(term.type) != "owl:FunctionalProperty"):
+  					termStr = """<span rel="rdf:type" href="http://www.w3.org/2002/07/owl#FunctionalProperty"></span>"""
+  				fp = "%s <td> %s </td></tr>" % (startStr, termStr)
+
+  			# end
+
+  			dn = os.path.join(self.basedir, "doc")
+  			filename = os.path.join(dn, term.id + ".en")
+
+  			s = ''
+  			try:
+  				f = open (filename, "r")
+  				s = f.read()
+  			except:
+  				s = ''
+
+  			sn = self.vocab.niceName(term.uri)
+  			s = termlink(s)
+
+  			# danbri added another term.id 20010101
+  			zz = eg % (term.id, term.uri, term.type, "Property", sn, term.label, term.comment, term.status, domainsOfProperty, rangesOfProperty + subPropertyOf + hasSubProperty + inverseOf + hasInverseProperty + propertyIsDefinedBy + rp + op + dp + ifp + fp, s, term.id, term.id)
+
+  			## we add to the relevant string - stable, unstable, testing or archaic
+  			if(term.status == "stable"):
+  				stableTxt = stableTxt + zz
+  			if(term.status == "testing"):
+  				testingTxt = testingTxt + zz
+  			if(term.status == "unstable"):
+  				unstableTxt = unstableTxt + zz
+  			if(term.status == "archaic"):
+  				archaicTxt = archaicTxt + zz
+  			if((term.status == None) or (term.status == "") or (term.status == "unknown")):
+  				archaicTxt = archaicTxt + zz
+
+  		## then add the whole thing to the main tl string
+  		tl = "%s %s" % (tl, stableTxt + "\n" + testingTxt + "\n" + unstableTxt + "\n" + archaicTxt)
+  		##    tl = "%s %s" % (tl, zz)
+
+  		## ensure termlist tag is closed
+  		return(tl + "\n" + queries + "</div>\n</div>")
+
+
+	def rdfa(self):
+
+		return("<html>rdfa here</html>")
+
+
+  	def htmlDocInfo(t, termdir = '../docs'):
+  		"""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."""
+  		if termdir == None:
+  			termdir = self.basedir
+
+  		doc = ""
+  		try:
+  			f = open("%s/%s.en" % (termdir, t), "r")
+  			doc = f.read()
+  			doc = termlink(doc)
+  		except:
+  			return "<p>No detailed documentation for this term.</p>"
+  		return doc
+
+  	# report what we've parsed from our various sources
+  	def report(self):
+  		s = "Report for vocabulary from " + self.vocab.filename + "\n"
+  		if self.vocab.uri != None:
+  			s += "URI: " + self.vocab.uri + "\n\n"
+  		for t in self.vocab.uterms:
+  			print "TERM as string: ", t
+  			s += t.simple_report()
+  		return s
+
Binary file ontologies/specgen/libvocab.pyc has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ontologies/specgen/specgen6.py	Tue Oct 04 18:05:11 2011 +0200
@@ -0,0 +1,242 @@
+#!/usr/bin/env python
+
+# This is a draft rewrite of specgen5, the family of scripts (originally
+# in Ruby, then Python) that are used with the Counter Ontology, Ordered Lists
+# Ontology and Info Service Ontology.
+# This version is based on danbri's specgen version (specgen5) and heavily extended
+# by Bob Ferris in July 2010 (the main extensions are in libvocab.py). This version is
+# a bit more FOAF independent ;)
+#
+# spegen6:
+#
+#   Copyright 2010 Bob Ferris <http://smiy.wordpress.com/author/zazi0815/>
+#
+# specgen5:
+#
+# 	Copyright 2008 Dan Brickley <http://danbri.org/>
+#
+# ...and probably includes bits of code that are:
+#
+# 	Copyright 2008 Uldis Bojars <captsolo@gmail.com>
+# 	Copyright 2008 Christopher Schmidt
+#
+# This software is licensed under the terms of the MIT License.
+#
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+
+
+import libvocab
+from libvocab import Vocab, VocabReport
+from libvocab import Term
+from libvocab import Class
+from libvocab import Property
+import sys
+import os.path
+import getopt
+
+
+# Make a spec
+def makeSpec(indir, uri, shortName,outdir,outfile, template, templatedir,indexrdfdir, ontofile):
+  spec = Vocab( indexrdfdir, ontofile)
+  spec.uri = uri
+  spec.addShortName(shortName)
+  spec.index() # slurp info from sources
+
+  out = VocabReport( spec, indir, template, templatedir ) 
+
+  filename = os.path.join(outdir, outfile)
+  print "Printing to ",filename
+
+  f = open(filename,"w")
+  result = out.generate()
+  f.write(result)
+
+# Make FOAF spec
+def makeFoaf():
+  makeSpec("examples/foaf/","http://xmlns.com/foaf/0.1/","foaf","examples/foaf/","_tmp_spec.html","template.html","examples/foaf/","examples/foaf/")
+
+
+def usage():
+  print "Usage:",sys.argv[0],"--indir=dir --ns=uri --prefix=prefix [--outdir=outdir] [--outfile=outfile] [--templatedir=templatedir] [--indexrdf=indexrdf] [--ontofile=ontofile]"
+  print "e.g. "
+  print sys.argv[0], " --indir=examples/foaf/ --ns=http://xmlns.com/foaf/0.1/ --prefix=foaf --ontofile=index.rdf"
+  print "or "
+  print sys.argv[0], " --indir=../../xmlns.com/htdocs/foaf/ --ns=http://xmlns.com/foaf/0.1/ --prefix=foaf --ontofile=index.rdf --templatedir=../../xmlns.com/htdocs/foaf/spec/ --indexrdfdir=../../xmlns.com/htdocs/foaf/spec/ --outdir=../../xmlns.com/htdocs/foaf/spec/"
+
+def main():
+  ##looking for outdir, outfile, indir, namespace, shortns
+
+  try:
+        opts, args = getopt.getopt(sys.argv[1:], None, ["outdir=", "outfile=", "indir=", "ns=", "prefix=", "templatedir=", "indexrdfdir=", "ontofile="])
+        #print opts
+  except getopt.GetoptError, err:
+        # print help information and exit:
+        print str(err) # will print something like "option -a not recognized"
+        print "something went wrong"
+        usage()
+        sys.exit(2)
+
+  indir = None #indir
+  uri = None #ns
+  shortName = None #prefix
+  outdir = None 
+  outfile = None
+  templatedir = None
+  indexrdfdir = None
+  ontofile = None
+
+  if len(opts) ==0:
+      print "No arguments found"
+      usage()
+      sys.exit(2)   
+  
+
+  for o, a in opts:
+      if o == "--indir":
+            indir = a
+      elif o == "--ns":
+            uri = a
+      elif o == "--prefix":
+            shortName = a
+      elif o == "--outdir":
+            outdir = a
+      elif o == "--outfile":
+            outfile = a
+      elif o == "--templatedir":
+            templatedir = a
+      elif o == "--indexrdfdir":
+            indexrdfdir = a
+      elif o == "--ontofile":
+      		ontofile = a
+
+#first check all the essentials are there
+
+  # check we have been given a indir
+  if indir == None or len(indir) ==0:
+      print "No in directory given"
+      usage()
+      sys.exit(2)   
+
+  # check we have been given a namespace url
+  if (uri == None or len(uri)==0):
+      print "No namespace uri given"
+      usage()
+      sys.exit(2)   
+
+  # check we have a prefix
+  if (shortName == None or len(shortName)==0):
+      print "No prefix given"
+      usage()
+      sys.exit(2)
+      
+  # check we have benn given an ontology file
+  if (ontofile == None or len(ontofile)==0):
+  	print "No ontology file given"
+        usage()
+        sys.exit(2)
+  else:
+  	print "Use ontology file ",ontofile    
+
+  # check outdir
+  if (outdir == None or len(outdir)==0):
+      outdir = indir
+      print "No outdir, using indir ",indir
+  
+  if (outfile == None or len(outfile)==0):
+      outfile = "_tmp_spec.html"
+      print "No outfile, using ",outfile
+
+  if (templatedir == None or len(templatedir)==0):
+      templatedir = indir
+      print "No templatedir, using ",templatedir
+
+  if (indexrdfdir == None or len(indexrdfdir)==0):
+      indexrdfdir = indir
+      print "No indexrdfdir, using ",indexrdfdir
+
+# now do some more checking
+  # check indir is a dir and it is readable and writeable
+  if (os.path.isdir(indir)):
+      print "In directory is ok ",indir
+  else:
+      print indir,"is not a directory"
+      usage()
+      sys.exit(2)   
+
+
+  # check templatedir is a dir and it is readable and writeable
+  if (os.path.isdir(templatedir)):
+      print "Template directory is ok ",templatedir
+  else:
+      print templatedir,"is not a directory"
+      usage()
+      sys.exit(2)   
+
+
+  # check indexrdfdir is a dir and it is readable and writeable
+  if (os.path.isdir(indexrdfdir)):
+      print "indexrdfdir directory is ok ",indexrdfdir
+  else:
+      print indexrdfdir,"is not a directory"
+      usage()
+      sys.exit(2)   
+
+  # check outdir is a dir and it is readable and writeable
+  if (os.path.isdir(outdir)):
+      print "Out directory is ok ",outdir
+  else:
+      print outdir,"is not a directory"
+      usage()
+      sys.exit(2)   
+
+  #check we can read infile    
+  try:
+    filename = os.path.join(indexrdfdir, ontofile)
+    f = open(filename, "r")
+  except:
+    print "Can't open ",ontofile,"  in ",indexrdfdir
+    usage()
+    sys.exit(2)   
+
+  #look for the template file
+  try:
+    filename = os.path.join(templatedir, "template.html")
+    f = open(filename, "r")
+  except:
+    print "No template.html in ",templatedir
+    usage()
+    sys.exit(2)   
+
+  # check we can write to outfile
+  try:
+    filename = os.path.join(outdir, outfile)
+    f = open(filename, "w")
+  except:
+    print "Cannot write to ",outfile," in",outdir
+    usage()
+    sys.exit(2)   
+
+  makeSpec(indir,uri,shortName,outdir,outfile,"template.html",templatedir,indexrdfdir, ontofile)
+  
+
+if __name__ == "__main__":
+    main()
+