From 604790ae372983c53aa25cd41764e7d9da50d32a Mon Sep 17 00:00:00 2001 From: soimugeowb Date: Mon, 13 Jan 2025 14:29:01 +0200 Subject: [PATCH 1/2] fix for ValidatorService --- .../protege/gateway/OwlEntityService.java | 13 +++++++- .../gateway/history/EntityHistoryService.java | 4 +-- .../gateway/ontology/OntologyService.java | 18 +++-------- .../gateway/validators/ValidatorService.java | 3 ++ .../protege/gateway/OwlEntityServiceTest.java | 32 ++++++++++--------- .../ontology/OwlOntologyServiceTest.java | 28 ++++++++-------- 6 files changed, 50 insertions(+), 48 deletions(-) diff --git a/src/main/java/edu/stanford/protege/gateway/OwlEntityService.java b/src/main/java/edu/stanford/protege/gateway/OwlEntityService.java index 5463191..7a4587a 100644 --- a/src/main/java/edu/stanford/protege/gateway/OwlEntityService.java +++ b/src/main/java/edu/stanford/protege/gateway/OwlEntityService.java @@ -7,6 +7,7 @@ import edu.stanford.protege.gateway.linearization.EntityLinearizationService; import edu.stanford.protege.gateway.ontology.OntologyService; import edu.stanford.protege.gateway.postcoordination.EntityPostCoordinationService; +import edu.stanford.protege.gateway.validators.ValidatorService; import edu.stanford.protege.webprotege.common.ChangeRequestId; import edu.stanford.protege.webprotege.common.EventId; import edu.stanford.protege.webprotege.common.ProjectId; @@ -41,20 +42,26 @@ public class OwlEntityService { @Value("${icatx.formId}") private String formId; + private final ValidatorService validatorService; + public OwlEntityService(EntityLinearizationService entityLinearizationService, EntityPostCoordinationService entityPostCoordinationService, EntityHistoryService entityHistoryService, @Nonnull EventDispatcher eventDispatcher, - OntologyService ontologyService) { + OntologyService ontologyService, + ValidatorService validatorService) { this.entityLinearizationService = entityLinearizationService; this.entityPostCoordinationService = entityPostCoordinationService; this.ontologyService = ontologyService; this.eventDispatcher = eventDispatcher; this.entityHistoryService = entityHistoryService; + this.validatorService = validatorService; } public OWLEntityDto getEntityInfo(String entityIri, String projectId) { + validatorService.validateProjectId(projectId); + validatorService.validateEntityExists(projectId, entityIri); return getEntityInfo(entityIri, projectId, SecurityContextHelper.getExecutionContext()); } @@ -96,6 +103,8 @@ public OWLEntityDto getEntityInfo(String entityIri, String projectId, ExecutionC } public List getEntityChildren(String entityIRI, String projectId) { + validatorService.validateProjectId(projectId); + validatorService.validateEntityExists(projectId, entityIRI); CompletableFuture> entityChildren = ontologyService.getEntityChildren(entityIRI, projectId); try { @@ -107,6 +116,7 @@ public List getEntityChildren(String entityIRI, String projectId) { } public String createClassEntity(String projectId, CreateEntityDto createEntityDto) { + validatorService.validateCreateEntityRequest(projectId, createEntityDto); CompletableFuture newCreatedEntityIri = ontologyService.createClassEntity(projectId, createEntityDto); try { return newCreatedEntityIri.get(); @@ -162,6 +172,7 @@ public OWLEntityDto updateEntity(OWLEntityDto owlEntityDto, String existingProje } private void validateEntityUpdate(OWLEntityDto owlEntityDto, String existingProjectId, String callerHash) { + callerVersionMatchesLatestVersion(owlEntityDto, existingProjectId, callerHash); entityIsNotItsOwnParent(owlEntityDto); linearizationParentsAreOnlyDirectParents(owlEntityDto, existingProjectId); diff --git a/src/main/java/edu/stanford/protege/gateway/history/EntityHistoryService.java b/src/main/java/edu/stanford/protege/gateway/history/EntityHistoryService.java index 643a1d5..d2c54e4 100644 --- a/src/main/java/edu/stanford/protege/gateway/history/EntityHistoryService.java +++ b/src/main/java/edu/stanford/protege/gateway/history/EntityHistoryService.java @@ -74,11 +74,9 @@ public CompletableFuture getEntityLatestChangeTime(String project @Async public CompletableFuture getEntityLatestChangeTime(String projectId, String entityIri, ExecutionContext executionContext) { - validatorService.validateProjectId(projectId); - validatorService.validateEntityExists(projectId, entityIri); return entityHistorySummaryExecutor.execute(new GetEntityHistorySummaryRequest(projectId, entityIri), executionContext) .thenApply(response -> { - if (response.entityHistorySummary() != null && response.entityHistorySummary().changes() != null && response.entityHistorySummary().changes().size() > 0) { + if (response.entityHistorySummary() != null && response.entityHistorySummary().changes() != null && !response.entityHistorySummary().changes().isEmpty()) { response.entityHistorySummary().changes().sort(Comparator.comparing(EntityChange::timestamp).reversed()); return response.entityHistorySummary().changes().get(0).timestamp(); } diff --git a/src/main/java/edu/stanford/protege/gateway/ontology/OntologyService.java b/src/main/java/edu/stanford/protege/gateway/ontology/OntologyService.java index 130c3fb..a2d48ec 100644 --- a/src/main/java/edu/stanford/protege/gateway/ontology/OntologyService.java +++ b/src/main/java/edu/stanford/protege/gateway/ontology/OntologyService.java @@ -9,7 +9,6 @@ import edu.stanford.protege.gateway.config.ApplicationBeans; import edu.stanford.protege.gateway.dto.*; import edu.stanford.protege.gateway.ontology.commands.*; -import edu.stanford.protege.gateway.validators.ValidatorService; import edu.stanford.protege.webprotege.common.ChangeRequestId; import edu.stanford.protege.webprotege.common.ProjectId; import edu.stanford.protege.webprotege.ipc.CommandExecutor; @@ -33,7 +32,6 @@ public class OntologyService { private final static Logger LOGGER = LoggerFactory.getLogger(OntologyService.class); - private final ValidatorService validatorService; private final CommandExecutor ancestorsExecutor; private final CommandExecutor logicalDefinitionExecutor; private final CommandExecutor formDataExecutor; @@ -47,7 +45,7 @@ public class OntologyService { private final CommandExecutor entityDiscussionExecutor; - public OntologyService(ValidatorService validatorService, CommandExecutor ancestorsExecutor, + public OntologyService(CommandExecutor ancestorsExecutor, CommandExecutor logicalDefinitionExecutor, CommandExecutor formDataExecutor, CommandExecutor entityChildrenExecutor, @@ -57,7 +55,6 @@ public OntologyService(ValidatorService validatorService, CommandExecutor updateLogicalDefinitionExecutor, CommandExecutor updateParentsExecutor, CommandExecutor updateLanguageTermsExecutor) { - this.validatorService = validatorService; this.ancestorsExecutor = ancestorsExecutor; this.logicalDefinitionExecutor = logicalDefinitionExecutor; this.formDataExecutor = formDataExecutor; @@ -71,7 +68,6 @@ public OntologyService(ValidatorService validatorService, CommandExecutor> getEntityParents(String entityIri, String projectId) { return getEntityParents(entityIri, projectId, SecurityContextHelper.getExecutionContext()); @@ -79,9 +75,7 @@ public CompletableFuture> getEntityParents(String entityIri, String @Async public CompletableFuture> getEntityParents(String entityIri, String projectId, ExecutionContext executionContext) { - validatorService.validateProjectId(projectId); - validatorService.validateEntityExists(projectId,entityIri); - return ancestorsExecutor.execute(new GetClassAncestorsRequest(IRI.create(entityIri), ProjectId.valueOf(projectId)),executionContext) + return ancestorsExecutor.execute(new GetClassAncestorsRequest(IRI.create(entityIri), ProjectId.valueOf(projectId)), executionContext) .thenApply(response -> response.getAncestorClassHierarchy().getChildren().stream().map(child -> child.getNode().getEntity().getIRI().toString()) .collect(Collectors.toList())); @@ -92,6 +86,7 @@ public CompletableFuture> getEntityParents(String entityIri, String public CompletableFuture getEntityLogicalConditions(String entityIri, String projectId) { return getEntityLogicalConditions(entityIri, projectId, SecurityContextHelper.getExecutionContext()); } + @Async public CompletableFuture getEntityLogicalConditions(String entityIri, String projectId, ExecutionContext executionContext) { return logicalDefinitionExecutor.execute(new GetLogicalDefinitionsRequest(ProjectId.valueOf(projectId), new OWLClassImpl(IRI.create(entityIri))), executionContext) @@ -104,7 +99,7 @@ public CompletableFuture getEntityLogicalConditi } @Async - public CompletableFuture getEntityLanguageTerms(String entityIri, String projectId, String formId){ + public CompletableFuture getEntityLanguageTerms(String entityIri, String projectId, String formId) { return getEntityLanguageTerms(entityIri, projectId, formId, SecurityContextHelper.getExecutionContext()); } @@ -168,8 +163,6 @@ public void updateLanguageTerms(String entityIri, String projectId, String formI } public CompletableFuture> getEntityChildren(String entityIri, String projectId) { - validatorService.validateProjectId(projectId); - validatorService.validateEntityExists(projectId, entityIri); return entityChildrenExecutor.execute(GetEntityChildrenRequest.create(IRI.create(entityIri), ProjectId.valueOf(projectId)), SecurityContextHelper.getExecutionContext()) .thenApply( response -> response.childrenIris() @@ -180,9 +173,7 @@ public CompletableFuture> getEntityChildren(String entityIri, Strin } - public CompletableFuture createClassEntity(String projectId, CreateEntityDto createEntityDto) { - validatorService.validateCreateEntityRequest(projectId, createEntityDto); return createClassEntityExecutor.execute( CreateClassesFromApiRequest.create( ChangeRequestId.generate(), @@ -212,5 +203,4 @@ public CompletableFuture getEntityDiscussionThreads(String entit } - } diff --git a/src/main/java/edu/stanford/protege/gateway/validators/ValidatorService.java b/src/main/java/edu/stanford/protege/gateway/validators/ValidatorService.java index f657fd8..e46d8df 100644 --- a/src/main/java/edu/stanford/protege/gateway/validators/ValidatorService.java +++ b/src/main/java/edu/stanford/protege/gateway/validators/ValidatorService.java @@ -14,6 +14,7 @@ import org.semanticweb.owlapi.model.IRI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.text.MessageFormat; @@ -43,11 +44,13 @@ public void validateCreateEntityRequest(String projectId, CreateEntityDto create validateEntityParents(projectId, createEntityDto.parent()); } + @Async private CompletableFuture isExistingProject(String projectId) { return isExistingProjectExecutor.execute(GetIsExistingProjectRequest.create(ProjectId.valueOf(projectId)), SecurityContextHelper.getExecutionContext()) .thenApply(GetIsExistingProjectResponse::isExistingProject); } + @Async private CompletableFuture> getExistingEntities(String projectId, String entity) { var entityIri = IRI.create(entity); return filterExistingEntitiesExecutor.execute(FilterExistingEntitiesRequest.create(ProjectId.valueOf(projectId), ImmutableSet.of(entityIri)), SecurityContextHelper.getExecutionContext()) diff --git a/src/test/java/edu/stanford/protege/gateway/OwlEntityServiceTest.java b/src/test/java/edu/stanford/protege/gateway/OwlEntityServiceTest.java index f784727..5b48972 100644 --- a/src/test/java/edu/stanford/protege/gateway/OwlEntityServiceTest.java +++ b/src/test/java/edu/stanford/protege/gateway/OwlEntityServiceTest.java @@ -10,9 +10,9 @@ import edu.stanford.protege.gateway.linearization.EntityLinearizationService; import edu.stanford.protege.gateway.ontology.OntologyService; import edu.stanford.protege.gateway.postcoordination.EntityPostCoordinationService; +import edu.stanford.protege.gateway.validators.ValidatorService; import edu.stanford.protege.webprotege.common.ProjectId; import edu.stanford.protege.webprotege.ipc.EventDispatcher; -import edu.stanford.protege.webprotege.ipc.ExecutionContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -53,14 +53,16 @@ public class OwlEntityServiceTest { private EventDispatcher eventDispatcher; @Mock EntityLogicalConditionsWrapper entityLogicalDefinition; + @Mock + ValidatorService validatorService; private OwlEntityService service; private final String existingProjectId = "b717d9a3-f265-46f5-bd15-9f1cf4b132c8"; - private final LocalDateTime latestUpdate = LocalDateTime.of(2024, 1, 1, 1, 1); + private final LocalDateTime latestUpdate = LocalDateTime.of(2024, 1, 1, 1, 1); - private final String eTag = Hashing.sha256().hashString(latestUpdate.toString(), StandardCharsets.UTF_8).toString(); + private final String eTag = Hashing.sha256().hashString(latestUpdate.toString(), StandardCharsets.UTF_8).toString(); @BeforeEach public void setUp() throws IOException { @@ -69,7 +71,7 @@ public void setUp() throws IOException { .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)); File specFile = new File("src/test/resources/dummyOwlEntityDto.json"); dto = objectMapper.readValue(specFile, OWLEntityDto.class); - service = new OwlEntityService(entityLinearizationService, entityPostCoordinationService,entityHistoryService,eventDispatcher, entityOntologyService); + service = new OwlEntityService(entityLinearizationService, entityPostCoordinationService, entityHistoryService, eventDispatcher, entityOntologyService, validatorService); } @@ -86,7 +88,7 @@ private void initializeGetMocks() { @Test - public void GIVEN_entityWithLinearizationParentDifferentThanExistingParents_WHEN_update_THEN_validationIsThrown(){ + public void GIVEN_entityWithLinearizationParentDifferentThanExistingParents_WHEN_update_THEN_validationIsThrown() { when(entityHistoryService.getEntityLatestChangeTime(eq(existingProjectId), eq(dto.entityIRI()))).thenReturn( CompletableFuture.supplyAsync(() -> LocalDateTime.of(2024, 1, 1, 1, 1)) ); @@ -100,9 +102,9 @@ public void GIVEN_entityWithLinearizationParentDifferentThanExistingParents_WHEN "UNKNOWN", "potatoParent", "http://id.who.int/icd/release/11/ocu", - null)); + null)); - ValidationException exception = assertThrows(ValidationException.class, () -> service.updateEntity(dto, existingProjectId, eTag)); + ValidationException exception = assertThrows(ValidationException.class, () -> service.updateEntity(dto, existingProjectId, eTag)); assertEquals("Entity has a linearization with parent potatoParent that is not in the available parents [http://id.who.int/icd/entity/1553463690]", exception.getMessage()); } @@ -114,35 +116,35 @@ public void GIVEN_entityThatIsPresentAsOwnParent_WHEN_update_THEN_validationExce ); dto.parents().add(dto.entityIRI()); - ValidationException exception = assertThrows(ValidationException.class, () -> service.updateEntity(dto, existingProjectId, eTag)); + ValidationException exception = assertThrows(ValidationException.class, () -> service.updateEntity(dto, existingProjectId, eTag)); assertEquals("Entity contains in the parents its own parents", exception.getMessage()); } @Test - public void GIVEN_callWithDifferentHash_WHEN_update_THEN_versionDoesNotMatchExceptionIsThrown(){ + public void GIVEN_callWithDifferentHash_WHEN_update_THEN_versionDoesNotMatchExceptionIsThrown() { when(entityHistoryService.getEntityLatestChangeTime(eq(existingProjectId), eq(dto.entityIRI()))).thenReturn( CompletableFuture.supplyAsync(() -> LocalDateTime.of(2024, 1, 1, 1, 1)) ); - VersionDoesNotMatchException exception = assertThrows(VersionDoesNotMatchException.class, () -> service.updateEntity(dto, existingProjectId, "PotatoTag")); + VersionDoesNotMatchException exception = assertThrows(VersionDoesNotMatchException.class, () -> service.updateEntity(dto, existingProjectId, "PotatoTag")); assertEquals("Received version out of date : Received hash PotatoTag is different from cd78e6f5802bff1df5f43103eb17e1b2cf17a3f4cf9b182e7d0194eb112ab3df", exception.getMessage()); } @Test - public void GIVEN_getCall_WHEN_titleIsMissing_THEN_exceptionIsThrown(){ + public void GIVEN_getCall_WHEN_titleIsMissing_THEN_exceptionIsThrown() { initializeGetMocks(); when(entityLanguageTerms.title()).thenReturn(new LanguageTerm(null, null)); - EntityIsMissingException exception = assertThrows(EntityIsMissingException.class, () -> service.getEntityInfo(dto.entityIRI(), existingProjectId)); + EntityIsMissingException exception = assertThrows(EntityIsMissingException.class, () -> service.getEntityInfo(dto.entityIRI(), existingProjectId)); assertEquals("Entity with iri http://id.who.int/icd/entity/1855860109 is missing", exception.getMessage()); } @Test - public void GIVEN_aValidUpdateRequest_WHEN_update_THEN_serviceIsCalled(){ + public void GIVEN_aValidUpdateRequest_WHEN_update_THEN_serviceIsCalled() { initializeGetMocks(); when(entityHistoryService.getEntityLatestChangeTime(eq(existingProjectId), eq(dto.entityIRI()))).thenReturn( @@ -163,7 +165,7 @@ public void GIVEN_aValidUpdateRequest_WHEN_update_THEN_serviceIsCalled(){ } @Test - public void GIVEN_validRequest_WHEN_callUpdate_THEN_entityUpdatedSuccessfullyIsEmitted(){ + public void GIVEN_validRequest_WHEN_callUpdate_THEN_entityUpdatedSuccessfullyIsEmitted() { initializeGetMocks(); when(entityHistoryService.getEntityLatestChangeTime(eq(existingProjectId), eq(dto.entityIRI()))).thenReturn( @@ -179,7 +181,7 @@ public void GIVEN_validRequest_WHEN_callUpdate_THEN_entityUpdatedSuccessfullyIsE } @Test - public void GIVEN_applicationExceptionFromLinearization_WHEN_callUpdate_THEN_entityUpdateFailedEventIsEmitted(){ + public void GIVEN_applicationExceptionFromLinearization_WHEN_callUpdate_THEN_entityUpdateFailedEventIsEmitted() { when(entityHistoryService.getEntityLatestChangeTime(eq(existingProjectId), eq(dto.entityIRI()))).thenReturn( CompletableFuture.supplyAsync(() -> LocalDateTime.of(2024, 1, 1, 1, 1)) diff --git a/src/test/java/edu/stanford/protege/gateway/ontology/OwlOntologyServiceTest.java b/src/test/java/edu/stanford/protege/gateway/ontology/OwlOntologyServiceTest.java index 441178a..cc968f6 100644 --- a/src/test/java/edu/stanford/protege/gateway/ontology/OwlOntologyServiceTest.java +++ b/src/test/java/edu/stanford/protege/gateway/ontology/OwlOntologyServiceTest.java @@ -1,20 +1,26 @@ package edu.stanford.protege.gateway.ontology; -import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; import com.fasterxml.jackson.databind.ObjectMapper; import edu.stanford.protege.gateway.config.ApplicationBeans; -import edu.stanford.protege.gateway.dto.*; +import edu.stanford.protege.gateway.dto.EntityLogicalConditionsWrapper; +import edu.stanford.protege.gateway.dto.EntityLogicalDefinition; import edu.stanford.protege.gateway.ontology.commands.*; -import edu.stanford.protege.gateway.validators.ValidatorService; import edu.stanford.protege.webprotege.common.ProjectId; import edu.stanford.protege.webprotege.ipc.CommandExecutor; -import org.junit.jupiter.api.*; +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.junit.jupiter.MockitoExtension; -import java.io.*; -import java.util.concurrent.*; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; @@ -48,10 +54,6 @@ public class OwlOntologyServiceTest { @Mock private CommandExecutor entityChildrenExecutor; - @Mock - private CommandExecutor filterExistingEntitiesExecutor; - @Mock - private CommandExecutor isExistingProjectExecutor; @Mock private CommandExecutor createClassEntityExecutor; @@ -62,9 +64,6 @@ public class OwlOntologyServiceTest { private CommandExecutor entityDiscussionExecutor; private GetLogicalDefinitionsResponse response; - @Mock - private ValidatorService validatorService; - private ProjectId projectId; private String entityIri; @@ -76,8 +75,7 @@ public void setUp() throws IOException { .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)); File specFile = new File("src/test/resources/dummyLogicalDefinitionResponse.json"); response = objectMapper.readValue(specFile, GetLogicalDefinitionsResponse.class); - service = new OntologyService(validatorService, - ancestorsExecutor, + service = new OntologyService(ancestorsExecutor, logicalDefinitionExecutor, formDataExecutor, entityChildrenExecutor, From 0c53ce80dd1c86db47e2af4b03488274ff8173cc Mon Sep 17 00:00:00 2001 From: soimugeowb Date: Mon, 13 Jan 2025 16:45:14 +0200 Subject: [PATCH 2/2] fix for ValidatorService --- src/main/resources/application.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 78ec33d..9e59e29 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -7,7 +7,7 @@ logging: root: DEBUG icatx: - formId: 0612d01f-a60f-4fe7-8421-d404915685d7 + formId: 013d9d4a-9dac-4d2f-aa52-2a40fad73b77 springdoc: swagger-ui: