Merging conflicting models? [message #1168809] |
Sun, 03 November 2013 15:38 |
Alan DW Messages: 119 Registered: March 2012 |
Senior Member |
|
|
Hello everyone,
I'm in the typical "repository" situtation: I have a local model in the state as it was when it was last synchronized with the server (the "common ancestor"), the model as it is now ("left") and the latest version of the model from the server ("right"). I need to perform a local update operation, which means that I must merge the server version and the current client version, with the last synchronized client version as the common ancestor.
After obtaining the "Comparison" object from the three-way-compare, how do I merge the differences? To start off, I'd like to merge only the non-conflicting differences. The BatchMerger states in its Javadoc that it will merge *all* differences, regardless whether they are conflicting or not. What's the preferred way to merge all non-conflicting changes?
After merging the non-conflicting changes, I have a callback to let the user decide which version of the conflicting element (left or right) he wants to use. I tried to do this in the following way:
IMerger.Registry registry = EMFCompareRCPPlugin.getDefault().getMergerRegistry();
IBatchMerger merger = new BatchMerger(registry);
PseudoConflictMerger pseudoConflictMerger = new PseudoConflictMerger();
//TODO merge all non-conflicting changes - but how?
for (Conflict conflict : comparison.getConflicts()) {
if (conflict.getKind() == ConflictKind.PSEUDO) {
// don't do anything except for marking it as merged
for (Diff diff : conflict.getDifferences()) {
pseudoConflictMerger.copyLeftToRight(diff, new BasicMonitor());
}
} else {
// call the callback operation
MergeConflictResolution resolution = conflictResolver.resolve(conflict);
switch (resolution) {
case USE_MINE:
merger.copyAllRightToLeft(conflict.getDifferences(), new BasicMonitor());
break;
case USE_THEIRS:
merger.copyAllLeftToRight(conflict.getDifferences(), new BasicMonitor());
break;
default:
throw new RuntimeException("Unknown MergeConflictResolution type: " + resolution);
}
}
}
This seems rather tedious to me, given that this is such a common task (I'd suppose). Is there actually a *simpler* way to achieve this? I've been looking for tutorials and how-to's on the web, but I really couldn't find any...
Any help is greatly appreciated!
Thanks,
Alan
|
|
|
Re: Merging conflicting models? [message #1171425 is a reply to message #1168809] |
Tue, 05 November 2013 08:12 |
|
Hi Alan,
Quote:The BatchMerger states in its Javadoc that it will merge *all* differences, regardless whether they are conflicting or not. What's the preferred way to merge all non-conflicting changes?
That is what the javadoc of the default constructor of the batch merger says. The javadoc of the other constructor answers your question with an example of code.
Since you are trying to merge everything, but with a little bit of logic for the conflicts, I'd say the easiest is probably to implement your own batch merger (Here I only give the code for the "left to right" part ... overriding the "right to left" one shouldn't be hard ) :
public void copyAllLeftToRight(Iterable<? extends Diff> differences, Monitor monitor) {
for (Diff diff : Iterables.filter(differences, filter)) {
if (diff.getState() != DifferenceState.MERGED) {
copyLeftToRight(diff, monitor);
}
}
}
private void copyLeftToRight(Diff diff, Monitor monitor) {
// The only diffs that need particular handling are the conflicting ones, less the pseudo-conflicts.
final IMerger merger = registry.getHighestRankingMerger(diff);
if (diff.getConflict() != null && diff.getConflict().getKind() != ConflictKind.PSEUDO) {
handleConflictCopy(diff, merger, monitor);
} else {
merger.copyLeftToRight(diff, monitor);
}
}
private void handleConflictCopy(Diff diff, IMerger merger, Monitor monitor) {
MergeConflictResolution resolution = conflictResolver.resolve(conflict);
switch (resolution) {
case USE_MINE:
merger.copyRightToLeft(diff, monitor);
break;
case USE_THEIRS:
merger.copyLeftToRight(diff, monitor);
break;
default:
throw new RuntimeException("Unknown MergeConflictResolution type: " + resolution);
}
}
Then you only need to call this merger instead of the default "new BatchMerger(registry)" you were using.
Laurent Goubet
Obeo
[Updated on: Tue, 05 November 2013 08:12] Report message to a moderator
|
|
|
|
Powered by
FUDForum. Page generated in 0.03997 seconds