#!/usr/bin/python
#
# Fixes the coral.py file so that it works correctly with reference
# counting and stuff.
#
#

import re
import sys

f = file(sys.argv[1], "r")

ref_counted_classes = { "ref_counted": True }

fix_ignore_del = 0
fix_init = 0
ref_in_init = 1

fix_dict_usage = 0
fix_getattr = 0
skip_eq = 0

fix_magic_setattr = 0

swig_setattr = 1

blurb_modifycmd = \
"""
"""

while 1:
	l = f.readline()
	if not l:
		break

	if re.search("cvar = _coral.cvar", l):
		continue
	if re.search("_swig_setattr\(self,.*, 'thisown'", l):
		continue
	# apply() is deprecated in python2.3
	m = re.search("(.*)apply\((.*),args\)(.*)", l)
	if m:
		l = m.group(1) + m.group(2) + "(*args)" + m.group(3) + "\n"

	if re.search("^import _", l):
		l = re.sub("^import _(.*)", "import lib\\1 as _\\1", l)
		print l
		print "import inspect"
		print "from coral.exceptions import WFRException"
		print "import os"
		print "import os.path"
		print ''
		print "def formatWellFormedRuleException(rule,object):"
		print "    t = object.__type__()"
		print "    p = []"
		print "    while t:"
		print "        p.append(t.getName())"
		print "        t = t.__package__()"
		print "    p.reverse()"
		print "    ps = \"::\".join(p)"
		print "    s=    \"\\nRule name: \" + ps + \".\" + rule.getFuncName()+\"\\n\""
		print "    try:"
		print "        s=s+\"Rule body:\\n\" + object.getCode()"
		print "    except:"
		print "        pass"
		print "    s = s + \"Offender:\" + str(object) + \"\\n\""
		print "    return s"
		print ""
		print "def isWellFormed(self,toIgnore=[]):"
		print "    cl = self.__type__().getAllSuperclasses()"
		print "    cl.append(self.__type__())"
		print "    for c in cl:"
		print "        for op in c.__operations__():"
		print "            if op.getFuncName() in toIgnore:"
		print "                continue"
		print "            if not op.isWFR():"
		print "                continue"
		print "            if not op.getFunc()(self):"
		print "                raise WFRException(\"Well-formed rule \" + c.getName() + \".\" + op.getFuncName() + \" does not hold \" + formatWellFormedRuleException(op, self), self)"
		print ""
		continue
	if re.search("if hasattr\(value,\"thisown\"\):", l):
		f.readline()
		continue

	#if swig_setattr and re.search("if method: return method\(self,value\)", l):
	#	swig_setattr = 0
	#	continue

	if re.search("def _swig_getattr", l):
		sys.stdout.write(l)
		sys.stdout.write("    method = class_type.__swig_getmethods__.get(name,None)\n")
		sys.stdout.write("    if method: return method(self)\n")
		#sys.stdout.write("    if name != \"this\" and name != \"thisown\":\n")
		sys.stdout.write("    if isinstance(self, EnumerationDefinition):\n")
		sys.stdout.write("    \treturn self.getIndexByDescription(name)\n")
		sys.stdout.write("    raise AttributeError,name\n")
		f.readline()
		f.readline()
		f.readline()
		# MAGIC SETATTR, only for Element... makes myclass.namespace = mymodel work
		t = ""
		t+= '\n'
		t+= "def Element_swig_setattr(self,name,value):\n"
		t+= "    if name == \"__project__\":\n"
		t+= "        return self.__setProject__(value)\n"
		t+= "    vtype = type(value)\n"
		t+= "    if vtype == list or issubclass(vtype, Slot):\n"
		# Bah, coralPyObjs can also accept lists...
		t+= "        if self.__type__().getPropertyByName(name).getTarget() == coralPyObj:\n"
		t+= "            self.__getSlotByNameInsert__(name, value)\n"
		t+= "            return\n"
		t+= "        feature = self.__getattr__(name)\n"
		t+= "        feature.resetSlot()\n"
		t+= "        for i in value:\n"
		t+= "            feature.add(i)\n"
		t+= "    elif value is None or isinstance(value, Element):\n"
		t+= "        self.__getSlotByNameInsertElement__(name, value)\n"
		t+= "    else:\n"
		# We'll just traceback here if we pass wrong arguments...
		t+= "        self.__getSlotByNameInsert__(name, value)\n"
		sys.stdout.write(t)
		continue

	### FIX REFCOUNTING
	if re.search("^class ref_counted\(_object\):", l):
		fix_ignore_del = 1
		sys.stdout.write(l)
		sys.stdout.write("    def __del__(self, *args):\n")
		sys.stdout.write("        if _coral: self.unref()\n")
		continue
	m = re.search("^class (.*)\((.*)\):", l)
	if m:
		newclass = m.group(1)
		superclasses = [x.strip() for x in m.group(2).split(",") ]
		for r in superclasses:
			if ref_counted_classes.has_key(r):
				ref_counted_classes[newclass] = True
				fix_ignore_del = 1
				break
		
	if re.search("class Element\(", l):
		fix_magic_setattr = 1
		fix_dict_usage = 1
		fix_getattr = 1
		# magic getattr. makes foo = myclass.namespace work
		sys.stdout.write(l)
		t = ""
		t += "    def __call__(self,*args,**kargs):\n"
		t += "        return self.__invoke__(*args,**kargs)\n"
		t += "    def __kill__(self): \n"
		t += "        self.__setProject__(None)\n"
		t += "        self.__resetAttrs__()\n"
		t += "    def __getattr__(self, name):\n"
		t += "        try:\n"
		t += "            t = self.__getSlotByName__(name)\n"
		t += "        except RuntimeError:\n"
		t += "            if name == \"__project__\":\n"
		t += "                return self.__getProject__()\n"
		t += "            if name == \"__meta__\":\n"
		t += "                return self.__type__().getCorrespondingElement()\n"
		t += "            try:\n"
		t += "                return self.__type__().__bindOperation__(name,self)\n"
		t += "            except AttributeError:\n"
		t += "                try:\n"
		t += "                    operation = self.__type__().__bindOperation__(\"__browse__\", self)(name)\n"
		t += "                except AttributeError:\n"
		t += "                    raise AttributeError(\"AttributeError: \" + str(self) + \" has no attribute '\" + str(name) + \"'\")\n"
		t += "                return operation\n"
		t += "        if t.getProperty().isAtMostOne():\n"
		t += "            # This makes things much faster, but we always have to keep the same slot!\n"
		t += "            self.__dict__[name] = t[0]\n"
		t += "            return t[0]\n"
		t += "        # This makes things much faster, but we always have to keep the same slot!\n"
		t += "        self.__dict__[name] = t\n"
		t += "        return t\n"
		t += "\n"
		sys.stdout.write(t)
		continue
	
	if re.search("class PresentationInstancePtr\(", l):
		fix_init = 1
	if re.search("class PackagesIteratorPtr\(", l):
		fix_init = 1
		ref_in_init = 0
	if re.search("class MDAEDIteratorPtr\(", l):
		fix_init = 1
		ref_in_init = 0
	if re.search("class SuperClassesIteratorPtr\(", l):
		fix_init = 1
		ref_in_init = 0
	if re.search("class SubClassesIteratorPtr\(", l):
		fix_init = 1
		ref_in_init = 0
	if re.search("class OperationsIteratorPtr\(", l):
		fix_init = 1
		ref_in_init = 0
	if re.search("class PropertyPtr\(", l):
		fix_init = 1
		fix_dict_usage = 1
	if re.search("class SlotIteratorPtr\(", l):
		fix_init = 1
	if re.search("class ElementPtr\(", l):
		fix_init = 1
		fix_dict_usage = 1
	if re.search("class ElementPrimitivePtr\(", l):
		fix_init = 1
		fix_dict_usage = 1
	if re.search("class ElementIteratorPtr\(", l):
		fix_init = 1
	if re.search("class ProjectPtr\(", l):
		fix_init = 1
	if re.search("class TransactionPtr\(", l):
		fix_init = 1
	if re.search("class CommandPtr\(", l):
		fix_init = 1
	if re.search("class ChangeElementPrimitiveCommandPtr\(", l):
		fix_init = 1
	if re.search("class ProjectChangeCommandPtr\(", l):
		fix_init = 1
	if re.search("class ProjectNameChangeCommandPtr\(", l):
		fix_init = 1
	if re.search("class NewProjectCommandPtr\(", l):
		fix_init = 1
	if re.search("class ElementCommandPtr\(", l):
		fix_init = 1
	if re.search("class ElementChangeSlotCommandPtr\(", l):
		fix_init = 1
	if re.search("class ElementNewCommandPtr\(", l):
		fix_init = 1
	if re.search("class ElementUUIDCommandPtr\(", l):
		fix_init = 1
	if re.search("class PyOperationPtr\(", l):
		fix_init = 1
	if re.search("class PackagePtr\(", l):
		fix_init = 1
	if re.search("class LanguagePtr\(", l):
		fix_init = 1
	if re.search("class ElementDefinitionPtr\(", l):
		fix_init = 1
	if re.search("class DatatypeDefinitionPtr\(", l):
		fix_init = 1
	if re.search("class EnumerationDefinitionPtr\(", l):
		fix_init = 1
	if re.search("class AbstractElementDefinitionPtr\(", l):
		fix_init = 1
	if re.search("class IteratorPtr\(", l):
		fix_init = 1
		ref_in_init = 0
	if re.search("class CollectionPtr\(", l):
		fix_init = 1
	if re.search("class SetPtr\(", l):
		fix_init = 1
	if re.search("class BagPtr\(", l):
		fix_init = 1
	if re.search("class OrderedSetPtr\(", l):
		fix_init = 1
	if re.search("class SequencePtr\(", l):
		fix_init = 1
	if re.search("class ModelFeatureIteratorPtr\(", l):
		fix_init = 1
		ref_in_init = 0
	if re.search("class PropertyIteratorPtr\(", l):
		fix_init = 1
		ref_in_init = 0
	if re.search("class ModelDifferencePtr\(", l):
		fix_init = 1
		ref_in_init = 0



	if re.search("class Slot\(", l):
		fix_ignore_del = 1
	if re.search("class Manager\(", l):
		fix_ignore_del = 1
	if re.search("class DCE_UUID\(", l):
		fix_ignore_del = 1
	if re.search("class ElementPrimitive\(", l):
		sys.stdout.write(l)
		fix_getattr=1
		l = ""
		t = ""
		t += "    def __getattr__(self,name):\n"
		t += "        if name == \"__meta__\":\n"
		t += "            return self.__type__().getCorrespondingElement()\n"
		t += "        return _swig_getattr(self, ElementPrimitive, name)\n"
   
		t += "    def __eq__(*args):\n"
		t += "        o = args[1]\n"
		t += "        s = args[0]\n"
		t += "        t = type(o)\n"
		t += "        if o is None:\n"
		t += "            return False\n"
		t += "        if t == int:\n"
		t += "            return int(s) == o\n"
		t += "        if t == float:\n"
		t += "            return float(s) == o\n"
		t += "        if t == unicode or t == str:\n"
		t += "            return unicode(s) == o\n"
		t += "        return _coral.ElementPrimitive___eq__(*args)\n"
		t += "    def __ne__(*args):\n"
		t += "        o = args[1]\n"
		t += "        s = args[0]\n"
		t += "        t = type(o)\n"
		t += "        if o is None:\n"
		t += "            return True\n"
		t += "        if t == int:\n"
		t += "            return int(s) != o\n"
		t += "        if t == float:\n"
		t += "            return float(s) != o\n"
		t += "        if t == unicode or t == str:\n"
		t += "            return unicode(s) != o\n"
		t += "        return _coral.ElementPrimitive___ne__(*args)\n"
		t += "    def __lt__(*args):\n"
		t += "        o = args[1]\n"
		t += "        s = args[0]\n"
		t += "        t = type(o)\n"
		t += "        if t == int:\n"
		t += "            return int(s) < o\n"
		t += "        if t == float:\n"
		t += "            return float(s) < o\n"
		t += "        if t == unicode or t == str:\n"
		t += "            return unicode(s) < o\n"
		t += "        return _coral.ElementPrimitive___lt__(*args)\n"
		t += "    def __le__(*args):\n"
		t += "        o = args[1]\n"
		t += "        s = args[0]\n"
		t += "        t = type(o)\n"
		t += "        if t == int:\n"
		t += "            return int(s) <= o\n"
		t += "        if t == float:\n"
		t += "            return float(s) <= o\n"
		t += "        if t == unicode or t == str:\n"
		t += "            return unicode(s) <= o\n"
		t += "        return _coral.ElementPrimitive___le__(*args)\n"
		t += "    def __gt__(*args):\n"
		t += "        o = args[1]\n"
		t += "        s = args[0]\n"
		t += "        t = type(o)\n"
		t += "        if t == int:\n"
		t += "            return int(s) > o\n"
		t += "        if t == float:\n"
		t += "            return float(s) > o\n"
		t += "        if t == unicode or t == str:\n"
		t += "            return unicode(s) > o\n"
		t += "        return _coral.ElementPrimitive___gt__(*args)\n"
		t += "    def __ge__(*args):\n"
		t += "        o = args[1]\n"
		t += "        s = args[0]\n"
		t += "        t = type(o)\n"
		t += "        if t == int:\n"
		t += "            return int(s) >= o\n"
		t += "        if t == float:\n"
		t += "            return float(s) >= o\n"
		t += "        if t == unicode or t == str:\n"
		t += "            return unicode(s) > o\n"
		t += "        return _coral.ElementPrimitive___ge__(*args)\n"

		t += "\n"
		t += "    def encode(self, encoding):\n"
		t += "        return self.__str__().encode(encoding)\n"

		t += "    def __getitem__(self, idx):\n"
		t += "        if self.oclIsKindOf(String):\n"
		t += "            return unicode(self)[idx]\n"
		t += "        assert 0\n"
		t += "    def __add__(self, other):\n"
		t += "        if self.oclIsKindOf(UnlimitedInteger):\n"
		t += "            return long(self) + other\n"
		t += "        if self.oclIsKindOf(UnlimitedReal):\n"
		t += "            return float(self) + other\n"
		t += "        if self.oclIsKindOf(String):\n"
		t += "            return unicode(self) + other\n"
		t += "        assert 0\n"
		
		t += "    def __sub__(self, other):\n"
		t += "        if self.oclIsKindOf(UnlimitedInteger):\n"
		t += "            return long(self) - other\n"
		t += "        if self.oclIsKindOf(UnlimitedReal):\n"
		t += "            return float(self) - other\n"
		t += "        #if self.oclIsKindOf(String):\n"
		t += "        #    return unicode(self) - other\n"
		t += "        assert 0\n"
		
		t += "    def __mul__(self, other):\n"
		t += "        if self.oclIsKindOf(UnlimitedInteger):\n"
		t += "            return long(self) * other\n"
		t += "        if self.oclIsKindOf(UnlimitedReal):\n"
		t += "            return float(self) * other\n"
		t += "        if self.oclIsKindOf(String):\n"
		t += "            return unicode(self) * other\n"
		t += "        assert 0\n"

		t += "    def __div__(self, other):\n"
		t += "        if self.oclIsKindOf(UnlimitedInteger):\n"
		t += "            return long(self) / other\n"
		t += "        if self.oclIsKindOf(UnlimitedReal):\n"
		t += "            return float(self) / other\n"
		t += "        if self.oclIsKindOf(String):\n"
		t += "            return unicode(self) / other\n"
		t += "        assert 0\n"

		t += "    def __floordiv__(self, other):\n"
		t += "        if self.oclIsKindOf(UnlimitedInteger):\n"
		t += "            return long(self) // other\n"
		t += "        if self.oclIsKindOf(UnlimitedReal):\n"
		t += "            return float(self) // other\n"
		t += "        #if self.oclIsKindOf(String):\n"
		t += "        #    return unicode(self) // other\n"
		t += "        assert 0\n"
		
		t += "    def __mod__(self, other):\n"
		t += "        if self.oclIsKindOf(UnlimitedInteger):\n"
		t += "            return long(self) % other\n"
		t += "        if self.oclIsKindOf(UnlimitedReal):\n"
		t += "            return float(self) % other\n"
		t += "        #if self.oclIsKindOf(String):\n"
		t += "        #    return unicode(self) % other\n"
		t += "        assert 0\n"
		
		t += "    def __radd__(self, other):\n"
		t += "        if self.oclIsKindOf(UnlimitedInteger):\n"
		t += "            return other + long(self)\n"
		t += "        if self.oclIsKindOf(UnlimitedReal):\n"
		t += "            return other + float(self)\n"
		t += "        if self.oclIsKindOf(String):\n"
		t += "            return other + unicode(self)\n"
		t += "        assert 0\n"
		
		t += "    def __rsub__(self, other):\n"
		t += "        if self.oclIsKindOf(UnlimitedInteger):\n"
		t += "            return other - long(self)\n"
		t += "        if self.oclIsKindOf(UnlimitedReal):\n"
		t += "            return other - float(self)\n"
		t += "        #if self.oclIsKindOf(String):\n"
		t += "        #    return other - unicode(self)\n"
		t += "        assert 0\n"

		t += "    def __rdiv__(self, other):\n"
		t += "        if self.oclIsKindOf(UnlimitedInteger):\n"
		t += "            return other / long(self)\n"
		t += "        if self.oclIsKindOf(UnlimitedReal):\n"
		t += "            return other / float(self)\n"
		t += "        #if self.oclIsKindOf(String):\n"
		t += "        #    return other / unicode(self)\n"
		t += "        assert 0\n"

		t += "    def __rfloordiv__(self, other):\n"
		t += "        if self.oclIsKindOf(UnlimitedInteger):\n"
		t += "            return other // long(self)\n"
		t += "        if self.oclIsKindOf(UnlimitedReal):\n"
		t += "            return other // float(self)\n"
		t += "        #if self.oclIsKindOf(String):\n"
		t += "        #    return other // unicode(self)\n"
		t += "        assert 0\n"

		t += "    def __neg__(self):\n"
		t += "        if self.oclIsKindOf(UnlimitedInteger):\n"
		t += "            return -long(self)\n"
		t += "        if self.oclIsKindOf(UnlimitedReal):\n"
		t += "            return -float(self)\n"
		t += "        #if self.oclIsKindOf(String):\n"
		t += "        #    return -unicode(self)\n"
		t += "        assert 0\n"

		t += "    def __pos__(self):\n"
		t += "        if self.oclIsKindOf(UnlimitedInteger):\n"
		t += "            return +long(self)\n"
		t += "        if self.oclIsKindOf(UnlimitedReal):\n"
		t += "            return +float(self)\n"
		t += "        if self.oclIsKindOf(String):\n"
		t += "            return +unicode(self)\n"
		t += "        assert 0\n"

		t += "    def __abs__(self):\n"
		t += "        if self.oclIsKindOf(UnlimitedInteger):\n"
		t += "            return abs(long(self))\n"
		t += "        if self.oclIsKindOf(UnlimitedReal):\n"
		t += "            return abs(float(self))\n"
		t += "        #if self.oclIsKindOf(String):\n"
		t += "        #    return abs(unicode(self))\n"
		t += "        assert 0\n"

		sys.stdout.write(t)
		skip_eq = 1
	if skip_eq:
		if re.search("def __eq__", l):
			continue
		if re.search("def __ne__", l):
			continue
		if re.search("def __lt__", l):
			continue
		if re.search("def __le__", l):
			continue
		if re.search("def __gt__", l):
			continue
		if re.search("def __ge__", l):
			skip_eq = 0
			continue
	if re.search("class AbstractElementDefinition\(", l):
		print l
		l = ""
		t = ""
		t += "    def getOperations(self):\n"
		t += "        return [ i for i in self.__operations__() ]\n"
		t += "    def getSuperclasses(self):\n"
		t += "        return [ i for i in self.__superclasses__() ]\n"
		t += "    def getAllSuperclasses(self):\n"
		t += "        return [ i for i in self.__all_superclasses__() ]\n"
		t += "    def getSubclasses(self):\n"
		t += "        return [ i for i in self.__subclasses__() ]\n"
		print t
		
	# Collection has our own __getattr__, so subclasses don't need one
	if re.search("class Set\(", l):
		fix_getattr = 1
	if re.search("class Bag\(", l):
		fix_getattr = 1
	if re.search("class OrderedSet\(", l):
		fix_getattr = 1
	if re.search("class Sequence\(", l):
		fix_getattr = 1
	if re.search("class Package\(", l):
		fix_getattr = 1
	if re.search("class Language\(", l):
		fix_getattr = 1

	# skip __getattr__
	if fix_getattr and re.search("__getattr__ = ", l):
		fix_getattr = 0
		continue

	if fix_magic_setattr and re.search("__setattr__", l):
		fix_magic_setattr = 0
		sys.stdout.write("    __setattr__ = lambda self, name, value: Element_swig_setattr(self, name, value)\n")
		continue
	if 1: #fix_dict_usage:
		l = re.sub("^( +)self.this ",    "\\1self.__dict__[\"this\"] ", l)
		if re.search("thisown", l) and not re.search("static", l):
			fix_dict_usage = 0
			continue
		if re.search("self.__class__", l) and not re.search("proxy of", l):
			fix_dict_usage = 0
			continue
	if re.search("class ElementDefinition\(", l):
		sys.stdout.write(l)
		continue
	
	if re.search("def __del__", l):
		if fix_ignore_del:
			fix_ignore_del = 0
		else:
			sys.stdout.write(l)
			# Create an error if we try to delete stuff!
			# _everything_ should be a subclass of ref_counted, and
			# thus refable, and thus ->unref() is the only
			# right thing to do..
			sys.stdout.write("    \tassert 0, \"This needs some trivial fixing\"\n")
		f.readline()
		f.readline()
		f.readline()
		continue

	if re.search("class Slot\(", l):
		sys.stdout.write(l)
		t = ""

	if re.search("def unionWith\(", l):
		continue
	if re.search("def setDifference\(", l):
		continue
	if re.search("def intersectWith\(", l):
		continue
	
	if re.search("class Collection\(", l):
		# Implicit collections
		fix_getattr = 1
		print l
		t = ""
		t += "    def __getattr__(self, name):\n"
		#t += "        if name == \"this\" or name[0] == \"_\":\n"
		#t += "            return self.__dict__[name]\n"
		t += "        o = None\n"
		t += "        c = self.newSimilarCollection()\n"
		t += "        for i in self:\n"
		t += "            for a in i.__getSlotByName__(name):\n"
		t += "                c.add(a)\n"
		t += "        return c\n"
		t += "    def __add__(self, coll):\n"
		t += "        res = self.clone()\n"
		t += "        res.unionWith(coll)\n"
		t += "        return res\n"
		t += "    def __sub__(self, coll):\n"
		t += "        return self.clone().setDifference(coll)\n"
		t += "    def __and__(self, coll):\n"
		t += "        res = self.clone()\n"
		t += "        res.intersectWith(coll)\n"
		t += "        return res\n"
		t += "    def unionWith(*args):\n"
		t += "        if isinstance(args[1], Slot):\n"
		t += "            return args[0].unionWith(args[1].getCollection())\n"
		t += "        return _coral.Collection_unionWith(*args)\n"
		t += "    def intersectWith(*args):\n"
		t += "        if isinstance(args[1], Slot):\n"
		t += "            return args[0].intersectWith(args[1].getCollection())\n"
		t += "        return _coral.Collection_intersectWith(*args)\n"
		t += "    def setDifference(*args):\n"
		t += "        if isinstance(args[1], Slot):\n"
		t += "            return args[0].setDifference(args[1].getCollection())\n"
		t += "        return _coral.Collection_setDifference(*args)\n"
		t += "    def collect(self, func):\n"
		t += "        # Does not have to be a Bag explicitly.\n"
		t += "        res = self.newSimilarCollection()\n"
		t += "        for i in self:\n"
		t += "            ans = func(i)\n"
		t += "            if ans:\n"
		t += "                res.append(ans)\n"
		t += "        return res\n"
		t += "    def select(self, func):\n"
		t += "        res = self.newSimilarCollection()\n"
		t += "        for i in self:\n"
		t += "            if func(i):\n"
		t += "                res.append(i)\n"
		t += "        return res\n"
		t += "    def reject(self, func):\n"
		t += "        res = self.newSimilarCollection()\n"
		t += "        for i in self:\n"
		t += "            if not func(i):\n"
		t += "                res.append(i)\n"
		t += "        return res\n"
		t += "    def forAll(self,f):\n"
		t += "        nitems=self.__len__()\n"
		t += "        if nitems == 0 or not inspect.getargspec(f)[0]:\n"
		t += "            return 1\n"
		t += "\n"
		t += "        nargs=len(inspect.getargspec(f)[0])\n"
		t += "        if inspect.getargspec(f)[3]:\n"
		t += "            nargs=nargs-len(inspect.getargspec(f)[3])\n"
		t += "            \n"
		t += "        assert(nargs>0)\n"
		t += "        index=[0]*nargs\n"
		t += "        \n"
		t += "        our_elems = []\n"
		t += "        for i in self:\n"
		t += "            our_elems.append(i)\n"
		t += "        \n"
		t += "        while 1:\n"
		t += "            args=[]\n"
		t += "            for x in index:\n"
		t += "                args.append(our_elems[x])\n"
		t += "            if not f(*args):\n"
		t += "                return 0\n"
		t += "            c=len(index)-1\n"
		t += "            index[c]=index[c]+1\n"
		t += "            while index[c]==nitems:\n"
		t += "                index[c]=0\n"
		t += "                c=c-1\n"
		t += "                if c<0:\n"
		t += "                    return 1\n"
		t += "                else:\n"
		t += "                    index[c]=index[c]+1 \n"
		t += "                if index[c]==nitems-1:\n"
		t += "                    c=c-1\n"
		t += "\n"
		t += "    def exists(self,f):\n"
		t += "        nitems=self.__len__()\n"
		t += "        if nitems == 0 or not inspect.getargspec(f)[0]:\n"
		t += "            return 0\n"
		t += "\n"
		t += "        nargs=len(inspect.getargspec(f)[0])\n"
		t += "        if inspect.getargspec(f)[3]:\n"
		t += "            nargs=nargs-len(inspect.getargspec(f)[3])\n"
		t += "            \n"
		t += "        assert(nargs>0)\n"
		t += "        index=[0]*nargs\n"
		t += "        \n"
		t += "        our_elems = []\n"
		t += "        for i in self:\n"
		t += "            our_elems.append(i)\n"
		t += "        \n"
		t += "        while 1:\n"
		t += "            args=[]\n"
		t += "            for x in index:\n"
		t += "                args.append(our_elems[x])\n"
		t += "            if f(*args):\n"
		t += "                return 1\n"
		t += "            c=len(index)-1\n"
		t += "            index[c]=index[c]+1\n"
		t += "            while index[c]==nitems:\n"
		t += "                index[c]=0\n"
		t += "                c=c-1\n"
		t += "                if c<0:\n"
		t += "                    return 0\n"
		t += "                else:\n"
		t += "                    index[c]=index[c]+1 \n"
		t += "                if index[c]==nitems-1:\n"
		t += "                    c=c-1\n"
		t += "		continue\n"
		sys.stdout.write(t)
		continue

		
	if re.search("class Slot\(", l):
		# magic Slot __getattr__ so that we enable
		# automatic collections for OCL2. Bah.
		fix_getattr = 1
		t = ""
                t += "    def __type__(self):\n"
                t +="          return self.getProperty()\n"
		t += "    def __getattr__(self, name):\n"
		#t += "        if name == \"this\" or name[0] == \"_\":\n"
		#t += "            return self.__dict__[name]\n"
		t += "        o = None\n"
		t += "        if name == \"__meta__\":\n"
		t += "            return self.__type__().getCorrespondingElement()\n"
		t += "        c = self.getCollection().newSimilarCollection()\n"
		t += "        isPrimitive = self.getProperty().getTarget().getPropertyByName(name).getTarget().isDatatypeDefinition()\n"
		t += "        for i in self:\n"
		t += "            if isPrimitive:\n"
		t += "                # BUG assumes [0] exists\n"
		t += "                c.add(i.__getSlotByName__(name)[0])\n"
		t += "            else:\n"
		t += "                for a in i.__getSlotByName__(name):\n"
		t += "                    c.add(a)\n"
		t += "        return c\n"
		
		t += "    def __mul__(self, v):\n"
		t += "        assert(type(v)==type(\"\"))\n"
		t += "        return v.join([str(x) for x in self])\n"
		t += "    def collect(self, func):\n"
		t += "        return self.getCollection().collect(func)\n"
		t += "    def select(self, func):\n"
		t += "        return self.getCollection().select(func)\n"
		t += "    def reject(self, func):\n"
		t += "        return self.getCollection().reject(func)\n"
		t += "    def exists(self, func):\n"
		t += "        return self.getCollection().exists(func)\n"
		t += "    def forAll(self, func):\n"
		t += "        return self.getCollection().forAll(func)\n"
		t += "    def __setslice__(self, start, stop, contents):\n"
		t += "        for i in xrange(start, stop):\n"
		t += "            self.drop_index(start)\n"
		t += "        for i in contents:\n"
		t += "            self.insert(i, start)\n"
		t += "            start += 1\n"
		t += "    def __getslice__(self, start, stop):\n"
		t += "        return [ self[i] for i in xrange(start, min(self.size(),stop)) ]\n"
		sys.stdout.write(t)
		continue

	if fix_init and re.search("def __init__", l):
		sys.stdout.write(l)
		if 1: #fix_dict_usage:
			sys.stdout.write("    \tself.__dict__[\"this\"] = this\n")
		else:
			sys.stdout.write("    \tself.this = this\n")
		if ref_in_init:
			sys.stdout.write("    \tself.ref()\n")
		f.readline()
		f.readline()
		fix_init = 0
		ref_in_init = 1
		continue
		

	# Fix ElementDefinition.__call__
	if re.search("def __call__", l):
		sys.stdout.write("    def __call__(*args, **kwargs):\n")
		sys.stdout.write("    \telem = _coral.ElementDefinition___call__(*args)\n")
		sys.stdout.write("    \tfor key in kwargs.keys():\n")
		sys.stdout.write("    \t\tsetattr(elem, key, kwargs[key])\n")
		sys.stdout.write("    \telem.unref()\n")
		sys.stdout.write("    \treturn elem\n")
		continue

	# Fix iteration mechanisms. Assume they return None
	# when sequence is over
	m = re.search("def next\(\*args\): return (.*)", l)
	if m:
		sys.stdout.write("    def next(*args):\n")
		sys.stdout.write("        t = " + m.group(1) + "\n")
		sys.stdout.write("        if t is None: raise StopIteration\n")
		sys.stdout.write("        return t\n")
		continue

	# Fix transactions.
	m = re.search("def endModifyCmd\(\*args\): return (.*)", l)
	if m:
		print "    def endModifyCmd(*args):"
		print "        res = _coral.Manager_endModifyCmd(*args)"
		print "        if res:"
		print "            storages = Project.getAllProjects()"
		print "            try:"
		print "                for st in storages:"
		print "                    for r in st.contents():"
		print "                        success = r.isWellFormedRecursive()"
		print "                        if not success:"
		print "                            raise WFRException()"
		print "            except:"
		print "                args[0].undo()"
		print "                raise #Re-raise it"
		continue
	m = re.search("def endTransaction\(\*args\): (.*)", l)
	if m:
		print "    def endTransaction(*args):"
		print "        return Manager.endModifyCmd(*args)"
		continue
	m = re.search("def endStrictTransaction\(\*args\): (.*)", l)
	if m:
		print "    def endStrictTransaction(*args):"
		print "        return Manager.endModifyCmd(*args)"
		continue

