def validateUniqueParticleAttribution(modelXbrl, particles, compositor):
    priorElementParticles = {}
    priorAnyParticles = []
    for i, particle in enumerate(particles):
        if isinstance(particle, ModelConcept):
            elementDeclaration = particle.dereference()
            if elementDeclaration is not None:  # none if element ref is invalid
                qname = elementDeclaration.qname
                if qname in priorElementParticles: # look for separating transitions
                    separatingTransitions = 0
                    if not isinstance(compositor, (ModelChoice, ModelAll)):
                        for j in range(i, priorElementParticles[qname], -1):
                            separatingTransitions += particles[j-1].minOccurs
                            if separatingTransitions:
                                break
                    if not separatingTransitions:
                        modelXbrl.error("xmlSchema:uniqueParticleAttribution",
                            _("Particles of %(compositor)s have non-unique attribution of element %(element)s"),
                            modelObject=particle, compositor=compositor.localName, element=qname)
                else:
                    for priorAnyIndex in priorAnyParticles:
                        # TBD check namespace overlap
                        separatingTransitions = 0
                        if not isinstance(compositor, (ModelChoice, ModelAll)):
                            for j in range(i, priorAnyIndex, -1):
                                separatingTransitions += particles[j-1].minOccurs
                                if separatingTransitions:
                                    break
                        if not separatingTransitions:
                            modelXbrl.error("xmlSchema:uniqueParticleAttribution",
                                _("Particle of %(compositor)s has non-unique xs:any preceding element %(element)s"),
                                modelObject=particle, compositor=compositor.localName, element=qname)
                priorElementParticles[qname] = i
        elif isinstance(particle, ModelAny):
            if i > 0 and particles[i-1].minOccurs == 0:
                modelXbrl.error("xmlSchema:uniqueParticleAttribution",
                    _("Particles of %(compositor)s have non-unique xs:any particle"),
                    modelObject=particle, compositor=compositor.localName)
            priorAnyParticles.insert(0, i)
        else:   # recurse
            particleDeclaration = particle.dereference()
            if particleDeclaration is not None:  # none if particle ref is invalid
                validateUniqueParticleAttribution(modelXbrl, particleDeclaration.particles, particle)
dataset/ETHPy150Open Arelle/Arelle/arelle/XmlValidateParticles.py/validateUniqueParticleAttribution/original