def METHOD_NAME(nd):
    if nd.attributes.keys() == {XMI.id, "start", "end"}:
        # Generalization, Substitution, Dependency, ...
        return uuid.uuid5(
            METHOD_NAME(by_id[nd.attributes["start"]].node),
            str(METHOD_NAME(by_id[nd.attributes["end"]].node))
        )
    elif nd.tag == "ownedAttribute":
        return uuid.uuid5(
            METHOD_NAME(nd.parent),
            nd.attributes["name"]
        )
    elif nd.tag == "ownedEnd":
        return uuid.uuid5(
            METHOD_NAME(nd.parent),
            "end%d" % nd.parent.children.index(nd)
        )
    elif nd.tag == "generalization":
        return uuid.uuid5(
            METHOD_NAME(nd.parent),
            str(METHOD_NAME(by_id[nd.attributes["general"]].node))
        )
    elif nd.tag == "ownedRule":
        elem = [c for c in nd.children if c.tag == "constrainedElement"][0]
        supplier = by_id[by_id[elem.attributes[XMI.idref]].node.attributes["supplier"]].node.attributes["name"]
        return uuid.uuid5(
            METHOD_NAME(nd.parent),
            supplier
        )
    elif nd.tag == 'packagedElement' and len(nd.attributes.keys() & {"supplier", "client"}) == 2:
        return uuid.uuid5(
            METHOD_NAME(by_id[nd.attributes["supplier"]].node),
            nd.attributes[XMI.type] + ";" + str(METHOD_NAME(by_id[nd.attributes["client"]].node))
        )
    elif nd.tag == 'packagedElement' and nd.attributes[XMI.type] == "uml:Association":
        ends = [c for c in nd.children if c.tag == "ownedEnd"]
        types = sum([[cc for cc in c.children if cc.tag == "type"] for c in ends], [])
        type_names = [by_id[t.attributes[XMI.idref]].node.attributes["name"] for t in types]
        attr_names = [c.attributes.get("name", "") for c in ends]
        return uuid.uuid5(
            METHOD_NAME(nd.parent),
            ";".join(type_names + attr_names)
        )
    attrs = {k: v for k, v in nd.attributes.items() if k != XMI.id}
    idref = attrs.get(XMI.idref)
    if idref:
        attrs[XMI.idref] = format_uuid(METHOD_NAME(by_id[idref].node))
    attr_string = ";".join(":".join(kv) for kv in sorted(attrs.items()))    
    assert "EAID" not in attr_string
    if attrs.get(XMI.type) == "uml:Package":
        print(attr_string)
    return uuid.uuid5(
        METHOD_NAME(nd.parent) if nd.parent else null_uuid,
        ";".join((nd.tag, attr_string))
    )