Skip to content

Overloaded EOperations produce duplicate cache keys; loading EMF's own Ecore.ecore crashes with ArgumentException #96

Description

@samatstariongroup

Context

Found while comparing ECoreNetto against the reference Java EMF implementation, scoped to reading
.ecore files. Ecore permits several EOperations with the same name on one EClass (overloads).
EMF's own authoritative metamodel file, org.eclipse.emf.ecore/model/Ecore.ecore, declares
getEStructuralFeature twice on EClass (lines 34 and 40 — the featureID and featureName
overloads).

Problem

EOperation.BuildIdentifier produces the same identifier for every same-named operation of a class:

protected override string BuildIdentifier()
{
    return $"EOperation::{this.EContainingClass.Identifier}/{this.Name}";
}

ENamedElement.ReadXml registers each element in the resource cache with Dictionary.Add:

this.EResource.Cache.Add(this.Identifier, this);

so the second overload throws and aborts the load:

System.ArgumentException: An item with the same key has already been added.
   at ECoreNetto.ENamedElement.ReadXml(XmlNode element)

Reproduced with ecoretools inspect -i Ecore.ecore against the file shipped in EMF. ECoreNetto
therefore cannot load the Ecore metamodel itself. (The copy in TestData/ecore.ecore happens to
omit the second overload, which is why the existing tests pass.)

EMF handles this by disambiguating name-based URI fragment segments with a positional suffix:
EModelElementImpl.eURIFragmentSegment emits name for the first occurrence and name.N for
subsequent duplicates, and eObjectForURIFragmentNameSegment parses the suffix back when
resolving. Cross-file references into such models use the same .N form (e.g.
Ecore.ecore#//EClass/getEStructuralFeature.1).

Suggested direction

  • Disambiguate duplicate identifiers the way EMF does: when building the identifier for an
    ENamedElement whose parent already contains a same-named sibling of the same kind, append the
    duplicate index (/name, /name.1, /name.2, ...). EParameter identifiers inherit the fix
    through the containing operation's identifier.
  • Accept the .N suffix in incoming URI fragments in Resource.GetEObject so references into
    overloaded operations resolve.
  • Regression test: load a model with two same-named operations (mirroring
    EClass.getEStructuralFeature from the real Ecore.ecore) and assert both operations are
    present with distinct identifiers and the load records no errors.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions