summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Pokorný <jpokorny@redhat.com>2013-03-28 14:32:11 +0100
committerJan Pokorný <jpokorny@redhat.com>2013-03-28 14:32:11 +0100
commitecfa44f1a8d78798ce850b63dcc618f813b225df (patch)
treeac8e78d8978078ab8c1b6859ec4f9fe4860035a5
parent823cb61b8532eb7234cac405d7787484a9c95a76 (diff)
downloadontogen-ecfa44f1a8d78798ce850b63dcc618f813b225df.tar.gz
ontogen-ecfa44f1a8d78798ce850b63dcc618f813b225df.tar.xz
ontogen-ecfa44f1a8d78798ce850b63dcc618f813b225df.zip
Make the whole toolchain run smoothly incl. generating the graph
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
-rw-r--r--isaviz-postprocess.xsl39
-rw-r--r--isaviz-preprocess.xsl15
-rw-r--r--ontogen.py95
-rw-r--r--ontogen.template2
-rw-r--r--quickstart/Makefile135
-rwxr-xr-xquickstart/template.py36
6 files changed, 283 insertions, 39 deletions
diff --git a/isaviz-postprocess.xsl b/isaviz-postprocess.xsl
new file mode 100644
index 0000000..a614cc1
--- /dev/null
+++ b/isaviz-postprocess.xsl
@@ -0,0 +1,39 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:template>
+ <xsl:template match="@*[starts-with(., 'file:/')]">
+ <xsl:attribute name="{name()}">
+ <xsl:value-of select="concat('.#', substring-after(., '#'))"/>
+ </xsl:attribute>
+ </xsl:template>
+ <xsl:template match="text()[starts-with(normalize-space(.), 'file:/')]">
+ <xsl:variable name="space-prefix">
+ <xsl:call-template name="iter-concat">
+ <xsl:with-param name="itercat" select="'&#160;'"/>
+ <xsl:with-param name="itercount"
+ select="floor(string-length(substring-before(., '#')) div 3 * 2)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat($space-prefix, '#', substring-after(., '#'))"/>
+ </xsl:template>
+
+ <xsl:template name="iter-concat">
+ <xsl:param name="itercat"/>
+ <xsl:param name="itercount"/>
+ <xsl:choose>
+ <xsl:when test="$itercount = 0"/>
+ <xsl:otherwise>
+ <xsl:value-of select="$itercat"/>
+ <xsl:call-template name="iter-concat">
+ <xsl:with-param name="itercat" select="$itercat"/>
+ <xsl:with-param name="itercount" select="$itercount - 1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/isaviz-preprocess.xsl b/isaviz-preprocess.xsl
new file mode 100644
index 0000000..b85a180
--- /dev/null
+++ b/isaviz-preprocess.xsl
@@ -0,0 +1,15 @@
+<!--
+ shamelessly copied from
+ http://en.wikipedia.org/wiki/Identity_transform#Using_XSLT
+ -->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:owl="http://www.w3.org/2002/07/owl#"
+ xmlns:ex="http://purl.org/net/ns/ex#">
+ <xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:template>
+ <xsl:template match="owl:Ontology|ex:Example|comment()"/>
+</xsl:stylesheet>
diff --git a/ontogen.py b/ontogen.py
index d2edd54..c5c3ff2 100644
--- a/ontogen.py
+++ b/ontogen.py
@@ -6,8 +6,10 @@
from sys import stdout, stderr
from datetime import date
from textwrap import TextWrapper, dedent
-from os import extsep, mkdir, symlink, remove
-from os.path import basename, dirname, exists, isdir, islink, join, splitext
+from os import extsep, getcwd, mkdir, symlink, remove
+from os.path import basename, dirname, exists, isdir, isfile, islink, join, \
+ splitext, sep as pathsep
+from shutil import copy2 as copy
from subprocess import call
from shlex import split
#import codecs
@@ -18,8 +20,10 @@ logging.basicConfig()
log = logging.getLogger(__name__)
+#VERSIONSEP = sep # non-unix paths -> problems
VERSIONSEP = '/'
ONTSEP = '#'
+INDEX = 'index.html'
TEMPLATE_GENSHI = join(dirname(__file__), 'ontogen.template')
TEMPLATE_XSLT = join(dirname(__file__), 'ns-schema.xsl')
@@ -48,16 +52,20 @@ class ClassProperty(property):
# another common fixer (adjusted): http://stackoverflow.com/a/13937525
class InheritDocstring(type):
def __init__(this, name, bases, attrs):
- if getattr(this, '__doc__', None) is None:
- setattr(this, '__doc__', super(this, this).__doc__)
+ if not getattr(this, '__doc__', None):
+ this.__doc__ = super(this, this).__doc__
+ super(InheritDocstring, InheritDocstring).__init__(this, name,
+ bases, attrs)
-def force_symlink(source, link_name):
+def custom_symlink(source, link_name, report=False):
if exists(link_name):
if islink(link_name):
remove(link_name)
else:
raise RuntimeError('{0} is in our way'.format(link_name))
+ if report is not False:
+ print '{0}: {1}'.format(report, link_name)
symlink(source, link_name)
@@ -89,6 +97,19 @@ class Example(object):
return ''
+# combine this "example" with Makefile to trigger the magic
+class ExampleSelfFigureProto(type):
+ def __new__(self, ontology):
+ base = ontology.base
+ class ExampleSelfFigure(Example):
+ """Illustrative figure of the vocabulary"""
+ image_full = ontology.version + VERSIONSEP + base + extsep + 'svg'
+ image = base + extsep + 'svg' # referenced from html
+ symlink = base + extsep + 'svg'
+
+ return ExampleSelfFigure
+
+
#
# Abstract RDF level
#
@@ -223,11 +244,17 @@ class Ontology(RDFEntity):
@ClassProperty
@classmethod
- def base(this):
+ def base_uri_full(this):
return this.base_uri + VERSIONSEP + this.version
@ClassProperty
@classmethod
+ def base(this):
+ # TODO: cache me please?
+ return this.base_uri.rpartition('/')[2]
+
+ @ClassProperty
+ @classmethod
def creator(this):
return ''
@@ -286,13 +313,14 @@ class Ontology(RDFEntity):
return proper_subclasses and unique_ids
@classmethod
- def _auto_filename(this):
- base = this.base_uri.rpartition('/')[2]
- if not exists(base):
- mkdir(base)
- elif not isdir(base):
- raise RuntimeError('{0} is not a directory'.format(base))
- return (base + VERSIONSEP + this.version + extsep + 'rdf',
+ def _prepare_targets(this):
+ base = this.base
+ version = this.version
+ if not exists(version):
+ mkdir(version)
+ elif not isdir(version):
+ raise RuntimeError('{0} is not a directory'.format(version))
+ return (version + VERSIONSEP + base + extsep + 'rdf',
base + extsep + 'rdf')
@classmethod
@@ -306,8 +334,8 @@ class Ontology(RDFEntity):
)
log.debug('running {0}'.format(split(cmd)))
if call(split(cmd)):
- raise RuntimeError('Something went wrong while running {0}'
- .format(cmd))
+ raise RuntimeError('Something went wrong while running {0}; pwd={1}'
+ .format(cmd, getcwd()))
@classmethod
def generate(this, ontologies=(), template=None, outfile='-', gendoc=True):
@@ -334,7 +362,7 @@ class Ontology(RDFEntity):
outobj = stdout
else:
if outfile == 'AUTO':
- outfile, symfile = this._auto_filename()
+ outfile, symfile = this._prepare_targets()
outobj = open(outfile, "w")
tmpldict = dict(Ontology=this, namespaces=namespaces)
@@ -345,14 +373,21 @@ class Ontology(RDFEntity):
# htmldoc
htmlfile = None
if gendoc and outfile != '-':
- htmlfile = splitext(outfile)[0] + extsep + 'html'
+ htmlfile = join(dirname(outfile), INDEX)
this.gendoc(outfile, htmlfile)
# symlink to base (non-versioned) only for the newest ontology
if ontologies[-1] is this and symfile:
- force_symlink(outfile, symfile)
+ custom_symlink(outfile, symfile, 'output')
if htmlfile:
- force_symlink(htmlfile, splitext(symfile)[0] + extsep + 'html')
+ custom_symlink(htmlfile, splitext(symfile)[0] + extsep + 'html',
+ 'html')
+ for ex in [e for e in this.examples if e.image]:
+ if ex.__name__ == 'ExampleSelfFigure':
+ custom_symlink(ex.image_full, ex.symlink, 'self-figure')
+ elif not pathsep in img:
+ img = ex.image
+ custom_symlink(join(this.base, img), img, 'image')
if outobj is not stdout:
outobj.close()
@@ -362,6 +397,27 @@ class Ontology(RDFEntity):
this.generate()
+class PrependFigure(InheritDocstring):
+ def __new__(this, name, bases, attrs):
+ ret = super(PrependFigure, PrependFigure).__new__(this, name, bases,
+ attrs)
+ try:
+ if all(map(lambda x: isinstance(x, basestring),
+ map(lambda x: getattr(ret, x, None),
+ ('base', 'version')))
+ ) or True:
+ setattr(ret, 'examples', [ExampleSelfFigureProto(ret)]
+ + list(getattr(ret, 'examples', ())))
+ except NotImplementedError:
+ pass
+ finally:
+ return ret
+
+
+class OntologyWithFigure(Ontology):
+ __metaclass__ = PrependFigure
+
+
#
# Generalized view
#
@@ -379,6 +435,7 @@ class Ontologies(object):
assert all(map(lambda o: o.valid(), ontologies))
assert reduce(lambda a, b: issubclass(a, b) or issubclass(b, a),
ontologies)
+ map(lambda a: setattr(a, '_final', True), ontologies)
merge = self._ontologies + list(ontologies)
self._ontologies = list(sorted(set(merge), key=lambda o: o.version))
# make it decorator-compatible
diff --git a/ontogen.template b/ontogen.template
index 7bdc287..a885b98 100644
--- a/ontogen.template
+++ b/ontogen.template
@@ -22,7 +22,7 @@
<owl:imports rdf:resource="http://purl.org/dc/elements/1.1/"/>
<owl:versionInfo>${Ontology.version}</owl:versionInfo><!--!
--><py:if test="Ontology.priorVersion">
- <owl:priorVersion>${Ontology.priorVersion.base}</owl:priorVersion><!--!
+ <owl:priorVersion>${Ontology.priorVersion.base_uri_full}</owl:priorVersion><!--!
--></py:if><py:if test="Ontology.label">
<rdfs:label>${Ontology.label}</rdfs:label><!--!
--></py:if><py:if test="Ontology.comment">
diff --git a/quickstart/Makefile b/quickstart/Makefile
new file mode 100644
index 0000000..07359b2
--- /dev/null
+++ b/quickstart/Makefile
@@ -0,0 +1,135 @@
+# prerequisities:
+# - xsltproc
+# - inkscape
+# - isaviz (http://www.w3.org/2001/11/IsaViz/)
+
+#DEBUG = 1
+ifndef DEBUG
+ DEBUG = 0
+endif
+ifeq (${DEBUG},0)
+ DEBUG_RM_DEP = rm -f -- $<
+else
+ DEBUG_RM_DEP =
+endif
+
+ONTOGEN_dir ?= ontogen
+HTML_NSSCHEMAXSL_file = ${ONTOGEN_dir}/ns-schema.xsl
+RDF_ISAVIZPREPROCESSXSL_file = ${ONTOGEN_dir}/isaviz-preprocess.xsl
+RDF_ISAVIZPOSTPROCESSXSL_file = ${ONTOGEN_dir}/isaviz-postprocess.xsl
+
+SVG_ISAVIZ_path ?= ~/wrkspc/sw/IsaViz
+SVG_ISAVIZ_runner ?= ./run.sh
+SVG_ISAVIZ_cfg = ~/isaviz.cfg
+SVG_ISAVIZ_font = Liberation Mono
+SVG_ISAVIZ_fontsize = 10
+# LR or TB (not recommended)
+SVG_ISAVIZ_orientation = LR
+SVG_ISAVIZ_charcount = 30
+
+SVG_BIGGERXSL_url = http://inkscape-forum.andreas-s.net/attachment/2730/bigger.xsl
+#SVG_BIGGERXSL_url = http://sourceforge.net/mailarchive/attachment.php?list_name=inkscape-user&message_id=20080925142218.2ba4194e%40nrri.umn.edu
+#SVG_BIGGERXSL_file ?= $(shell \
+# wget -nv -nc --content-disposition --delete-after ${SVG_BIGGERXSL_url} \
+# | cut -d' ' -f6 \
+#)
+SVG_BIGGERXSL_file = bigger.xsl
+SVG_BIGGERXSL_scale = 0.9
+
+TARGETS_PY = $(shell \
+ find -maxdepth 1 -name '*.py' -and -executable -and -type f -printf '%f\n' \
+)
+TARGETS = $(TARGETS_PY:.py=)
+REMOVE = ${TARGETS:=.requires} ${TARGETS:=.1.rdf} ${TARGETS:=.1.svg} ${TARGETS:=.2.svg}
+REMOVE_SYMLINKS = ${TARGETS:=.rdf} ${TARGETS:=.html} ${TARGETS:=.svg}
+
+.PHONY = ${TARGETS} clean mrproper
+
+# top-level wrapper
+${TARGETS}: %: %.requires
+ ${DEBUG_RM_DEP}
+
+ifneq ($(MAKECMDGOALS),clean)
+ $(foreach target,${TARGETS},$(eval -include ${target:=.requires}))
+endif
+
+# rdf + html
+$(TARGETS:=.requires): %.requires: %.rdf
+ touch $<
+
+$(TARGETS:=.rdf) : %.rdf: %.py
+ ./$< AUTO | grep -E '^self-figure: ' | cut -d' ' -f2 \
+ | xargs -I'{}' find -L {} -printf '$(@:.rdf=): %f\n' \
+ >> $(@:.rdf=.requires)
+ # ^ -not/-empty condition?
+
+# only used if html accidentally deleted and rdf kept
+$(TARGETS:=.html):: %.html: %.rdf
+ xsltproc --stringparam xmlfile $< ${HTML_NSSCHEMAXSL_file} $< > $@
+
+$(TARGETS:=.svg): %.svg: %.2.svg ${SVG_BIGGERXSL_file}
+ xsltproc --stringparam scale ${SVG_BIGGERXSL_scale} \
+ ${SVG_BIGGERXSL_file} $< > $@
+ inkscape $@ --verb FitCanvasToDrawing --verb FileVacuum \
+ --verb FileSave --verb FileClose
+ ${DEBUG_RM_DEP}
+
+$(TARGETS:=.1.rdf): %.1.rdf: %.rdf ${RDF_ISAVIZPREPROCESSXSL_file}
+ xsltproc ${RDF_ISAVIZPREPROCESSXSL_file} $< > $@
+
+$(TARGETS:=.2.svg): %.2.svg: %.1.svg ${RDF_ISAVIZPOSTPROCESSXSL_file}
+ xsltproc ${RDF_ISAVIZPOSTPROCESSXSL_file} $< > $@
+ ${DEBUG_RM_DEP}
+
+$(TARGETS:=.1.svg): %.svg: %.rdf ${SVG_ISAVIZ_path}/${SVG_ISAVIZ_runner}
+ @echo " Sorry, this part currently requires manual actions:"
+ @echo " 1. File - Import - Replace - RDF/XML from file: $<"
+ @echo " 2. View - Suggest Layout (only to get a better form; 14pt?)"
+ @echo " 3. Optionally increase font size for better final look"
+ @echo " via Edit - Preferences - Rendering/GSS"
+ @echo " 4. Export - SVG: $@"
+ mv ${SVG_ISAVIZ_cfg} ${SVG_ISAVIZ_cfg}.$(@:.1.svg=) || :
+ touch ${SVG_ISAVIZ_cfg}
+ echo '<?xml version="1.0" encoding="UTF-8"?>' >>${SVG_ISAVIZ_cfg}
+ echo '<isv:config xmlns:isv="http://www.w3.org/2001/10/IsaViz">' >>${SVG_ISAVIZ_cfg}
+ echo ' <isv:directories>' >>${SVG_ISAVIZ_cfg}
+ echo ' <isv:tmpDir value="true">/tmp</isv:tmpDir>' >>${SVG_ISAVIZ_cfg}
+ echo ' <isv:projDir>/tmp</isv:projDir>' >>${SVG_ISAVIZ_cfg}
+ echo ' <isv:rdfDir>$(CURDIR)</isv:rdfDir>' >>${SVG_ISAVIZ_cfg}
+ echo ' <isv:dotExec>/bin/dot</isv:dotExec>' >>${SVG_ISAVIZ_cfg}
+ #echo ' <isv:graphvizFontDir>/tmp</isv:graphvizFontDir>' >>${SVG_ISAVIZ_cfg}
+ echo ' </isv:directories>' >>${SVG_ISAVIZ_cfg}
+ echo ' <isv:constants abbrevSyntax="true"' >>${SVG_ISAVIZ_cfg}
+ echo ' alwaysIncludeLang="false"' >>${SVG_ISAVIZ_cfg}
+ echo ' anonymousNodes="genid:"' >>${SVG_ISAVIZ_cfg}
+ echo ' antialiasing="false"' >>${SVG_ISAVIZ_cfg}
+ echo ' backgroundColor="-1579033"' >>${SVG_ISAVIZ_cfg}
+ echo ' defaultLang="en"' >>${SVG_ISAVIZ_cfg}
+ echo ' defaultNamespace=""' >>${SVG_ISAVIZ_cfg}
+ echo ' displayLabels="false"' >>${SVG_ISAVIZ_cfg}
+ echo ' graphFont="${SVG_ISAVIZ_font} Plain ${SVG_ISAVIZ_fontsize}"' \
+ >>${SVG_ISAVIZ_cfg}
+ echo ' graphOrient="${SVG_ISAVIZ_orientation}"' >>${SVG_ISAVIZ_cfg}
+ echo ' incGSSstyling="false"' >>${SVG_ISAVIZ_cfg}
+ echo ' maxLitCharCount="${SVG_ISAVIZ_charcount}"' >>${SVG_ISAVIZ_cfg}
+ echo ' parsingMode="0"' >>${SVG_ISAVIZ_cfg}
+ echo ' prefixInTf="true"' >>${SVG_ISAVIZ_cfg}
+ echo ' saveWindowLayout="false"' >>${SVG_ISAVIZ_cfg}
+ echo ' showAnonIds="false" swingFont="SansSerif Plain 12"/>' \
+ >>${SVG_ISAVIZ_cfg}
+ echo '</isv:config>' >>${SVG_ISAVIZ_cfg}
+ pushd ${SVG_ISAVIZ_path} 2>/dev/null && \
+ ( ${SVG_ISAVIZ_runner} || : ) && \
+ popd 2>/dev/null
+ mv ${SVG_ISAVIZ_cfg}.$(@:.1.svg=) ${SVG_ISAVIZ_cfg} || rm -f ${SVG_ISAVIZ_cfg}
+ ${DEBUG_RM_DEP}
+
+${SVG_BIGGERXSL_file}:
+ wget -nv -nc --content-disposition ${SVG_BIGGERXSL_url} -O- > $@
+
+clean:
+ for f in ${REMOVE_SYMLINKS}; do rm -f -- $$(readlink $$f) $$f; done
+ rm -f -- ${REMOVE}
+
+mrproper: clean
+ rm -f -- ${SVG_BIGGERXSL_file}
diff --git a/quickstart/template.py b/quickstart/template.py
index 0eaea7f..ead6874 100755
--- a/quickstart/template.py
+++ b/quickstart/template.py
@@ -4,9 +4,13 @@
from sys import argv
#from genshi.input import XML
-from ontogen.ontogen import Property, Class, Example, Ontology, Ontologies
+from ontogen.ontogen import Property, Class, Example, OntologyWithFigure, \
+ Ontologies
-BASE = 'http://purl.org/net/foo'
+#from ontogen.ontogen import log
+#log.setLevel('DEBUG')
+
+BASE = 'http://example.org/net/template'
#
@@ -26,6 +30,7 @@ class TFoo(Foo):
Represents foos that are special because of the T-shape.
"""
+
#
# properties
#
@@ -49,21 +54,15 @@ class baz(bar):
# examples
#
-# v0.1
-
-class ex_0_1_schema(Example):
- """Illustrative figure of the vocabulary."""
- image = '0.1.svg'
-
class ex_0_1(Example):
"""An example snippet.
-<foo:tfoo about="#mytfoo">
- <foo:baz>test</foo:baz>
-</foo:tfoo>
+<tmpl:tfoo about="#mytfoo">
+ <tmpl:baz>test</tmpl:baz>
+</tmpl:tfoo>
"""
- pfx = 'foo:'
+ pfx = 'tmpl:'
#
@@ -74,7 +73,7 @@ class ex_0_1(Example):
ontologies = Ontologies()
-class foo(Ontology):
+class template(OntologyWithFigure):
"""Descriptive vocabulary for foos
This vocabulary serves a purpose of shedding light into semantics
@@ -82,13 +81,13 @@ class foo(Ontology):
"""
base_uri = BASE
#creator = XML('''\
- # <dc:foo xmlns:dc="http://purl.org/dc/elements/1.1/"
- # >John Doe</dc:foo>''')
+ # <dc:X xmlns:dc="http://purl.org/dc/elements/1.1/"
+ # >John Doe</dc:X>''')
creator = 'John Doe'
@ontologies.include
-class foo_0_1(foo):
+class template_0_1(template):
version = '0.1'
issued = '2013-02-19'
modified = '2013-03-20'
@@ -101,14 +100,13 @@ class foo_0_1(foo):
baz,
]
examples = [
- ex_0_1_schema,
ex_0_1,
]
#@ontologies.include
-#@foo_0_1.supersededBy
-#class foo_0_2(foo):
+#@template_0_1.supersededBy
+#class template_0_2(template):
# ...