diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/register/RegistryController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/register/RegistryController.java index 8a9a88bba..b3ddb310f 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/register/RegistryController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/register/RegistryController.java @@ -4,16 +4,36 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; +import org.springframework.util.StopWatch; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.server.ResponseStatusException; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.backendapi.controller.queue.AbstractQueueController; -import ru.spcex.clearing.backendapi.controller.request.cud.registry.*; +import ru.spcex.clearing.backendapi.controller.request.cud.registry.ChangeRefundDateActionNew; +import ru.spcex.clearing.backendapi.controller.request.cud.registry.ChangeStatusExtractActionNew; +import ru.spcex.clearing.backendapi.controller.request.cud.registry.IdentificationFundsActionNew; +import ru.spcex.clearing.backendapi.controller.request.cud.registry.RSplitDepositActionNew; +import ru.spcex.clearing.backendapi.controller.request.cud.registry.ReturnDepositActionNew; import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse; import ru.spcex.clearing.backendapi.controller.response.cud.CudResponse; import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse; @@ -22,14 +42,11 @@ import ru.spcex.clearing.backendapi.service.IStateLoader; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.Consts; import ru.spcex.platform.enumeration.RegistryDesignation; +import ru.spcex.platform.enumeration.RegistryStatus; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; - -import java.time.LocalDate; -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ExecutionException; +import ru.spcex.platform.utils.enumeration.IEnumKey; @Controller @RequestMapping("/registries") @@ -43,8 +60,8 @@ public class RegistryController extends AbstractQueueController { super(operator); this.stateLoader = stateLoader; this.predicateBuilder = imdgProvider - .getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class) - .predicateBuilder(); + .getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class) + .predicateBuilder(); } @ApiOperation(value = "get all registries.") @@ -54,18 +71,18 @@ public class RegistryController extends AbstractQueueController { public CommonGetAllResponse getAll() { // long t1 = System.currentTimeMillis(); ImdgPredicate filter = predicateBuilder.or( - predicateBuilder.equals("registryDesignation", RegistryDesignation.A.getKey()), - predicateBuilder.equals("registryDesignation", RegistryDesignation.D.getKey()), - predicateBuilder.and( - predicateBuilder.or( - predicateBuilder.equals("registryDesignation", RegistryDesignation.O.getKey()), - predicateBuilder.equals("registryDesignation", RegistryDesignation.T.getKey()) - ), - predicateBuilder.greatEqual("settlementDate", LocalDate.now()) - ) + predicateBuilder.equals("registryDesignation", RegistryDesignation.A.getKey()), + predicateBuilder.equals("registryDesignation", RegistryDesignation.D.getKey()), + predicateBuilder.and( + predicateBuilder.or( + predicateBuilder.equals("registryDesignation", RegistryDesignation.O.getKey()), + predicateBuilder.equals("registryDesignation", RegistryDesignation.T.getKey()) + ), + predicateBuilder.greatEqual("settlementDate", LocalDate.now()) + ) ); Collection> all = stateLoader.getAllMetaTransform(IMDGDistributedNames.Map_Registry, Registry.class, - filter); + filter); // long t2 = System.currentTimeMillis(); // log.info("Info select and format {} data {}", all.size(), t2 - t1); CommonGetAllResponse response = new CommonGetAllResponse(); @@ -74,13 +91,60 @@ public class RegistryController extends AbstractQueueController { return response; } + @ApiOperation(value = "get registries by filter.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CommonGetAllResponse.class)}) + @RequestMapping(value = "/filter", method = RequestMethod.GET) + @ResponseBody + public CommonGetAllResponse getByFilter(@RequestParam(name = "designation", required = false) Optional> designations, + @RequestParam(name = "status", required = false) Optional status, + @RequestParam(name = "pageSize", required = false) Optional pageSize, + @RequestParam(name = "pageIndex", required = false) Optional pageIndex) { + if (designations.isEmpty() && status.isEmpty()) { + throw new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE, "Request should have at least one of the parameters: designation, status"); + } + + StopWatch sw = new StopWatch("registry-controller-stopwatch"); + sw.start(); + + List filters = new ArrayList<>(); + designations.ifPresent(ds -> filters.add(predicateBuilder.in("registryDesignation", ds.stream() + .map(d -> Optional.ofNullable(IEnumKey.getEnumByKey(RegistryDesignation.class, d)) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE, "Unknown registry designation: " + d))) + .map(RegistryDesignation::getKey) + .toArray(String[]::new)))); + status.ifPresent(s -> filters.add(predicateBuilder.in("registryStatus", Optional.ofNullable(IEnumKey.getEnumByKey(RegistryStatus.class, s)) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE, "Unknown registry status: " + s)) + .getKey()))); + + AtomicReference>> all = new AtomicReference<>(); + pageIndex.ifPresentOrElse(index -> { + ImdgPredicate filter = predicateBuilder.and(filters.toArray(ImdgPredicate[]::new)); + all.set(stateLoader.getAllMetaTransformWithPagination(IMDGDistributedNames.Map_Registry, Registry.class, filter, + index, pageSize.orElse(100))); + }, + () -> { + ImdgPredicate filter = predicateBuilder.and(filters.toArray(ImdgPredicate[]::new)); + all.set(stateLoader.getAllMetaTransform(IMDGDistributedNames.Map_Registry, Registry.class, filter)); + }); + + sw.stop(); + log.info("Info select and format {} data took {} ms", all.get().size(), sw.getLastTaskTimeMillis()); + + sw.start(); + CommonGetAllResponse response = new CommonGetAllResponse(); + response.fromEntity(all.get()); + sw.stop(); + log.info("Info select and format {} data {}", all.get().size(), sw.getLastTaskTimeMillis()); + return response; + } + @ApiOperation(value = "Досрочное изъятие части денежных средств по договору") @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) @RequestMapping(value = "/splitDeposit", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody public CudResponse splitDepositAction( - @ApiParam(value = "Параметры команды в JSON формате.", required = true) - @RequestBody RSplitDepositActionNew rSplitDepositActionNew) throws ExecutionException, InterruptedException { + @ApiParam(value = "Параметры команды в JSON формате.", required = true) + @RequestBody RSplitDepositActionNew rSplitDepositActionNew) throws ExecutionException, InterruptedException { return processRequest(Consts.REGISTRY_SPLIT_DEPOSIT_ACTION, rSplitDepositActionNew); } @@ -89,10 +153,10 @@ public class RegistryController extends AbstractQueueController { @RequestMapping(value = "/returnDeposit/{id}", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody public CudResponse returnDepositAction( - @ApiParam(value = "Идентификатор изменяемого объекта.", required = true, example = "1234") - @PathVariable("id") Long id, - @ApiParam(value = "Параметры команды в JSON формате.", required = true) - @RequestBody ReturnDepositActionNew returnDepositAction) throws ExecutionException, InterruptedException { + @ApiParam(value = "Идентификатор изменяемого объекта.", required = true, example = "1234") + @PathVariable("id") Long id, + @ApiParam(value = "Параметры команды в JSON формате.", required = true) + @RequestBody ReturnDepositActionNew returnDepositAction) throws ExecutionException, InterruptedException { returnDepositAction.setId(id); return processRequest(Consts.REGISTRY_RETURN_DEPOSIT_ACTION, returnDepositAction); } @@ -102,10 +166,10 @@ public class RegistryController extends AbstractQueueController { @RequestMapping(value = "/identificationFunds/{id}", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody public CudResponse identificationFundsAction( - @ApiParam(value = "Идентификатор изменяемого объекта.", required = true, example = "1234") - @PathVariable("id") Long id, - @ApiParam(value = "Параметры команды в JSON формате.", required = true) - @RequestBody IdentificationFundsActionNew identificationFundsActionNew) throws ExecutionException, InterruptedException { + @ApiParam(value = "Идентификатор изменяемого объекта.", required = true, example = "1234") + @PathVariable("id") Long id, + @ApiParam(value = "Параметры команды в JSON формате.", required = true) + @RequestBody IdentificationFundsActionNew identificationFundsActionNew) throws ExecutionException, InterruptedException { identificationFundsActionNew.setId(id); return processRequest(Consts.REGISTRY_IDENTIFICATION_FUNDS, identificationFundsActionNew); } @@ -115,10 +179,10 @@ public class RegistryController extends AbstractQueueController { @RequestMapping(value = "/changeRefundDate/{groupId}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody public CudResponse changeRefundDate( - @ApiParam(value = "Идентификатор группы связанных регистров.", required = true, example = "1234") - @PathVariable("groupId") Long groupId, - @ApiParam(value = "Параметры команды в JSON формате.", required = true) - @RequestBody ChangeRefundDateActionNew returnDepositAction) throws ExecutionException, InterruptedException { + @ApiParam(value = "Идентификатор группы связанных регистров.", required = true, example = "1234") + @PathVariable("groupId") Long groupId, + @ApiParam(value = "Параметры команды в JSON формате.", required = true) + @RequestBody ChangeRefundDateActionNew returnDepositAction) throws ExecutionException, InterruptedException { returnDepositAction.setGroupId(groupId); return processRequest(Consts.REGISTRY_CHANGE_REFUND_DATE_ACTION, returnDepositAction); } @@ -128,10 +192,10 @@ public class RegistryController extends AbstractQueueController { @RequestMapping(value = "/changeStatusExtract/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody public CudResponse changeStatusExtract( - @ApiParam(value = "Идентификатор регистра.", required = true, example = "1234") - @PathVariable("id") Long id, - @ApiParam(value = "Параметры команды в JSON формате.", required = true) - @RequestBody ChangeStatusExtractActionNew changeStatusExtractAction) throws ExecutionException, InterruptedException { + @ApiParam(value = "Идентификатор регистра.", required = true, example = "1234") + @PathVariable("id") Long id, + @ApiParam(value = "Параметры команды в JSON формате.", required = true) + @RequestBody ChangeStatusExtractActionNew changeStatusExtractAction) throws ExecutionException, InterruptedException { changeStatusExtractAction.setId(id); return processRequest(Consts.REGISTRY_CHANGE_STATUS_EXTRACT_ACTION, changeStatusExtractAction); } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/IStateLoader.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/IStateLoader.java index 6b403ccc2..ac8442ffc 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/IStateLoader.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/IStateLoader.java @@ -17,9 +17,10 @@ public interface IStateLoader { Collection> getAllMetaTransformSpecificClass(String mapName, Class clazz); Collection> getAllMetaTransform(String mapName, Class clazz, Map> conditions); Collection> getAllMetaTransform(String mapName, Class clazz, ImdgPredicate conditions); + Collection> getAllMetaTransformWithPagination(String mapName, Class clazz, ImdgPredicate conditions, Integer pageSize, Integer pageIndex); Collection> getAllMetaTransform( - String searchMapName, - String mapName, - Class clazz, - ImdgPredicate conditions); + String searchMapName, + String mapName, + Class clazz, + ImdgPredicate conditions); } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/impl/StateLoaderImpl.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/impl/StateLoaderImpl.java index dcc6f5fee..eaa7dbf73 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/impl/StateLoaderImpl.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/impl/StateLoaderImpl.java @@ -1,5 +1,11 @@ package ru.spcex.clearing.backendapi.service.impl; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; @@ -10,9 +16,6 @@ import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - @Service public class StateLoaderImpl implements IStateLoader { private final Map> allImdgMaps; @@ -73,6 +76,13 @@ public class StateLoaderImpl implements IStateLoader { return responseFactory.responseFromObjectCollection(all); } + @Override + public Collection> getAllMetaTransformWithPagination(String mapName, Class clazz, ImdgPredicate conditions, Integer pageSize, Integer pageIndex) { + Imdg imdg = getImdg(mapName, clazz); + Collection all = imdg.getCollectionObjectsByPredicateWithPaging(conditions, pageSize, pageIndex); + return responseFactory.responseFromObjectCollection(all); + } + @SuppressWarnings("unchecked") private Imdg getImdg(String mapName, Class clazz) { return (Imdg) allImdgMaps.computeIfAbsent(mapName, (mapName1) -> imdgProvider.getImdg(mapName, clazz)); diff --git a/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/adapter/ImdgHazelcast.java b/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/adapter/ImdgHazelcast.java index ffa8bc146..99d766c1b 100644 --- a/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/adapter/ImdgHazelcast.java +++ b/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/adapter/ImdgHazelcast.java @@ -1,5 +1,6 @@ package ru.spcex.platform.imdg.iml.hazelcast.adapter; +import com.hazelcast.query.PagingPredicate; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -319,6 +320,23 @@ public class ImdgHazelcast implements Imdg { return searchResult; } + public Collection getCollectionObjectsByPredicateWithPaging(ImdgPredicate predicate, Integer pageSize, Integer pageIndex) { + Predicate hazelcastPredicate = ((ImdgPredicateHazelcast) predicate).getRawPredicate(); + PagingPredicate pagingPredicate = new PagingPredicate(hazelcastPredicate, pageSize); + pagingPredicate.setPage(pageIndex); + + Set ids = map.keySet(pagingPredicate); + Iterator idIterator = ids.iterator(); + Collection searchResult = new ArrayList<>(); + while (idIterator.hasNext()) { + T element = map.get(idIterator.next()); + if (element != null) { + searchResult.add(element); + } + } + return searchResult; + } + @Override public T getSingleObjectByPredicate(ImdgPredicate predicate) { Collection els = getCollectionObjectsByPredicate(predicate); diff --git a/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/Imdg.java b/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/Imdg.java index d728806c8..996fec6e5 100644 --- a/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/Imdg.java +++ b/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/Imdg.java @@ -116,6 +116,10 @@ public interface Imdg { throw new UnsupportedOperationException("not implemented getCollectionObjectsByPredicate"); } + default Collection getCollectionObjectsByPredicateWithPaging(ImdgPredicate predicate, Integer pageSize, Integer pageIndex) { + throw new UnsupportedOperationException("not implemented getCollectionObjectsByPredicateWithPaging"); + } + // Predicate API default T getSingleObjectByPredicate(ImdgPredicate predicate) { throw new UnsupportedOperationException("not implemented getSingleObjectByPredicate");