Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [epsilon-dev] IModel / CachedModel enhancements proposal

Hi Sina,

Happy New Year as well! Let's see:

* Having an isLoaded() method would be good, but it's a bit strange to have a default implementation that always returns true. We have a base Model class for most of our models - would it make sense to have a default "proper" implementation there?

* Having a way to iterate through the contents of a model (as opposed to an eager construction of a collection) would be good - in fact, in Hawk I recently implemented an optimisation that "faked" a collection this way - works great for the typical .all.first queries (obviously, .all.size still triggers a full iteration). Still, given that Stream is a richer API than Iterator and that BaseStream has an .iterator() method to produce an iterator, it might be better to have a default implementation of iterateAllOf* based on streamAllOf* rather than the other way around, unless there is some issue in supporting Iterator#remove from a converted stream.

BTW, do we want to support Iterator#remove at all from iterateAllContentsFromModel()?

Kind regards,
Antonio

On Tue, 1 Jan 2019 at 16:59, Sina Madani <sinadoom@xxxxxxxxxxxxxx> wrote:

Hi all and a Happy New Year!

 

I thought I would suggest a couple of additions to IModel or CachedModel (which would of course be non-abstract methods to avoid breaking existing implementations) for discussion.

 

default boolean isLoaded() {

    return true;

}

 

Jon, Horacio, Betty and I were discussing the idea of being able to detect whether a model has already been loaded. Currently there isn’t a general way to do this, so in some implementations a call to load() may unnecessary reload the model. CachedModel may override this to return allContentsAreCached if caching is enabled, for example.

 

protected Iterator<ModelElementType> iterateAllContentsFromModel() {

    return allContentsFromModel().iterator();

}

 

The second idea was proposed by Horacio (albeit not in this exact form) which is presumably motivated by the efficiency of iterators compared to collections. Iterators can produce values lazily (EMF already uses TreeIterator, for example), whilst Collections must be populated eagerly even if only part of the collection is used. Implementations could therefore override this method to provide lazy model iteration which would be more efficient. This method could then be used to replace some allContentsFromModel invocations. We could then also add similar variants for getAllOf* (where * = Kind/Type), e.g.:

 

default Iterator<?> iterateAllOf*(String type) {

    return getAllOf*(type).iterator();

}

 

Of course this would be overridden by CachedModel to use the iterator-based allContentsFromModel.

Additionally, I propose a complimentary pair of methods for getAllOf* as follows:

 

default Stream<?> streamAllOf*(String type) {

    return getAllOf*(type).stream();

}

 

With the associated streamAllOf*FromModel() as well in the case of CachedModel. This would also allow for lazy model iteration but with a richer API since many queries and transformations can be performed using Streams both lazily and in parallel if desired. Models that implement iterateAllContentsFromModel and iterateAllOf* can then make use of this to create a stream as follows:

 

public Stream<?> streamAllOf*(String type) {

    return StreamSupport.stream(

Spliterators.spliteratorUnknownSize(iterateAllOf*(type), 0),

false

);

}

 

Please feel free to add your thoughts / suggestions.

 

Thanks,

Sina



--
Antonio Garcia-Dominguez

Back to the top