#!/usr/bin/python

#
# This is a dumb script to parse the ontology found at demo/xesam.rdfs
# and output a moinmoin-wiki formatting to stdout.
#
# WARNING
# It is absolutely not written with performance in mind so don't even
# think about putting it on a server which generates the page per request.
#
#

HEADER_GLOBAL = \
"""
"""

HEADER_FIELD = \
"""
<<Anchor(fields)>>
== Fields ==
"""

HEADER_SOURCE = \
"""
<<Anchor(sources)>>
== Sources ==
Sources are defined in a hierarchial structure where each source category implies the listed fields
as well as the fields implied by the parent source category.
"""

HEADER_CATEGORY = \
"""
<<Anchor(contents)>>
== Contents ==
Contents are defined in a hierarchial structure where each content category implies the listed fields
as well as the fields implied by the parent content category.
"""

HEADER_EXTERNALS = \
"""
<<Anchor(externals)>>
== External Entities ==
The items listed in this section a referenced from this ontology, but is not 
an integral part of it.
"""

SOURCE_TEMPLATE = \
"""
<<Anchor(%(escId)s)>>
==== %(External)sSource, %(Id)s ====
{{{             Url: }}}[[%(Url)s]]
  
{{{         Parents: }}}%(ParentList)s
  
{{{        Children: }}}%(Children)s
  
{{{  Fields implied: }}}%(FieldList)s

 '''Description:''' %(Comment)s
    
 '''All fields:''' %(AllFields)s
"""

CAT_TEMPLATE = \
"""
<<Anchor(%(escId)s)>>
==== %(External)sContent, %(Id)s ====
{{{             Url: }}}[[%(Url)s]]

{{{         Parents: }}}%(ParentList)s

{{{        Children: }}}%(Children)s

{{{  Fields implied: }}}%(FieldList)s

 '''Description:''' %(Comment)s
    
 '''All fields:''' %(AllFields)s
"""

FIELD_TEMPLATE = \
"""
<<Anchor(%(escId)s)>>
==== %(External)sField, %(Id)s ====
{{{   Data type: }}}%(DataType)s

{{{         Url: }}}[[%(Url)s]]

{{{      Parent: }}}%(ParentList)s

{{{    Children: }}}%(Children)s

{{{  Belongs to: }}}%(CategoryList)s

 '''Description:''' %(Comment)s
"""


import demo
from os.path import *
import sys

from xesam.ontology import *
from xesam.ontology import rdf

def print_ontology (onto_paths, external_ontos=None):
	parser = rdf.RdfXmlParser()
	roots = parser.parse (onto_paths, external_ontos=external_ontos)
	onto = Ontology (roots)
	
	fields = list(onto.get_fields())
	contents = list(onto.get_contents())
	sources = list(onto.get_sources())
	
	for l in fields, contents, sources:
		l.sort(lambda x, y : cmp (x.get_id(), y.get_id()))
	
	print HEADER_GLOBAL

	print HEADER_SOURCE
	
	for src in sources:
		if not src.is_external ():
				print format_src (src)
	
	print HEADER_CATEGORY
	
	for cont in contents:
		if not cont.is_external ():
				print format_cat (cont)
		
	print HEADER_FIELD
	
	for f in fields:
		if not f.is_external ():
				print format_field (f)
	
	return parser
	

def esc (string):
	return string.replace(":", "")

def get_parent_list (mapper):
	parent_list = ""
	for parent in mapper.get_parents():
		if isinstance (parent, RootItem):
			continue
		parent_list += "[[#%s|%s]]" % (esc(parent.get_id()), parent.get_id())
		parents = list(parent.get_parents())
		if len(parents) > 1: # This mapper has multiple parents, hint it with a star
			parent_list += "*"
		parent = parents[0]
		while not isinstance(parent,RootItem):
			parent_list += " < [[#%s|%s]]" % (esc(parent.get_id()), parent.get_id())
			parents = list(parent.get_parents())
			if len(parents) > 1: # This mapper has multiple parents, hint it with a star
				parent_list += "*"
			parent = parents[0]
		parent_list += "<<BR>>"
	
	if len(parent_list) == 0:
		return "None"
	if parent_list.endswith("<<BR>>"):
		parent_list = parent_list[:-6]
	return parent_list

