"""
.. autoclass:: Fresnel
:show-inheritance:
"""
__all__ = ["Fresnel", "Lens"]
try:
from xml.etree import ElementTree as ET
except:
from elementtree import ElementTree as ET
from urllib import urlencode
from ordf.collection import Collection
from ordf.graph import Graph
from ordf.namespace import *
from ordf.term import Literal, URIRef, BNode
from datetime import datetime
log = __import__("logging").getLogger(__name__)
class Lens(Graph):
"""
"""
def __init__(self, fresnel, identifier):
super(Lens, self).__init__(identifier=identifier)
self.fresnel = fresnel
self.group = None
self.stylesheets = None
def properties(self, graph, resource):
properties = []
for properties in self.objects(self.identifier, FRESNEL["showProperties"]):
properties = Collection(self, properties)
properties = list(properties)
break
hideProperties = []
for hideProperties in self.objects(self.identifier, FRESNEL["hideProperties"]):
hideProperties = Collection(self, hideProperties)
hideProperties = list(hideProperties)
break
subProperties = []
for prop in properties:
if isinstance(prop, BNode) and self.one((prop, RDF["type"], FRESNEL["PropertyDescription"])):
x = self.one((prop, FRESNEL["sublens"], None))
if x:
lens = self.fresnel.lenses.get(x[2])
else:
lens = None
for prop in self.objects(prop, FRESNEL["property"]):
if prop not in hideProperties:
yield prop, lens, self.group.formats.get(prop, Format())
subProperties.append(prop)
elif prop == FRESNEL["allProperties"]:
for prop in graph.distinct_predicates(resource, None):
if prop not in hideProperties and prop not in subProperties and prop not in properties:
yield prop, None, self.group.formats.get(prop, Format())
else:
if prop not in hideProperties:
yield prop, None, self.group.formats.get(prop, Format())
def formatResource(self, graph, resource):
if self.group:
stylesheets = set(self.group.stylesheets)
else:
stylesheets = set
elem = ET.Element("div")
css = ["fresnel_resource"]
if isinstance(resource, URIRef):
elem.set("about", resource)
elif isinstance(resource, BNode):
elem.set("about", "[_:%s]" % resource)
log.debug(" Resource: %s" % resource)
if isinstance(resource, URIRef):
uri = ET.Element("div")
uri.set("class", "fresnel_resource_uri")
a = ET.Element("a")
a.set("href", resource)
a.text = resource
try:
qname = self.namespace_manager.qname(resource)
if not qname.startswith("_"):
a.text = qname
except:
pass
uri.append(a)
elem.append(uri)
properties = self.properties(graph, resource)
for property, lens, format in properties:
styles, prop = self.formatProperty(graph, lens, format, resource, property)
if prop:
elem.append(prop)
[stylesheets.add(x) for x in styles]
elem.set("class", " ".join(css))
return stylesheets, elem
def formatProperty(self, graph, lens, format, resource, property):
log.debug(" Property: %s" % property)
log.debug(" Format: %s" % format)
elem = ET.Element("div")
css, styles = format.propertyStyles
css = ["fresnel_property"] + css
elem.set("class", " ".join(css))
if styles: elem.set("style", " ".join(styles))
label = format.label(property)
if label is not None:
span = ET.Element("span")
span.set("class", "fresnel_label")
a = ET.Element("a")
a.set("href", property)
a.text = label
span.append(a)
elem.append(span)
values = [
self.formatValue(graph, lens, format, resource, property, v)
for v in graph.objects(resource, property)
]
stylesheets = set()
if values:
container = ET.Element("div")
container.set("class", "fresnel_container")
[([stylesheets.add(s) for s in sheets], container.append(value))
for (sheets, value) in values]
elem.append(container)
elem.set("class", " ".join(css))
else:
elem = None
return stylesheets, elem
def rst(self, span, value):
try:
from docutils import core
parts = core.publish_parts(source=value, writer_name="html")
doc = u'<?xml version="1.0" encoding="utf-8"?>\n' + \
u'<html>\n' + parts["body"] + u"</html>\n"
elem = ET.XML(doc.encode("utf-8"))
for c in elem.getchildren():
span.append(c)
except ImportError:
span.text = value
def formatValue(self, graph, lens, format, resource, property, value):
elem = ET.Element("div")
css, styles = format.valueStyles
css = ["fresnel_value"] + css
elem.set("class", " ".join(css))
if styles: elem.set("style", " ".join(styles))
if format.group:
stylesheets = set(format.group.stylesheets)
else:
stylesheets = set()
ns, uri, local = self.namespace_manager.compute_qname(property)
if ns.startswith("_"):
ns = "ns%s" % ns[1:]
elem.set("xmlns:%s" % ns, uri)
pcurie = "%s:%s" % (ns, local)
if isinstance(value, Literal):
elem.set("property", pcurie)
elem.set("content", value)
if value.language:
sp = ET.Element("span")
sp.set("class", "fresnel_object_language")
sp.text = u" (%s) " % value.language
elem.append(sp)
self.rst(elem, value)
elem.set("xml:lang", value.language)
elif value.datatype:
elem.set("xml:lang", "")
if value.datatype == XSD["dateTime"]:
try:
dt = datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f")
elem.text = dt.ctime()
except:
elem.text = value
else:
elem.text = value
elem.set("datatype", value.datatype)
else:
elem.set("xml:lang", "")
self.rst(elem, value)
elif isinstance(value, URIRef) or isinstance(value, BNode):
elem.set("rel", pcurie)
if isinstance(value, URIRef):
elem.set("resource", value)
else:
elem.set("resource", "[_:%s]" % value)
if lens:
styles, rsrc = lens.formatResource(graph, value)
[stylesheets.add(x) for x in styles]
elem.append(rsrc)
elif isinstance(value, BNode):
lens = DefaultLens(self.fresnel, self.group)
styles, rsrc = lens.formatResource(graph, value)
[stylesheets.add(x) for x in styles]
elem.append(rsrc)
else:
if isinstance(value, URIRef):
if format.one((format.identifier, FRESNEL["value"], FRESNEL["image"])):
a = ET.Element("img")
a.set("src", value)
try:
qname = self.namespace_manager.qname(property)
a.set("alt", "qname")
except:
a.set("alt", property)
else:
# if format.one((format.identifier, FRESNEL["value"], FRESNEL["externalLink"])):
a = ET.Element("a")
a.set("href", value)
try:
pfx, uri, rest = self.compute_qname(value)
if not pfx.startswith("_"):
value = u"%s:%s" % (pfx, rest)
except:
pass
a.text = value
else:
a = ET.Element("span")
a.text = value
elem.append(a)
return stylesheets, elem
class DefaultLens(Lens):
def __init__(self, fresnel, group):
super(DefaultLens, self).__init__(fresnel, None)
self.group = group
def properties(self, graph, resource):
for prop in graph.distinct_predicates(resource):
yield prop, None, self.group.formats.get(prop, Format())
class Group(Graph):
def __init__(self, *av, **kw):
super(Group, self).__init__(*av, **kw)
self.lenses = {}
self.formats = {}
@property
def stylesheets(self):
if not hasattr(self, "__stylesheets__"):
self.__stylesheets__ = list(self.distinct_objects(self.identifier, FRESNEL["stylesheetLink"]))
return self.__stylesheets__
class Format(Graph):
def __init__(self, *av, **kw):
super(Format, self).__init__(*av, **kw)
self.group = None
def label(self, property):
# what spaghetti is this!
for _s, _p, label in self.triples((self.identifier, FRESNEL["label"], None)):
if label == FRESNEL["none"]:
return None
else:
return label
try:
qname = self.namespace_manager.qname(property)
if not qname.startswith("_"):
return qname
except:
pass
label = ":" + property.rsplit("/", 1)[-1].rsplit("#", 1)[-1]
return label
def styles(self, predicate):
css, styles = [], []
for s in self.objects(self.identifier, predicate):
if s.datatype == FRESNEL["stylingInstructions"]:
styles.append(s)
elif s.datatype == FRESNEL["styleClass"]:
css.append(s)
return css, styles
@property
def propertyStyles(self):
return self.styles(FRESNEL["propertyStyle"])
@property
def valueStyles(self):
return self.styles(FRESNEL["valueStyle"])
[docs]class Fresnel(Graph):
"""
.. automethod:: format
"""
__types__ = []
def __init__(self, *av, **kw):
super(Fresnel, self).__init__(*av, **kw)
self.lenses = {}
self.classLenses = {}
self.instanceLenses = {}
self.groups = {}
self._compiled = False
def compile(self):
if self._compiled:
return
self._compiled = True
for l in self.distinct_subjects(RDF["type"], FRESNEL["Lens"]):
lens = Lens(fresnel=self, identifier=l)
lens += self.bnc((l, None, None))
self.lenses[l] = lens
for cls in lens.objects(l, FRESNEL["classLensDomain"]):
self.classLenses[cls] = lens
for cls in lens.objects(l, FRESNEL["instanceLensDomain"]):
self.instanceLenses[cls] = lens
for grp in lens.objects(l, FRESNEL["group"]):
group = self.groups.get(grp)
if group is None:
group = Group(identifier=grp)
group += self.bnc((grp, None, None))
self.groups[grp] = group
group.lenses[l] = lens
lens.group = group
for fmt in self.distinct_subjects(RDF["type"], FRESNEL["Format"]):
format = Format(identifier=fmt)
format += self.bnc((fmt, None, None))
for grp in format.objects(fmt, FRESNEL["group"]):
group = self.groups.get(grp)
if group is None:
group = Group(identifier=grp)
group += self.bnc((grp, None, None))
self.groups[grp] = group
for dom in format.objects(fmt, FRESNEL["propertyFormatDomain"]):
group.formats[dom] = format
format.group = group
from ordf.command import Command
class Render(Command):
parser = Command.StandardParser(usage="%prog [options]")
parser.add_option("-t", "--template",
dest="template",
help="HTML Template")
parser.add_option("-r", "--resource",
dest="resource",
help="Resource to format")
default_template = """\
<html>
<body>
<fresnel />
</body>
</html>"""
def command(self):
template = self.default_template
if self.options.template:
template = open(self.options.template).read()
template = ET.fromstring(template)
fresnel_uri, graph_uri = self.args
tmp = self.handler.get(fresnel_uri)
fresnel = Fresnel(store=tmp.store, identifier=tmp.identifier)
graph = self.handler.get(graph_uri)
stylesheets, tree = fresnel.format(graph, URIRef(self.options.resource) if self.options.resource else None)
head = template.find("head")
if head is None:
head = ET.Element("head")
template.insert(0, head)
for sheet in stylesheets:
link = ET.Element("link")
link.set("rel", "stylesheet")
link.set("href", sheet)
link.set("type", "text/css")
head.append(link)
meta = ET.Element("meta")
meta.set("http-equiv", "Content-Type")
meta.set("content", "text/html; charset=utf-8")
head.append(meta)
# guess at a good title for the document
resource = URIRef(self.options.resource) if self.options.resource else graph.identifier
title = None
for label in DC["title"], FOAF["name"], RDFS["label"]:
for title in graph.distinct_objects(resource, label):
break
if title is not None:
break
if title is None:
title = resource
tt = ET.Element("title")
tt.text = title
head.append(tt)
def find_fresnel(parent):
index = 0
for child in parent:
# if child.tag == "{http://www.w3.org/1999/xhtml}fresnel":
if child.tag == "fresnel":
return parent, child, index
next = find_fresnel(child)
if next is not None:
return next
index += 1
parent, replace, index = find_fresnel(template)
parent.remove(replace)
parent.insert(index, tree)
doc = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">'
doc += '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">'
for child in template:
doc += ET.tostring(child, encoding="utf-8")
doc += '</html>'
print doc
# from xml.dom import minidom
# from StringIO import StringIO
# doc = minidom.parse(StringIO(doc))
# print doc.toprettyxml()
def render():
Render().command()