geoffreywiseman/Moo

Matcher for Collection Updates

Closed this issue · 2 comments

When updating a collection from one side to another, how do you determine which item to update?

The simplest way is to iterate collections and do matches in order, but when collections aren't ordered or when insertions may be made between existing elements, this may result in many unnecessary updates.

When dealing with items persisted to the database, you might want to use the persistent identifier as a way to match the items. In some cases, even that won't be sufficient (e.g. saving repeatedly from a client that is unaware of the persistent ids).

In any case, the user needs to be able to customize the logic to match items in the source collection with items in the destination collection.

You might implement this with a clear interface for matchers:

public interface CollectionMatcher<S,D> {
    public void setMatches( Collection<D> matches );
    public D getMatch( S source );
}

And a way to annotate a property as using a particular kind of matcher:

public class Book {
    @TranslateCollection(value=Author.class,matcher=AuthorMatcher.class)
    private List<Author>();
}

This is a fairly idiomatic Java way to solve the problem, although it's not terribly flexible.

Another way I've considered would be a little more like the translation expression approach, were you could identify a way to get a match as an expression, which could use an object from the context:

public class Book {
    @TranslateCollection(value=Author.class,matchExpression="authorMatcher.findMatch(this)")
    private List<Author>();
}

The problem with this is that it's difficult for the translation context to contain a list of possible matches, so it's hard to work that into the translation expression. It could be done, but it's awkward. They could be preloaded into the matcher before the update/translation, but that makes a lot more work for the user of Moo that could probably be performed /by/ Moo.

I think getting more flexibility by making common cases harder is a bad idea, so I think I'm leaning towards the matcher approach above.