#	# Fix isWellFormedRecursive
#	m = re.search("def isWellFormedRecursive\(\*args\):", l)
#	if m:
#		t = ""
#		t += "    def isWellFormedRecursive(*args):\n"
#		t += "      res = _coral.Element_isWellFormed(*args)\n"
#		t += "      self = args[0]\n"
#		t += "      for ff in self.__all_slots__():\n"
#		t += "            mm = ff.getProperty()\n"
#		t += "            if mm.getTarget().isDatatypeDefinition():\n"
#		t += "                continue\n"
#		t += "            if mm.isComposition():\n"
#		t += "                if mm.isAtMostOne():\n"
#		t += "                    walkchildren = [ ff[0] ]\n"
#		t += "                else:\n"
#		t += "                    walkchildren = ff\n"
#		t += "                for i in walkchildren:\n"
#		t += "                    isWellFormed(i)\n"
#		t += "      isWellFormed(self)\n"
#		print t
#		continue
#
	# Fix RuntimeError of std::exception to WFRException
	# NO, DON'T! It just hides the bloody error message!
	# # # # fixthese = ["add", "drop", "append" ]
	# # # # for i in fixthese:
	# # # # 	m = re.search("(def %s\(\*args\):) return (.*)" % i, l)
	# # # # 	if m:
	# # # # 		print "    " + m.group(1)
	# # # # 		print "        try:"
	# # # # 		print "            res = " + m.group(2)
	# # # # 		print "        except:"
	# # # # 		print "            raise WFRException()"
	# # # # 		print "        return res"
	# # # # 		l = ""
	# # # # 		break


	sys.stdout.write(l)