def get_field_ids (mapper):
	fields = [field.get_id() for field in mapper.get_fields()]
	fields.sort()
	return fields
	
def get_all_field_ids (mapper):
	all_fields = [field.get_id() for field in mapper.get_all_fields()]
	all_fields.sort()
	return all_fields

def format_src (src):
	info = {}
	info.update (src.get_properties())
	info["Id"] = src.get_id()
	info["escId"] = esc(src.get_id())
	info["FieldList"] = ", ".join(["[[#%s|%s]]" % (esc(field_id),field_id) for field_id in get_field_ids(src)])
	info["AllFields"] = ", ".join(["[[#%s|%s]]" % (esc(field_id),field_id) for field_id in get_all_field_ids(src)])
	info["ParentList"] = get_parent_list(src)
	info["Children"] = ", ".join(["[[#%s|%s]]" % (esc(child_id),child_id) for child_id in src.get_child_names()])
	info["External"] = src.is_external() and "External " or ""
	return SOURCE_TEMPLATE % info

def format_cat (cat):
	info = {}
	info.update (cat.get_properties())
	info["Id"] = cat.get_id()
	info["escId"] = esc(cat.get_id())
	info["FieldList"] = ", ".join(["[[#%s|%s]]" % (esc(field_id),field_id) for field_id in get_field_ids(cat)])
	info["AllFields"] = ", ".join(["[[#%s|%s]]" % (esc(field_id),field_id) for field_id in get_all_field_ids(cat)])
	info["ParentList"] = get_parent_list(cat)
	info["Children"] = ", ".join(["[[#%s|%s]]" % (esc(child_id),child_id) for child_id in cat.get_child_names()])
	info["External"] = cat.is_external() and "External " or ""
	return CAT_TEMPLATE % info
	
def format_field (field):
	info = {}
	info.update (field.get_properties())
	
	info["DataType"] = field["DataType"]
	if info["DataType"] is None : info["DataType"] = "Abstract field. Contains no data."
	elif not field["Cardinality"] : info["DataType"] = "List of %ss" % info["DataType"]
	
	info["ParentList"] = get_parent_list(field)#", ".join(["[#%s %s]" % (parent.get_id(), parent.get_id()) for parent in field.get_parents()])
	info["Id"] = field.get_id()
	info["escId"] = esc(field.get_id())
	info["CategoryList"] = ", ".join (["[[#%s|%s]]" % (esc(cat.get_id()), cat.get_id()) for cat in field.get_categories()])
	info["Children"] = ", ".join(["[[#%s|%s]]" % (esc(child_id),child_id) for child_id in field.get_child_names()])
	info["External"] = field.is_external() and "External " or ""
	return FIELD_TEMPLATE % info

def print_externals (parser):
	if len(parser.get_external_refs()) > 0:
		print HEADER_EXTERNALS
		
		externals = list(parser.get_external_refs().itervalues())
		externals.sort (lambda x, y : cmp (x.get_id(), y.get_id()))
		
		for ext in externals:
			if ext.get_type() == Item.TYPE_FIELD:
				print format_field(ext)
			if ext.get_type() == Item.TYPE_SOURCE:
				print format_source(ext)
			if ext.get_type() == Item.TYPE_CONTENT:
				print format_cat(ext)

if __name__ == "__main__":
	if len(sys.argv) == 1:
		print "USAGE:\n\t%s <ontology-file>..." % (sys.argv[0]) 
		print "\nAll listed ontology files will be included in the final document"
		print "\nPrepend 'ext:' to include a file as an extenal ontology that will not be included only cross referenced"
		print ""
		raise SystemExit
	
	external_sources = []
	onto_sources = []
	
	for f in sys.argv[1:]:
		if f.startswith ("ext:"):
			external_sources.append(f[4:])
		else:
			onto_sources.append(f)
	
	external_parser = rdf.RdfXmlParser ()
	external_roots = external_parser.parse(external_sources)
	external_onto = Ontology(external_roots)
	
	parser = print_ontology(onto_sources, external_ontos=[external_onto])
	print_externals (parser)
	
