Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » Compare » Three Way Merge - Help needed
Three Way Merge - Help needed [message #915967] Tue, 18 September 2012 06:11 Go to next message
Francesca Herpertz is currently offline Francesca Herpertz
Messages: 1
Registered: September 2012
Junior Member
Hello all together,

I am currently working on the stardust project. It is a plugnin for creating and modeling processes and their activities etc. It is emf based and we are creating browserbased version of the modeler. Collaborative modeling should be supported. Now I need to implement an optimistic concurrency method. I wanted to use the emf compare API, which comes in handy with some features, because our model is EMF-based.

Now here is my current scenario:

A User is modeling and changes a name of a node.

Following is done in the backend: The original model is copied twice (deep copy and lets say the are called copy_A and copy_B). The changes are made on the first copy. Then copy_A and copy_B are merged together when they are not conflicting. Copy_B is now the merged version. This works fine.

Now, while this happens some other person could have changed the model and added e.g. antoher node to the model. Because of this I create another copy from my original model (where the new changes are included) and I make a three-way-merge with the merged copy_B, the newly created copy_C (including the newly added node) and my original model as parent.
I expect now, that when I merge copy_B and copy_C the changes from copy_B (the changed Name) and the newly added process are in copy_C...

When I now check my copy_C the name is changed but the process I created is deleted, although the process was created in the original and in the copy.

Here is my code (ModelType and processes etc. are derived from EMF Objects and the editing session just tracks undo/redo ):

  public void createProcess() throws InterruptedException
   
   {
      ModelType original = newBpmModel().withIdAndName("test", "test").build();
      
      EditingSession editSession = new EditingSession();
      editSession.trackModel(original);
      editSession.beginEdit();
      newProcessDefinition(original).withIdAndName("PD_1", "Test Process 1").build();
      editSession.endEdit();
      
      /**
       * workingCopy - The copy on which the changes are applied
       * workingCopyOriginal - A copy of the status before changes are applied
       */
      ModelType workingCopy = (ModelType)org.eclipse.emf.ecore.util.EcoreUtil.copy(original);
      ModelType workingCopyOriginal = (ModelType)org.eclipse.emf.ecore.util.EcoreUtil.copy(original);
      
      /**
       * Start working on the Copy. Change the process name
       */
      EditingSession anotherSession = new EditingSession();
      anotherSession.trackModel(workingCopy);
      anotherSession.beginEdit();
      workingCopy.getProcessDefinition().get(0).setName("VollHorst");
      anotherSession.endEdit();
      
      
      MatchModel wCtoOWC = MatchService.doMatch((EObject) workingCopy, (EObject) workingCopyOriginal, Collections.<String, Object> emptyMap());
      DiffModel diffWorkCopyAndOrig = DiffService.doDiff(wCtoOWC);
      EList<DiffElement> differences1 = diffWorkCopyAndOrig.getOwnedElements();
      

      editSession.beginEdit();
      newProcessDefinition(original).withIdAndName("ID_20", "another Test Process").build();
      editSession.endEdit();
      
      try
      {
         getSubdiffs(differences1, "", false);
         MergeService.merge(differences1, true);
         System.out.println("Merged working copy t' to copy t with following change: Process name was changed to " +workingCopyOriginal.getProcessDefinition().get(0).getName());
         
         ModelType currentOriginal = (ModelType)org.eclipse.emf.ecore.util.EcoreUtil.copy(original);
         MatchResourceSet wCOtoCurrentOriginal = MatchService.doResourceSetMatch((ResourceSet)workingCopyOriginal, (ResourceSet)currentOriginal, Collections.<String, Object> emptyMap());
         DiffResourceSet diff2 = DiffService.doDiff(wCOtoCurrentOriginal);
         for (DiffModel d : diff2.getDiffModels()){
            EList<DiffElement> ele = d.getDifferences();
            MergeService.merge(ele, true);
            
         }

         System.out.println("Merged working copy t' to copy t with following change: Process name was changed to " +workingCopyOriginal.getProcessDefinition().get(0).getName());
         System.out.println("Merged working copy t' to original with following change: Process added " +workingCopyOriginal.getProcessDefinition().get(1).getName());
      }
      catch (Exception e)
      {
         e.printStackTrace();
      }
      


   public void getSubdiffs(EList<DiffElement> subdif, String indent, Boolean conflicting) 
   {
      if (subdif.isEmpty())
      {
         return;
      }
      else if (conflicting)
      {
         System.out.println("Conflict detected. Stopping Execution.");
         throw new ConcurrentModificationException();
        
      }
      else
      {
         for (DiffElement de : subdif)
         {
            System.out.println(indent + de.isConflicting());
            System.out.println(indent + de.getKind());
            getSubdiffs(de.getSubDiffElements(), indent + "  ", de.isConflicting());

         }
      }
   }

}





I am working on my bachelor thesis and it would be great, if any of you could help me.

Regards and thanks in advance,
Francesca

[Updated on: Tue, 18 September 2012 06:13]

Report message to a moderator

Re: Three Way Merge - Help needed [message #957508 is a reply to message #915967] Thu, 25 October 2012 05:20 Go to previous message
Laurent Goubet is currently offline Laurent Goubet
Messages: 1621
Registered: July 2009
Senior Member
Hi Francesca,

When you compare Copy_B (changed name) with Copy_C (new process) using the original as common ancestor, EMF Compare will detect two differences :


  1. Name of <copy> changed from <original> to <new name>
  2. <new process> has been remotely added


Now what happens if you merge both differences from right to left?

merge of (1) : name gets changed in the left (Copy_C) from <origin> to <new name>. Fine, this is what you are trying to achieve.
merge of (2) : new process gets deleted from left (Copy_C). This is your issue : this was a change made in the left, you should not be merging this one since merging a "left" change "to" the left will only "undo" that change.

In other words, if you copy "all" changes from one side to the other, you get two identical copies of an object. This is what "merge all" means, and this is how EMF Compare is supposed to work (well, that's how any "diff" software works Smile). What you want to do is not "get two identical copies" but "get a merged version of the changes". You need to filter out from the list of differences you merge any diff that came from the "left" model.

With EMF Compare 2, this would only be a matter of filtering out any Diff which "source" is "DifferenceSource.LEFT". With EMF Compare 1, you need to filter out of the list of differences those for which "isRemote()" returns true.

Laurent Goubet
Obeo
Previous Topic:Merging Models with Extended Types
Next Topic:How to compare unordered list
Goto Forum:
  


Current Time: Thu Jul 31 03:24:16 EDT 2014

Powered by FUDForum. Page generated in 0.04606 seconds