@@ -105,6 +105,7 @@ public class UMLModelDiff {
105105 private Map <MergeVariableReplacement , Set <CandidateMergeVariableRefactoring >> mergeMap = new LinkedHashMap <MergeVariableReplacement , Set <CandidateMergeVariableRefactoring >>();
106106 private List <UMLCommentListDiff > commentsMovedBetweenClasses = new ArrayList <UMLCommentListDiff >();
107107 private Map <MethodInvocationReplacement , UMLOperationBodyMapper > consistentMethodInvocationRenames = new LinkedHashMap <>();
108+ private List <UMLClassMoveDiff > classMoveDiffListToBePostProcessed = new ArrayList <>();
108109
109110 public UMLModelDiff (UMLModel parentModel , UMLModel childModel ) {
110111 this .parentModel = parentModel ;
@@ -778,6 +779,11 @@ public void checkForMovedClasses(Set<String> repositoryDirectories, UMLClassMatc
778779 UMLClassMoveDiff classMoveDiff = new UMLClassMoveDiff (removedClass , addedClass , this , matchResult );
779780 diffSet .add (classMoveDiff );
780781 }
782+ else {
783+ UMLClassMoveDiff classMoveDiff = new UMLClassMoveDiff (removedClass , addedClass , this , matchResult );
784+ if (!classMoveDiffListToBePostProcessed .contains (classMoveDiff ))
785+ classMoveDiffListToBePostProcessed .add (classMoveDiff );
786+ }
781787 }
782788 }
783789 if (!diffSet .isEmpty ()) {
@@ -841,6 +847,11 @@ public void checkForMovedClasses(Set<String> repositoryDirectories, UMLClassMatc
841847 UMLClassMoveDiff classMoveDiff = new UMLClassMoveDiff (removedClass , addedClass , this , matchResult );
842848 diffSet .add (classMoveDiff );
843849 }
850+ else {
851+ UMLClassMoveDiff classMoveDiff = new UMLClassMoveDiff (removedClass , addedClass , this , matchResult );
852+ if (!classMoveDiffListToBePostProcessed .contains (classMoveDiff ))
853+ classMoveDiffListToBePostProcessed .add (classMoveDiff );
854+ }
844855 }
845856 }
846857 if (!diffSet .isEmpty ()) {
@@ -4365,6 +4376,63 @@ else if(r.getRefactoringType().equals(RefactoringType.EXTRACT_AND_MOVE_OPERATION
43654376 }
43664377 }
43674378 }
4379+ //check the presence of the same class being moved to multiple targets
4380+ Map <String , Set <String >> moveTargetMap = new LinkedHashMap <>();
4381+ for (Refactoring r : refactorings ) {
4382+ if (r instanceof PackageLevelRefactoring pack ) {
4383+ UMLClass originalClass = pack .getOriginalClass ();
4384+ UMLClass movedClass = pack .getMovedClass ();
4385+ if (!originalClass .isTopLevel () && !movedClass .isTopLevel ()) {
4386+ String outerOriginalClass = originalClass .getPackageName ();
4387+ String outerMovedClass = movedClass .getPackageName ();
4388+ String topOriginalClass = outerOriginalClass .contains ("." ) ? outerOriginalClass .substring (0 , outerOriginalClass .lastIndexOf ("." )) : outerOriginalClass ;
4389+ String topMovedClass = outerMovedClass .contains ("." ) ? outerMovedClass .substring (0 , outerMovedClass .lastIndexOf ("." )) : outerMovedClass ;
4390+ if (moveTargetMap .containsKey (outerOriginalClass )) {
4391+ moveTargetMap .get (outerOriginalClass ).add (outerMovedClass );
4392+ }
4393+ else if (moveTargetMap .containsKey (topOriginalClass )) {
4394+ moveTargetMap .get (topOriginalClass ).add (topMovedClass );
4395+ }
4396+ else {
4397+ Set <String > set = new LinkedHashSet <>();
4398+ set .add (outerMovedClass );
4399+ moveTargetMap .put (outerOriginalClass , set );
4400+ }
4401+ }
4402+ }
4403+ }
4404+ for (UMLClassMoveDiff moveDiff : classMoveDiffListToBePostProcessed ) {
4405+ boolean proceed = false ;
4406+ UMLClass originalClass = moveDiff .getOriginalClass ();
4407+ UMLClass movedClass = moveDiff .getMovedClass ();
4408+ if (!originalClass .isTopLevel () && !movedClass .isTopLevel ()) {
4409+ String outerOriginalClass = originalClass .getPackageName ();
4410+ if (moveTargetMap .containsKey (outerOriginalClass ) && moveTargetMap .get (outerOriginalClass ).size () > 1 ) {
4411+ proceed = true ;
4412+ }
4413+ }
4414+ if (!classMoveDiffList .contains (moveDiff ) && proceed ) {
4415+ moveDiff .process ();
4416+ refactorings .addAll (moveDiff .getRefactorings ());
4417+ classMoveDiffList .add (moveDiff );
4418+ Refactoring refactoring = new MoveClassRefactoring (moveDiff .getOriginalClass (), moveDiff .getMovedClass ());
4419+ refactorings .add (refactoring );
4420+ removedClasses .remove (moveDiff .getOriginalClass ());
4421+ addedClasses .remove (moveDiff .getMovedClass ());
4422+ //eliminate inner classes being reported as moved
4423+ List <MoveClassRefactoring > toBeRemoved = new ArrayList <MoveClassRefactoring >();
4424+ for (Refactoring r : refactorings ) {
4425+ if (r instanceof MoveClassRefactoring ) {
4426+ MoveClassRefactoring moveClass = (MoveClassRefactoring )r ;
4427+ if (moveClass .getOriginalClassName ().startsWith (moveDiff .getOriginalClassName () + "." ) &&
4428+ moveClass .getMovedClassName ().startsWith (moveDiff .getNextClassName () + "." )) {
4429+ toBeRemoved .add (moveClass );
4430+ }
4431+ }
4432+ }
4433+ this .refactorings .removeAll (toBeRemoved );
4434+ }
4435+ }
43684436 //match any remaining interface methods with changes in signature
43694437 for (UMLClassDiff classDiff : commonClassDiffList ) {
43704438 if (classDiff .getOriginalClass ().isInterface () && classDiff .getNextClass ().isInterface ()) {
0 commit comments