#!/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 = \
"""
= Ontology =
All objects are characterized by two main properties; ''Source'' and ''Content''.
These are read as fields on the object and in addition to characterizing the type
and representation of the object also imply which other fields to expect.

''Source'': The physical representation of the object.

''Content'': The abstract interpretation of the object.

And example could be an office document stored on the harddisk. It would have source
''File'' and category ''Document''.

=== Categories and Fields ===
''Source'' and ''Content'' are called ''categories''. Technically speaking a category is
the top level of a branch in the ontology tree that is not a field. Third party can install
new categories, but this is not expected to be a common thing. The two default categories
of the xesam core ontology should suffice for most purposes.

A category define what fields make sense on an object belonging to it. These fields are
not guaranteed to be set though.
"""

HEADER_FIELD = \
"""
[[Anchor(fields)]]
== Fields ==
"""

HEADER_SOURCE = \
"""
[[Anchor(sources)]]
== Sources ==
"""

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

SOURCE_TEMPLATE = \
"""
[[Anchor(%(Id)s)]]
==== Source, %(Id)s ====
  ||<)#dddddd> {{{Url}}}    || {{{%(Url)s}}} ||
  ||<)#dddddd> {{{Parents}}} || %(ParentList)s ||
  ||<)#dddddd> {{{Children}}}      || %(Children)s ||
  ||<)#dddddd> {{{Fields implied}}} || %(FieldList)s ||
  '''Description:''' %(Comment)s
    
  '''All fields:''' %(AllFields)s
"""

CAT_TEMPLATE = \
"""
[[Anchor(%(Id)s)]]
==== Content, %(Id)s ====
  ||<)#dddddd> {{{Url}}}    || {{{%(Url)s}}} ||
  ||<)#dddddd> {{{Parents}}} || %(ParentList)s ||
  ||<)#dddddd> {{{Children}}}      || %(Children)s ||
  ||<)#dddddd> {{{Fields implied}}} || %(FieldList)s ||
  '''Description:''' %(Comment)s
    
  '''All fields:''' %(AllFields)s
"""

FIELD_TEMPLATE = \
"""
[[Anchor(%(Id)s)]]
==== Field, %(Id)s ====
  ||<)#dddddd> {{{Url}}}         || {{{%(Url)s}}} ||
  ||<)#dddddd> {{{Parent}}}      || %(ParentList)s ||
  ||<)#dddddd> {{{Children}}}      || %(Children)s ||
  ||<)#dddddd> {{{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)
	
	# We need a list of ids to get alphabetical sorting
	item_ids = []
	item_map = {}
	for root in roots:
		item_ids.append(root.get_id())
		item_map[root.get_id()] = root
		if isinstance(root,FieldMapper):
			for field in root.get_all_fields():	
				item_ids.append(field.get_id())
				item_map[field.get_id()] = field
		
		children= root.get_all_children()
		for child in children:
			item_ids.append(child.get_id())
			item_map[child.get_id()] = child
			if isinstance(root,FieldMapper):
				for field in child.get_fields():	
					item_ids.append(field.get_id())
					item_map[field.get_id()] = field
	item_ids = list(set(item_ids)) # Remove dupes
	item_ids.sort()
	
	print HEADER_GLOBAL
	
	print HEADER_SOURCE
	
	for item_id in item_ids:
		item = item_map[item_id]
		if item.get_type() == Item.TYPE_SOURCE:
			if not item.is_external ():
				print format_src (item)
	
	print HEADER_CATEGORY
	
	for item_id in item_ids:
		item = item_map[item_id]
		if item.get_type() == Item.TYPE_CONTENT:
			if not item.is_external ():
				print format_cat (item)
		
	print HEADER_FIELD
	
	for item_id in item_ids:
		item = item_map[item_id]
		if item.get_type() == Item.TYPE_FIELD:
			if not item.is_external ():
				print format_field (item)
	
	

def get_parent_list (mapper):
	parent_list = ""
	for parent in mapper.get_parents():
		if isinstance (parent, RootItem):
			continue
		parent_list += "[#%s %s]" % (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]" % (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["FieldList"] = ", ".join(["[#%s %s]" % (field_id,field_id) for field_id in get_field_ids(src)])
	info["AllFields"] = ", ".join(["[#%s %s]" % (field_id,field_id) for field_id in get_all_field_ids(src)])
	info["ParentList"] = get_parent_list(src)
	info["Children"] = ", ".join(["[#%s %s]" % (child_id,child_id) for child_id in src.get_child_names()])
	
	return SOURCE_TEMPLATE % info

def format_cat (cat):
	info = {}
	info.update (cat.get_properties())
	info["Id"] = cat.get_id()
	info["FieldList"] = ", ".join(["[#%s %s]" % (field_id,field_id) for field_id in get_field_ids(cat)])
	info["AllFields"] = ", ".join(["[#%s %s]" % (field_id,field_id) for field_id in get_all_field_ids(cat)])
	info["ParentList"] = get_parent_list(cat)
	info["Children"] = ", ".join(["[#%s %s]" % (child_id,child_id) for child_id in cat.get_child_names()])
	return CAT_TEMPLATE % info
	
def format_field (field):
	info = {}
	info.update (field.get_properties())
	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["CategoryList"] = ", ".join (["[#%s %s]" % (cat.get_id(), cat.get_id()) for cat in field.get_categories()])
	info["Children"] = ", ".join(["[#%s %s]" % (child_id,child_id) for child_id in field.get_child_names()])
	return FIELD_TEMPLATE % info


#def format_item (item, item_type=None):
#	if isinstance(item, FieldMapper) and item_type == item.get_type():
#		print format_cat(item)
#	elif isinstance (item, FieldMapper) and item_type == item.get_type():
#		print format_src (item)
#	elif isinstance (item, Field) and item_type == item.get_type():
##	
#	for child in item.get_children ():
#		format_item(child, item_type)
#	
#	if isinstance (item, FieldMapper):
#		for field in item.get_fields():
#			format_item (field, item_type)


if __name__ == "__main__":
	if len(sys.argv) == 1:
		print "USAGE:\n\t%s <ontology-file>" % (sys.argv[0]) 
		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)
	
	print_ontology(onto_sources, external_ontos=[external_onto])
