From 50db62deb682ace14009dcceb43289f7b8a173ca Mon Sep 17 00:00:00 2001 From: Kriti Jain Date: Wed, 14 Aug 2024 13:12:44 -0500 Subject: [PATCH] creating an end point for migrating fqm --- descriptors/ModuleDescriptor-template.json | 15 +++- .../fqm/resource/MigrationController.java | 35 +++++++++ .../swagger.api/mod-fqm-manager.yaml | 29 +++++++- .../schemas/FqmMigrateRequest.json | 27 +++++++ .../schemas/FqmMigrateResponse.json | 46 ++++++++++++ .../controller/MigrationControllerTest.java | 72 +++++++++++++++++-- 6 files changed, 218 insertions(+), 6 deletions(-) create mode 100644 src/main/resources/swagger.api/schemas/FqmMigrateRequest.json create mode 100644 src/main/resources/swagger.api/schemas/FqmMigrateResponse.json diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index db72c81bd..a7e21d5cb 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -77,6 +77,12 @@ "permissionsRequired": ["fqm.version.get"], "modulePermissions": ["perms.users.get"] }, + { + "methods": ["POST"], + "pathPattern": "/fqm/migrate", + "permissionsRequired": ["fqm.migrate.post"], + "modulePermissions": ["perms.users.get"] + }, { "methods": ["POST"], "pathPattern": "/query/contents", @@ -183,6 +189,12 @@ "description": "Get the version of fqm", "visible": true }, + { + "permissionName": "fqm.migrate.post", + "displayName": "FQM - Submit FQM Migration", + "description": "Submit FQM Migration and get results", + "visible": true + }, { "permissionName": "fqm.materializedViews.post", "displayName": "FQM - Refresh materialized views", @@ -205,7 +217,8 @@ "fqm.query.async.results.get", "fqm.query.async.delete", "fqm.query.sync.get", - "fqm.version.get" + "fqm.version.get", + "fqm.migrate.post" ], "visible": true } diff --git a/src/main/java/org/folio/fqm/resource/MigrationController.java b/src/main/java/org/folio/fqm/resource/MigrationController.java index 633fd597b..ed89bc1e0 100644 --- a/src/main/java/org/folio/fqm/resource/MigrationController.java +++ b/src/main/java/org/folio/fqm/resource/MigrationController.java @@ -1,18 +1,53 @@ package org.folio.fqm.resource; import lombok.RequiredArgsConstructor; +import org.folio.fqm.domain.dto.FqmMigrateRequest; +import org.folio.fqm.domain.dto.FqmMigrateResponse; +import org.folio.fqm.domain.dto.FqmMigrateResponseWarningsInner; +import org.folio.fqm.migration.MigratableQueryInformation; import org.folio.fqm.service.MigrationService; +import org.folio.spring.i18n.service.TranslationService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; + @RestController @RequiredArgsConstructor public class MigrationController implements FqmVersionApi { private final MigrationService migrationService; + private final TranslationService translationService; + @Override public ResponseEntity getFqmVersion() { return new ResponseEntity<>(migrationService.getLatestVersion(), HttpStatus.OK); } + + @Override + public ResponseEntity fqmMigrate(FqmMigrateRequest fqmMigrateRequest) { + MigratableQueryInformation migratableQueryInformation = new MigratableQueryInformation( + fqmMigrateRequest.getEntityTypeId(), + fqmMigrateRequest.getFqlQuery(), + fqmMigrateRequest.getFields() + ); + + MigratableQueryInformation updatedQueryInfo = migrationService.migrate(migratableQueryInformation); + + FqmMigrateResponse fqmMigrateResponse = new FqmMigrateResponse() + .entityTypeId(updatedQueryInfo.entityTypeId()) + .fqlQuery(updatedQueryInfo.fqlQuery()) + .fields(updatedQueryInfo.fields()) + .warnings(updatedQueryInfo.warnings().stream() + .map(warning -> new FqmMigrateResponseWarningsInner() + .type(warning.getType() != null ? warning.getType().toString() : null) + .description(warning.getDescription(translationService) != null ? + warning.getDescription(translationService) : "No description provided" + ) + ) + .toList() + ); + + return new ResponseEntity<>(fqmMigrateResponse, HttpStatus.OK); + } } diff --git a/src/main/resources/swagger.api/mod-fqm-manager.yaml b/src/main/resources/swagger.api/mod-fqm-manager.yaml index 9e236ea5e..34e0d90d1 100644 --- a/src/main/resources/swagger.api/mod-fqm-manager.yaml +++ b/src/main/resources/swagger.api/mod-fqm-manager.yaml @@ -79,6 +79,30 @@ paths: $ref: '#/components/responses/badRequestResponse' '500': $ref: '#/components/responses/internalServerErrorResponse' + /fqm/migrate: + post: + summary: fqm migrate request + operationId: fqmMigrate + tags: + - fqmVersion + requestBody: + description: 'Request for FQM version submitted successfully' + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/fqmMigrateRequest' + responses: + '201': + description: 'FQM version updated successfully' + content: + application/json: + schema: + $ref: '#/components/schemas/fqmMigrateResponse' + '400': + $ref: '#/components/responses/badRequestResponse' + '500': + $ref: '#/components/responses/internalServerErrorResponse' components: parameters: @@ -133,6 +157,10 @@ components: type: array items: type: string + fqmMigrateRequest: + $ref: schemas/FqmMigrateRequest.json + fqmMigrateResponse: + $ref: schemas/FqmMigrateResponse.json responses: badRequestResponse: @@ -155,4 +183,3 @@ components: code: unexpected.error schema: $ref: "#/components/schemas/errorResponse" - diff --git a/src/main/resources/swagger.api/schemas/FqmMigrateRequest.json b/src/main/resources/swagger.api/schemas/FqmMigrateRequest.json new file mode 100644 index 000000000..ac532bf1e --- /dev/null +++ b/src/main/resources/swagger.api/schemas/FqmMigrateRequest.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Entity Upgrade Request", + "description": "Schema for a request to upgrade an entity payload, including an entity type ID, FQL query, and list of fields.", + "type": "object", + "properties": { + "entityTypeId": { + "description": "ID of the entity type to be upgraded", + "type": "string", + "format": "UUID" + }, + "fqlQuery": { + "description": "FQL query string to be used for the upgrade", + "type": "string" + }, + "fields": { + "description": "List of fields to be included in the upgrade", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "entityTypeId" + ] +} diff --git a/src/main/resources/swagger.api/schemas/FqmMigrateResponse.json b/src/main/resources/swagger.api/schemas/FqmMigrateResponse.json new file mode 100644 index 000000000..062f71864 --- /dev/null +++ b/src/main/resources/swagger.api/schemas/FqmMigrateResponse.json @@ -0,0 +1,46 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Entity Upgrade Response", + "description": "Schema for a response to upgrade FQM", + "type": "object", + "properties": { + "entityTypeId": { + "description": "ID of the entity type upgraded successfully", + "type": "string", + "format": "UUID" + }, + "fqlQuery": { + "description": "FQL query string upgraded successfully", + "type": "string" + }, + "fields": { + "description": "List of fields upgraded successfully", + "type": "array", + "items": { + "type": "string" + } + }, + "warnings": { + "description": "List of warnings issued during the upgrade", + "type": "array", + "items": { + "type": "object", + "properties": { + "description": { + "description": "Description of the warning", + "type": "string" + }, + "type": { + "description": "Type of warning", + "type": "string" + } + }, + "required": [ + ] + } + } +}, + "required": [ + "entityTypeId" + ] +} diff --git a/src/test/java/org/folio/fqm/controller/MigrationControllerTest.java b/src/test/java/org/folio/fqm/controller/MigrationControllerTest.java index 4b494ae7f..3a21f0244 100644 --- a/src/test/java/org/folio/fqm/controller/MigrationControllerTest.java +++ b/src/test/java/org/folio/fqm/controller/MigrationControllerTest.java @@ -1,24 +1,39 @@ package org.folio.fqm.controller; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.folio.fqm.domain.dto.FqmMigrateRequest; +import org.folio.fqm.migration.MigratableQueryInformation; +import org.folio.fqm.migration.warnings.DeprecatedEntityWarning; +import org.folio.fqm.migration.warnings.Warning; import org.folio.fqm.resource.MigrationController; import org.folio.fqm.service.MigrationService; import org.folio.spring.FolioExecutionContext; +import org.folio.spring.i18n.service.TranslationService; +import org.folio.spring.integration.XOkapiHeaders; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.RequestBuilder; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import java.util.List; +import java.util.UUID; + +import static org.hamcrest.Matchers.is; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @WebMvcTest(MigrationController.class) class MigrationControllerTest { private static final String GET_VERSION_URL = "/fqm/version"; + + private static final String POST_FQM_MIGRATE_REQUEST = "/fqm/migrate"; @Autowired private MockMvc mockMvc; @@ -28,6 +43,9 @@ class MigrationControllerTest { @MockBean private FolioExecutionContext executionContext; + @MockBean + private TranslationService translationService; + @Test void shouldReturnVersion() throws Exception { String tenantId = "tenant_01"; @@ -35,10 +53,56 @@ void shouldReturnVersion() throws Exception { when(migrationService.getLatestVersion()).thenReturn("1"); RequestBuilder builder = MockMvcRequestBuilders .get(GET_VERSION_URL) - .accept(MediaType.APPLICATION_JSON); + .accept(APPLICATION_JSON); mockMvc .perform(builder) .andExpect(status().isOk()) .andExpect(content().string("1")); } + + @Test + void shouldMigrateFqmSuccessfully1() throws Exception { + String tenantId = "tenant_01"; + UUID entityTypeID = UUID.randomUUID(); + FqmMigrateRequest fqmMigrateRequest = getFqmMigrateRequest(entityTypeID); + + MigratableQueryInformation migratableQueryInformation = mock(MigratableQueryInformation.class); + + Warning deprecatedEntityWarning = mock(DeprecatedEntityWarning.class); + List warningList = List.of(deprecatedEntityWarning); + + when(deprecatedEntityWarning.getType()).thenReturn(Warning.WarningType.DEPRECATED_ENTITY); + when(deprecatedEntityWarning.getDescription(any())).thenReturn("def"); + + when(executionContext.getTenantId()).thenReturn(tenantId); + when(migratableQueryInformation.entityTypeId()).thenReturn(entityTypeID); + when(migratableQueryInformation.fqlQuery()).thenReturn("users.active"); + when(migratableQueryInformation.fields()).thenReturn(List.of("field1", "field2")); + when(migratableQueryInformation.warnings()).thenReturn(warningList); + + when(migrationService.migrate(any(MigratableQueryInformation.class))).thenReturn(migratableQueryInformation); + + RequestBuilder builder = MockMvcRequestBuilders + .post(POST_FQM_MIGRATE_REQUEST) + .header(XOkapiHeaders.TENANT, tenantId) + .contentType(APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(fqmMigrateRequest)); + + mockMvc + .perform(builder) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.entityTypeId", is(entityTypeID.toString()))) + .andExpect(jsonPath("$.fqlQuery", is("users.active"))) + .andExpect(jsonPath("$.fields", is(List.of("field1", "field2")))) + .andExpect(jsonPath("$.warnings[0].type", is("DEPRECATED_ENTITY"))) // Matching the warning type + .andExpect(jsonPath("$.warnings[0].description", is("def"))); // Matching the warning description + } + @NotNull + private static FqmMigrateRequest getFqmMigrateRequest(UUID entityTypeID) { + FqmMigrateRequest fqmMigrateRequest = new FqmMigrateRequest(); + fqmMigrateRequest.setEntityTypeId(entityTypeID); + fqmMigrateRequest.setFqlQuery("users.active"); + fqmMigrateRequest.setFields(List.of("field1", "field2")); + return fqmMigrateRequest; + } }