Search code examples
javalistgenericsemf

EMF generic List


My model contains an interface called Result. I have multiple classes that implement said interface. Now i want to add Lists of results as Results. I want to be able to create sth like:

List < ResultImplA >

, which

  • can contain only the chosen Resulttype
  • implements my Result interface,
  • is an EObject (can be contained in Elists etc.)
  • concrete Instances can be generated via EMF (DomainFactory.eINSTANCE.create...()

I tried using EMF generics, which cover 1 and 2 but i can't create them in my code. I can only use it as a superclass for other classes that specifiy the generic, but i do not want to create an additional List class for all my Results. The DomainFactory only provides me with an implementation of ResultList< Result >.


Solution

  • I'm not quite sure what you're trying to accomplish. You want a Class, which is an EList and a Result? Technically this is possible and can be accomplished by extending the BasicEList or implementing EList class:

    class ResultImpl extends BasicEList<E> implements Result
    

    or

    class ResultImpl extends MinimalEObjectImpl.Container implements EList<E>, Result
    

    But this is all nonesense, either way you would need to implement a ton of methods on your own and would likely crash EMF constantly...

    What you could do is: make an EClass say "ResultList" which has your Result as Super Class and add an EReference (name = "results", EType: Result, (upperbound: -1) to it. So you could generate a Class which is basically a Wrapper for Results EObjects.

    Further: To make your ResultList 'behave' like a List, for example in loops:

    for(Result r : aResultList)
    

    you could implement the java.lang.Iterable<Result> Interface in your ResultList Class and create your own custom java.util.Iterator<Result> nested class in your ResultList Class, which provides you with the elements of your EReference directly:

    Eg nested Iterator class (nested in your ResultList class):

    private class ResultIterator implements Iterator<Result> {
            private int index = 0;
    
            @Override
            public boolean hasNext() {
                return index < size;
            }
    
            @Override
            public Result next() {
                return results.get(index++);
            }
        }
    

    Because you have implemented the Iterable Interface you need to implement the public Iterator<Result> iterator() Method, which simply returns your custom Iterator:

    @Override
    public Iterator<Result> iterator() {
        return new ResultIterator();
    }
    

    Update: If you decided to create an EClass with a generic EType parameter and you want to create an instance of this class, there should be something like this in your factoryImpl:

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
    * @generated
    */
    public <T> ResultList<T> createResultList() {
        ResultListImpl<T> resultList = new ResultListImpl<T>();
    return resultList;
    }
    

    so you should be able to use it like:

    ResultList<Result> someResultList = Yourfactory.eINSTANCE.createResultList();