diff --git a/src/main/java/edu/stanford/protege/webprotege/bulkop/MoveToParentIcdActionHandler.java b/src/main/java/edu/stanford/protege/webprotege/bulkop/MoveToParentIcdActionHandler.java index 48e43f754..12fe72a33 100644 --- a/src/main/java/edu/stanford/protege/webprotege/bulkop/MoveToParentIcdActionHandler.java +++ b/src/main/java/edu/stanford/protege/webprotege/bulkop/MoveToParentIcdActionHandler.java @@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableSet; import edu.stanford.protege.webprotege.DataFactory; import edu.stanford.protege.webprotege.access.AccessManager; +import edu.stanford.protege.webprotege.change.ChangeApplicationResult; import edu.stanford.protege.webprotege.dispatch.AbstractProjectActionHandler; import edu.stanford.protege.webprotege.entity.OWLEntityData; import edu.stanford.protege.webprotege.hierarchy.ClassHierarchyProvider; @@ -95,10 +96,6 @@ public Class getActionClass() { @NotNull @Override public MoveEntitiesToParentIcdResult execute(@NotNull MoveEntitiesToParentIcdAction action, @NotNull ExecutionContext executionContext) { - if (isNotOwlClass(action.parentEntity())) { - return new MoveEntitiesToParentIcdResult(false, ImmutableMap.of()); - } - var isDestinationRetiredClass = false; var isAnyClassReleased = action.entities().stream().anyMatch(releasedClassesChecker::isReleased); @@ -143,29 +140,23 @@ public MoveEntitiesToParentIcdResult execute(@NotNull MoveEntitiesToParentIcdAct ImmutableSet clses = action.entities().stream().collect(toImmutableSet()); var changeListGenerator = factory.create(action.changeRequestId(), clses, action.parentEntity().asOWLClass(), action.commitMessage()); - changeManager.applyChanges(executionContext.userId(), changeListGenerator); - - clses.stream() - .flatMap(cls -> Stream.of(linearizationManager.mergeLinearizationsFromParents(cls.getIRI(), Set.of(action.parentEntity().getIRI()), action.projectId(), executionContext))) - .forEach(completableFuture -> { - try { - completableFuture.get(); - } catch (InterruptedException | ExecutionException e) { - logger.error("MergeLinearizationsError: " + e); - } - }); + ChangeApplicationResult result = changeManager.applyChanges(executionContext.userId(), changeListGenerator); + + if(result.getSubject()){ + clses.stream() + .flatMap(cls -> Stream.of(linearizationManager.mergeLinearizationsFromParents(cls.getIRI(), Set.of(action.parentEntity().getIRI()), action.projectId(), executionContext))) + .forEach(completableFuture -> { + try { + completableFuture.get(); + } catch (InterruptedException | ExecutionException e) { + logger.error("MergeLinearizationsError: " + e); + } + }); + } return new MoveEntitiesToParentIcdResult(isDestinationRetiredClass, ImmutableMap.of()); } - private boolean isEntityAnOwlClass(OWLEntity entity) { - return entity.isOWLClass(); - } - - private boolean isNotOwlClass(OWLEntity entity) { - return !isEntityAnOwlClass(entity); - } - private MoveEntitiesToParentIcdResult getResultWithParentAsLinearizationPathParent(Map> parentsThatAreLinPathParent) { ImmutableMap> result = parentsThatAreLinPathParent .entrySet() diff --git a/src/test/java/edu/stanford/protege/webprotege/bulkop/MoveToParentIcdActionHandlerTest.java b/src/test/java/edu/stanford/protege/webprotege/bulkop/MoveToParentIcdActionHandlerTest.java index 8b130f9ad..2adf36a50 100644 --- a/src/test/java/edu/stanford/protege/webprotege/bulkop/MoveToParentIcdActionHandlerTest.java +++ b/src/test/java/edu/stanford/protege/webprotege/bulkop/MoveToParentIcdActionHandlerTest.java @@ -2,6 +2,8 @@ import com.google.common.collect.ImmutableSet; import edu.stanford.protege.webprotege.access.AccessManager; +import edu.stanford.protege.webprotege.change.ChangeApplicationResult; +import edu.stanford.protege.webprotege.change.OntologyChange; import edu.stanford.protege.webprotege.common.ProjectId; import edu.stanford.protege.webprotege.common.UserId; import edu.stanford.protege.webprotege.entity.OWLEntityData; @@ -12,6 +14,7 @@ import edu.stanford.protege.webprotege.ipc.ExecutionContext; import edu.stanford.protege.webprotege.linearization.LinearizationManager; import edu.stanford.protege.webprotege.linearization.MergeWithParentEntitiesResponse; +import edu.stanford.protege.webprotege.owlapi.RenameMap; import edu.stanford.protege.webprotege.project.chg.ChangeManager; import edu.stanford.protege.webprotege.renderer.RenderingManager; import org.junit.jupiter.api.BeforeEach; @@ -27,6 +30,7 @@ import org.semanticweb.owlapi.model.OWLEntity; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; @@ -69,6 +73,13 @@ class MoveToParentIcdActionHandlerTest { private MoveToParentIcdActionHandler actionHandler; private ExecutionContext executionContext; + @Mock + private ChangeApplicationResult changeApplicationResult; + @Mock + private List ontologyChangeList; + @Mock + private RenameMap renameMap; + @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); @@ -83,6 +94,10 @@ void setUp() { linParentChecker, renderingManager, classHierarchyProvider); + + when(changeApplicationResult.getRenameMap()).thenReturn(renameMap); + when(changeApplicationResult.getChangeList()).thenReturn(ontologyChangeList); + when(changeApplicationResult.getSubject()).thenReturn(true); } private OWLClass mockOwlEntityAsClass(OWLEntity entity, String iri) { @@ -97,23 +112,6 @@ private OWLClass mockOwlEntityAsClass(OWLEntity entity, String iri) { return owlClass; } - @Test - void GIVEN_nonOwlClassParent_WHEN_executeCalled_THEN_returnsFailure() { - - OWLEntity entity = mock(OWLEntity.class); - OWLClass entityClass = mockOwlEntityAsClass(entity, "http://example.org/entity"); - OWLEntity parent = mock(OWLEntity.class); - OWLClass parentClass = mockOwlEntityAsClass(parent, "http://example.org/parent"); - MoveEntitiesToParentIcdAction action = new MoveEntitiesToParentIcdAction(null, projectId, ImmutableSet.of(entityClass), parentClass, "Test Commit Message"); - - when(parent.isOWLClass()).thenReturn(false); - - MoveEntitiesToParentIcdResult result = actionHandler.execute(action, executionContext); - - assertFalse(result.isDestinationRetiredClass()); - assertTrue(result.entitiesForWhichParentIsLinPathParent().isEmpty()); - } - @Test void GIVEN_retiredParent_WHEN_executeCalled_THEN_returnsFailure() { OWLEntity entity = mock(OWLEntity.class); @@ -143,7 +141,7 @@ void GIVEN_validMove_WHEN_executeCalled_THEN_success() { MoveEntitiesToParentIcdAction action = new MoveEntitiesToParentIcdAction(null, projectId, ImmutableSet.of(mockOwlEntityAsClass(entity, "http://example.org/entity")), parentClass, "Test Commit Message"); - when(changeManager.applyChanges(any(), any())).thenReturn(null); + doReturn(changeApplicationResult).when(changeManager).applyChanges(any(), any()); when(linearizationManager.mergeLinearizationsFromParents(any(), any(), any(), any())) .thenReturn(CompletableFuture.completedFuture(null)); @@ -159,9 +157,10 @@ void GIVEN_linearizationPathParents_WHEN_executeCalled_THEN_resultContainsLinear OWLEntity newParent = mock(OWLEntity.class); OWLEntity currParent = mock(OWLEntity.class); String currentParentIri = "http://example.org/parent"; + String newParentIri = "http://example.org/newParent"; OWLClass entityClass = mockOwlEntityAsClass(entity, "http://example.org/entity"); OWLClass currParentClass = mockOwlEntityAsClass(currParent, currentParentIri); - OWLClass newParentClass = mockOwlEntityAsClass(currParent, currentParentIri); + OWLClass newParentClass = mockOwlEntityAsClass(newParent, newParentIri); when(classHierarchyProvider.getParents(any())).thenReturn(Set.of(currParentClass)); diff --git a/src/test/java/edu/stanford/protege/webprotege/hierarchy/MoveHierarchyNodeIcdActionHandlerTest.java b/src/test/java/edu/stanford/protege/webprotege/hierarchy/MoveHierarchyNodeIcdActionHandlerTest.java new file mode 100644 index 000000000..03ec5e8c6 --- /dev/null +++ b/src/test/java/edu/stanford/protege/webprotege/hierarchy/MoveHierarchyNodeIcdActionHandlerTest.java @@ -0,0 +1,231 @@ +package edu.stanford.protege.webprotege.hierarchy; + +import edu.stanford.protege.webprotege.access.AccessManager; +import edu.stanford.protege.webprotege.change.ChangeApplicationResult; +import edu.stanford.protege.webprotege.change.OntologyChange; +import edu.stanford.protege.webprotege.common.ProjectId; +import edu.stanford.protege.webprotege.common.UserId; +import edu.stanford.protege.webprotege.entity.EntityNode; +import edu.stanford.protege.webprotege.icd.LinearizationParentChecker; +import edu.stanford.protege.webprotege.icd.ReleasedClassesChecker; +import edu.stanford.protege.webprotege.icd.hierarchy.ClassHierarchyRetiredClassDetector; +import edu.stanford.protege.webprotege.ipc.ExecutionContext; +import edu.stanford.protege.webprotege.linearization.LinearizationManager; +import edu.stanford.protege.webprotege.owlapi.RenameMap; +import edu.stanford.protege.webprotege.project.chg.ChangeManager; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; +import org.semanticweb.owlapi.model.IRI; +import org.semanticweb.owlapi.model.OWLClass; +import org.semanticweb.owlapi.model.OWLEntity; + +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class MoveHierarchyNodeIcdActionHandlerTest { + + @Mock + private AccessManager accessManager; + + @Mock + private MoveEntityChangeListGeneratorFactory factory; + + @Mock + private ReleasedClassesChecker releasedClassesChecker; + + @Mock + private ClassHierarchyRetiredClassDetector retiredAncestorDetector; + + @Mock + private ChangeManager changeManager; + + @Mock + private LinearizationManager linearizationManager; + + @Mock + private LinearizationParentChecker linParentChecker; + + private ProjectId projectId; + private MoveHierarchyNodeIcdActionHandler actionHandler; + private ExecutionContext executionContext; + + @Mock + private ChangeApplicationResult changeApplicationResult; + @Mock + private List ontologyChangeList; + @Mock + private RenameMap renameMap; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + projectId = ProjectId.generate(); + executionContext = new ExecutionContext(UserId.getGuest(), ""); + + actionHandler = new MoveHierarchyNodeIcdActionHandler( + accessManager, + factory, + releasedClassesChecker, + retiredAncestorDetector, + changeManager, + linearizationManager, + linParentChecker + ); + + when(changeApplicationResult.getRenameMap()).thenReturn(renameMap); + when(changeApplicationResult.getChangeList()).thenReturn(ontologyChangeList); + when(changeApplicationResult.getSubject()).thenReturn(true); + } + + @Test + void GIVEN_retiredParent_WHEN_executeCalled_THEN_returnsFailure() { + Path fromNodePath = mock(Path.class); + Path toNodeParentPath = mock(Path.class); + MoveHierarchyNodeIcdAction action = new MoveHierarchyNodeIcdAction(null, + projectId, + ClassHierarchyDescriptor.create(), + fromNodePath, + toNodeParentPath, + DropType.MOVE); + + var entityNode = mock(EntityNode.class); + var owlEntity = mock(OWLEntity.class); + var owlClass = mock(OWLClass.class); + when(fromNodePath.getLast()).thenReturn(java.util.Optional.of(entityNode)); + when(entityNode.getEntity()).thenReturn(owlEntity); + when(owlEntity.isOWLClass()).thenReturn(true); + when(owlEntity.asOWLClass()).thenReturn(owlClass); + + var destinationNode = mock(EntityNode.class); + var destinationEntity = mock(OWLEntity.class); + var destinationClass = mock(OWLClass.class); + when(toNodeParentPath.getLast()).thenReturn(java.util.Optional.of(destinationNode)); + when(destinationNode.getEntity()).thenReturn(destinationEntity); + when(destinationEntity.isOWLClass()).thenReturn(true); + when(destinationEntity.asOWLClass()).thenReturn(destinationClass); + + + when(releasedClassesChecker.isReleased(any())).thenReturn(true); + when(retiredAncestorDetector.isRetired(any())).thenReturn(true); + + MoveHierarchyNodeIcdResult result = actionHandler.execute(action, executionContext); + + assertFalse(result.moved()); + assertTrue(result.isDestinationRetiredClass()); + assertFalse(result.isInitialParentLinPathParent()); + } + + @Test + void GIVEN_validMove_WHEN_executeCalled_THEN_success() { + Path fromNodePath = mock(Path.class); + Path toNodeParentPath = mock(Path.class); + MoveHierarchyNodeIcdAction action = new MoveHierarchyNodeIcdAction(null, + projectId, + ClassHierarchyDescriptor.create(), + fromNodePath, + toNodeParentPath, + DropType.MOVE); + + var entityNode = mock(EntityNode.class); + var entity = mock(OWLEntity.class); + var sourceIri = IRI.create("http://example.org/destination"); + when(fromNodePath.getLast()).thenReturn(java.util.Optional.of(entityNode)); + when(entityNode.getEntity()).thenReturn(entity); + when(entity.isOWLClass()).thenReturn(true); + when(entity.getIRI()).thenReturn(sourceIri); + + var destinationNode = mock(EntityNode.class); + var destinationEntity = mock(OWLEntity.class); + var destinationClass = mock(OWLClass.class); + var destinationIri = IRI.create("http://example.org/destination"); + when(toNodeParentPath.getLast()).thenReturn(java.util.Optional.of(destinationNode)); + when(destinationNode.getEntity()).thenReturn(destinationEntity); + when(destinationEntity.isOWLClass()).thenReturn(true); + when(destinationEntity.asOWLClass()).thenReturn(destinationClass); + when(destinationEntity.getIRI()).thenReturn(destinationIri); + + when(releasedClassesChecker.isReleased(entity)).thenReturn(false); + doReturn(changeApplicationResult).when(changeManager).applyChanges(any(), any()); + when(linearizationManager.mergeLinearizationsFromParents(any(), any(), any(), any())) + .thenReturn(CompletableFuture.completedFuture(null)); + + MoveHierarchyNodeIcdResult result = actionHandler.execute(action, executionContext); + + assertTrue(result.moved()); + assertFalse(result.isDestinationRetiredClass()); + assertFalse(result.isInitialParentLinPathParent()); + + verify(linearizationManager).mergeLinearizationsFromParents( + entity.getIRI(), + Set.of(destinationEntity.getIRI()), + action.projectId(), + executionContext + ); + } + + + @Test + void GIVEN_linearizationPathParents_WHEN_executeCalled_THEN_resultContainsLinearizationPathParents() { + Path fromNodePath = mock(Path.class); + Path toNodeParentPath = mock(Path.class); + MoveHierarchyNodeIcdAction action = new MoveHierarchyNodeIcdAction(null, + projectId, + ClassHierarchyDescriptor.create(), + fromNodePath, + toNodeParentPath, + DropType.MOVE); + + var entityNode = mock(EntityNode.class); + var entity = mock(OWLEntity.class); + var entityIri = IRI.create("http://example.org/entity"); + when(fromNodePath.getLast()).thenReturn(java.util.Optional.of(entityNode)); + when(entityNode.getEntity()).thenReturn(entity); + when(entity.isOWLClass()).thenReturn(true); + when(entity.getIRI()).thenReturn(entityIri); + + var destinationNode = mock(EntityNode.class); + var destinationEntity = mock(OWLEntity.class); + var destinationIri = IRI.create("http://example.org/destination"); + when(toNodeParentPath.getLast()).thenReturn(java.util.Optional.of(destinationNode)); + when(destinationNode.getEntity()).thenReturn(destinationEntity); + when(destinationEntity.getIRI()).thenReturn(destinationIri); + + var previousParent = mock(EntityNode.class); + var previousParentEntity = mock(OWLEntity.class); + var previousParentIri = IRI.create("http://example.org/previousParent"); + when(fromNodePath.getLastPredecessor()).thenReturn(java.util.Optional.of(previousParent)); + when(previousParent.getEntity()).thenReturn(previousParentEntity); + when(previousParentEntity.getIRI()).thenReturn(previousParentIri); + + when(linParentChecker.getParentThatIsLinearizationPathParent(entityIri, + Set.of(previousParentIri), + action.projectId()) + ).thenReturn(Set.of(previousParentIri)); + + MoveHierarchyNodeIcdResult result = actionHandler.execute(action, executionContext); + + assertFalse(result.moved()); + assertFalse(result.isDestinationRetiredClass()); + assertTrue(result.isInitialParentLinPathParent()); + + verify(linParentChecker).getParentThatIsLinearizationPathParent( + entityIri, + Set.of(previousParentIri), + action.projectId() + ); + } + +}