#!/usr/bin/python

# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What The Fuck You Want
# To Public License, Version 2, as published by Sam Hocevar. See
# http://sam.zoy.org/wtfpl/COPYING for more details.

import os, re, sys

def sanitizeName(name):
	return re.sub("[^a-zA-Z]","",name)

testdir = "workspace/hausarbeit"
positions = "position.inc.mp"
files=[]
sym = { "private" : "-", "public" : "+", "protected" : "#" }
lastName = ""

"""Get a list of the files, which should be processed"""
def dirreader(dir):
	files=[]
	for file in os.listdir(dir):
		if os.path.isdir(dir+"/"+file):
			ret = dirreader(dir+"/"+file)
			for f in ret:
				files.append(f)
		elif file[-4:] == "java":
			files.append(dir+"/"+file)
	return files

classes=[]
parameter=[]
extends={}
implements=[]
uses=[]
tobecheckedclasses=[]
print "input metauml;"
print "beginfig(1)"
for f in dirreader(testdir):
	print "% Processing file "+f.split("/")[-1]
	ret=""
	vars=[]
	func=[]
	name=""
	special=[]
	template=""
	lastName
	fh = open(f,"r")
	for line in fh.readlines():
		l = line.strip().split(" ")
		if l.count("class") > 0 and l.count("abstract") > 0:
			l.remove("abstract")
			special.append("abstract")
		if l[0] == "public" or l[0] == "private" or l[0] == "protected":
			# only take the first class
			rest = " ".join(l[2:])
			rest = rest[:rest.find("{")]
			if l[2].find("<") != -1:
				if (l.count("class") > 0 or l.count("interface")) and ret == "":
					print "% Class is parametrized with parameters "+rest[rest.find("<"):rest.find(">")+1]
					name=sanitizeName(rest[:rest.find("<")])
					for p in rest[rest.find("<")+1:rest.find(">")].split(","):	
						template = "ClassTemplate."+name+"T(\""+ p +"\")("+name+");"
						parameter.append(name+"T")
				rest=rest[rest.find(">")+1:]
				dispName = l[2][:l[2].find("<")];
			else:
				if (l.count("class") > 0 or l.count("interface")) and ret == "":
					name=sanitizeName(l[2])
					dispName = l[2]
			if l.count("class") > 0:
				if ret == "":
					# check if name is parametrized
					ret="Class."+name+"(\""+dispName+"\")"
					if name in classes:
						print "% WARNING: dublicate class"
					classes.append(name)
				else:
					continue
			elif l.count("interface") > 0:
				ret="Class."+name+"(\""+dispName+"\")"
				special.append("interface")
				classes.append(name)
			elif line.find("=") == -1 and line.find("(") > -1:
				footprint = " ".join(l[1:])
				func.append(sym[l[0]]+footprint[:footprint.find(")")+1].strip())
			else:
				if l.count("static") > 0:
					l.remove("static")
				if l.count("final") > 0:
					l.remove("final")
				rest = " ".join(l[1:])
				if line.find("=") > -1:
					signature = rest[:rest.find("=")].strip()
				else:
					signature = rest[:rest.find(";")].strip()
				uses.append({name : signature.split(" ")[0]})
				vars.append(sym[l[0]]+signature)
			if rest.find("extends") != -1:
				list=rest[rest.find("extends")+8:].split(" ")
				if list[0][-1] == ",":
					extends[name]=" ".join(list[0:2])
				else:
					extends[name]=list[0]
			if rest.find("implements") != -1:
				rest = rest[rest.find("implements")+11:]
				rest.replace(" ","")
				for i in rest.split(","):
					implements.append({name : i.strip()})
		elif l[0] == "package":	
			pass
		#	print "Package declaration: "+" ".join(l[1:])
		elif l[0] == "import":
			pass
		#	print "Import: "+" ".join(l[1:])
		elif line.find("=") > 0:
			left = line[:line.find("=")]
			left = left.strip().split(" ")
			if len(left) == 2:
				no = ord(left[1][0])
				if ((no > 100 and no < 133) or (no > 140 and no <173)) and left[0][:2] != "//":
					if left[0].find("<") > -1:
						uses.append({name : sanitizeName(left[0][left[0].find("<")+1:left[0].find(">")])})
						var = left[0][:left[0].find("<")]
					elif left[0].find("[") > -1:
						var = left[0][:left[0].find("[")]
					else:
						var = left[0]
					uses.append({name : sanitizeName(var)})
		elif line.find("new ") > 0:
			rest = line;
