#PLEASE DO NOT EDIT THIS CODE
#This code was generated using the UMPLE 1.38.0.8942.247e17422 modeling language!


class B:
    def __init__(self):
        self._myC = []

    def getMyC1(self, index):
        return self._myC[index]

    def getMyC2(self):
        return tuple(self._myC)

    def getMyC(self, *args, **kwargs):
        bound = __class__._bindArguments(("index",), False, args, kwargs)
        if bound is not None and (isinstance(bound[0], int) and not isinstance(bound[0], bool)):
            return __class__.getMyC1(self, *bound)
        bound = __class__._bindArguments((), False, args, kwargs)
        if bound is not None:
            return __class__.getMyC2(self, *bound)
        raise TypeError("No method matches provided parameters")

    def numberOfMyC(self):
        return len(self._myC)

    def hasMyC(self):
        return len(self._myC) > 0

    def indexOfMyC(self, aMyC):
        return next((i for i, x in enumerate(self._myC) if x is aMyC), -1)

    @staticmethod
    def minimumNumberOfMyC():
        return 0

    def addMyC1(self, aMyD):
        from example.C import C
        return C.alternateConstructor(aMyD, self)

    def addMyC2(self, aMyC):
        if any(x is aMyC for x in self._myC):
            return False
        existingB = aMyC.getB()
        isNewB = existingB is not None and existingB is not self
        if isNewB:
            if not aMyC.setB(self):
                return False
        else:
            self._myC.append(aMyC)
        return True

    def addMyC(self, *args, **kwargs):
        from example.C import C
        from example.D import D
        bound = __class__._bindArguments(("aMyC",), False, args, kwargs)
        if bound is not None and (bound[0] is None or isinstance(bound[0], C)):
            return __class__.addMyC2(self, *bound)
        bound = __class__._bindArguments(("aMyD",), False, args, kwargs)
        if bound is not None and (bound[0] is None or isinstance(bound[0], D)):
            return __class__.addMyC1(self, *bound)
        raise TypeError("No method matches provided parameters")

    def removeMyC(self, aMyC):
        if aMyC.getB() is self:
            return False
        index = next((i for i, x in enumerate(self._myC) if x is aMyC), -1)
        if index >= 0:
            del self._myC[index]
        return True

    def addMyCAt(self, aMyC, index):
        if not self.addMyC2(aMyC):
            return False
        if index < 0:
            index = 0
        if index > self.numberOfMyC():
            index = self.numberOfMyC() - 1
        del self._myC[next((i for i, x in enumerate(self._myC) if x is aMyC), -1)]
        self._myC.insert(index, aMyC)
        return True

    def addOrMoveMyCAt(self, aMyC, index):
        if not any(x is aMyC for x in self._myC):
            return self.addMyCAt(aMyC, index)
        if index < 0:
            index = 0
        if index > self.numberOfMyC():
            index = self.numberOfMyC() - 1
        del self._myC[next((i for i, x in enumerate(self._myC) if x is aMyC), -1)]
        self._myC.insert(index, aMyC)
        return True

    def delete(self):
        while len(self._myC) > 0:
            aMyC = self._myC[-1]
            aMyC.delete()
            index = next((i for i, x in enumerate(self._myC) if x is aMyC), -1)
            if index >= 0:
                del self._myC[index]

    @staticmethod
    def _bindArguments(names, varargs, args, kwargs):
        if len(args) > len(names) and not varargs:
            return None
        bound = list(args[:len(names)])
        for name in names[len(bound):]:
            if name not in kwargs:
                return None
            bound.append(kwargs[name])
        if len(kwargs) != len(names) - min(len(args), len(names)):
            return None
        if varargs:
            bound.append(args[len(names):])
        return bound

#PLEASE DO NOT EDIT THIS CODE
#This code was generated using the UMPLE 1.38.0.8942.247e17422 modeling language!


class C:
    def __init__(self, aB):
        self._myD = None
        self._b = None
        from example.D import D
        self._myD = D.alternateConstructor(self)
        if not self.setB(aB):
            raise RuntimeError("Unable to create myC due to b. See https://manual.umple.org?RE002ViolationofAssociationMultiplicity.html")

    @classmethod
    def alternateConstructor(cls, aMyD, aB):
        self = cls.__new__(cls)
        __class__._alternateInit(self, aMyD, aB)
        return self

    def _alternateInit(self, aMyD, aB):
        self._myD = None
        self._b = None
        if aMyD is None or aMyD.getC() is not None:
            raise RuntimeError("Unable to create C due to aMyD. See https://manual.umple.org?RE002ViolationofAssociationMultiplicity.html")
        self._myD = aMyD
        if not self.setB(aB):
            raise RuntimeError("Unable to create myC due to b. See https://manual.umple.org?RE002ViolationofAssociationMultiplicity.html")

    def getMyD(self):
        return self._myD

    def getB(self):
        return self._b

    def setB(self, aB):
        if aB is None:
            return False
        existingB = self._b
        self._b = aB
        if existingB is not None and existingB is not aB:
            existingB.removeMyC(self)
        self._b.addMyC(self)
        return True

    def delete(self):
        existingMyD = self._myD
        self._myD = None
        if existingMyD is not None:
            existingMyD.delete()
        placeholderB = self._b
        self._b = None
        if placeholderB is not None:
            placeholderB.removeMyC(self)

#PLEASE DO NOT EDIT THIS CODE
#This code was generated using the UMPLE 1.38.0.8942.247e17422 modeling language!


class D:
    def __init__(self, aBForC):
        self._c = None
        from example.C import C
        self._c = C.alternateConstructor(self, aBForC)

    @classmethod
    def alternateConstructor(cls, aC):
        self = cls.__new__(cls)
        __class__._alternateInit(self, aC)
        return self

    def _alternateInit(self, aC):
        self._c = None
        if aC is None or aC.getMyD() is not None:
            raise RuntimeError("Unable to create D due to aC. See https://manual.umple.org?RE002ViolationofAssociationMultiplicity.html")
        self._c = aC

    def getC(self):
        return self._c

    def delete(self):
        existingC = self._c
        self._c = None
        if existingC is not None:
            existingC.delete()