#			print "% BLASTART: "+line[line.find("new ")+4:]
			while rest.find("new ") > 0:
				rest = rest[rest.find("new ")+4:]
				out = rest[:rest.find("(")]
				if out.find("[") == -1:
					uses.append({name : sanitizeName(out)})
				rest = rest[rest.find("("):]
		else:
			pass
#			print "Nothing: "+l[0]
	fh.close()
	if name == "":
		ret = ""
	if len(vars) > 0:
		ret = ret+"\n\t(\""+"\",\n\t \"".join(vars)+"\")"
	else:
		ret = ret+"()\n\t"
	if len(func) > 0:
		ret = ret+"\n\t(\""+"\",\n\t \"".join(func)+"\");\n"
	else:
		ret = ret+"();\n"
#	if lastName != "":
#		ret = ret + name+".n = "+lastName+".s + (0, -20);\n"
#	else:
#		print "% No lastName"
	for s in special:
		if s == "interface":
			ret = ret + "classStereotypes." + name + "(\"<<interface>>\");\n"
		elif s == "abstract":
			ret = ret + "classStereotypes." + name + "(\"<<abstract>>\");\n"
	if template != "":
		ret = ret + template + "\n"
#	ret = ret + "drawObject("+name+");\n"
	lastName = name
	print ret
	print "% -----------------------"
print "% Draw everything"
if not os.path.exists(positions):
	fh = open(positions,"w")
	fh.write("topToBottom(20)("+", ".join(classes)+");")
	fh.close()
fh = open(positions,"r")
for l in fh.readlines():
	print l,
fh.close()
#print "topToBottom(20)("+", ".join(classes)+");"
print "drawObjects("+", ".join(classes + parameter)+");"
print "% Links"
foreign=[]

for i in implements:
	tmp = i.values()[0]
	if tmp.find("<") != -1:
		print "% parametrized Link: "+tmp[tmp.find("<"):tmp.find(">")+1]
		tmp = tmp[:tmp.find("<")]
	if tmp in classes:
		print "% Implements"
		print "clink(inheritance)("+tmp+", "+i.keys()[0]+");"
	else:
		if tmp not in foreign:
			foreign.append(tmp)

for k, v in extends.iteritems():
	if v.find("<") != -1:
		print "% parametrized Link: "+v[v.find("<"):v.find(">")+1]
		v = v[:v.find("<")]
	if v in classes:
		print "clink(inheritance)("+sanitizeName(v)+", "+sanitizeName(k)+");"
	else:
		if v not in foreign:
			foreign.append(v)
used=[]
for i in uses:
	if i in used:
		continue
	else:
		used.append(i)
	tmp = i.values()[0]
	if tmp.find("<") != -1:
		tmp = tmp[tmp.find("<")+1:tmp.find(">")]
	if tmp[-2:] == "[]":
		tmp = tmp[:-2]
	if sanitizeName(tmp) == sanitizeName(i.keys()[0]):
		continue;
	if sanitizeName(tmp) in classes:
		print "clink(aggregation)("+sanitizeName(tmp)+", "+sanitizeName(i.keys()[0])+");"
	else:
		if tmp not in foreign:
			foreign.append(tmp)

#for c in foreign:
#	print "Class."+sanitizeName(c)+"(c)()();"
print "endfig;"
print "end"

