Compare commits

..

11 commits

140 changed files with 1050 additions and 4611 deletions

View file

@ -1,23 +0,0 @@
FROM eclipse-temurin:17-jre-alpine
MAINTAINER ru.nbch
VOLUME /opt/app/logs/app
VOLUME /opt/app/logs/json
VOLUME /opt/app/logs/access
VOLUME /opt/app/reports
WORKDIR /opt/app
COPY maven/elastic-apm-agent-1.45.0.jar /opt/app/elastic-apm-agent.jar
COPY maven/credit-tracker.jar /opt/app/credit-tracker.jar
COPY maven/start-credit-tracker.sh /opt/app/start-credit-tracker.sh
COPY maven/credit-tracker.properties /opt/app/credit-tracker.properties
COPY maven/monitoring-request.xsd /opt/app/monitoring-request.xsd
COPY maven/signal-package.xsd /opt/app/signal-package.xsd
COPY maven/ca_nbki.cer /usr/local/share/ca-certificates/corp.crt
RUN apk add --no-cache ca-certificates \
&& update-ca-certificates \
RUN apk add gcompat bash
RUN chmod +x /opt/app/start-credit-tracker.sh
ENTRYPOINT ["/opt/app/start-credit-tracker.sh"]

View file

@ -1,33 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFpTCCA42gAwIBAgIQXRfulgQYrrRFEpmSkmctvzANBgkqhkiG9w0BAQsFADBH
MRMwEQYKCZImiZPyLGQBGRYDbXNrMRQwEgYKCZImiZPyLGQBGRYEbmJraTEaMBgG
A1UEAxMRTkJLSS1Sb290LUNBLTIwMzIwHhcNMTQwNTE1MDYxODMzWhcNMzcwMjAx
MTE1OTEyWjBHMRMwEQYKCZImiZPyLGQBGRYDbXNrMRQwEgYKCZImiZPyLGQBGRYE
bmJraTEaMBgGA1UEAxMRTkJLSS1Sb290LUNBLTIwMzIwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQCjS1l6kx+tjX2PGmQcVw9wg0Q6SCeWbiz7rxAYZPqE
OGckXWWjtfUOc8BhD3+BnC4BQ414X1HP2OWQ97pa2LogTksbpNpJ0+p82IPAYxV+
zpI0FnW09FpzjtB6l/1kE9gKecjBoFG3xDhhFmpzCeK7tsKt94j84XPV/Zo82gYM
egmqhOfQZ+2HAChBj7gaBJALybFN34wkvN9bWdBPmK/j1jQikEAT8QE9qwcdmCKB
snHw+heYX4uJyZEkXEzW8GxQfTaAL+3d8HdRm1ZT/dN9KScF3Tp13LnQPCcixYoB
dF9Pd3P8JDAQX1KUVceLq6e75Q36EQaHHfEA8iQjaKlEzD049QbfAfCzKkSTnxHk
rOGwhm/h3ipwdAL4eqWkXfRriEvQU2fXGYXS0bhDT0/vBVAhHUMZ15/Oww0QSlc9
clpau6rYG4m/Fmm8LPyEHROenbNwu35TqLl+CUFES25aE2oZcH6+SyE5dDgpX9e1
Plt3fT6DuEDuT+rWvm0N8NVPNlQP/1lcbvP1oQrby07LToPatdKF9V5g8MX/19bP
BFsQsUHLlfffWMqqX8W/OPt5da3XL6U7Z8aBdhS7VAqqrvNhAbJBxgyJAzSfSwtZ
K5dZTKrJMZqmosUSIrLVr+9oXlbqJjKGNWQjwCfRQmPPkCpmpy1SRg8NPDoa3OVU
3wIDAQABo4GMMIGJMBMGCSsGAQQBgjcUAgQGHgQAQwBBMAsGA1UdDwQEAwIBhjAP
BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSkqLxdQSQ2+UIWrqSnms7lhp5zLjAQ
BgkrBgEEAYI3FQEEAwIBATAjBgkrBgEEAYI3FQIEFgQUvM7jX4RA4XBrZqhNhpl6
EDcEMZEwDQYJKoZIhvcNAQELBQADggIBAINqzWxlGXFgMwSlWmH4ocDa0A3ip51C
nEaWB58aomzOZYHnNLXj4KiwY59TMDkiRiql4wWCw2AJBVv2//7JwOqrk8rixq02
95NVX9TNefMKY3oo/g9bSqEsxoHgOoXP0QiY4GrYwAL6Bl0d/V9KUw5+BzBx/DKo
ncWD6KHnwFPBnHhIWiFlRAy2dX55rg6YSpB5/IlTQxGTjeg0OjX5w0ZE3L/0GZBl
O5W2E0RvUSErbjzoisxrhG48Mo5TtoGTmazKHRDqRCuZVnV0uEL9XaUOOV3G+LlP
/ujADUkF4iiIgoynB0W30fpwEqQFBSUxe+KzMw10ojaYaSz2g/HEg9ZKxy1a/bDL
6Va+vUMrypg26+MFrEdUwpPuORV1chtah/t+OxSk1dO82cuhjmRHX79mRwqjmXUs
5I/fNey8JWLCAV+Acf24CepdeYzeBGdh94t9FqTWw7aJaN5vL9ghwyG7JT8ozAfp
wYa1vq3nq+7SiELenQYYEUl792V8OsRV6N9nJkoLC12R9HGHjxMja5O2+Sw9LU4p
TjQcJt+qhT/c5+i6tQMjJUCTpXtOkaEezwrPpbUcoluGsz9vxs84eDtHiwumUCGj
XgaMSjcnY35dgne/x3kXcLYazdUYDoyYOEkgKG7ncSFg0lnIgwtYpqW6tzL3t9KN
Tsm6UcBOJAnv
-----END CERTIFICATE-----

View file

@ -1,72 +1,38 @@
server.port=${SERVER_PORT:8099}
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.directory=/opt/app/logs/access
server.tomcat.accesslog.prefix=access_log
server.tomcat.accesslog.suffix=.log
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b
server.port=8099
# datasources
# indic
ct.indic-data-source-settings.driver=com.ibm.db2.jcc.DB2Driver
ct.indic-data-source-settings.url=${DB_URL_INDIC:jdbc:db2://10.230.227.101:2668/cprosd22:currentSchema=INDIC;}
ct.indic-data-source-settings.username=${USERNAME_INDIC:tester}
ct.indic-data-source-settings.password=${PASSWORD_INDIC:tester}
ct.indic-data-source-settings.maximum-pool-size=${MAXIMUM_POOL_SIZE_INDIC:10}
ct.indic-data-source-settings.minimum-idle=${MINIMUM_IDLE_INDIC:10}
ct.indic-data-source-settings.connection-timeout=${CONNECTION_TIMEOUT_INDIC:10000}
ct.indic-data-source-settings.validation-timeout=${VALIDATION_TIMEOUT_INDIC:5000}
ct.indic-data-source-settings.idle-timeout=${IDLE_TIMEOUT_INDIC:600000}
ct.indic-data-source-settings.max-lifetime=${MAX_LIFETIME_INDIC:1800000}
ct.indic-data-source-settings.keepalive-time=${KEEPALIVE_TIME_INDIC:0}
ct.indic-data-source-settings.leak-detection-threshold=${LEAK_DETECTION_THRESHOLD_INDIC:0}
ct.indic-data-source-settings.url=jdbc:db2://10.230.227.101:2668/cprosd22:currentSchema=INDIC;
ct.indic-data-source-settings.username=tester
ct.indic-data-source-settings.password=tester
# signal
ct.signal-data-source-settings.driver=org.postgresql.Driver
ct.signal-data-source-settings.url=${DB_URL_SIGNAL:jdbc:postgresql://10.200.200.133:5432/credit_tracker}
ct.signal-data-source-settings.username=${USERNAME_SIGNAL:credit_tracker_user}
ct.signal-data-source-settings.password=${PASSWORD_SIGNAL:-}
ct.signal-data-source-settings.maximum-pool-size=${MAXIMUM_POOL_SIZE_SIGNAL:10}
ct.signal-data-source-settings.minimum-idle=${MINIMUM_IDLE_SIGNAL:10}
ct.signal-data-source-settings.connection-timeout=${CONNECTION_TIMEOUT_SIGNAL:10000}
ct.signal-data-source-settings.validation-timeout=${VALIDATION_TIMEOUT_SIGNAL:5000}
ct.signal-data-source-settings.idle-timeout=${IDLE_TIMEOUT_SIGNAL:600000}
ct.signal-data-source-settings.max-lifetime=${MAX_LIFETIME_SIGNAL:1800000}
ct.signal-data-source-settings.keepalive-time=${KEEPALIVE_TIME_SIGNAL:0}
ct.signal-data-source-settings.leak-detection-threshold=${LEAK_DETECTION_THRESHOLD_SIGNAL:0}
ct.signal-data-source-settings.url=jdbc:postgresql://10.200.200.133:5432/credit_tracker
ct.signal-data-source-settings.username=credit_tracker_user
ct.signal-data-source-settings.password=
# scoring
ct.scoring-data-source-settings.driver=com.ibm.db2.jcc.DB2Driver
ct.scoring-data-source-settings.url=${DB_URL_SCORING:jdbc:db2://10.230.227.101:2668/cprosd22:currentSchema=TEST_2_INDIC;}
ct.scoring-data-source-settings.username=${USERNAME_SCORING:tester}
ct.scoring-data-source-settings.password=${PASSWORD_SCORING:tester}
ct.scoring-data-source-settings.maximum-pool-size=${MAXIMUM_POOL_SIZE_SCORING:10}
ct.scoring-data-source-settings.minimum-idle=${MINIMUM_IDLE_SCORING:10}
ct.scoring-data-source-settings.connection-timeout=${CONNECTION_TIMEOUT_SCORING:10000}
ct.scoring-data-source-settings.validation-timeout=${VALIDATION_TIMEOUT_SCORING:5000}
ct.scoring-data-source-settings.idle-timeout=${IDLE_TIMEOUT_SCORING:600000}
ct.scoring-data-source-settings.max-lifetime=${MAX_LIFETIME_SCORING:1800000}
ct.scoring-data-source-settings.keepalive-time=${KEEPALIVE_TIME_SCORING:0}
ct.scoring-data-source-settings.leak-detection-threshold=${LEAK_DETECTION_THRESHOLD_SCORING:0}
ct.scoring-data-source-settings.url=jdbc:db2://10.230.227.101:2668/cprosd22:currentSchema=TEST_2_INDIC;
ct.scoring-data-source-settings.username=tester
ct.scoring-data-source-settings.password=tester
ct.max_xml_file_size=${ACCEPTED_XML_SIZE:1024}
spring.servlet.multipart.max-file-size=${ACCEPTED_ARCHIVE_SIZE:2048MB}
spring.servlet.multipart.max-request-size=${ACCEPTED_ARCHIVE_SIZE:2048MB}
spring.servlet.multipart.max-file-size=2048MB
spring.servlet.multipart.max-request-size=2048MB
# xsd paths
ct.xsd-validation.monitoring-request-path=monitoring-request.xsd
ct.xsd-validation.signal-package-path=signal-package.xsd
ct.signals-root-uri=${SIGNALS_ROOT_URI:http://10.230.227.102:11094/signalRUalfa/}
ct.signals-token=${SIGNALS_TOKEN:gttcHxwcGojoAvZK}
ct.signals-user=${SIGNALS_USER:0001ZZ000001}
ct.load-dir=/opt/app/reports
#ct.load-dir=D:\\folder_name\\signals
ct.signals-root-uri=http://10.230.227.102:11094/signalRUalfa/
ct.signals-token=gttcHxwcGojoAvZK
ct.signals-user=0001ZZ000001
ct.load-dir=D:\\folder_name\\signals
# min
ct.monitoring-interval=${MONITORING_INTERVAL:15}
ct.monitoring-interval=15
# days
ct.update-flags-cron-expression=${UPDATE_FLAGS_CRON_EXPRESSION:0 0 22 * * *}
ct.days-to-update-flags=${DAYS_TO_UPDATE_FLAGS:30}
ct.encoding=windows-1251
ct.update-flags-interval=1
ct.days-to-update-flags=30

View file

@ -1,77 +0,0 @@
#commons
APP_VERSION=1.24
REGISTRY_URL=rh8-vm3.nbki.msk:5000
JMX_PORT=
JMX_HOSTNAME=
#volumes
REPORT_DIR=D:\folder_name\signals
LOGS_DIR=D:\folder_name\signals\logs\app
JSON_LOGS_DIR=D:\folder_name\signals\logs\json
ACCESS_LOGS_DIR=D:\folder_name\signals\logs\access
#APM settings
APM_SERVICE_NAME=credit-tracker
APM_SERVER_URLS=test
APM_ENVIRONMENT=test
APM_SERVICE_NODE_NAME=test
HOST_PORT=8081
SERVER_PORT=8099
# datasources
# indic
DB_URL_INDIC=jdbc:db2://10.230.227.101:2668/cprosd22:currentSchema=INDIC;
USERNAME_INDIC=tester
PASSWORD_INDIC=tester
MAXIMUM_POOL_SIZE_INDIC=10
MINIMUM_IDLE_INDIC=10
CONNECTION_TIMEOUT_INDIC=10000
VALIDATION_TIMEOUT_INDIC=5000
IDLE_TIMEOUT_INDIC=600000
MAX_LIFETIME_INDIC=1800000
KEEPALIVE_TIME_INDIC=0
LEAK_DETECTION_THRESHOLD_INDIC=0
# signal
DB_URL_SIGNAL=jdbc:postgresql://10.200.200.133:5432/credit_tracker
USERNAME_SIGNAL=credit_tracker_user
PASSWORD_SIGNAL=
MAXIMUM_POOL_SIZE_SIGNAL=10
MINIMUM_IDLE_SIGNAL=10
CONNECTION_TIMEOUT_SIGNAL=10000
VALIDATION_TIMEOUT_SIGNAL=5000
IDLE_TIMEOUT_SIGNAL=600000
MAX_LIFETIME_SIGNAL=1800000
KEEPALIVE_TIME_SIGNAL=0
LEAK_DETECTION_THRESHOLD_SIGNAL=0
# scoring
DB_URL_SCORING=jdbc:db2://10.230.227.101:2668/cprosd22:currentSchema=TEST_2_INDIC;
USERNAME_SCORING=tester
PASSWORD_SCORING=tester
MAXIMUM_POOL_SIZE_SCORING=10
MINIMUM_IDLE_SCORING=10
CONNECTION_TIMEOUT_SCORING=10000
VALIDATION_TIMEOUT_SCORING=5000
IDLE_TIMEOUT_SCORING=600000
MAX_LIFETIME_SCORING=1800000
KEEPALIVE_TIME_SCORING=0
LEAK_DETECTION_THRESHOLD_SCORING=0
# размер в mb
ACCEPTED_XML_SIZE=1024
ACCEPTED_ARCHIVE_SIZE=2048MB
SIGNALS_ROOT_URI=http://10.230.227.102:11094/signalRUalfa/
SIGNALS_TOKEN=gttcHxwcGojoAvZK
SIGNALS_USER=0001ZZ000001
# min
MONITORING_INTERVAL=15
# days
UPDATE_FLAGS_CRON_EXPRESSION=0 22 * * *
DAYS_TO_UPDATE_FLAGS=30

View file

@ -1,63 +0,0 @@
services:
credit-tracker:
image: ${REGISTRY_URL}/credit-tracker:${APP_VERSION}
container_name: credit-tracker
restart: always
volumes:
- ${LOGS_DIR}:/opt/app/logs/app
- ${JSON_LOGS_DIR}:/opt/app/logs/json
- ${REPORT_DIR}:/opt/app/reports
- ${ACCESS_LOGS_DIR}:/opt/app/logs/access
ports:
- "${HOST_PORT}:${SERVER_PORT}"
environment:
- TZ=Europe/Moscow
- APM_SERVICE_NAME=${APM_SERVICE_NAME}
- APM_SERVER_URLS=${APM_SERVER_URLS}
- APM_ENVIRONMENT=${APM_ENVIRONMENT}
- APM_SERVICE_NODE_NAME=${APM_SERVICE_NODE_NAME}
- APM_SERVICE_VERSION=${APP_VERSION}
- JMX_PORT=${JMX_PORT}
- JMX_HOSTNAME=${JMX_HOSTNAME}
- SERVER_PORT=${SERVER_PORT}
- DB_URL_INDIC=${DB_URL_INDIC}
- USERNAME_INDIC=${USERNAME_INDIC}
- PASSWORD_INDIC=${PASSWORD_INDIC}
- MAXIMUM_POOL_SIZE_INDIC=${MAXIMUM_POOL_SIZE_INDIC}
- MINIMUM_IDLE_INDIC=${MINIMUM_IDLE_INDIC}
- CONNECTION_TIMEOUT_INDIC=${CONNECTION_TIMEOUT_INDIC}
- VALIDATION_TIMEOUT_INDIC=${VALIDATION_TIMEOUT_INDIC}
- IDLE_TIMEOUT_INDIC=${IDLE_TIMEOUT_INDIC}
- MAX_LIFETIME_INDIC=${MAX_LIFETIME_INDIC}
- KEEPALIVE_TIME_INDIC=${KEEPALIVE_TIME_INDIC}
- LEAK_DETECTION_THRESHOLD_INDIC=${LEAK_DETECTION_THRESHOLD_INDIC}
- DB_URL_SIGNAL=${DB_URL_SIGNAL}
- USERNAME_SIGNAL=${USERNAME_SIGNAL}
- PASSWORD_SIGNAL=${PASSWORD_SIGNAL}
- MAXIMUM_POOL_SIZE_SIGNAL=${MAXIMUM_POOL_SIZE_SIGNAL}
- MINIMUM_IDLE_SIGNAL=${MINIMUM_IDLE_SIGNAL}
- CONNECTION_TIMEOUT_SIGNAL=${CONNECTION_TIMEOUT_SIGNAL}
- VALIDATION_TIMEOUT_SIGNAL=${VALIDATION_TIMEOUT_SIGNAL}
- IDLE_TIMEOUT_SIGNAL=${IDLE_TIMEOUT_SIGNAL}
- MAX_LIFETIME_SIGNAL=${MAX_LIFETIME_SIGNAL}
- KEEPALIVE_TIME_SIGNAL=${KEEPALIVE_TIME_SIGNAL}
- LEAK_DETECTION_THRESHOLD_SIGNAL=${LEAK_DETECTION_THRESHOLD_SIGNAL}
- DB_URL_SCORING=${DB_URL_SCORING}
- USERNAME_SCORING=${USERNAME_SCORING}
- PASSWORD_SCORING=${PASSWORD_SCORING}
- MAXIMUM_POOL_SIZE_SCORING=${MAXIMUM_POOL_SIZE_SCORING}
- MINIMUM_IDLE_SCORING=${MINIMUM_IDLE_SCORING}
- CONNECTION_TIMEOUT_SCORING=${CONNECTION_TIMEOUT_SCORING}
- VALIDATION_TIMEOUT_SCORING=${VALIDATION_TIMEOUT_SCORING}
- IDLE_TIMEOUT_SCORING=${IDLE_TIMEOUT_SCORING}
- MAX_LIFETIME_SCORING=${MAX_LIFETIME_SCORING}
- KEEPALIVE_TIME_SCORING=${KEEPALIVE_TIME_SCORING}
- LEAK_DETECTION_THRESHOLD_SCORING=${LEAK_DETECTION_THRESHOLD_SCORING}
- ACCEPTED_XML_SIZE=${ACCEPTED_XML_SIZE}
- ACCEPTED_ARCHIVE_SIZE=${ACCEPTED_ARCHIVE_SIZE}
- SIGNALS_ROOT_URI=${SIGNALS_ROOT_URI}
- SIGNALS_TOKEN=${SIGNALS_TOKEN}
- SIGNALS_USER=${SIGNALS_USER}
- MONITORING_INTERVAL=${MONITORING_INTERVAL}
- UPDATE_FLAGS_INTERVAL=${UPDATE_FLAGS_INTERVAL}
- DAYS_TO_UPDATE_FLAGS=${DAYS_TO_UPDATE_FLAGS}

431
pom.xml
View file

@ -1,275 +1,170 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ru.nbch</groupId>
<artifactId>credit-tracker</artifactId>
<version>1.24</version>
<name>credit_tracker</name>
<description>Credit Tracker Application</description>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ru.nbch</groupId>
<artifactId>credit_tracker</artifactId>
<version>1.0</version>
<name>credit_tracker</name>
<description>Credit Tracker Application</description>
<properties>
<java.version>17</java.version>
<git.info.prefix>git_info</git.info.prefix>
<git.info.filename>git.properties</git.info.filename>
<registry.url>10.230.238.56:5000</registry.url>
<!-- <registry.url>rh8-vm3.nbki.msk:5000</registry.url>-->
</properties>
<properties>
<java.version>17</java.version>
<git.info.prefix>git_info</git.info.prefix>
<git.info.filename>git.properties</git.info.filename>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.ibm.db2</groupId>
<artifactId>jcc</artifactId>
<version>12.1.0.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.12</version>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.5.12</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.17.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.18.0</version>
</dependency>
<!-- JAXB API -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.2</version>
</dependency>
<!--JAXB runtime implementation: eclipse moxy-->
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>4.0.2</version>
</dependency>
<!-- Activation dependency needed for JAXB -->
<dependency>
<groupId>com.sun.activation</groupId>
<artifactId>jakarta.activation</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>co.elastic.apm</groupId>
<artifactId>apm-agent-api</artifactId>
<version>1.43.0</version>
</dependency>
<dependency>
<groupId>com.internetitem</groupId>
<artifactId>logback-elasticsearch-appender</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>7.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.ibm.db2</groupId>
<artifactId>jcc</artifactId>
<version>12.1.0.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.12</version>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.5.12</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.17.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.18.0</version>
</dependency>
<!-- JAXB API -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.2</version>
</dependency>
<!--JAXB runtime implementation: eclipse moxy-->
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>4.0.2</version>
</dependency>
<!-- Activation dependency needed for JAXB -->
<dependency>
<groupId>com.sun.activation</groupId>
<artifactId>jakarta.activation</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.4</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>docker-push-dev</id>
<build>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.45.0</version>
<executions>
<execution>
<id>Build and deploy docker container</id>
<phase>install</phase>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<images>
<image>
<name>${project.artifactId}:${project.version}</name>
<registry>${registry.url}</registry>
<build>
<dockerFile>${project.basedir}/Dockerfile</dockerFile>
<assembly>
<inline>
<files>
<file>
<source>
${project.build.directory}/${project.build.finalName}.jar
</source>
<outputDirectory>.</outputDirectory>
</file>
<file>
<source>
${project.basedir}/apm-agent/elastic-apm-agent-1.45.0.jar
</source>
<outputDirectory>.</outputDirectory>
</file>
<file>
<source>${project.basedir}/start-credit-tracker.sh</source>
<outputDirectory>.</outputDirectory>
</file>
<file>
<source>${project.basedir}/credit-tracker.properties</source>
<outputDirectory>.</outputDirectory>
</file>
<file>
<source>${project.basedir}/monitoring-request.xsd</source>
<outputDirectory>.</outputDirectory>
</file>
<file>
<source>${project.basedir}/signal-package.xsd</source>
<outputDirectory>.</outputDirectory>
</file>
<file>
<source>
${project.basedir}/ca_nbki.cer
</source>
<outputDirectory>.</outputDirectory>
</file>
</files>
</inline>
</assembly>
<tags>
<tag>${project.version}</tag>
</tags>
</build>
</image>
</images>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<finalName>credit-tracker</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>4.9.10</version>
<executions>
<execution>
<id>get-the-git-infos</id>
<goals>
<goal>revision</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
<configuration>
<failOnNoGitDirectory>false</failOnNoGitDirectory>
<dotGitDirectory>${project.basedir}/${git.info.relative.dir}</dotGitDirectory>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>
${project.build.outputDirectory}/${git.info.filename}
</generateGitPropertiesFilename>
<prefix>${git.info.prefix}</prefix>
<includeOnlyProperties>
<includeOnlyProperty>${git.info.prefix}.commit.id</includeOnlyProperty>
<includeOnlyProperty>${git.info.prefix}.branch</includeOnlyProperty>
<includeOnlyProperty>${git.info.prefix}.build.version</includeOnlyProperty>
<includeOnlyProperty>${git.info.prefix}.build.time</includeOnlyProperty>
<includeOnlyProperty>${git.info.prefix}.closest.tag.name</includeOnlyProperty>
</includeOnlyProperties>
</configuration>
</plugin>
</plugins>
</build>
<build>
<finalName>credit-tracker</finalName>
<plugins>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>4.9.10</version>
<executions>
<execution>
<id>get-the-git-infos</id>
<goals>
<goal>revision</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
<configuration>
<failOnNoGitDirectory>false</failOnNoGitDirectory>
<dotGitDirectory>${project.basedir}/${git.info.relative.dir}</dotGitDirectory>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>
${project.build.outputDirectory}/${git.info.filename}
</generateGitPropertiesFilename>
<prefix>${git.info.prefix}</prefix>
<includeOnlyProperties>
<includeOnlyProperty>${git.info.prefix}.commit.id</includeOnlyProperty>
<includeOnlyProperty>${git.info.prefix}.branch</includeOnlyProperty>
<includeOnlyProperty>${git.info.prefix}.build.version</includeOnlyProperty>
<includeOnlyProperty>${git.info.prefix}.build.time</includeOnlyProperty>
<includeOnlyProperty>${git.info.prefix}.closest.tag.name</includeOnlyProperty>
</includeOnlyProperties>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -4,7 +4,6 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import ru.nbch.credit_tracker.service.MonitoringService;
import ru.nbch.credit_tracker.service.UpdateProcessingPackagesService;
import ru.nbch.credit_tracker.service.UpdatingFlagsService;
@SpringBootApplication
@ -12,12 +11,10 @@ public class CreditTrackerApplication {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(CreditTrackerApplication.class, args);
UpdateProcessingPackagesService updateProcessingPackagesService = ctx.getBean(UpdateProcessingPackagesService.class);
MonitoringService monitoringService = ctx.getBean(MonitoringService.class);
UpdatingFlagsService updatingFlagsService = ctx.getBean(UpdatingFlagsService.class);
monitoringService.run();
updatingFlagsService.run();
updateProcessingPackagesService.run();
}
}

View file

@ -1,17 +1,16 @@
package ru.nbch.credit_tracker.builder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import ru.nbch.credit_tracker.entities.external_request.signals.Person;
import ru.nbch.credit_tracker.entities.signal_package.Person;
import ru.nbch.credit_tracker.service.indic.PersonService;
import ru.nbch.credit_tracker.utils.CTUtil;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
@Slf4j
public class PersonFactoryBuilder {
private final static DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("dd.MM.yyyy");
private final static DateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy");
private final static String DEFAULT_DATE = "01.01.2000";
private final static String IP = "0";
@ -25,12 +24,10 @@ public class PersonFactoryBuilder {
private final static String CONSENT_HASH = "hash";
private final static String CONSENT_DIV_CODE = "000-000";
private final static String INQ_PURPOSE = "16";
private final static String ODT = "Иной документ";
private final static String CONSENT_ISSUE_AUTHORITY = "Кем выдан";
private PersonService.PersonData personData;
private Long uid;
private String uid;
public static PersonFactoryBuilder builder() {
return new PersonFactoryBuilder();
@ -41,7 +38,7 @@ public class PersonFactoryBuilder {
return this;
}
public PersonFactoryBuilder uid(Long uid) {
public PersonFactoryBuilder uid(String uid) {
this.uid = uid;
return this;
}
@ -56,24 +53,20 @@ public class PersonFactoryBuilder {
person.setS(nameData.getLastName());
person.setN(nameData.getFirstName());
person.setM(StringUtils.isNotBlank(nameData.getMiddleName()) ? nameData.getMiddleName() : null);
person.setD(DATE_FORMAT.format(nameData.getBirthDate()));
person.setD(DATE_FORMAT.format(CTUtil.localDatetoDate(nameData.getBirthDate())));
person.setPn(getPn(passportData.getSerNum(), passportData.getIdNum()));
person.setPd(DATE_FORMAT.format(LocalDate.now())); // Do not use passport iss_date. Signal service could reject the package
person.setDt(getDt(passportData.getIdType(), passportData.getIdType2()));
if (person.getDt() != null && person.getDt().equals("999")) {
person.setOdt(ODT);
person.setConsentOdt(ODT);
}
person.setPd(passportData.getIssDate() != null ? DATE_FORMAT.format(CTUtil.localDatetoDate(passportData.getIssDate())) : DEFAULT_DATE);
person.setDt(StringUtils.isNotBlank(passportData.getIdType2()) ? passportData.getIdType2() : passportData.getIdType());
person.setIp(IP);
person.setUid(uid);
person.setOksm(OKSM);
person.setConsentDate(DATE_FORMAT.format(LocalDate.now()));
person.setConsentDate(DATE_FORMAT.format(CTUtil.localDatetoDate(LocalDate.now())));
person.setConsentPurpose(CONSENT_PURPOSE);
person.setReportUser(REPORT_USER);
person.setLiability(LIABILITY);
person.setConsentPeriod(CONSENT_PERIOD);
person.setAgrDate(DATE_FORMAT.format(LocalDate.now()));
person.setAgrDate(DATE_FORMAT.format(CTUtil.localDatetoDate(LocalDate.now())));
person.setReportUserRegNum(REPORT_USER_REG_NUM);
person.setReportUserTaxID(REPORT_USER_TAX_ID);
person.setConsentHash(CONSENT_HASH);
@ -86,7 +79,6 @@ public class PersonFactoryBuilder {
person.setConsentPd(person.getPd());
person.setConsentDivCode(CONSENT_DIV_CODE);
person.setConsentDt(person.getDt());
person.setConsentIssueAuthority(CONSENT_ISSUE_AUTHORITY);
person.setInqPurpose(INQ_PURPOSE);
return person;
}
@ -96,29 +88,4 @@ public class PersonFactoryBuilder {
String normIdNum = CTUtil.normalize(idNum);
return StringUtils.isNotBlank(normSerNum) ? normSerNum + normIdNum : normIdNum;
}
private String getDt(String idType, String idType2) {
if (StringUtils.isNotBlank(idType2)) {
return idType2;
} else {
return switch (idType) {
case "21" -> "21";
case "22" -> "22.1";
case "09" -> "22.2";
case "26" -> "23";
case "04" -> "24";
case "07" -> "25";
case "14", "03" -> "27";
case "10" -> "31";
case "15" -> "32";
case "13" -> "37";
case "06", "27" -> "28";
case "01", "02" -> "999";
default -> {
log.warn("ID_TYPE2 is blank and no matching found for ID_TYPE {}", idType);
yield "";
}
};
}
}
}

View file

@ -1,28 +0,0 @@
package ru.nbch.credit_tracker.component;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Slf4j
@Component
public class MapperTimingAspect {
@Around("within(@org.apache.ibatis.annotations.Mapper *)")
public Object timeMapper(ProceedingJoinPoint pjp) throws Throwable {
long start = System.nanoTime();
try {
return pjp.proceed();
} finally {
long tookMs = (System.nanoTime() - start) / 1_000_000;
String method = pjp.getSignature().toShortString();
if (tookMs > 1000) {
log.warn("Slow mapper call {} took {} ms", method, tookMs);
} else {
log.debug("Mapper call {} took {} ms", method, tookMs);
}
}
}
}

View file

@ -1,19 +0,0 @@
package ru.nbch.credit_tracker.config.datasource;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.jdbc.DataSourceBuilder;
import ru.nbch.credit_tracker.config.settings.DataSourceSettings;
public class DatabaseConfig {
protected HikariDataSource createDataSource(DataSourceSettings settings) {
return DataSourceBuilder.create()
.driverClassName(settings.driver())
.url(settings.url())
.username(settings.username())
.password(settings.password())
.type(HikariDataSource.class)
.build();
}
}

View file

@ -7,11 +7,11 @@ import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.config.settings.DataSourceSettings;
import javax.sql.DataSource;
import java.sql.Connection;
@ -23,32 +23,26 @@ import java.sql.SQLException;
basePackages = "ru.nbch.credit_tracker.mapper.indic",
sqlSessionFactoryRef = "sqlSessionIndic"
)
public class IndicDataSourceConfig extends DatabaseConfig {
public class IndicDataSourceConfig {
@Value("classpath:mybatis/mapper/indic/*.xml")
private Resource[] resources;
@Bean(name = "indicDataSource")
public DataSource dataSource(CreditTrackerSettings config) throws SQLException {
DataSourceSettings indicSetings = config.getIndicDataSourceSettings();
HikariDataSource dataSource = createDataSource(indicSetings);
dataSource.setMaximumPoolSize(indicSetings.maximumPoolSize());
dataSource.setMinimumIdle(indicSetings.minimumIdle());
dataSource.setConnectionTimeout(indicSetings.connectionTimeout());
dataSource.setValidationTimeout(indicSetings.validationTimeout());
dataSource.setIdleTimeout(indicSetings.idleTimeout());
dataSource.setMaxLifetime(indicSetings.maxLifetime());
dataSource.setKeepaliveTime(indicSetings.keepaliveTime());
dataSource.setLeakDetectionThreshold(indicSetings.leakDetectionThreshold());
DataSourceBuilder<HikariDataSource> dataSourceBuilder = (DataSourceBuilder<HikariDataSource>) DataSourceBuilder.create();
dataSourceBuilder.driverClassName(config.getIndicDataSourceSettings().driver());
dataSourceBuilder.url(config.getIndicDataSourceSettings().url());
dataSourceBuilder.username(config.getIndicDataSourceSettings().username());
dataSourceBuilder.password(config.getIndicDataSourceSettings().password());
HikariDataSource dataSource = dataSourceBuilder.build();
try (Connection connection = dataSource.getConnection()) {
connection.isValid(3);
} catch (SQLException e) {
log.error("Unable to connect to Indic url={}", indicSetings.url(), e);
log.error("Unable to connect to Indic url={}", config.getIndicDataSourceSettings().url(), e);
throw e;
}
log.info("Connected to Indic: url={}", indicSetings.url());
log.info("Connected to Indic: url={}", config.getIndicDataSourceSettings().url());
return dataSource;
}

View file

@ -7,48 +7,41 @@ import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.config.settings.DataSourceSettings;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@Slf4j
@Configuration
@MapperScan(
basePackages = "ru.nbch.credit_tracker.mapper.scoring",
sqlSessionFactoryRef = "sqlSessionScoring"
)
public class ScoringDataSourceConfig extends DatabaseConfig {
public class ScoringDataSourceConfig {
@Value("classpath:mybatis/mapper/scoring/*.xml")
private Resource[] resources;
@Bean(name = "scoringDataSource")
public DataSource dataSource(CreditTrackerSettings config) throws SQLException {
DataSourceSettings scoringSetings = config.getScoringDataSourceSettings();
HikariDataSource dataSource = createDataSource(scoringSetings);
dataSource.setMaximumPoolSize(scoringSetings.maximumPoolSize());
dataSource.setMinimumIdle(scoringSetings.minimumIdle());
dataSource.setConnectionTimeout(scoringSetings.connectionTimeout());
dataSource.setValidationTimeout(scoringSetings.validationTimeout());
dataSource.setIdleTimeout(scoringSetings.idleTimeout());
dataSource.setMaxLifetime(scoringSetings.maxLifetime());
dataSource.setKeepaliveTime(scoringSetings.keepaliveTime());
dataSource.setLeakDetectionThreshold(scoringSetings.leakDetectionThreshold());
DataSourceBuilder<HikariDataSource> dataSourceBuilder = (DataSourceBuilder<HikariDataSource>) DataSourceBuilder.create();
dataSourceBuilder.driverClassName(config.getScoringDataSourceSettings().driver());
dataSourceBuilder.url(config.getScoringDataSourceSettings().url());
dataSourceBuilder.username(config.getScoringDataSourceSettings().username());
dataSourceBuilder.password(config.getScoringDataSourceSettings().password());
HikariDataSource dataSource = dataSourceBuilder.build();
try (Connection connection = dataSource.getConnection()) {
connection.isValid(3);
} catch (SQLException e) {
log.error("Unable to connect to Scoring url={}", scoringSetings.url(), e);
log.error("Unable to connect to Scoring url={}", config.getScoringDataSourceSettings().url(), e);
throw e;
}
log.info("Connected to Scoring: url={}", scoringSetings.url());
log.info("Connected to Scoring: url={}", config.getScoringDataSourceSettings().url());
return dataSource;
}

View file

@ -7,11 +7,11 @@ import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.config.settings.DataSourceSettings;
import javax.sql.DataSource;
import java.sql.Connection;
@ -23,31 +23,25 @@ import java.sql.SQLException;
basePackages = "ru.nbch.credit_tracker.mapper.signal",
sqlSessionFactoryRef = "sqlSessionSignal"
)
public class SignalDataSourceConfig extends DatabaseConfig {
public class SignalDataSourceConfig {
@Value("classpath:mybatis/mapper/signal/*.xml")
private Resource[] resources;
@Bean(name = "signalDataSource")
public DataSource dataSource(CreditTrackerSettings config) throws SQLException {
DataSourceSettings signalSetings = config.getSignalDataSourceSettings();
HikariDataSource dataSource = createDataSource(signalSetings);
dataSource.setMaximumPoolSize(signalSetings.maximumPoolSize());
dataSource.setMinimumIdle(signalSetings.minimumIdle());
dataSource.setConnectionTimeout(signalSetings.connectionTimeout());
dataSource.setValidationTimeout(signalSetings.validationTimeout());
dataSource.setIdleTimeout(signalSetings.idleTimeout());
dataSource.setMaxLifetime(signalSetings.maxLifetime());
dataSource.setKeepaliveTime(signalSetings.keepaliveTime());
dataSource.setLeakDetectionThreshold(signalSetings.leakDetectionThreshold());
DataSourceBuilder<HikariDataSource> dataSourceBuilder = (DataSourceBuilder<HikariDataSource>) DataSourceBuilder.create();
dataSourceBuilder.driverClassName(config.getSignalDataSourceSettings().driver());
dataSourceBuilder.url(config.getSignalDataSourceSettings().url());
dataSourceBuilder.username(config.getSignalDataSourceSettings().username());
// dataSourceBuilder.password(config.getSignalDataSourceSettings().password()); TODO uncomment whe password will be set
HikariDataSource dataSource = dataSourceBuilder.build();
try (Connection connection = dataSource.getConnection()) {
connection.isValid(3);
} catch (SQLException e) {
log.error("Unable to connect to Signal url={}", signalSetings.url(), e);
log.error("Unable to connect to Signal url={}", config.getSignalDataSourceSettings().url(), e);
throw e;
}
log.info("Connected to Signal: url={}", signalSetings.url());
log.info("Connected to Signal: url={}", config.getSignalDataSourceSettings().url());
return dataSource;
}

View file

@ -1,19 +0,0 @@
package ru.nbch.credit_tracker.config.mdc;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ConditionalOnClass(Aspect.class)
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AopMdcConfig {
@Bean
public MdcAspect mdcAspect() {
return new MdcAspect();
}
}

View file

@ -1,49 +0,0 @@
package ru.nbch.credit_tracker.config.mdc;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.MDC;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import ru.nbch.credit_tracker.entities.user_request.monitoring_request.MonitoringRequest;
@Slf4j
@Aspect
public class MdcAspect {
// For methods that set an MDC value (from a method argument) and then clear it at the end
@Around("@annotation(setAndClearMdc)")
public Object setAndClearMdcAdvice(ProceedingJoinPoint pjp, SetAndClearMdc setAndClearMdc) throws Throwable {
Object[] args = pjp.getArgs();
int index = setAndClearMdc.argIndex();
Object obj = (args != null && args.length > index) ? args[index] : null;
if (obj instanceof MonitoringRequest request) {
if (request.getPackageName() != null) {
putMdcValue(setAndClearMdc.key(), request.getPackageName());
}
} else if (obj instanceof UserPackage userPackage) {
if (userPackage.getPackageName() != null) {
putMdcValue(setAndClearMdc.key(), userPackage.getPackageName());
}
} else if (obj instanceof String packageName) {
putMdcValue(setAndClearMdc.key(), packageName);
} else {
log.debug("no packageName found for for {}", pjp.toShortString());
}
try {
return pjp.proceed();
} finally {
MDC.remove(setAndClearMdc.key());
}
}
private void putMdcValue(String key, String value) {
try {
MDC.put(key, "[" + value + "] ");
} catch (Throwable e) {
log.error("{}", ExceptionUtils.getStackTrace(e));
}
}
}

View file

@ -1,15 +0,0 @@
package ru.nbch.credit_tracker.config.mdc;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// Annotation to set an MDC key based on a method argument and clear it after method execution
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SetAndClearMdc {
String key() default "ru.nbch.credit_tracker.log.mdc.key";
// The index of the method argument to use for the MDC value (defaults to the first argument)
int argIndex() default 0;
}

View file

@ -1,70 +1,35 @@
package ru.nbch.credit_tracker.config.rest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.user_response.errors.*;
import ru.nbch.credit_tracker.enums.SignalError;
import ru.nbch.credit_tracker.entities.response.errors.*;
import ru.nbch.credit_tracker.exceptions.SignalClientException;
import ru.nbch.credit_tracker.exceptions.SignalException;
import ru.nbch.credit_tracker.exceptions.SignalServerException;
import ru.nbch.credit_tracker.utils.error.SimpleMessageResolver;
import java.nio.charset.Charset;
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
private final SimpleMessageResolver messageResolver = new SimpleMessageResolver();
private final String encoding;
public GlobalExceptionHandler(CreditTrackerSettings settings) {
this.encoding = settings.getEncoding();
}
@ExceptionHandler(value = MaxUploadSizeExceededException.class, produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<MonitoringError> handleMaxUploadSizeExceeded(MaxUploadSizeExceededException ex) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(new MediaType("application", "xml", Charset.forName(encoding)));
MonitoringError error = new MonitoringError();
error.setStatus("error");
error.setErrorCode(SignalError.ERROR_009.getCode());
error.setErrorText(SignalError.ERROR_009.getKey());
return new ResponseEntity<>(error, headers, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(value = SignalException.class, produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<CommonError> handleClientException(SignalException ex) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(new MediaType("application", "xml", Charset.forName(encoding)));
String errorText = messageResolver.resolve(ex.getErrorMessage());
headers.setContentType(new MediaType("application", "xml", Charset.forName("windows-1251")));
CommonError commonError = getCommonError(ex);
commonError.setStatus("error");
commonError.setErrorCode(ex.getErrorMessage().getSubject().getCode());
commonError.setErrorText(errorText);
commonError.setErrorCode(ex.getErrorMessage().getSubject().getErrorCode());
commonError.setErrorText(messageResolver.resolve(ex.getErrorMessage()));
if (ex instanceof SignalClientException) {
String packageName = ((SignalClientException) ex).getPackageName();
if(packageName != null ) {
log.warn("Response error: {}. PackageName: {}", errorText, packageName);
} else {
log.warn("Response error: {}", errorText);
}
return new ResponseEntity<>(commonError, headers, HttpStatus.BAD_REQUEST);
} else {
Exception cause = ((SignalServerException) ex).getCause();
log.error(cause.getMessage(), cause);
return new ResponseEntity<>(commonError, headers, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@ -74,7 +39,6 @@ public class GlobalExceptionHandler {
switch (ex.getErrorFormat()) {
case MonitoringError -> commonError = new MonitoringError();
case MonitoringActivePackagesError -> commonError = new MonitoringActivePackagesError();
case MonitoringAllPackagesError -> commonError = new MonitoringAllPackagesError();
case MonitoringDownloadError -> commonError = new MonitoringDownloadError();
case MonitoringReportListError -> commonError = new MonitoringReportListError();
case MonitoringPackageDeleteError -> commonError = new MonitoringPackageDeleteError();

View file

@ -2,7 +2,6 @@ package ru.nbch.credit_tracker.config.rest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.web.client.RestTemplate;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
@ -22,6 +21,6 @@ public class RestConfig {
@Bean(name = "executorService")
public ExecutorService executorService() {
return Executors.newCachedThreadPool(new CustomizableThreadFactory("package-registration-"));
return Executors.newCachedThreadPool();
}
}

View file

@ -1,132 +0,0 @@
package ru.nbch.credit_tracker.config.rest.filters;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
@Component
@Slf4j
@Order(0)
public class HttpLoggingFilter extends OncePerRequestFilter {
private static final Set<String> SENSITIVE_HEADERS = Set.of("authorization", "cookie", "set-cookie");
private static final int MAX_BODY = 10 * 1024;
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
String path = request.getRequestURI();
return path.startsWith("/actuator/health") || path.startsWith("/swagger")
|| path.startsWith("/v3/api-docs") || path.startsWith("/static/") || path.equals("/");
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
long startNs = System.nanoTime();
ContentCachingRequestWrapper req = wrapRequest(request);
ContentCachingResponseWrapper resp = new ContentCachingResponseWrapper(response);
String correlationId = Optional.ofNullable(request.getHeader("X-Correlation-Id"))
.filter(StringUtils::hasText)
.orElse(UUID.randomUUID().toString());
resp.setHeader("X-Correlation-Id", correlationId);
logIncomingRequest(req, correlationId);
try {
chain.doFilter(req, resp);
} finally {
long tookMs = (System.nanoTime() - startNs) / 1_000_000;
Map<String, String> reqParams = paramsMap(req);
Map<String, String> reqHeaders = headersMap(req);
Map<String, String> respHeaders = headersMap(resp);
mask(reqHeaders);
mask(respHeaders);
log.info(
"HTTP (RESPONSE) {} {} | status={} | took={}ms | cid={} | reqHeaders={} | reqParams={} | respHeaders={}",
req.getMethod(),
req.getRequestURI(),
resp.getStatus(),
tookMs,
correlationId,
reqHeaders,
reqParams,
respHeaders
);
resp.copyBodyToResponse();
}
}
private void logIncomingRequest(ContentCachingRequestWrapper req, String correlationId) {
Map<String, String> reqParams = paramsMap(req);
Map<String, String> reqHeaders = headersMap(req);
mask(reqHeaders);
log.info(
"HTTP (REQUEST) {} {} | cid={} | reqHeaders={} | reqParams={}",
req.getMethod(),
req.getRequestURI(),
correlationId,
reqHeaders,
reqParams
);
}
private static ContentCachingRequestWrapper wrapRequest(HttpServletRequest request) throws IOException {
return (request instanceof ContentCachingRequestWrapper c) ? c : new ContentCachingRequestWrapper(request, MAX_BODY);
}
private static Map<String, String> headersMap(HttpServletRequest req) {
return Collections.list(req.getHeaderNames()).stream()
.collect(Collectors.toMap(h -> h, req::getHeader, (a, b) -> a, LinkedHashMap::new));
}
private static Map<String, String> paramsMap(HttpServletRequestWrapper req) {
Map<String, String> paramsMap = new LinkedHashMap<>();
req.getParameterMap().forEach((k, v) -> {
String params = String.join(", ", v);
paramsMap.put(k, params);
});
try {
Collection<Part> fileParts = req.getParts();
fileParts.forEach(part -> {
paramsMap.put(part.getName(), part.getSubmittedFileName());
});
} catch (Exception e) {
// ignore
}
return paramsMap;
}
private static Map<String, String> headersMap(HttpServletResponse resp) {
return resp.getHeaderNames().stream()
.collect(Collectors.toMap(h -> h, resp::getHeader, (a, b) -> a, LinkedHashMap::new));
}
private static void mask(Map<String, String> headers) {
headers.replaceAll((k, v) -> SENSITIVE_HEADERS.contains(k.toLowerCase()) ? "***" : v);
}
}

View file

@ -1,55 +0,0 @@
package ru.nbch.credit_tracker.config.rest.filters;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import ru.nbch.credit_tracker.config.rest.wrappers.CachedHttpRequestWrapper;
import java.io.IOException;
@Component
@Slf4j
@Order(1)
public class MemberCodeHttpLoggingFilter extends OncePerRequestFilter {
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
String path = request.getRequestURI();
return !(path.startsWith("/api/v1/signal/all_packages") || path.startsWith("/api/v1/signal/active_packages"));
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
CachedHttpRequestWrapper req = wrapRequest(request);
String body = IOUtils.toString(req.getBody(), req.getCharacterEncoding());
if (StringUtils.isNotBlank(body)) {
try {
int startIndex = body.indexOf("<UserId>") + 8;
int endIndex = body.indexOf("</UserId>");
String userId = body.substring(startIndex, endIndex);
log.info(
"HTTP (REQUEST) {} {} | memberCode={}",
req.getMethod(),
req.getRequestURI(),
userId.substring(0, 6)
);
} catch (Exception e) {
// ignore
}
}
filterChain.doFilter(req, response);
}
private static CachedHttpRequestWrapper wrapRequest(HttpServletRequest request) throws IOException {
return new CachedHttpRequestWrapper(request);
}
}

View file

@ -1,25 +0,0 @@
package ru.nbch.credit_tracker.config.rest.wrappers;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import lombok.Getter;
import java.io.IOException;
@Getter
public class CachedHttpRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public CachedHttpRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
this.body = request.getInputStream().readAllBytes();
}
@Override
public ServletInputStream getInputStream() {
return new CachedServletInputStream(body);
}
}

View file

@ -1,33 +0,0 @@
package ru.nbch.credit_tracker.config.rest.wrappers;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import java.io.ByteArrayInputStream;
public class CachedServletInputStream extends ServletInputStream {
private final ByteArrayInputStream byteArray;
public CachedServletInputStream(byte[] data) {
this.byteArray = new ByteArrayInputStream(data);
}
public int read() {
return byteArray.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
}
}

View file

@ -26,11 +26,9 @@ public class CreditTrackerSettings {
private String signalsToken;
private String signalsuser;
private Long maxXmlFileSize;
private String loadDir;
private Long monitoringInterval;
private String updateFlagsCronExpression;
private Long updateFlagsInterval;
private Long daysToUpdateFlags;
private String encoding;
}

View file

@ -4,13 +4,5 @@ public record DataSourceSettings(
String username,
String password,
String url,
String driver,
Integer maximumPoolSize,
Integer minimumIdle,
long connectionTimeout,
long validationTimeout,
long idleTimeout,
long maxLifetime,
long keepaliveTime,
long leakDetectionThreshold
String driver
) {}

View file

@ -3,46 +3,45 @@ package ru.nbch.credit_tracker.config.xml;
import jakarta.xml.bind.JAXBException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.external_response.monitoring_report_file.SgnlReportMonitorigSetupError;
import ru.nbch.credit_tracker.entities.external_response.online_report.SgnlOnlineReport;
import ru.nbch.credit_tracker.entities.user_request.active_packages.MonitoringActivePackagesRequest;
import ru.nbch.credit_tracker.entities.user_request.all_packages.MonitoringAllPackagesRequest;
import ru.nbch.credit_tracker.entities.user_response.errors.MonitoringError;
import ru.nbch.credit_tracker.entities.user_response.success.MonitoringSetupResponse;
import ru.nbch.credit_tracker.entities.request.monitoring_request.MonitoringRequest;
import ru.nbch.credit_tracker.entities.response.errors.MonitoringError;
import ru.nbch.credit_tracker.entities.response.monitoring_signal_response.MonitoringSignalResponse;
import ru.nbch.credit_tracker.entities.response.online_download.OnlineDownloadReport;
import ru.nbch.credit_tracker.entities.response.online_report.SgnlOnlineReport;
import ru.nbch.credit_tracker.entities.response.success.MonitoringResponse;
import ru.nbch.credit_tracker.entities.signal_package.Signals;
import ru.nbch.credit_tracker.service.xml.jaxb.IXmlProcessor;
import ru.nbch.credit_tracker.service.xml.jaxb.XmlProcessorImplAnyClasses;
import ru.nbch.credit_tracker.service.xml.stax.*;
import ru.nbch.credit_tracker.service.xml.stax.SgnlReportStatusStaxReader;
import ru.nbch.credit_tracker.service.xml.stax.StaxReader;
import ru.nbch.credit_tracker.service.xml.stax.StaxXmlProcessor;
import ru.nbch.credit_tracker.service.xml.stax.XmlProcessorStaxImpl;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
@Configuration
public class XmlConfig {
@Bean
public IXmlProcessor xmlProcessor(CreditTrackerSettings settings) throws JAXBException {
return new XmlProcessorImplAnyClasses(Charset.forName(settings.getEncoding()),
public IXmlProcessor xmlProcessor() throws JAXBException {
return new XmlProcessorImplAnyClasses(Charset.forName("windows-1251"),
// unmarshalling classes
MonitoringRequest.class,
OnlineDownloadReport.class,
SgnlOnlineReport.class,
SgnlReportMonitorigSetupError.class,
MonitoringActivePackagesRequest.class,
MonitoringAllPackagesRequest.class,
// marshalling classes
Signals.class,
MonitoringError.class,
MonitoringSetupResponse.class);
MonitoringResponse.class,
MonitoringSignalResponse.class);
}
@Bean
public StaxXmlProcessor staxXmlProcessor() {
List<Supplier<StaxReader<?>>> staxReader = new ArrayList<>();
staxReader.add(SgnlReportStatusStaxReader::new);
staxReader.add(MonitoringRequestStaxReader::new);
staxReader.add(OnlineDownloadReportPersonsStaxReader::new);
staxReader.add(MonitoringSignalResponseStaxXmlReader::new);
staxReader.add(MonitoringReportErrorsStaxtReader::new);
List<StaxReader<?>> staxReader = new ArrayList<>();
staxReader.add(new SgnlReportStatusStaxReader());
return new XmlProcessorStaxImpl(staxReader);
}
}

View file

@ -5,13 +5,11 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import ru.nbch.credit_tracker.entities.user_request.active_packages.MonitoringActivePackagesRequest;
import ru.nbch.credit_tracker.entities.user_request.all_packages.MonitoringAllPackagesRequest;
import ru.nbch.credit_tracker.entities.user_response.active_packages.MonitoringActivePackagesResponse;
import ru.nbch.credit_tracker.entities.user_response.all_packages.MonitoringAllPackagesResponse;
import ru.nbch.credit_tracker.entities.user_response.success.MonitoringPackageDeleteResponse;
import ru.nbch.credit_tracker.entities.user_response.success.MonitoringReportListResponse;
import ru.nbch.credit_tracker.entities.user_response.success.MonitoringSetupResponse;
import ru.nbch.credit_tracker.entities.request.active_packages.MonitoringActivePackagesRequest;
import ru.nbch.credit_tracker.entities.response.active_packages.MonitoringActivePackagesResponse;
import ru.nbch.credit_tracker.entities.response.success.MonitoringPackageDeleteResponse;
import ru.nbch.credit_tracker.entities.response.success.MonitoringReportListResponse;
import ru.nbch.credit_tracker.entities.response.success.MonitoringResponse;
import ru.nbch.credit_tracker.facade.SignalFacade;
@RestController
@ -25,7 +23,7 @@ public class SignalController {
}
@PostMapping(value = "/set", produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<MonitoringSetupResponse> setupMonitoring(@RequestParam("file") MultipartFile file) {
public ResponseEntity<MonitoringResponse> setupMonitoring(@RequestParam("file") MultipartFile file) {
return signalFacade.setupMonitoring(file);
}
@ -34,11 +32,6 @@ public class SignalController {
return signalFacade.findActivePackages(activePackagesRequest);
}
@PostMapping(value = "/all_packages", consumes = MediaType.APPLICATION_XML_VALUE, produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<MonitoringAllPackagesResponse> findAllPackages(@RequestBody MonitoringAllPackagesRequest allPackagesRequest) {
return signalFacade.findAllPackages(allPackagesRequest);
}
@PostMapping(value = "/delete", params = {"username", "packageName"}, produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<MonitoringPackageDeleteResponse> deletePackage(@RequestParam("username") String username, @RequestParam("packageName") String packageName) {
return signalFacade.deletePackage(username, packageName);

View file

@ -8,8 +8,8 @@ import java.time.LocalDateTime;
@Getter
@Setter
public class Hit {
private Long id;
private Long packageId;
private Integer id;
private Integer packageId;
private String subjectId;
private Integer signalType;
private LocalDateTime responseSentAt;

View file

@ -10,13 +10,12 @@ import java.time.LocalDateTime;
@NoArgsConstructor
@Builder
public class PhoneFidMap {
private Long id;
private Long packageId;
private Integer id;
private Integer packageId;
private String subjectId;
private String phone;
private Integer fid;
private Integer flagDebt5000;
private Integer flag90days;
private LocalDateTime calculatedAt;
private String errorText;
}

View file

@ -10,12 +10,10 @@ import java.time.LocalDateTime;
@Setter
@Builder
public class UserPackage {
private Long id;
private Integer id;
private String userId;
private String packageName;
private LocalDateTime createdAt;
private String status;
private LocalDateTime deactivatedAt;
private String lastDownloadedReport;
private LocalDateTime monitoringAt;
}

View file

@ -1,72 +0,0 @@
package ru.nbch.credit_tracker.entities.external_response.monitoring_report_error;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
@Setter
@Getter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"id",
"version",
"user",
"reportCreated"
})
@XmlRootElement(name = "Errors")
public class MonitoringReportErrors {
@XmlElement(name = "Id")
protected String id;
@XmlElement(name = "Version")
protected String version;
@XmlElement(name = "User")
protected String user;
@XmlElement(name = "ReportCreated")
protected String reportCreated;
@XmlElement(name = "p")
protected List<P> persons;
public List<P> getPersons() {
if (persons == null) {
persons = new ArrayList<>();
}
return this.persons;
}
private P currentPerson;
public void createCurrentPerson() {
currentPerson = new P();
}
public P getCurrentPerson() {
return currentPerson;
}
public void finalizePerson() {
getPersons().add(currentPerson);
}
@Getter
@Setter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
})
public static class P {
@XmlAttribute(name = "uid")
protected Long uid;
@XmlValue
protected String value;
}
}

View file

@ -1,21 +0,0 @@
package ru.nbch.credit_tracker.entities.external_response.monitoring_report_file;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlType;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"filename"
})
public class ErrorsForNextReport {
@XmlElement(name = "filename", required = true)
protected String filename;
}

View file

@ -1,24 +0,0 @@
package ru.nbch.credit_tracker.entities.external_response.monitoring_report_file;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlType;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"memberCode",
"packCode"
})
public class InputParams {
@XmlElement(name = "memberCode", required = true)
protected String memberCode;
@XmlElement(name = "packCode", required = true)
protected String packCode;
}

View file

@ -1,20 +0,0 @@
package ru.nbch.credit_tracker.entities.external_response.monitoring_report_file;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlType;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"errorsForNextReport"
})
public class OperationReport {
@XmlElement(name = "ErrorsForNextReport")
protected ErrorsForNextReport errorsForNextReport;
}

View file

@ -1,22 +0,0 @@
package ru.nbch.credit_tracker.entities.external_response.monitoring_report_file;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"inputParams",
"operationReport"
})
@XmlRootElement(name = "SgnlReport")
public class SgnlReportMonitorigSetupError {
@XmlElement(name = "InputParams", required = true)
protected InputParams inputParams;
@XmlElement(name = "OperationReport", required = true)
protected OperationReport operationReport;
}

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_request.active_packages;
package ru.nbch.credit_tracker.entities.request.active_packages;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;

View file

@ -0,0 +1,31 @@
package ru.nbch.credit_tracker.entities.request.monitoring_request;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"userId",
"password",
"packageName",
"subjects"
})
@XmlRootElement(name = "MonitoringRequest")
public class MonitoringRequest {
@XmlElement(name = "UserId", required = true)
protected String userId;
@XmlElement(name = "Password", required = true)
protected String password;
@XmlElement(name = "PackageName", required = true)
protected String packageName;
@XmlElement(name = "Subjects", required = true)
protected Subjects subjects;
}

View file

@ -1,5 +1,5 @@
package ru.nbch.credit_tracker.entities.user_request.monitoring_request;
package ru.nbch.credit_tracker.entities.request.monitoring_request;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_request.monitoring_request;
package ru.nbch.credit_tracker.entities.request.monitoring_request;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.active_packages;
package ru.nbch.credit_tracker.entities.response.active_packages;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.active_packages;
package ru.nbch.credit_tracker.entities.response.active_packages;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.active_packages;
package ru.nbch.credit_tracker.entities.response.active_packages;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.errors;
package ru.nbch.credit_tracker.entities.response.errors;
public interface CommonError {
void setStatus(String status);

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.errors;
package ru.nbch.credit_tracker.entities.response.errors;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.errors;
package ru.nbch.credit_tracker.entities.response.errors;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
@ -17,9 +17,9 @@ public class MonitoringDownloadError implements CommonError {
@XmlElement(name = "Status", required = true)
protected String status;
@XmlElement(name = "Code",required = true)
@XmlElement(name = "ErrorCode",required = true)
protected String errorCode;
@XmlElement(name = "Message",required = true)
@XmlElement(name = "ErrorText",required = true)
protected String errorText;
}

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.errors;
package ru.nbch.credit_tracker.entities.response.errors;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.errors;
package ru.nbch.credit_tracker.entities.response.errors;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.errors;
package ru.nbch.credit_tracker.entities.response.errors;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
@ -17,9 +17,9 @@ public class MonitoringReportListError implements CommonError {
@XmlElement(name = "Status", required = true)
protected String status;
@XmlElement(name = "Code",required = true)
@XmlElement(name = "ErrorCode",required = true)
protected String errorCode;
@XmlElement(name = "Message",required = true)
@XmlElement(name = "ErrorText",required = true)
protected String errorText;
}

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_response.errors;
package ru.nbch.credit_tracker.entities.response.external_errors;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_response.errors;
package ru.nbch.credit_tracker.entities.response.external_errors;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_response.errors;
package ru.nbch.credit_tracker.entities.response.external_errors;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.monitoring_signal_response;
package ru.nbch.credit_tracker.entities.response.monitoring_signal_response;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
@ -17,5 +17,5 @@ public class MonitoringSignalResponse {
@XmlElement(name = "PackageName", required = true)
protected String packageName;
@XmlElement(name = "Subjects", required = true)
protected Subjects subjects = new Subjects();
protected Subjects subjects;
}

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.monitoring_signal_response;
package ru.nbch.credit_tracker.entities.response.monitoring_signal_response;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.monitoring_signal_response;
package ru.nbch.credit_tracker.entities.response.monitoring_signal_response;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
@ -24,17 +24,4 @@ public class Signals {
return this.signals;
}
private Signal currentSignal;
public void createCurrentSignal() {
currentSignal = new Signal();
}
public Signal getCurrentSignal() {
return currentSignal;
}
public void finalizeSignal() {
getSignals().add(currentSignal);
}
}

View file

@ -1,5 +1,5 @@
package ru.nbch.credit_tracker.entities.user_response.monitoring_signal_response;
package ru.nbch.credit_tracker.entities.response.monitoring_signal_response;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
@ -30,7 +30,7 @@ public class Subject {
@XmlElement(name = "Flag90_12", required = true)
protected Integer flag9012;
@XmlElement(name = "Signals", required = true)
protected Signals signals = new Signals();
protected Signals signals;
}

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.monitoring_signal_response;
package ru.nbch.credit_tracker.entities.response.monitoring_signal_response;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
@ -24,18 +24,4 @@ public class Subjects {
return this.subjects;
}
private Subject currentSubject;
public void createCurrentSubject() {
currentSubject = new Subject();
}
public Subject getCurrentSubject() {
return currentSubject;
}
public void finalizeSubject() {
getSubjects().add(currentSubject);
}
}

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_response.online_download;
package ru.nbch.credit_tracker.entities.response.online_download;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
@ -42,18 +42,4 @@ public class Inquiry {
return this.signals;
}
private Signal currentSignal;
public void createCurrentSignal() {
currentSignal = new Signal();
}
public Signal getCurrentSignal() {
return currentSignal;
}
public void finalizeSignal() {
getSignals().add(currentSignal);
}
}

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_response.online_download;
package ru.nbch.credit_tracker.entities.response.online_download;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_response.online_download;
package ru.nbch.credit_tracker.entities.response.online_download;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
@ -16,7 +16,7 @@ import java.util.List;
public class Person {
@XmlAttribute(name = "uid", required = true)
protected Long uid;
protected String uid;
@XmlElement(name = "Inquiry", required = true)
protected List<Inquiry> inquiries;
@ -27,18 +27,4 @@ public class Person {
}
return this.inquiries;
}
private Inquiry currentInquiry;
public void createCurrentInquiry() {
currentInquiry = new Inquiry();
}
public Inquiry getCurrentInquiry() {
return currentInquiry;
}
public void finalizeInquiry() {
getInquiries().add(currentInquiry);
}
}

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_response.online_download;
package ru.nbch.credit_tracker.entities.response.online_download;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
@ -24,18 +24,5 @@ public class Persons {
return this.persons;
}
private Person currentPerson;
public void createCurrentPerson() {
currentPerson = new Person();
}
public Person getCurrentPerson() {
return currentPerson;
}
public void finalizePerson() {
getPersons().add(currentPerson);
}
}

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_response.online_download;
package ru.nbch.credit_tracker.entities.response.online_download;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_response.online_report;
package ru.nbch.credit_tracker.entities.response.online_report;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_response.online_report;
package ru.nbch.credit_tracker.entities.response.online_report;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_response.online_report;
package ru.nbch.credit_tracker.entities.response.online_report;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_response.online_report;
package ru.nbch.credit_tracker.entities.response.online_report;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_response.online_report;
package ru.nbch.credit_tracker.entities.response.online_report;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.success;
package ru.nbch.credit_tracker.entities.response.success;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.success;
package ru.nbch.credit_tracker.entities.response.success;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.user_response.success;
package ru.nbch.credit_tracker.entities.response.success;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
@ -11,7 +11,7 @@ import lombok.Setter;
"status",
})
@XmlRootElement(name = "MonitoringResponse")
public class MonitoringSetupResponse {
public class MonitoringResponse {
@XmlElement(name = "Status", required = true)
protected String status = "OK";

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_request.signals;
package ru.nbch.credit_tracker.entities.signal_package;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_request.signals;
package ru.nbch.credit_tracker.entities.signal_package;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_request.signals;
package ru.nbch.credit_tracker.entities.signal_package;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
@ -15,7 +15,7 @@ public class Person {
@XmlValue
protected String value;
@XmlAttribute(name = "uid", required = true)
protected Long uid;
protected String uid;
@XmlAttribute(name = "oksm", required = true)
protected String oksm;
@XmlAttribute(name = "s", required = true)
@ -34,8 +34,6 @@ public class Person {
protected String pd;
@XmlAttribute(name = "dt", required = true)
protected String dt;
@XmlAttribute(name = "odt")
protected String odt;
@XmlAttribute(name = "ip", required = true)
protected String ip;
@XmlAttribute(name = "consentDate")
@ -75,10 +73,6 @@ public class Person {
protected String consentDivCode;
@XmlAttribute(name = "consentDt")
protected String consentDt;
@XmlAttribute(name = "consentOdt")
protected String consentOdt;
@XmlAttribute(name = "consentIssueAuthority")
protected String consentIssueAuthority;
@XmlAttribute(name = "inqPurpose")
protected String inqPurpose;

View file

@ -1,4 +1,4 @@
package ru.nbch.credit_tracker.entities.external_request.signals;
package ru.nbch.credit_tracker.entities.signal_package;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;

View file

@ -1,5 +1,5 @@
package ru.nbch.credit_tracker.entities.external_request.signals;
package ru.nbch.credit_tracker.entities.signal_package;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
@ -25,8 +25,6 @@ public class Signals {
protected Conditions conditions;
@XmlAttribute(name = "online", required = true)
protected String online;
@XmlAttribute(name = "processWithErrors", required = true)
protected String processWithErrors;
public Conditions getConditions() {
if (conditions == null) {

View file

@ -1,22 +0,0 @@
package ru.nbch.credit_tracker.entities.user_request.all_packages;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"userId",
"password"
})
@XmlRootElement(name = "MonitoringAllPackagesRequest")
public class MonitoringAllPackagesRequest {
@XmlElement(name = "UserId", required = true)
protected String userId;
@XmlElement(name = "Password", required = true)
protected String password;
}

View file

@ -1,51 +0,0 @@
package ru.nbch.credit_tracker.entities.user_request.monitoring_request;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"userId",
"password",
"packageName",
"subjects"
})
@XmlRootElement(name = "MonitoringRequest")
public class MonitoringRequest {
@XmlElement(name = "UserId", required = true)
protected String userId;
@XmlElement(name = "Password", required = true)
protected String password;
@XmlElement(name = "PackageName", required = true)
protected String packageName;
@XmlElement(name = "Subjects", required = true)
protected Subjects subjects;
public Subjects getSubjects() {
if (subjects == null) {
subjects = new Subjects();
}
return subjects;
}
private Subject currentSubject;
public void createCurrentSubject() {
currentSubject = new Subject();
}
public Subject getCurrentSubject() {
return currentSubject;
}
public void finalizeSubject() {
getSubjects().getSubject().add(currentSubject);
}
}

View file

@ -1,24 +0,0 @@
package ru.nbch.credit_tracker.entities.user_response.all_packages;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"status",
"membercode",
"packages"
})
@XmlRootElement(name = "MonitoringAllPackagesResponse")
public class MonitoringAllPackagesResponse {
@XmlElement(name = "Status", required = true)
protected String status;
@XmlElement(name = "Membercode", required = true)
protected String membercode;
@XmlElement(name = "Packages", required = true)
protected PackagesAll packages;
}

View file

@ -1,29 +0,0 @@
package ru.nbch.credit_tracker.entities.user_response.all_packages;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlType;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"packageName",
"createdAt",
"status",
"deactivatedAt"
})
public class PackageAll {
@XmlElement(name = "PackageName", required = true)
protected String packageName;
@XmlElement(name = "CreatedAt", required = true)
protected String createdAt;
@XmlElement(name = "Status", required = false)
protected String status;
@XmlElement(name = "DeactivatedAt", required = false)
protected String deactivatedAt;
}

View file

@ -1,26 +0,0 @@
package ru.nbch.credit_tracker.entities.user_response.all_packages;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlType;
import java.util.ArrayList;
import java.util.List;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"packages"
})
public class PackagesAll {
@XmlElement(name = "Package", required = true)
protected List<PackageAll> packages;
public List<PackageAll> getPackages() {
if (packages == null) {
packages = new ArrayList<>();
}
return this.packages;
}
}

View file

@ -1,25 +0,0 @@
package ru.nbch.credit_tracker.entities.user_response.errors;
import jakarta.xml.bind.annotation.*;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MonitoringAllPackagesResponse", propOrder = {
"status",
"errorCode",
"errorText"
})
@XmlRootElement(name = "MonitoringAllPackagesResponse")
public class MonitoringAllPackagesError implements CommonError {
@XmlElement(name = "Status", required = true)
protected String status;
@XmlElement(name = "Code",required = true)
protected String errorCode;
@XmlElement(name = "Message",required = true)
protected String errorText;
}

View file

@ -2,27 +2,24 @@ package ru.nbch.credit_tracker.enums;
public enum SignalError implements IEnumKeyCode {
ERROR_001("001", "Ошибка распаковки архива"),
ERROR_002("002", "Отсутствует обязательный элемент: {}"),
ERROR_003("003", "Элемент ClientId не соответствует формату XXXXXXXXX. Id: {}"),
ERROR_002("002", "Отсутствует обязательный элемент: "),
ERROR_003("003", "Элемент ClientId не соответствует формату XXXXXXXXX"),
ERROR_004("004", "Указан неуникальный Id в пакете: "),
ERROR_005("005", "Неверный логин или пароль"),
ERROR_006("006", "Доступ к услуге закрыт, обратитесь к курирующему менеджеру"),
ERROR_007("007", "В системе уже существует пакет с таким именем"),
ERROR_008("008", "PackageName не соответствует допустимому формату"),
ERROR_009("009", "Превышен допустимый размер пакета"),
ERROR_010("010", "Идентификатор субъекта (Id) не соответствует допустимому формату: {}"),
ERROR_010("010", "Идентификатор субъекта (Id) не соответствует допустимому формату"),
ERROR_011("011", "Получен невалидный XML"),
ERROR_012("012", "Пакет {} не найден"),
ERROR_012("012", "Пакет не найден"),
ERROR_013("013", "На стороне сервиса произошла ошибка, попробуйте повторить запрос позже или сообщите в техническую поддержку"),
ERROR_014("014", "Файл с именем {} не найден "),
ERROR_015("015", "У данного пользователя не найдено активных пакетов"),
ERROR_016("016", "Нет активного пакета с именем {}"),
ERROR_014("014", "Файл не найден"),
ERROR_015("015", "Клиент с указанным membercode не найден"),
ERROR_016("016", "Нет активного пакета с именем "),
ERROR_017("017", "При обработке запроса произошла ошибка. Повторите запрос позже или обратитесь в службу технической поддержки"), // TODO get rid of duplicate?
ERROR_018("018", "Пакет {} находится в обработке. Дождитесь его установки на мониторинг и повторите попытку позже."),
ERROR_019("019", "У данного пользователя не найдено ни одного пакета"),
ERROR_020("020", "Пакет {} был отклонён при установке на мониторинг. Отчеты не формируются."),
ERROR_021("021", "Обработка пакета {} завершилась с ошибкой, отчёты недоступны. Обратитесь в техническую поддержку."),
ERROR_022("022", "Пакет {} снят с мониторинга, отчёты больше недоступны.");
ERROR_100("100", "Непредвиденная ошибка");
private final String code;
private final String message;

View file

@ -2,7 +2,6 @@ package ru.nbch.credit_tracker.enums;
public enum XmlErrorFormat {
MonitoringActivePackagesError,
MonitoringAllPackagesError,
MonitoringDownloadError,
MonitoringError,
MonitoringPackageDeleteError,

View file

@ -7,10 +7,7 @@ import ru.nbch.credit_tracker.enums.XmlErrorFormat;
@Getter
public class SignalClientException extends SignalException {
private final String packageName;
public SignalClientException(EnumKeyMessage errorMessage, XmlErrorFormat errorFormat, String packageName) {
public SignalClientException(EnumKeyMessage errorMessage, XmlErrorFormat errorFormat) {
super(errorMessage, errorFormat);
this.packageName = packageName;
}
}

View file

@ -1,17 +1,12 @@
package ru.nbch.credit_tracker.exceptions;
import lombok.Getter;
import ru.nbch.credit_tracker.enums.EnumKeyMessage;
import ru.nbch.credit_tracker.enums.XmlErrorFormat;
@Getter
public class SignalServerException extends SignalException {
private final Exception cause;
public SignalServerException(EnumKeyMessage errorMessage, XmlErrorFormat errorFormat, Exception cause) {
public SignalServerException(EnumKeyMessage errorMessage, XmlErrorFormat errorFormat) {
super(errorMessage, errorFormat);
this.cause = cause;
}
}

View file

@ -1,55 +1,41 @@
package ru.nbch.credit_tracker.facade;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.io.FileUrlResource;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import ru.nbch.credit_tracker.config.mdc.SetAndClearMdc;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import ru.nbch.credit_tracker.entities.user_request.active_packages.MonitoringActivePackagesRequest;
import ru.nbch.credit_tracker.entities.user_request.all_packages.MonitoringAllPackagesRequest;
import ru.nbch.credit_tracker.entities.user_request.monitoring_request.MonitoringRequest;
import ru.nbch.credit_tracker.entities.user_response.active_packages.MonitoringActivePackagesResponse;
import ru.nbch.credit_tracker.entities.user_response.active_packages.Package;
import ru.nbch.credit_tracker.entities.user_response.active_packages.Packages;
import ru.nbch.credit_tracker.entities.user_response.all_packages.MonitoringAllPackagesResponse;
import ru.nbch.credit_tracker.entities.user_response.all_packages.PackageAll;
import ru.nbch.credit_tracker.entities.user_response.all_packages.PackagesAll;
import ru.nbch.credit_tracker.entities.user_response.success.MonitoringPackageDeleteResponse;
import ru.nbch.credit_tracker.entities.user_response.success.MonitoringReportListResponse;
import ru.nbch.credit_tracker.entities.user_response.success.MonitoringSetupResponse;
import ru.nbch.credit_tracker.entities.request.active_packages.MonitoringActivePackagesRequest;
import ru.nbch.credit_tracker.entities.request.monitoring_request.MonitoringRequest;
import ru.nbch.credit_tracker.entities.response.active_packages.MonitoringActivePackagesResponse;
import ru.nbch.credit_tracker.entities.response.active_packages.Package;
import ru.nbch.credit_tracker.entities.response.active_packages.Packages;
import ru.nbch.credit_tracker.entities.response.success.MonitoringPackageDeleteResponse;
import ru.nbch.credit_tracker.entities.response.success.MonitoringReportListResponse;
import ru.nbch.credit_tracker.entities.response.success.MonitoringResponse;
import ru.nbch.credit_tracker.entities.signal_package.Signals;
import ru.nbch.credit_tracker.enums.SignalError;
import ru.nbch.credit_tracker.enums.Status;
import ru.nbch.credit_tracker.enums.XmlErrorFormat;
import ru.nbch.credit_tracker.exceptions.SignalClientException;
import ru.nbch.credit_tracker.service.MonitoringErrorProcesingService;
import ru.nbch.credit_tracker.service.SignalService;
import ru.nbch.credit_tracker.service.indic.PhoneService;
import ru.nbch.credit_tracker.service.scoring.AuthorizationService;
import ru.nbch.credit_tracker.service.signal.SignalRestService;
import ru.nbch.credit_tracker.service.xml.stax.StaxXmlProcessor;
import ru.nbch.credit_tracker.service.xml.jaxb.IXmlProcessor;
import ru.nbch.credit_tracker.utils.CTUtil;
import ru.nbch.credit_tracker.utils.ValidationService;
import ru.nbch.credit_tracker.utils.ValidationUtil;
import ru.nbch.credit_tracker.utils.ZipUtils;
import javax.xml.stream.XMLStreamException;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@ -59,43 +45,33 @@ import static ru.nbch.credit_tracker.utils.error.ExceptionUtils.serverExcp;
@Slf4j
@Service
@EnableAspectJAutoProxy(exposeProxy = true)
public class SignalFacade {
private SignalFacade self;
private static final long MAX_XML_FILE_SIZE = 2L * 1024 * 1024 * 1024;
private final CreditTrackerSettings config;
private final AuthorizationService authorizationService;
private final SignalService signalService;
private final SignalRestService signalRestService;
private final MonitoringErrorProcesingService monitoringErrorProcesingService;
private final ValidationService validationService;
private final StaxXmlProcessor staxXmlProcessor;
private final IXmlProcessor xmlProcessor;
private final ExecutorService executor;
private final long maxXmlFileSize;
public SignalFacade(CreditTrackerSettings config,
AuthorizationService authorizationService,
SignalService signalService,
SignalRestService signalRestService,
MonitoringErrorProcesingService monitoringErrorProcesingService,
ValidationService validationService,
StaxXmlProcessor staxXmlProcessor,
IXmlProcessor xmlProcessor,
@Qualifier("executorService") ExecutorService executor) {
this.config = config;
this.authorizationService = authorizationService;
this.signalService = signalService;
this.signalRestService = signalRestService;
this.monitoringErrorProcesingService = monitoringErrorProcesingService;
this.validationService = validationService;
this.staxXmlProcessor = staxXmlProcessor;
this.xmlProcessor = xmlProcessor;
this.executor = executor;
this.maxXmlFileSize = config.getMaxXmlFileSize() * 1024 * 1024;
}
public ResponseEntity<MonitoringSetupResponse> setupMonitoring(MultipartFile file) {
public ResponseEntity<MonitoringResponse> setupMonitoring(MultipartFile file) {
// первичные валидации
if (file.isEmpty() || !isZipFile(file)) {
throw clientExcp(SignalError.ERROR_001, XmlErrorFormat.MonitoringError);
@ -103,16 +79,15 @@ public class SignalFacade {
// Валидация Архива на количетсво файлов, размер и расширение
MonitoringRequest monitoringRequest;
Long packageId;
Integer packageId;
ZipInputStream zipInputStream = null;
String filePath;
try {
zipInputStream = new ZipInputStream(file.getInputStream());
Optional<ZipEntry> xmlFileEntry = ZipUtils.extractValidEntry(zipInputStream);
if (xmlFileEntry.isEmpty()) {
throw clientExcp(SignalError.ERROR_001, XmlErrorFormat.MonitoringError);
}
if (xmlFileEntry.get().getSize() > maxXmlFileSize) {
if (xmlFileEntry.get().getSize() > MAX_XML_FILE_SIZE) {
throw clientExcp(SignalError.ERROR_009, XmlErrorFormat.MonitoringError);
}
@ -120,18 +95,19 @@ public class SignalFacade {
zipInputStream = new ZipInputStream(file.getInputStream());
zipInputStream.getNextEntry();
filePath = writeTmpFile(zipInputStream);
monitoringRequest = xmlProcessor.read(zipInputStream, MonitoringRequest.class);
} catch (Exception e) {
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
}
throw serverExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringError, e);
log.error(e.getMessage(), e);
throw serverExcp(SignalError.ERROR_100, XmlErrorFormat.MonitoringError);
} finally {
if (zipInputStream != null) {
try {
zipInputStream.close();
} catch (IOException e) {
throw serverExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringError, e);
throw serverExcp(SignalError.ERROR_100, XmlErrorFormat.MonitoringError);
}
}
}
@ -139,16 +115,10 @@ public class SignalFacade {
// валидация xml
try {
monitoringRequest = readAndValidateMonitoringRequest(filePath);
} catch (Exception e) {
CTUtil.removeFile(filePath);
if (e.getCause() instanceof XMLStreamException) {
throw clientExcp(SignalError.ERROR_011, XmlErrorFormat.MonitoringError);
}
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
}
throw serverExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringError, e);
ValidationUtil.validateMonitoringRequest(monitoringRequest);
} catch (SignalClientException e) {
signalService.rejectPackage(monitoringRequest);
throw e;
}
try {
@ -156,100 +126,46 @@ public class SignalFacade {
AuthorizationService.AuthResult authResult = authorizationService.findAuthInfo(monitoringRequest.getUserId(), monitoringRequest.getPassword());
if (!authResult.isSuccess()) {
signalService.rejectPackage(monitoringRequest);
throw clientExcp(authResult.getError(), monitoringRequest.getPackageName(), XmlErrorFormat.MonitoringError);
throw clientExcp(authResult.getError(), XmlErrorFormat.MonitoringError);
}
// проверка на уникальность пакета
if (signalService.isPackageNotUnique(monitoringRequest)) {
signalService.rejectPackage(monitoringRequest);
throw clientExcp(SignalError.ERROR_007, monitoringRequest.getPackageName(), XmlErrorFormat.MonitoringError);
throw clientExcp(SignalError.ERROR_007, XmlErrorFormat.MonitoringError);
}
packageId = signalService.registerPackage(monitoringRequest);
log.info("Package registered. PackageId {}. Status: {}", packageId, Status.PROCESSING.name());
} catch (Exception e) {
CTUtil.removeFile(filePath);
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
}
throw serverExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringError, e);
log.error(e.getMessage(), e);
throw serverExcp(SignalError.ERROR_100, XmlErrorFormat.MonitoringError);
}
// в отдельном потоке запускаем регистрацию субъектов, поиск фидов и расчет флагов просрочек
getCurrentProxy().registerFidsAndDebts(packageId, monitoringRequest.getPackageName(), filePath);
// в отдельном потоке запускаем поиск фидов и расчет флагов просрочек
registerFidsAndDebts(packageId, monitoringRequest.getPackageName());
return ResponseEntity.ok().body(new MonitoringSetupResponse());
return ResponseEntity.ok().body(new MonitoringResponse());
}
private MonitoringRequest readAndValidateMonitoringRequest(String filePath) {
MonitoringRequest monitoringRequest;
try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(Path.of(filePath)), 8 * 1024 * 1024)) {
monitoringRequest = staxXmlProcessor.read(in, MonitoringRequest.class,
request -> {
try {
validationService.validateMonitoringRequest(request);
} catch (SignalClientException e) {
if (request != null) {
signalService.rejectPackage(request);
}
request = null;
throw e;
}
request.getSubjects().getSubject().clear();
},
request -> request.getSubjects().getSubject().isEmpty()
,
40000, "/MonitoringRequest/Subjects/Subject");
} catch (IOException e) {
throw new RuntimeException("Error while parsing and validating monitoring request", e);
}
return monitoringRequest;
}
private String writeTmpFile(ZipInputStream zipInputStream) throws IOException {
String folderPath = config.getLoadDir() + File.separator + "tmp_folder" + File.separator;
String filePath = folderPath + UUID.randomUUID() + "monitoring_request.xml";
CTUtil.createFolder(folderPath);
try (OutputStream out = Files.newOutputStream(Path.of(filePath))) {
byte[] buffer = new byte[8 * 1024 * 1024];
int bytesRead;
while ((bytesRead = zipInputStream.read(buffer)) > 0) {
out.write(buffer, 0, bytesRead);
}
return filePath;
}
}
@SetAndClearMdc(argIndex = 1)
public void registerFidsAndDebts(Long packageId, String packageName, String filePath) {
Map<String, String> context = MDC.getCopyOfContextMap();
private void registerFidsAndDebts(Integer packageId, String packageName) {
executor.execute(() -> {
if (context != null) {
MDC.setContextMap(context);
}
try {
signalService.registerSubjects(filePath, packageId);
CTUtil.removeFile(filePath);
SignalService.UpdateResult updateResult = signalService.updateSubjects(packageId, null);
if (updateResult.isNoFidsFound()) {
log.info("No fids found for PackageId: {} PackageName: {}. Package status ON_MONITORING. No registration in signal service.", packageId, packageName);
signalService.updatePackageStatus(packageId, Status.ON_MONITORING);
return;
}
if (signalRestService.setupMonitoring(packageId)) {
LocalDateTime monitoringAt = LocalDateTime.now();
log.info("Package was successfully registered in signal service. PackageId: {} PackageName: {}, MonitoringAt: {}", packageId, packageName, monitoringAt);
signalService.updatePackageOnMonitoringSuccess(packageId, monitoringAt);
monitoringErrorProcesingService.findErrors(packageId);
} else {
log.info("Package registration was rejected by signal service. PackageId: {} PackageName: {}", packageId, packageName);
signalService.updatePackageStatus(packageId, Status.ERROR);
List<PhoneService.FidsPhoneData> phoneFidsData = signalService.registerSubjectsFidAndDebts(packageId);
if (!phoneFidsData.isEmpty()) {
Signals signals = signalService.buildSignals(packageId, phoneFidsData);
// TODO validate xsd?
if (signalRestService.update(signals)) {
log.info("Package was successfully registered in signal service. PackageId: {} PackageName: {}", packageId, packageName);
signalService.updatePackageStatus(packageId, Status.ON_MONITORING);
} else {
log.info("Package registration was rejected by signal service. PackageId: {} PackageName: {}", packageId, packageName);
signalService.updatePackageStatus(packageId, Status.ERROR);
}
}
} catch (Exception e) {
CTUtil.removeFile(filePath);
signalService.updatePackageStatus(packageId, Status.ERROR);
log.error("Ошибка при поиске фидов или расчете флагов просрочек. Package_id {}", packageId, e);
}
@ -258,8 +174,8 @@ public class SignalFacade {
private boolean isZipFile(MultipartFile file) {
return file.getContentType() != null &&
(file.getContentType().equals("application/zip") || file.getContentType().equals("application/x-zip-compressed")) ||
file.getOriginalFilename() != null && file.getOriginalFilename().toLowerCase().endsWith(".zip");
(file.getContentType().equals("application/zip") || file.getContentType().equals("application/x-zip-compressed")) ||
file.getOriginalFilename() != null && file.getOriginalFilename().toLowerCase().endsWith(".zip");
}
public ResponseEntity<MonitoringActivePackagesResponse> findActivePackages(MonitoringActivePackagesRequest activePackagesRequest) {
@ -290,43 +206,8 @@ public class SignalFacade {
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
}
throw serverExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringActivePackagesError, e);
}
}
public ResponseEntity<MonitoringAllPackagesResponse> findAllPackages(MonitoringAllPackagesRequest allPackagesRequest) {
try {
AuthorizationService.AuthResult authResult = authorizationService.findAuthInfo(allPackagesRequest.getUserId(), allPackagesRequest.getPassword());
if (!authResult.isSuccess()) {
throw clientExcp(authResult.getError(), XmlErrorFormat.MonitoringAllPackagesError);
}
List<UserPackage> activePackages = signalService.findAllPackages(allPackagesRequest.getUserId());
if (!activePackages.isEmpty()) {
MonitoringAllPackagesResponse response = new MonitoringAllPackagesResponse();
response.setStatus("OK");
response.setMembercode(allPackagesRequest.getUserId().substring(0, 6));
PackagesAll packages = new PackagesAll();
activePackages.forEach(data -> {
PackageAll pack = new PackageAll();
pack.setPackageName(data.getPackageName());
pack.setCreatedAt(data.getCreatedAt() != null ? data.getCreatedAt().toString() : null);
pack.setStatus(data.getStatus());
if (data.getStatus().equals(Status.DELETED.name())) {
pack.setDeactivatedAt(data.getDeactivatedAt() != null ? data.getDeactivatedAt().toString() : null);
}
packages.getPackages().add(pack);
});
response.setPackages(packages);
return ResponseEntity.ok(response);
} else {
throw clientExcp(SignalError.ERROR_019, XmlErrorFormat.MonitoringAllPackagesError);
}
} catch (Exception e) {
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
}
throw serverExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringAllPackagesError, e);
log.error(e.getMessage(), e);
throw serverExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringActivePackagesError);
}
}
@ -351,26 +232,15 @@ public class SignalFacade {
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
}
throw serverExcp(SignalError.ERROR_017, XmlErrorFormat.MonitoringPackageDeleteError, e);
log.error(e.getMessage(), e);
throw serverExcp(SignalError.ERROR_017, XmlErrorFormat.MonitoringPackageDeleteError);
}
}
public ResponseEntity<MonitoringReportListResponse> getReportList(String username, String packageName) {
try {
if (signalService.isPackagesByStatusExist(username, packageName, Status.PROCESSING)) {
throw clientExcp(SignalError.ERROR_018, XmlErrorFormat.MonitoringReportListError, packageName);
}
if (signalService.isPackagesByStatusExist(username, packageName, Status.REJECTED)) {
throw clientExcp(SignalError.ERROR_020, XmlErrorFormat.MonitoringReportListError, packageName);
}
if (signalService.isPackagesByStatusExist(username, packageName, Status.ERROR)) {
throw clientExcp(SignalError.ERROR_021, XmlErrorFormat.MonitoringReportListError, packageName);
}
if (signalService.isPackagesByStatusExist(username, packageName, Status.DELETED)) {
throw clientExcp(SignalError.ERROR_022, XmlErrorFormat.MonitoringReportListError, packageName);
}
if (!signalService.isPackagesByStatusExist(username, packageName, Status.ON_MONITORING)) {
throw clientExcp(SignalError.ERROR_012, XmlErrorFormat.MonitoringReportListError, packageName);
if (!signalService.isPackageExists(username, packageName)) {
throw clientExcp(SignalError.ERROR_016, XmlErrorFormat.MonitoringReportListError, packageName);
}
String memberCode = username.substring(0, 6);
@ -378,35 +248,42 @@ public class SignalFacade {
String dirPath = config.getLoadDir() + File.separator + memberCode;
File folder = new File(dirPath);
MonitoringReportListResponse.Reports reports = new MonitoringReportListResponse.Reports();
if (folder.exists() && folder.isDirectory()) {
MonitoringReportListResponse.Reports reports = new MonitoringReportListResponse.Reports();
File[] files = folder.listFiles();
if (files != null) {
for (File file : files) {
if (file.isFile() && file.getName().startsWith(filePrefix)) {
reports.getReports().add(file.getName());
}
if (files == null) {
throw clientExcp(SignalError.ERROR_012, XmlErrorFormat.MonitoringReportListError, packageName);
}
for (File file : files) {
if (file.isFile() && file.getName().startsWith(filePrefix)) {
reports.getReports().add(file.getName());
}
}
if (reports.getReports().isEmpty()) {
throw clientExcp(SignalError.ERROR_012, XmlErrorFormat.MonitoringReportListError, packageName);
} else {
MonitoringReportListResponse response = new MonitoringReportListResponse();
response.setPackageName(packageName);
response.setReports(reports);
return ResponseEntity.ok(response);
}
} else {
log.error("Пакет {} был найден в бд для memberCode {}, но ни одного архива не было найдено в папке {}", packageName, username, dirPath);
throw clientExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringReportListError, packageName);
}
MonitoringReportListResponse response = new MonitoringReportListResponse();
response.setPackageName(packageName);
response.setReports(reports);
return ResponseEntity.ok(response);
} catch (Exception e) {
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
}
throw serverExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringReportListError, e);
log.error(e.getMessage(), e);
throw serverExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringReportListError);
}
}
public ResponseEntity<Resource> downloadFile(String fileName) {
try {
String memberCode = CTUtil.getMemberCodeFromFileName(fileName);
if (memberCode == null) {
throw clientExcp(SignalError.ERROR_014, XmlErrorFormat.MonitoringDownloadError, fileName);
}
String dirPath = config.getLoadDir() + File.separator + memberCode;
File folder = new File(dirPath);
@ -416,21 +293,15 @@ public class SignalFacade {
return ResponseEntity.ok().body(new FileUrlResource(file.getPath()));
}
} else {
throw clientExcp(SignalError.ERROR_014, XmlErrorFormat.MonitoringDownloadError, fileName);
throw clientExcp(SignalError.ERROR_014, XmlErrorFormat.MonitoringDownloadError);
}
throw clientExcp(SignalError.ERROR_014, XmlErrorFormat.MonitoringDownloadError, fileName);
throw clientExcp(SignalError.ERROR_014, XmlErrorFormat.MonitoringDownloadError);
} catch (Exception e) {
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
}
throw serverExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringDownloadError, e);
log.error(e.getMessage(), e);
throw serverExcp(SignalError.ERROR_013, XmlErrorFormat.MonitoringDownloadError);
}
}
private SignalFacade getCurrentProxy() {
if (self == null) {
self = (SignalFacade) AopContext.currentProxy();
}
return self;
}
}

View file

@ -3,23 +3,19 @@ package ru.nbch.credit_tracker.mapper.signal;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
import ru.nbch.credit_tracker.entities.user_request.monitoring_request.Subject;
import ru.nbch.credit_tracker.entities.request.monitoring_request.Subject;
import java.util.List;
@Mapper
public interface PhoneFidMapMapper {
void registerSubjects(@Param("subjects") List<Subject> subjects, @Param("packageId") Long packageId);
void registerSubjects(@Param("subjects") List<Subject> subjects, @Param("packageId") Integer packageId);
List<PhoneFidMap> findFullPhoneFidMap(@Param("packageId") Long packageId, @Param("offset") int offset, @Param("limit") int limit);
List<PhoneFidMap> findPhoneFidMaps(@Param("packageId") Integer packageId);
List<PhoneFidMap> findFullPhoneFidMap(@Param("packageId") Integer packageId);
void updatePhoneFidMaps(@Param("subjects") List<PhoneFidMap> subjects);
void updatePhoneFidMapsErrors(@Param("subjects") List<PhoneFidMap> subjects);
PhoneFidMap findPhoneFidMapById(@Param("id") Long packageId);
boolean hasNonNullFids(@Param("packageId") Long packageId);
boolean hasOldRow(@Param("packageId") Long packageId, @Param("daysCount") Integer daysCount);
}

View file

@ -14,23 +14,18 @@ public interface UserPackageMapper {
boolean isPackageExists(@Param("userId") String userId, @Param("packageName") String packageName, @Param("status") String status);
boolean hasActivePackages(@Param("userId") String userId, @Param("packageName") String packageName, @Param("statuses") List<String> statuses);
void deletePackage(@Param("userId") String userId, @Param("packageName") String packageName, @Param("status") String newStatus, @Param("previousStatus") String previousStatus, @Param("deactivatedAt") LocalDateTime deactivatedAt);
Long insertPackage(@Param("userPackage") UserPackage userPackage);
Integer insertPackage(@Param("userPackage") UserPackage userPackage);
void updatePackageStatus(@Param("packageId") Long packageId, @Param("status") String status);
void updatePackageStatus(@Param("packageId") Integer packageId, @Param("status") String status);
void updatePackageLastDownloadedReport(@Param("id") Long id, @Param("fileName") String fileName);
void updatePackageLastDownloadedReport(@Param("id") Integer id, @Param("fileName") String fileName);
void updatePackageOnMonitoringSuccess(@Param("id") Long id, @Param("monitoringAt") LocalDateTime monitoringAt);
UserPackage findPackage(@Param("id") Integer id);
UserPackage findPackage(@Param("id") Long id);
List<UserPackage> findUserPackages(@Param("userId") String userId, @Param("statuses") List<String> status);
List<UserPackage> findUserPackages(@Param("userId") String userId, @Param("status") String status);
List<UserPackage> findAllPackagesByStatus(@Param("status") String status);
List<UserPackage> findAllPackagesByUserId(@Param("userId") String userId);
}

View file

@ -1,59 +0,0 @@
package ru.nbch.credit_tracker.service;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.config.mdc.SetAndClearMdc;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import ru.nbch.credit_tracker.service.signal.SignalRestService;
import ru.nbch.credit_tracker.utils.CTUtil;
@Slf4j
@Service
@EnableAspectJAutoProxy(exposeProxy = true)
public class MonitoringErrorProcesingService {
private MonitoringErrorProcesingService self;
private final SignalService signalService;
private final SignalRestService signalRestService;
public MonitoringErrorProcesingService(SignalService signalService, SignalRestService signalRestService) {
this.signalService = signalService;
this.signalRestService = signalRestService;
}
public void findErrors(Long packageId) {
UserPackage userPackage = signalService.findPackage(packageId);
getCurrentProxy().processPackage(userPackage, packageId);
}
@SetAndClearMdc
public void processPackage(UserPackage userPackage, Long packageId) {
if (userPackage != null) {
String packCode = userPackage.getUserId().substring(0, 6) + "_" + userPackage.getPackageName();
log.info("Проверка на ошибки при постановке на мониторинг. packCode={}, packageId={}", packCode, packageId);
String fileName = signalRestService.getErrorFileName(packageId, packCode);
if (StringUtils.isNotBlank(fileName)) {
String filePath = signalRestService.loadErrorFile(packageId, fileName);
if (StringUtils.isNotBlank(filePath)) {
try {
signalService.updateSubjectsErrors(filePath, packageId);
} catch (Exception e) {
log.error("Ошибка при записи сообщений об ошибках в сформированных субъектах для мониторинга. Package_id = {}", packageId, e);
}
CTUtil.removeFile(filePath);
}
}
}
}
private MonitoringErrorProcesingService getCurrentProxy() {
if (self == null) {
self = (MonitoringErrorProcesingService) AopContext.currentProxy();
}
return self;
}
}

View file

@ -1,67 +1,55 @@
package ru.nbch.credit_tracker.service;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.dto.Hit;
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import ru.nbch.credit_tracker.entities.external_response.online_download.Inquiry;
import ru.nbch.credit_tracker.entities.external_response.online_download.Person;
import ru.nbch.credit_tracker.entities.external_response.online_download.Persons;
import ru.nbch.credit_tracker.entities.external_response.online_report.Report;
import ru.nbch.credit_tracker.entities.external_response.online_report.SgnlOnlineReport;
import ru.nbch.credit_tracker.entities.user_response.monitoring_signal_response.MonitoringSignalResponse;
import ru.nbch.credit_tracker.entities.user_response.monitoring_signal_response.Signal;
import ru.nbch.credit_tracker.entities.user_response.monitoring_signal_response.Signals;
import ru.nbch.credit_tracker.entities.user_response.monitoring_signal_response.Subject;
import ru.nbch.credit_tracker.entities.response.monitoring_signal_response.*;
import ru.nbch.credit_tracker.entities.response.online_download.Inquiry;
import ru.nbch.credit_tracker.entities.response.online_download.OnlineDownloadReport;
import ru.nbch.credit_tracker.entities.response.online_download.Person;
import ru.nbch.credit_tracker.entities.response.online_report.Report;
import ru.nbch.credit_tracker.entities.response.online_report.SgnlOnlineReport;
import ru.nbch.credit_tracker.service.signal.SignalRestService;
import ru.nbch.credit_tracker.service.xml.stax.MonitoringSignalResponseStaxXmlWriter;
import ru.nbch.credit_tracker.service.xml.stax.StaxXmlProcessor;
import ru.nbch.credit_tracker.service.xml.jaxb.IXmlProcessor;
import ru.nbch.credit_tracker.utils.CTUtil;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* Сервис периодического опроса официального сервиса сигналов на наличие новых отчетов по пакетам находящимся в статусе ON_MONITORING
*/
@Slf4j
@Service
public class MonitoringService {
private final SignalRestService signalRestService;
private final SignalService signalService;
private final StaxXmlProcessor staxXmlProcessor;
private final IXmlProcessor xmlProcessor;
private final CreditTrackerSettings config;
public MonitoringService(SignalRestService signalRestService,
SignalService signalService,
StaxXmlProcessor staxXmlProcessor,
IXmlProcessor xmlProcessor,
CreditTrackerSettings config) {
this.signalRestService = signalRestService;
this.signalService = signalService;
this.staxXmlProcessor = staxXmlProcessor;
this.xmlProcessor = xmlProcessor;
this.config = config;
}
public void run() {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new CustomizableThreadFactory("monitoring-"));
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
long period = config.getMonitoringInterval() != null ? config.getMonitoringInterval() : 15;
scheduler.scheduleAtFixedRate(this::monitor, 0, period, TimeUnit.MINUTES);
}
@ -70,144 +58,71 @@ public class MonitoringService {
log.info("Start monitoring");
List<UserPackage> packages = signalService.findPackagesOnMonitoring();
for (UserPackage userPackage : packages) {
MDC.put("ru.nbch.credit_tracker.log.mdc.key", "[" + userPackage.getPackageName() +"]");
processPackage(userPackage);
MDC.remove("ru.nbch.credit_tracker.log.mdc.key");
log.info("Processing package {}", userPackage.getPackageName());
SgnlOnlineReport onlineReports = signalRestService.getReports(userPackage.getUserId().substring(0, 6) + "_" + userPackage.getPackageName());
if (onlineReports == null) {
log.info("No reports found for package {}", userPackage.getPackageName());
continue;
}
List<String> fileNames = onlineReports.getOperationReport().getReports().getReports().stream().map(Report::getFilename)
.filter(fileName -> CTUtil.parseDateFromReportFileName(fileName) != null).toList(); // TODO оптимизировать
if (fileNames.isEmpty()) {
log.info("No new report found for package {}", userPackage.getPackageName());
continue;
}
Optional<String> newReport = Optional.of(fileNames)
.orElseGet(Collections::emptyList)
.stream().max(Comparator.comparing(CTUtil::parseDateFromReportFileName)); // отфильтровали только те имена, которые парсятся в дату, так что null тут не придет
LocalDateTime lastDownloadedReportDate = CTUtil.parseDateFromReportFileName(userPackage.getLastDownloadedReport());
if (userPackage.getLastDownloadedReport() != null) {
log.info("Last downloaded report found for package {}. Last Downloaded Report Name: {}", userPackage.getPackageName(), userPackage.getLastDownloadedReport());
} else {
log.info("Last Downloaded Report Name is empty");
}
OnlineDownloadReport report = null;
if (userPackage.getLastDownloadedReport() == null && newReport.isPresent()) {
report = loadReport(newReport.get()); // по этому пакету еще не было загруженных отчетов, продолжаем работу с полученным
} else if (lastDownloadedReportDate != null && newReport.isPresent()) {
LocalDateTime newReportDate = CTUtil.parseDateFromReportFileName(newReport.get());
if (newReportDate.isAfter(lastDownloadedReportDate)) {
report = loadReport(newReport.get()); // полученный отчет новее записанного в базу
}
}
if (report == null) {
log.info("Report was not loaded for package {}", userPackage.getPackageName());
continue;
}
MonitoringSignalResponse response = generateResponse(userPackage, report.getPersons().getPersons());
String fileName = createResponseFile(userPackage, response);
if (fileName != null) {
log.info("New report fileName: {}", fileName);
updateSignalHits(userPackage, response, fileName);
signalService.updateLastDownloadedReport(userPackage.getId(), newReport.get());
} else {
log.info("Report was not created for package {}", userPackage.getPackageName());
}
}
log.info("Finish monitoring");
}
private void processPackage(UserPackage userPackage) {
log.info("Processing package");
if (!signalService.hasNonNullfids(userPackage.getId())) {
log.info("Package has no fids. Package will be skipped.");
return;
}
SgnlOnlineReport onlineReports = signalRestService.getReports(userPackage.getUserId().substring(0, 6) + "_" + userPackage.getPackageName());
if (onlineReports == null) {
log.info("No reports found for package");
return;
}
// Формируем список имен файлов, по которым сработали сигналы. Сюда входят только те имена, у которых парсится дата формирования отчета
List<String> fileNames = onlineReports.getOperationReport().getReports().getReports().stream().map(Report::getFilename)
.filter(fileName -> CTUtil.parseDateFromReportFileName(fileName) != null).toList();
if (fileNames.isEmpty()) {
log.info("No new report found for package");
return;
}
LocalDateTime lastDownloadedReportDate = CTUtil.parseDateFromReportFileName(userPackage.getLastDownloadedReport());
if (lastDownloadedReportDate != null) {
// Отбираем только те отчеты, дата которых позже даты последнего загруженного отчета
fileNames = fileNames.stream()
.filter(fileName -> CTUtil.parseDateFromReportFileName(fileName).isAfter(lastDownloadedReportDate)) // отфильтровали только те имена, которые парсятся в дату, так что null тут не придет
.sorted(Comparator.comparing(CTUtil::parseDateFromReportFileName)) // Сортируем по дате
.toList();
} else {
fileNames = fileNames.stream()
.sorted(Comparator.comparing(CTUtil::parseDateFromReportFileName)) // Сортируем по дате
.toList();
}
if (StringUtils.isNotBlank(userPackage.getLastDownloadedReport())) {
log.info("Last downloaded report found for package. Last Downloaded Report Name: {}", userPackage.getLastDownloadedReport());
} else {
log.info("Last Downloaded Report Name is empty");
}
for (String newReport : fileNames) {
try {
String loadedReportPath = null;
if (StringUtils.isBlank(userPackage.getLastDownloadedReport())) {
loadedReportPath = loadReport(userPackage.getId(), newReport); // по этому пакету еще не было загруженных отчетов, продолжаем работу с полученным
} else if (lastDownloadedReportDate != null) {
LocalDateTime newReportDate = CTUtil.parseDateFromReportFileName(newReport);
if (newReportDate.isAfter(lastDownloadedReportDate)) {
loadedReportPath = loadReport(userPackage.getId(), newReport); // полученный отчет новее записанного в базу
}
}
if (loadedReportPath == null) {
log.info("Report was not loaded for package");
continue;
}
String responsePath = generateResponse(userPackage, loadedReportPath);
String fileName = null;
if (responsePath != null) {
fileName = createResponseFile(userPackage, responsePath);
}
if (fileName != null) {
log.info("New report fileName: {}", fileName);
updateSignalHits(userPackage, responsePath, fileName);
signalService.updateLastDownloadedReport(userPackage.getId(), newReport);
} else {
log.info("Report was not created for package");
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
/**
* Формирует результирующий xml файл для конечного пользователя на основе файла из официального сервиса сигналов
* @return Путь к временному рещультирующему файлу
*/
private String generateResponse(UserPackage userPackage, String loadedReportPath) {
AtomicBoolean generateResponse = new AtomicBoolean(false); // Выставляется в true, если хотя бы один субъект с мониторинга подошел под условие срабатывания сигнала. В этом случае отчет сохраняется
String folderPath = config.getLoadDir() + File.separator + "tmp_folder" + File.separator;
String responsePath = folderPath + UUID.randomUUID() + "_response_output.xml";
CTUtil.createFolder(folderPath);
private MonitoringSignalResponse generateResponse(UserPackage userPackage, List<Person> persons) {
MonitoringSignalResponse response = new MonitoringSignalResponse();
response.setPackageName(userPackage.getPackageName()); // Имя пакета, переданного при установке
// Запись в результрующий файл
MonitoringSignalResponseStaxXmlWriter staxXmlWriter = new MonitoringSignalResponseStaxXmlWriter(config.getEncoding());
staxXmlWriter.writeWithStax(responsePath, response,
writer -> {
try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(Path.of(loadedReportPath)), 8 * 1024 * 1024)) {
staxXmlProcessor.read(in, Persons.class,
personsData -> { // как только считали пачку Persons сразу записали ее в результирующий файл
List<Subject> subjectsBatch = processPersons(personsData.getPersons());
if (!subjectsBatch.isEmpty()) {
generateResponse.set(true);
}
writer.accept(subjectsBatch);
personsData.getPersons().clear(); // чистим список для экономии памяти
},
pesons -> pesons.getPersons().isEmpty()
,
10000,
"/Report/Persons/Person");
} catch (IOException e) {
throw new RuntimeException("Error while parsing nbki downloaded report", e);
}
});
CTUtil.removeFile(loadedReportPath);
if (!generateResponse.get()) { // ни один субъект не подошел под условие, удаляем временный отчет
CTUtil.removeFile(responsePath);
return null;
}
return responsePath;
}
private List<Subject> processPersons(List<Person> persons) {
List<Subject> subjects = new ArrayList<>();
Subjects subjects = new Subjects();
List<PhoneFidMap> phoneFidMapList = signalService.findFullSubjectsData(userPackage.getId());
for (Person person : persons) {
Signals signals = new Signals();
for (Inquiry inquiry : person.getInquiries()) {
// Отбираем только тех фл, у которых bus_category in (MFO, MKK, MFK) и есть сигналы с кодом 16
if (!CTUtil.checkBusCategory(inquiry.getBusCategory()) || inquiry.getSignals().stream().noneMatch(signal -> signal.getN().equals(16))) {
if (!CTUtil.checkBusCategory(inquiry.getBusCategory()) && inquiry.getSignals().stream().anyMatch(signal -> signal.getN().equals(16))) {
continue;
}
Signal signal = new Signal();
@ -219,101 +134,84 @@ public class MonitoringService {
// Если есть хотя бы один заполненный сигнал, значит заполняем остальные данные
if (!signals.getSignals().isEmpty()) {
PhoneFidMap subjectData = signalService.findPhoneFidMapById(person.getUid());
if (subjectData != null) {
phoneFidMapList.stream().filter(p -> p.getSubjectId().equals(person.getUid())).findFirst().ifPresent(subjectData -> {
Subject subject = new Subject();
subject.setId(subjectData.getSubjectId()); // Уникальный идентификатор субъекта (равен Id из XML-пакета при установке мониторинга)
subject.setClientId(subjectData.getPhone());
subject.setFlagDebt5000(subjectData.getFlagDebt5000());
subject.setFlag9012(subjectData.getFlag90days());
subject.setSignals(signals);
subjects.add(subject);
}
subjects.getSubjects().add(subject);
});
}
}
return subjects;
response.setSubjects(subjects);
return response;
}
/**
* Архивирует результирующий xml файл для пользователя
* @return Путь к результрующему файлу. Пример <loadDir>/<member_code>/0001ZZ_MY_BATCH_TEST_0717_04_20250723_101929.zip
*/
private String createResponseFile(UserPackage userPackage, String responsePath) {
private String createResponseFile(UserPackage userPackage, MonitoringSignalResponse response) {
try {
String fileName = CTUtil.generateResponseReportFileName(userPackage.getUserId(), userPackage.getPackageName());
Thread.sleep(1000); // Если отчеты формируются слишком быстро, нужно подождать секунду, тк в имени отчета LocalDateTime до секунд
String folderPath = config.getLoadDir() + File.separator + userPackage.getUserId().substring(0, 6) + File.separator;
String filePath = config.getLoadDir() + File.separator + userPackage.getUserId().substring(0, 6) + File.separator;
File folder = new File(folderPath);
File folder = new File(filePath);
if (!folder.exists()) {
folder.mkdir();
}
try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(Path.of(responsePath)), 8 * 1024 * 1024);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(folderPath + fileName + ".zip"));
ZipOutputStream zos = new ZipOutputStream(bos)) {
String xmlStr = xmlProcessor.asString(response, true);
byte[] xmlBytes = xmlStr.getBytes(Charset.forName("windows-1251"));
try (FileOutputStream fos = new FileOutputStream(filePath + fileName + ".zip");
ZipOutputStream zos = new ZipOutputStream(fos)) {
ZipEntry zipEntry = new ZipEntry(fileName + ".xml");
zos.putNextEntry(zipEntry);
byte[] buffer = new byte[8 * 1024 * 1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) > 0) {
zos.write(buffer, 0, bytesRead);
}
zos.finish();
zos.write(xmlBytes);
zos.closeEntry();
}
return fileName;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
log.error("Ошибка при записи отчета пользователя в файл: ", e);
}
CTUtil.removeFile(responsePath);
return null;
}
private void updateSignalHits(UserPackage userPackage, String responsePath, String reportFileName) {
private void updateSignalHits(UserPackage userPackage, MonitoringSignalResponse response, String reportFileName) {
log.info("Updating signal hits for {}", userPackage.getPackageName());
LocalDateTime responseSentAt = LocalDateTime.now();
// Считываем результирующий файл пачками и обновляем таблицу hits
try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(Path.of(responsePath)), 8 * 1024 * 1024)) {
staxXmlProcessor.read(in, MonitoringSignalResponse.class,
response -> { // как только считали пачку Subjects сразу обновлям таблицу hits
List<Hit> hits = new ArrayList<>();
response.getSubjects().getSubjects().forEach(subject -> {
subject.getSignals().getSignals().forEach(signal -> {
Hit hit = new Hit();
hit.setPackageId(userPackage.getId());
hit.setSubjectId(subject.getId());
hit.setSignalType(1);
hit.setResponseSentAt(responseSentAt);
hit.setReportFileName(reportFileName);
hits.add(hit);
});
if (!hits.isEmpty()) {
signalService.insertHits(hits);
}
});
response.getSubjects().getSubjects().clear(); // чистим список для экономии памяти
},
response -> response.getSubjects().getSubjects().isEmpty()
,
10000,
"/MonitoringSignalResponse/Subjects/Subject");
} catch (IOException e) {
throw new RuntimeException("Error while updating hits", e);
}
CTUtil.removeFile(responsePath); // удалям результирующий xml файл с диска (Он уже заархивирован к этому моменту)
List<Hit> hits = new ArrayList<>();
response.getSubjects().getSubjects().forEach(subject -> {
subject.getSignals().getSignals().forEach(signal -> {
Hit hit = new Hit();
hit.setPackageId(userPackage.getId());
hit.setSubjectId(subject.getId());
hit.setSignalType(1);
hit.setResponseSentAt(responseSentAt);
hit.setReportFileName(reportFileName);
hits.add(hit);
});
});
signalService.insertHits(hits);
log.info("Signal hits updated for package {}", userPackage.getPackageName());
}
public String loadReport(Long packageId, String reportName) {
return signalRestService.downloadReport(packageId, reportName);
private OnlineDownloadReport loadReport(String reportName) {
byte[] archive = signalRestService.downloadReport(reportName);
if (archive == null) {
return null;
}
OnlineDownloadReport report;
try (GZIPInputStream zipInputStream = new GZIPInputStream(new ByteArrayInputStream(archive))) {
report = xmlProcessor.read(zipInputStream, OnlineDownloadReport.class);
} catch (Exception e) {
log.error(e.getMessage(), e);
return null;
}
return report;
}
}

View file

@ -1,7 +1,5 @@
package ru.nbch.credit_tracker.service;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.builder.PersonFactoryBuilder;
@ -9,11 +7,11 @@ import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.dto.Hit;
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import ru.nbch.credit_tracker.entities.external_request.signals.Auth;
import ru.nbch.credit_tracker.entities.external_request.signals.Person;
import ru.nbch.credit_tracker.entities.external_request.signals.Signals;
import ru.nbch.credit_tracker.entities.external_response.monitoring_report_error.MonitoringReportErrors;
import ru.nbch.credit_tracker.entities.user_request.monitoring_request.MonitoringRequest;
import ru.nbch.credit_tracker.entities.request.monitoring_request.MonitoringRequest;
import ru.nbch.credit_tracker.entities.request.monitoring_request.Subject;
import ru.nbch.credit_tracker.entities.signal_package.Auth;
import ru.nbch.credit_tracker.entities.signal_package.Person;
import ru.nbch.credit_tracker.entities.signal_package.Signals;
import ru.nbch.credit_tracker.enums.Status;
import ru.nbch.credit_tracker.service.indic.FlagsService;
import ru.nbch.credit_tracker.service.indic.PersonService;
@ -21,19 +19,12 @@ import ru.nbch.credit_tracker.service.indic.PhoneService;
import ru.nbch.credit_tracker.service.signal.HitsService;
import ru.nbch.credit_tracker.service.signal.PhoneFidMapService;
import ru.nbch.credit_tracker.service.signal.UserPackageService;
import ru.nbch.credit_tracker.service.xml.stax.SignalsStaxXmlWriter;
import ru.nbch.credit_tracker.service.xml.stax.StaxXmlProcessor;
import ru.nbch.credit_tracker.utils.CTUtil;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Slf4j
@Service
@ -46,7 +37,6 @@ public class SignalService {
private final PhoneService phoneService;
private final FlagsService flagsService;
private final PersonService personService;
private final StaxXmlProcessor staxXmlProcessor;
private final int batchSize = 10000;
@ -56,8 +46,7 @@ public class SignalService {
PhoneFidMapService phoneFidMapService,
PhoneService phoneService,
FlagsService flagsService,
PersonService personService,
StaxXmlProcessor staxXmlProcessor) {
PersonService personService) {
this.config = config;
this.hitsService = hitsService;
this.userPackageService = userPackageService;
@ -65,126 +54,76 @@ public class SignalService {
this.phoneService = phoneService;
this.flagsService = flagsService;
this.personService = personService;
this.staxXmlProcessor = staxXmlProcessor;
}
public boolean isPackageNotUnique(MonitoringRequest request) {
return userPackageService.isPackageNotUnique(request.getUserId(), request.getPackageName());
}
public Long registerPackage(MonitoringRequest request) {
public Integer registerPackage(MonitoringRequest request) {
UserPackage userPackage = UserPackage.builder()
.userId(request.getUserId())
.packageName(request.getPackageName())
.createdAt(LocalDateTime.now())
.status(Status.PROCESSING.name())
.build();
return userPackageService.insertPackage(userPackage);
}
public void registerSubjects(String filePath, Long packageId) {
log.info("Start registering subjects. PackageId: {}", packageId);
try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(Path.of(filePath)), 8 * 1024 * 1024)) {
staxXmlProcessor.read(in, MonitoringRequest.class,
request -> {
if (!request.getSubjects().getSubject().isEmpty()) {
phoneFidMapService.registerSubjects(request.getSubjects().getSubject(), packageId);
log.trace("Registered subject's batch. Total count: {}. PackageId: {}", request.getSubjects().getSubject().size(), packageId);
request.getSubjects().getSubject().clear();
}
},
request -> request.getSubjects().getSubject().isEmpty()
,
batchSize, "/MonitoringRequest/Subjects/Subject");
} catch (IOException e) {
throw new RuntimeException("Error while parsing monitoring request", e);
Integer packageId = userPackageService.insertPackage(userPackage);
List<Subject> subjects = request.getSubjects().getSubject();
for (int i = 0; i < subjects.size(); i += batchSize) {
int end = Math.min(i + batchSize, subjects.size());
phoneFidMapService.registerSubjects(subjects.subList(i, end), packageId); // TODO преобразовывать список в List<PhoneFidMap> ?
}
log.info("Subjects were registered. PackageId: {}", packageId);
return packageId;
}
/**
* Обрабатывает все PhoneFidMap по packageId, выгружая их пачками и фильтруя по переданному фильтру
*/
public UpdateResult updateSubjects(Long packageId, Predicate<PhoneFidMap> filter) {
boolean updated = false;
boolean noFidsFound = true;
int offset = 0;
List<PhoneFidMap> batch;
do {
batch = phoneFidMapService.findFullPhoneFidMap(packageId, offset, batchSize);
List<PhoneFidMap> filteredItems;
if (filter != null) {
filteredItems = batch.stream().filter(filter).toList();
} else {
filteredItems = batch;
}
if (!updated && !filteredItems.isEmpty()) {
updated = true;
}
if (!filteredItems.isEmpty()) {
boolean fidsFound = updateFlags(filteredItems, packageId);
if (noFidsFound) {
noFidsFound = !fidsFound;
}
}
offset += batchSize;
} while (!batch.isEmpty());
return new UpdateResult(updated, noFidsFound);
public List<PhoneService.FidsPhoneData> registerSubjectsFidAndDebts(Integer packageId) {
List<PhoneFidMap> subjects = phoneFidMapService.findPhoneFidMaps(packageId);
return updateFlags(subjects, packageId);
}
/**
* Обрабатывает пачку PhoneFidMap: обновляет фиды и флаги просрочек
* @return fidsFound true - если хотя бы по одному номеру был найден фид, false - в противном случае
*/
public boolean updateFlags(List<PhoneFidMap> subjects, Long packageId) {
log.info("Start calculating fids and flags for subjects batch. PackageId: {}", packageId);
Map<String, Integer> fidsMap = phoneService.findFidsPhoneData(subjects);
public List<PhoneService.FidsPhoneData> updateFlags(List<PhoneFidMap> subjects, Integer packageId) {
List<PhoneService.FidsPhoneData> fidsPhoneDataList = phoneService.findFidsPhoneData(subjects);
LocalDateTime calculatedAt = LocalDateTime.now();
boolean fidsFound = fidsMap.values().stream().anyMatch(Objects::nonNull);
Map<Integer, FlagsService.FlagsData> flagsDataMap = flagsService.findFlags(fidsMap.values().stream().filter(Objects::nonNull).toList());
List<PhoneFidMap> subjectToUpdate = new ArrayList<>();
for (int i = 0; i < fidsPhoneDataList.size(); i += batchSize) {
int end = Math.min(i + batchSize, fidsPhoneDataList.size());
List<PhoneService.FidsPhoneData> currentList = fidsPhoneDataList.subList(i, end);
Map<Integer, FlagsService.FlagsData> flagsDataMap = flagsService.findFlags(currentList.stream().map(PhoneService.FidsPhoneData::getFid).filter(Objects::nonNull).toList());
List<PhoneFidMap> subjectToUpdate = new ArrayList<>();
subjects.forEach(subject -> {
Integer fid = fidsMap.get("9" + subject.getPhone());
if (fid != null) {
FlagsService.FlagsData flagsData = flagsDataMap.get(fid);
subject = PhoneFidMap.builder()
.id(subject.getId())
.packageId(packageId)
.subjectId(subject.getSubjectId())
.phone(subject.getPhone())
.fid(fid)
.flagDebt5000(flagsData.getFlagDebt5000())
.flag90days(flagsData.getFlag90days())
.calculatedAt(calculatedAt)
.build();
} else {
subject = PhoneFidMap.builder()
.id(subject.getId())
.packageId(packageId)
.subjectId(subject.getSubjectId())
.phone(subject.getPhone())
.calculatedAt(calculatedAt)
.build();
currentList.forEach(data -> {
PhoneFidMap subject;
if (data.getFid() != null) {
FlagsService.FlagsData flagsData = flagsDataMap.get(data.getFid());
subject = PhoneFidMap.builder()
.id(data.getId())
.packageId(packageId)
.subjectId(data.getSubjectId())
.phone(data.getPhone())
.fid(data.getFid())
.flagDebt5000(flagsData.getFlagDebt5000())
.flag90days(flagsData.getFlag90days())
.calculatedAt(calculatedAt)
.build();
} else {
subject = PhoneFidMap.builder()
.id(data.getId())
.packageId(packageId)
.subjectId(data.getSubjectId())
.phone(data.getPhone())
.calculatedAt(calculatedAt)
.build();
}
subjectToUpdate.add(subject);
});
int updateBatchSize = batchSize / 8; // 8 параметров на одну запись для обновления. Максимальное количество параметров ~65000
for (int j = 0; j < subjectToUpdate.size(); j += updateBatchSize) {
int endIndex = Math.min(j + updateBatchSize, subjectToUpdate.size());
phoneFidMapService.updatePhoneFidMaps(subjectToUpdate.subList(j, endIndex));
}
subjectToUpdate.add(subject);
});
int updateBatchSize = batchSize / 9; // 9 параметров на одну запись для обновления. Максимальное количество параметров ~65000
for (int j = 0; j < subjectToUpdate.size(); j += updateBatchSize) {
int endIndex = Math.min(j + updateBatchSize, subjectToUpdate.size());
phoneFidMapService.updatePhoneFidMaps(subjectToUpdate.subList(j, endIndex));
log.trace("Updated fids and flags for subject's batch from: {} to: {}. Total count: {}. PackageId: {}", j, endIndex, subjectToUpdate.size(), packageId);
}
log.info("Finish calculating fids and flags for subjects. PackageId: {}. Batch size: {}", packageId, subjects.size());
return fidsFound;
return fidsPhoneDataList;
}
public void rejectPackage(MonitoringRequest request) {
@ -197,82 +136,40 @@ public class SignalService {
userPackageService.insertPackage(userPackage);
}
public void updatePackageStatus(Long packageId, Status status) {
public void updatePackageStatus(Integer packageId, Status status) {
userPackageService.updatePackageStatus(packageId, status);
}
public void updatePackageOnMonitoringSuccess(Long packageId, LocalDateTime monitoringAt) {
userPackageService.updatePackageOnMonitoringSuccess(packageId, monitoringAt);
}
/**
* Формирует файл запроса в официальный сервис сигналов, выгружая паспортные данные пачками и сразу записывая их в файл
*
* @return Путь к файлу запроса к официальному сервису сигналов на постановку на мониторинг
*/
public String writeSignals(Long packageId) {
String folderPath = config.getLoadDir() + File.separator + "tmp_folder" + File.separator;
String filePath = folderPath + UUID.randomUUID() + "_output.xml";
CTUtil.createFolder(folderPath);
Signals signals = buildSignals(packageId);
SignalsStaxXmlWriter signalsStaxXmlWriter = new SignalsStaxXmlWriter(config.getEncoding());
signalsStaxXmlWriter.writeWithStax(filePath,
signals,
writer -> buildPersons(packageId, writer));
return filePath;
}
private Signals buildSignals(Long packageId) {
public Signals buildSignals(Integer packageId, List<PhoneService.FidsPhoneData> fids) {
UserPackage userPackage = userPackageService.findPackage(packageId);
Signals signals = new Signals();
signals.setOnline("2"); // Всегда=2 (только онлайн-сигналы)
signals.setProcessWithErrors("1"); // Всегда=1 (обработать пакет полностью, по обнаруженным ошибкам (при наличии) сформировать файл отказа, записи без ошибок установить на мониторинг)
signals.setId(userPackage.getUserId().substring(0, 6) + "_" + userPackage.getPackageName()); // <MEMBERCODE>_<PackageName>
Auth auth = new Auth();
auth.setUser(config.getSignalsuser());
signals.setAuth(auth);
for (int i = 0; i < fids.size(); i += batchSize) {
int end = Math.min(i + batchSize, fids.size());
List<Person> persons = findPersons(fids.subList(i, end));
if (!persons.isEmpty()) {
signals.getConditions().getPersons().getPerson().addAll(persons);
}
}
return signals;
}
/**
* Обрабатывает все PhoneFidMap по packageId, выгружая их пачками и фильтруя по переданному фильтру.
* writer записывает пачку сразу в файл
*/
private void buildPersons(Long packageId, Consumer<List<Person>> writer) {
int offset = 0;
List<PhoneFidMap> batch;
do {
batch = phoneFidMapService.findFullPhoneFidMap(packageId, offset, batchSize);
List<Person> persons = findPersons(batch);
if (!persons.isEmpty()) {
writer.accept(persons); // записывает пачку Persons в файл
}
offset += batchSize;
} while (!batch.isEmpty());
}
/**
* Формирует список Person для постановки на мониторинг в официальный сервис сигналов на основе списка PhoneFidMap
*/
private List<Person> findPersons(List<PhoneFidMap> subjects) {
if (subjects.isEmpty()) {
return Collections.emptyList();
}
private List<Person> findPersons(List<PhoneService.FidsPhoneData> fidsPhoneData) {
List<Person> persons = new ArrayList<>();
Map<Integer, PersonService.PersonData> personFidMap = personService.findPersonData(subjects.stream()
.map(PhoneFidMap::getFid)
Map<Integer, PersonService.PersonData> personFidMap = personService.findPersonData(fidsPhoneData.stream()
.map(PhoneService.FidsPhoneData::getFid)
.filter(Objects::nonNull).toList());
subjects.forEach(data -> {
fidsPhoneData.forEach(data -> {
if (data.getFid() != null) {
PersonService.PersonData personData = personFidMap.get(data.getFid());
Person person = PersonFactoryBuilder.builder()
.personData(personData)
.uid(data.getId())
.uid(data.getSubjectId())
.build();
if (person != null) {
persons.add(person);
@ -282,49 +179,14 @@ public class SignalService {
return persons;
}
public void updateSubjectsErrors(String filePath, Long packageId) {
log.info("Start updating subjects errors. PackageId: {}", packageId);
try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(Path.of(filePath)), 8 * 1024 * 1024)) {
staxXmlProcessor.read(in, MonitoringReportErrors.class,
request -> {
if (!request.getPersons().isEmpty()) {
List<PhoneFidMap> subjects = request.getPersons().stream().map(p -> {
log.warn("Ошибка при формировании субъекта. package_id = {}, id = {}. Описание: {}", packageId, p.getUid(), p.getValue());
return PhoneFidMap.builder()
.id(p.getUid())
.errorText(p.getValue())
.build();
}).toList();
phoneFidMapService.updatePhoneFidMapsErrors(subjects);
log.trace("Updated subject's batch. Total count: {}. PackageId: {}", request.getPersons().size(), packageId);
request.getPersons().clear();
}
},
request -> request.getPersons().isEmpty()
,
batchSize, "/Errors/p");
} catch (IOException e) {
throw new RuntimeException("Error while parsing MonitoringReportErrors", e);
}
log.info("Subject's errors were updated. PackageId: {}", packageId);
}
public List<UserPackage> findActivePackages(String userId) {
return userPackageService.findUserPackages(userId, Status.ON_MONITORING);
}
public List<UserPackage> findAllPackages(String userId) {
return userPackageService.findAllPackagesByUserId(userId);
}
public boolean isPackageExists(String username, String packageName) {
return userPackageService.isPackageExists(username, packageName, Status.ON_MONITORING);
}
public boolean isPackagesByStatusExist(String username, String packageName, Status status) {
return userPackageService.hasActivePackages(username, packageName, status);
}
public void deletePackage(String username, String packageName, LocalDateTime deactivatedAt) {
userPackageService.deletePackage(username, packageName, Status.DELETED, Status.ON_MONITORING, deactivatedAt);
}
@ -333,34 +195,15 @@ public class SignalService {
return userPackageService.findAllPackagesByStatus(Status.ON_MONITORING);
}
public List<UserPackage> findPackagesOnProcessing() {
return userPackageService.findAllPackagesByStatus(Status.PROCESSING);
public List<PhoneFidMap> findFullSubjectsData(Integer packageId) {
return phoneFidMapService.findFullPhoneFidMap(packageId);
}
public void insertHits(List<Hit> hits) {
hitsService.insertHits(hits);
}
public void updateLastDownloadedReport(Long id, String fileName) {
public void updateLastDownloadedReport(Integer id, String fileName) {
userPackageService.updatePackageLastDownloadedReport(id, fileName);
}
public PhoneFidMap findPhoneFidMapById(Long id) {
return phoneFidMapService.findPhoneFidMapById(id);
}
public boolean hasNonNullfids(Long packageId) {
return phoneFidMapService.hasNonNullfids(packageId);
}
public UserPackage findPackage(Long packageId) {
return userPackageService.findPackage(packageId);
}
@Getter
@AllArgsConstructor
public static class UpdateResult {
private boolean updated;
private boolean noFidsFound;
}
}

View file

@ -1,76 +0,0 @@
package ru.nbch.credit_tracker.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.config.mdc.SetAndClearMdc;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import ru.nbch.credit_tracker.enums.Status;
import ru.nbch.credit_tracker.service.signal.SignalRestService;
import java.util.List;
/**
* Сервис для завершения обработки пакетов находящихся в статусе PROCESSING
* Запускается при старте приложения и отрабатывает 1 раз
*/
@Slf4j
@Service
@EnableAspectJAutoProxy(exposeProxy = true)
public class UpdateProcessingPackagesService {
private UpdateProcessingPackagesService self;
private final SignalService signalService;
private final SignalRestService signalRestService;
private final MonitoringErrorProcesingService monitoringErrorProcesingService;
public UpdateProcessingPackagesService(SignalService signalService,
SignalRestService signalRestService,
MonitoringErrorProcesingService monitoringErrorProcesingService) {
this.signalService = signalService;
this.signalRestService = signalRestService;
this.monitoringErrorProcesingService = monitoringErrorProcesingService;
}
public void run() {
log.info("Start updating processing packages");
List<UserPackage> packages = signalService.findPackagesOnProcessing();
for (UserPackage userPackage : packages) {
log.info("Updating flags for Package {}", userPackage.getPackageName());
getCurrentProxy().process(userPackage.getId(), userPackage.getPackageName());
}
log.info("Finish updating processing packages");
}
@SetAndClearMdc(argIndex = 1)
public void process(Long packageId, String packageName) {
try {
SignalService.UpdateResult updateResult = signalService.updateSubjects(packageId, null);
if (updateResult.isNoFidsFound()) {
log.info("No fids found for PackageId: {} . Package status ON_MONITORING. No registration in signal service.", packageId);
signalService.updatePackageStatus(packageId, Status.ON_MONITORING);
return;
}
if (signalRestService.setupMonitoring(packageId)) {
log.info("Package was successfully registered in signal service. PackageId: {}", packageId);
signalService.updatePackageStatus(packageId, Status.ON_MONITORING);
monitoringErrorProcesingService.findErrors(packageId);
} else {
log.info("Package registration was rejected by signal service. PackageId: {}", packageId);
signalService.updatePackageStatus(packageId, Status.ERROR);
}
} catch (Exception e) {
signalService.updatePackageStatus(packageId, Status.ERROR);
log.error("Ошибка при поиске фидов или расчете флагов просрочек. Package_id {}", packageId, e);
}
}
private UpdateProcessingPackagesService getCurrentProxy() {
if (self == null) {
self = (UpdateProcessingPackagesService) AopContext.currentProxy();
}
return self;
}
}

View file

@ -1,82 +1,66 @@
package ru.nbch.credit_tracker.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import ru.nbch.credit_tracker.entities.signal_package.Signals;
import ru.nbch.credit_tracker.enums.Status;
import ru.nbch.credit_tracker.service.indic.PhoneService;
import ru.nbch.credit_tracker.service.signal.SignalRestService;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import ru.nbch.credit_tracker.enums.Status;
import ru.nbch.credit_tracker.mapper.signal.PhoneFidMapMapper;
import ru.nbch.credit_tracker.service.signal.SignalRestService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* Сервис периодического обновления фидов и флагов просрочек по пакетам находящимся в статусе ON_MONITORING
* По обновленным пакетам формируется новый запрос постановки на мониторинг в официальный сервис сигналов
*/
@Slf4j
@Service
public class UpdatingFlagsService {
private final SignalService signalService;
private final SignalRestService signalRestService;
private final MonitoringErrorProcesingService monitoringErrorProcesingService;
private final Long daysToUpdateFlags;
private final String updateFlagsCronExpression;
private final PhoneFidMapMapper phoneFidMapMapper;
private final Long updateFlagsInterval;
public UpdatingFlagsService(SignalService signalService,
SignalRestService signalRestService,
MonitoringErrorProcesingService monitoringErrorProcesingService,
CreditTrackerSettings config,
PhoneFidMapMapper phoneFidMapMapper) {
CreditTrackerSettings config) {
this.signalService = signalService;
this.signalRestService = signalRestService;
this.monitoringErrorProcesingService = monitoringErrorProcesingService;
this.daysToUpdateFlags = config.getDaysToUpdateFlags() != null ? config.getDaysToUpdateFlags() : 1;
this.updateFlagsCronExpression = config.getUpdateFlagsCronExpression() != null ? config.getUpdateFlagsCronExpression() : "*/10 * * * * *";
this.phoneFidMapMapper = phoneFidMapMapper;
this.updateFlagsInterval = config.getUpdateFlagsInterval() != null ? config.getUpdateFlagsInterval() : 1;
}
public void run() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(1);
scheduler.initialize();
scheduler.schedule(this::update, new CronTrigger(updateFlagsCronExpression));
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(this::update, 0, updateFlagsInterval, TimeUnit.DAYS);
}
public void update() {
private void update() {
log.info("Start updating flags");
List<UserPackage> packages = signalService.findPackagesOnMonitoring();
for (UserPackage userPackage : packages) {
MDC.put("ru.nbch.credit_tracker.log.mdc.key", "[" + userPackage.getPackageName() +"]");
log.info("Check on updating flags for Package {}", userPackage.getPackageName());
boolean hasOldRow = phoneFidMapMapper.hasOldRow(userPackage.getId(), daysToUpdateFlags.intValue());
log.info("There are {} old rows", hasOldRow ? "exist" : "doesn't exist");
if (hasOldRow) {
updateFlags(userPackage);
}
MDC.remove("ru.nbch.credit_tracker.log.mdc.key");
log.info("Updating flags for Package {}", userPackage.getPackageName());
List<PhoneFidMap> subjects = signalService.findFullSubjectsData(userPackage.getId())
.stream().filter(subject -> subject.getCalculatedAt() != null && hasDaysPassed(subject.getCalculatedAt())).toList();
updateFlags(userPackage.getId(), subjects, userPackage.getPackageName());
}
log.info("Finish updating flags");
}
private void updateFlags(UserPackage userPackage) {
Long packageId = userPackage.getId();
String packageName = userPackage.getPackageName();
private void updateFlags(Integer packageId, List<PhoneFidMap> subjects, String packageName) {
try {
signalService.updatePackageStatus(packageId, Status.PROCESSING);
SignalService.UpdateResult updateResult = signalService.updateSubjects(packageId, null);
if (updateResult.isUpdated()) {
if (signalRestService.setupMonitoring(packageId)) {
LocalDateTime monitoringAt = userPackage.getMonitoringAt() != null ? userPackage.getMonitoringAt() : LocalDateTime.now();
log.info("Flags were updated successfully. PackageId: {} PackageName: {} MonitoringAt: {}. Package status changed to ON_MONITORING", packageId, packageName, monitoringAt);
signalService.updatePackageOnMonitoringSuccess(packageId, monitoringAt);
monitoringErrorProcesingService.findErrors(packageId);
List<PhoneService.FidsPhoneData> phoneFidsData = signalService.updateFlags(subjects, packageId);
if (!phoneFidsData.isEmpty()) {
Signals signals = signalService.buildSignals(packageId, phoneFidsData);
if (signalRestService.update(signals)) {
log.info("Flags were updated successfully. PackageId: {} PackageName: {}. Package status changed to ON_MONITORING", packageId, packageName);
signalService.updatePackageStatus(packageId, Status.ON_MONITORING);
} else {
log.info("Updated package registration was rejected by signal service. PackageId: {} PackageName: {}", packageId, packageName);
signalService.updatePackageStatus(packageId, Status.ERROR);

View file

@ -70,27 +70,23 @@ public class PersonService {
}
private Map<Integer, PassportData> findPassportData(List<Integer> fids) {
Map<Integer, PassportData> resultMap = new HashMap<>();
Map<Integer, PassportData> passportDataMap = new HashMap<>();
List<PassportData> passports = mapper.findPassportData(fids);
Map<Integer, List<PassportData>> passportsMap = passports.stream()
.collect(Collectors.groupingBy(PassportData::getFid));
fids.forEach(fid -> {
PassportData passport = findPassport(passportsMap.get(fid));
PassportData passport = findPassport(passports.stream()
.filter(passportData -> passportData.getFid().equals(fid))
.collect(Collectors.toList()));
if (passport != null) {
resultMap.put(fid, passport);
passportDataMap.put(fid, passport);
}
});
return resultMap;
return passportDataMap;
}
private PassportData findPassport(List<PassportData> passports) {
if (passports == null || passports.isEmpty()) {
return null;
}
List<PassportData> documents = passports.stream()
.filter(this::isDUL)
.toList(); // берем только ДУЛ
@ -143,7 +139,7 @@ public class PersonService {
} catch (NumberFormatException e) {
idType2 = null;
}
return (idType != null && idType <= 30 && idType != 12) || (idType2 != null && (idType2 >= 1 || idType2 <= 999));
return (idType != null && idType <= 30) || (idType2 != null && (idType2 >= 1 || idType2 <= 999));
}
private boolean requiredFieldPresent(NameData nameData, PassportData passportData) {

View file

@ -1,5 +1,6 @@
package ru.nbch.credit_tracker.service.indic;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.springframework.stereotype.Service;
@ -7,10 +8,7 @@ import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
import ru.nbch.credit_tracker.mapper.indic.PhoneMapper;
import java.time.LocalDate;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
@Service
@ -22,13 +20,28 @@ public class PhoneService {
this.mapper = mapper;
}
/**
* Ищет фиды по номерам телефона
* @return Map: key - номер телефона; value - fid
*/
public Map<String, Integer> findFidsPhoneData(List<PhoneFidMap> subjects) {
List<String> phones = subjects.stream().map(subject -> "9" + subject.getPhone()).toList();
return convertFidsDataToMap(mapper.findFids(phones));
public List<FidsPhoneData> findFidsPhoneData(List<PhoneFidMap> subjects) {
List<FidsPhoneData> fidsPhoneDataList = new ArrayList<>();
int batchSize = 10000;
for (int i = 0; i < subjects.size(); i += batchSize) {
int end = Math.min(i + batchSize, subjects.size());
List<PhoneFidMap> currentSubjects = subjects.subList(i, end);
List<String> phones = currentSubjects.stream().map(subject -> "9" + subject.getPhone()).toList();
List<FidsData> fidsData = mapper.findFids(phones);
Map<String, Integer> fidsMap = convertFidsDataToMap(fidsData);
currentSubjects.forEach(subject -> {
String phone = "9" + subject.getPhone();
Integer fid = fidsMap.get(phone);
if (fid != null) {
fidsPhoneDataList.add(new FidsPhoneData(subject.getId(), fid, subject.getPhone(), subject.getSubjectId()));
} else {
fidsPhoneDataList.add(new FidsPhoneData(subject.getId(), null, subject.getPhone(), subject.getSubjectId()));
}
});
}
return fidsPhoneDataList;
}
private Map<String, Integer> convertFidsDataToMap(List<FidsData> fidsData) {
@ -48,6 +61,16 @@ public class PhoneService {
));
}
@Getter
@Setter
@AllArgsConstructor
public static class FidsPhoneData {
private Integer id;
private Integer fid;
private String phone;
private String subjectId;
}
@Getter
@Setter
public static class FidsData {

View file

@ -4,7 +4,6 @@ import jakarta.xml.bind.DatatypeConverter;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.enums.SignalError;
import ru.nbch.credit_tracker.mapper.scoring.ModelUsersMapper;
@ -14,23 +13,17 @@ import java.util.List;
@Service
public class AuthorizationService {
private static final String SGNL_CODE = "SGNL";
private static final String SALT = "-*-XUSER_";
private static final String SALT = "-*-XUSER_"; // TODO move salt to props?
private final ModelUsersMapper mapper;
private final String encoding;
public AuthorizationService(ModelUsersMapper mapper,
CreditTrackerSettings settings) {
public AuthorizationService(ModelUsersMapper mapper) {
this.mapper = mapper;
this.encoding = settings.getEncoding();
}
public AuthResult findAuthInfo(String userId, String password) throws Exception {
if (userId.length() > 12) {
return new AuthResult(false, SignalError.ERROR_005);
}
String hashedPassword = hashPassword(password);
List<String> productCodes = mapper.findUserProductCodes(userId, hashedPassword);
List<String> productCodes = mapper.findUserProductCodes(userId, hashedPassword); // TODO столбец username имеет ограничение на длину. Добавить обработку или валиться с 500?
if (productCodes.isEmpty()) {
return new AuthResult(false, SignalError.ERROR_005);
}
@ -43,7 +36,7 @@ public class AuthorizationService {
private String hashPassword(String password) throws Exception {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest((SALT + password).getBytes(encoding));
byte[] messageDigest = md.digest((SALT + password).getBytes("windows-1251"));
return DatatypeConverter.printHexBinary(messageDigest).toLowerCase();
} catch (Exception e) {
throw new Exception("Unable to hash password", e);

View file

@ -2,7 +2,7 @@ package ru.nbch.credit_tracker.service.signal;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
import ru.nbch.credit_tracker.entities.user_request.monitoring_request.Subject;
import ru.nbch.credit_tracker.entities.request.monitoring_request.Subject;
import ru.nbch.credit_tracker.mapper.signal.PhoneFidMapMapper;
import java.util.List;
@ -16,27 +16,19 @@ public class PhoneFidMapService {
this.mapper = mapper;
}
public void registerSubjects(List<Subject> subjects, Long packageId) {
public void registerSubjects(List<Subject> subjects, Integer packageId) {
mapper.registerSubjects(subjects, packageId);
}
public List<PhoneFidMap> findFullPhoneFidMap(Long packageId, int offset, int limit) {
return mapper.findFullPhoneFidMap(packageId, offset, limit);
public List<PhoneFidMap> findPhoneFidMaps(Integer packageId) {
return mapper.findPhoneFidMaps(packageId);
}
public List<PhoneFidMap> findFullPhoneFidMap(Integer packageId) {
return mapper.findFullPhoneFidMap(packageId);
}
public void updatePhoneFidMaps(List<PhoneFidMap> subjects) {
mapper.updatePhoneFidMaps(subjects);
}
public void updatePhoneFidMapsErrors(List<PhoneFidMap> subjects) {
mapper.updatePhoneFidMapsErrors(subjects);
}
public PhoneFidMap findPhoneFidMapById(Long id) {
return mapper.findPhoneFidMapById(id);
}
public boolean hasNonNullfids(Long packageId) {
return mapper.hasNonNullFids(packageId);
}
}

View file

@ -3,7 +3,7 @@ package ru.nbch.credit_tracker.service.signal;
import jakarta.xml.bind.DatatypeConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.FileUrlResource;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
@ -11,25 +11,17 @@ import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.external_response.errors.SgnlReport;
import ru.nbch.credit_tracker.entities.external_response.monitoring_report_file.SgnlReportMonitorigSetupError;
import ru.nbch.credit_tracker.entities.external_response.online_report.SgnlOnlineReport;
import ru.nbch.credit_tracker.service.SignalService;
import ru.nbch.credit_tracker.entities.response.external_errors.SgnlReport;
import ru.nbch.credit_tracker.entities.response.online_report.SgnlOnlineReport;
import ru.nbch.credit_tracker.entities.signal_package.Signals;
import ru.nbch.credit_tracker.service.xml.jaxb.IXmlProcessor;
import ru.nbch.credit_tracker.service.xml.stax.StaxXmlProcessor;
import ru.nbch.credit_tracker.utils.CTUtil;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.MessageDigest;
import java.util.Base64;
import java.util.UUID;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@Slf4j
@ -39,38 +31,25 @@ public class SignalRestService {
private static String UPDATE_URI = "update";
private static String DELETE_URI = "delete";
private static String GET_REPORTS_URI = "onlinereport";
private static String GET_REPORT_URI = "report";
private static String DOWNLOAD_REPORT_URI = "download";
private static String DOWNLOAD_ONLINE_REPORT_URI = "onlinedownload";
private static String DOWNLOAD_REPORT_URI = "onlinedownload";
private final RestTemplate restTemplate;
private final IXmlProcessor xmlProcessor;
private final StaxXmlProcessor staxProcessor;
private final SignalService signalService;
private final String authToken;
private final CreditTrackerSettings config;
public SignalRestService(@Qualifier(value = "restTemplate") RestTemplate restTemplate,
IXmlProcessor xmlProcessor,
StaxXmlProcessor staxProcessor,
SignalService signalService,
CreditTrackerSettings config) throws Exception {
this.restTemplate = restTemplate;
this.xmlProcessor = xmlProcessor;
this.staxProcessor = staxProcessor;
this.signalService = signalService;
this.config = config;
this.authToken = buildToken(config.getSignalsToken(), config.getSignalsuser());
}
/**
* Ставит пакет на мониторинг в официальный сервис сигналов
* @return true - если пакет успешно поставился на мониторинг. false - в противном случае
*/
public boolean setupMonitoring(Long packageId) throws Exception {
String path = signalService.writeSignals(packageId);
Resource request = compressFile(path);
public boolean update(Signals signals) throws Exception {
Resource request = compressFile(signals);
MultiValueMap<String, Resource> body = new LinkedMultiValueMap<>();
body.add("file", request);
@ -85,8 +64,6 @@ public class SignalRestService {
if (response.getStatusCode().value() == 302) {
// good response
CTUtil.removeFile(path);
CTUtil.removeFile(path + ".gz");
return true;
} else if (response.getStatusCode().value() == 200 && response.getBody() != null) {
SgnlReport error = staxProcessor.read(response.getBody(), SgnlReport.class);
@ -95,80 +72,11 @@ public class SignalRestService {
} else {
log.error("неизвестная ошибка при постановке пакета на мониторинг в официальный сервис сигналов: {}", response.getBody());
}
CTUtil.removeFile(path);
CTUtil.removeFile(path + ".gz");
return false;
}
return false;
}
/**
* @return имя файла с ошибками по поставленному на мониторинг отчету
*/
public String getErrorFileName(Long packageId, String packCode) {
String url = GET_REPORT_URI + "?packCode=" + packCode;
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(authToken);
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(headers);
ResponseEntity<String> response = restTemplate.exchange(
url,
HttpMethod.GET,
requestEntity,
String.class
);
String answer = response.getBody();
SgnlReport error = staxProcessor.read(answer, SgnlReport.class);
if (error.getError().getDescription() != null) {
log.error("Ошибка при получении имени файла ошибки из сервиса НБКИ. packCode={}. Описание: {}", packCode, error.getError().getDescription());
return null;
}
try {
SgnlReportMonitorigSetupError report = xmlProcessor.read(answer, SgnlReportMonitorigSetupError.class);
if (report.getOperationReport().getErrorsForNextReport() != null) {
String fileName = report.getOperationReport().getErrorsForNextReport().getFilename();
log.warn("Найдены ошибки по пакету. packCode={}, packageId={}, fileName = {}", packCode, packageId, fileName);
return fileName;
} else {
log.info("Пакет был поставлен на мониторинг без ошибок. packCode={}, packageId={}", packCode, packageId);
}
} catch (Exception e) {
log.error("Ошибка при получении имени файла ошибки из сервиса НБКИ. Код ошибки: {} packCode={}", response.getStatusCode().value(), packCode);
}
return null;
}
/**
* Загружает .gz отчет ошибок из официального сервиса сигналов, разархивирует в tmp_folder
*
* @return путь к разархивированному файлу. Пример: <loadDir>/tmp_folder/<package_id>/0001XX_MY_BATCH_223112.1.errors.xml.gz
*/
public String loadErrorFile(Long packageId, String fileName) {
String url = DOWNLOAD_REPORT_URI + "?fNameRequest=" + fileName;
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(authToken);
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(headers);
ResponseEntity<byte[]> response = restTemplate.exchange(
url,
HttpMethod.GET,
requestEntity,
byte[].class
);
return unzipReport(response, packageId, fileName);
}
/**
* Удаляет пакет с мониторинга
*/
public void deletePackage(String username, String packageName) {
String packCode = username.substring(0, 6) + "_" + packageName;
String url = DELETE_URI + "?packCode=" + packCode;
@ -191,9 +99,6 @@ public class SignalRestService {
}
}
/**
* @return Список отчетов, по которым сработали сигналы из официального сервиса сигналов
*/
public SgnlOnlineReport getReports(String packCode) {
String url = GET_REPORTS_URI + "?packCode=" + packCode;
@ -224,13 +129,8 @@ public class SignalRestService {
}
}
/**
* Загружает .gz отчет из официального сервиса сигналов, разархивирует в tmp_folder
*
* @return путь к разархивированному файлу. Пример: <loadDir>/tmp_folder/<package_id>/0001XX_MY_BATCH_204.1.online.2025-07-08T20-00-46.xml.gz.xml
*/
public String downloadReport(Long packageId, String reportName) {
String url = DOWNLOAD_ONLINE_REPORT_URI + "?fNameReport=" + reportName;
public byte[] downloadReport(String reportName) {
String url = DOWNLOAD_REPORT_URI + "?fNameReport=" + reportName;
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(authToken);
@ -244,41 +144,18 @@ public class SignalRestService {
byte[].class
);
return unzipReport(response,packageId, reportName);
}
private String unzipReport(ResponseEntity<byte[]> response, Long packageId, String reportName) {
boolean isGzipped = response.getHeaders().getContentType() != null
&& response.getHeaders().getContentType().toString().equals("application/x-gzip");
if (!isGzipped && isXmlError(response.getBody())) {
SgnlReport error = staxProcessor.read(response.getBody(), SgnlReport.class);
byte[] answer = response.getBody();
if (isXmlError(response.getBody())) {
SgnlReport error = staxProcessor.read(answer, SgnlReport.class);
if (error.getError().getDescription() != null) {
log.error("Ошибка при скачивание отчета. fNameReport={}. Описание: {}", reportName, error.getError().getDescription());
return null;
}
log.error("Неизвестная ошибка при скачивание отчета. fNameReport={}", reportName);
return null;
} else {
String folderPath = config.getLoadDir() + File.separator + "tmp_folder" + File.separator;
String filePath = folderPath + UUID.randomUUID() + reportName + ".xml";
CTUtil.createFolder(folderPath);
try (InputStream in = new GZIPInputStream(new ByteArrayInputStream(response.getBody()));
OutputStream out = Files.newOutputStream(Path.of(filePath))) {
byte[] buffer = new byte[8 * 1024 * 1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, bytesRead);
}
return filePath;
} catch (Exception e) {
log.error(e.getMessage(), e);
return null;
}
}
return answer;
}
private String buildToken(String signalsToken, String signalsuser) throws Exception {
@ -294,20 +171,20 @@ public class SignalRestService {
}
}
public Resource compressFile(String path) throws Exception {
try (InputStream in = Files.newInputStream(Path.of(path));
OutputStream out = Files.newOutputStream(Path.of(path + ".gz"));
GZIPOutputStream gzipOut = new GZIPOutputStream(out)) {
private Resource compressFile(Signals signals) throws Exception {
String requestData = xmlProcessor.asString(signals, false);
byte[] buffer = new byte[8 * 1024 * 1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) > 0) {
gzipOut.write(buffer, 0, bytesRead);
}
gzipOut.finish();
return new FileUrlResource(path + ".gz");
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
try (GZIPOutputStream gzipStream = new GZIPOutputStream(byteStream)) {
gzipStream.write(requestData.getBytes(Charset.forName("windows-1251")));
}
return new ByteArrayResource(byteStream.toByteArray()) {
@Override
public String getFilename() {
return "arhive.gz";
}
};
}
private boolean isXmlError(byte[] data) {

View file

@ -6,7 +6,6 @@ import ru.nbch.credit_tracker.enums.Status;
import ru.nbch.credit_tracker.mapper.signal.UserPackageMapper;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
@Service
@ -26,40 +25,28 @@ public class UserPackageService {
return mapper.isPackageExists(userId.substring(0, 6), packageName, status.name());
}
public boolean hasActivePackages(String userId, String packageName, Status... status) {
return mapper.hasActivePackages(userId.substring(0, 6), packageName, Arrays.stream(status).map(Enum::name).toList());
}
public void deletePackage(String userId, String packageName, Status newStatus, Status previousStatus, LocalDateTime deactivatedAt) {
mapper.deletePackage(userId.substring(0, 6), packageName, newStatus.name(), previousStatus.name(), deactivatedAt);
}
public Long insertPackage(UserPackage userPackage) {
public Integer insertPackage(UserPackage userPackage) {
return mapper.insertPackage(userPackage);
}
public void updatePackageStatus(Long packageId, Status status) {
public void updatePackageStatus(Integer packageId, Status status) {
mapper.updatePackageStatus(packageId, status.name());
}
public void updatePackageLastDownloadedReport(Long id, String fileName) {
public void updatePackageLastDownloadedReport(Integer id, String fileName) {
mapper.updatePackageLastDownloadedReport(id, fileName);
}
public void updatePackageOnMonitoringSuccess(Long id, LocalDateTime monitoringAt) {
mapper.updatePackageOnMonitoringSuccess(id, monitoringAt);
}
public UserPackage findPackage(Long id) {
public UserPackage findPackage(Integer id) {
return mapper.findPackage(id);
}
public List<UserPackage> findUserPackages(String userId, Status... status) {
return mapper.findUserPackages(userId.substring(0, 6), Arrays.stream(status).map(Enum::name).toList());
}
public List<UserPackage> findAllPackagesByUserId(String userId) {
return mapper.findAllPackagesByUserId(userId.substring(0, 6));
public List<UserPackage> findUserPackages(String userId, Status status) {
return mapper.findUserPackages(userId.substring(0, 6), status.name());
}
public List<UserPackage> findAllPackagesByStatus(Status status) {

View file

@ -6,76 +6,40 @@ import javax.xml.stream.XMLStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.function.Consumer;
import java.util.function.Function;
public abstract class BaseStaxReader<T> implements StaxReader<T> {
private final Deque<String> stack = new ArrayDeque<>();
protected final StringBuilder buffer = new StringBuilder();
protected abstract T createObject();
@Override
public T read(XMLStreamReader reader) throws XMLStreamException {
return read(reader, null, null, null, null);
}
public T read(XMLStreamReader reader, Consumer<T> objProcessor, Function<T, Boolean> emptyBatchCheckFunction, Integer batchSize, String endBatchElementPath) throws XMLStreamException {
T obj = createObject();
int objCount = 0;
try {
while (reader.hasNext()) {
boolean breakExecution = false;
int ev = reader.next();
switch (ev) {
case XMLStreamConstants.START_ELEMENT -> {
buffer.setLength(0);
startElement(reader.getLocalName());
innerProcessStartElement(reader, obj);
}
case XMLStreamConstants.CHARACTERS -> {
String text = reader.getText().trim();
if (!text.isEmpty()) buffer.append(text);
}
case XMLStreamConstants.ATTRIBUTE -> {
breakExecution = innerProcess(reader, obj);
}
case XMLStreamConstants.END_ELEMENT -> {
breakExecution = innerProcess(reader, obj);
String lastElementPath = getPath();
endElement();
if (objProcessor != null) {
if (endBatchElementPath.equals(lastElementPath)) {
objCount++;
if (objCount == batchSize) {
objProcessor.accept(obj); // обрабатываем пачку элементов
objCount = 0;
}
}
}
}
default -> {
}
while (reader.hasNext()) {
boolean breakExecution = false;
int ev = reader.next();
switch (ev) {
case XMLStreamConstants.START_ELEMENT -> {
buffer.setLength(0);
startElement(reader.getLocalName());
}
if (breakExecution) break;
}
if (objProcessor != null) {
if (emptyBatchCheckFunction == null) {
objProcessor.accept(obj); // Дополнительная обработка пачки если: batchSize меньше количества элементов в xml или дообрабатываем "хвост" меньший чем batchSize
} else if (!emptyBatchCheckFunction.apply(obj)) { // Проверка на пустоту пачки, чтобы не обрабатывать пустой список
objProcessor.accept(obj);
case XMLStreamConstants.CHARACTERS -> {
String text = reader.getText().trim();
if (!text.isEmpty()) buffer.append(text);
}
case XMLStreamConstants.END_ELEMENT -> {
breakExecution = innerProcess(reader, obj);
endElement();
}
default -> {}
}
return obj;
} catch (Exception e) {
stack.clear();
throw e;
if (breakExecution) break;
}
return obj;
}
protected abstract boolean innerProcess(XMLStreamReader reader, T obj) throws XMLStreamException;
protected abstract void innerProcessStartElement(XMLStreamReader reader, T obj) throws XMLStreamException;
public void startElement(String localName) {
localName = substringAfterColon(localName);

View file

@ -1,255 +0,0 @@
package ru.nbch.credit_tracker.service.xml.stax;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.Location;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import java.io.IOException;
import java.io.Writer;
public class IndentingXMLEventWriter implements XMLEventWriter {
private final XMLEventWriter core;
private String indent = " ";
private final Characters indentEvent = new CharactersImpl() {
public String getData() {
return IndentingXMLEventWriter.this.indent;
}
};
private String newLine;
private final Characters newLineEvent = new CharactersImpl() {
public String getData() {
return IndentingXMLEventWriter.this.newLine;
}
};
private int depth = 0;
private boolean hasText;
private boolean hasEndTag;
public IndentingXMLEventWriter(XMLEventWriter core) {
if (core == null) {
throw new IllegalArgumentException();
} else {
this.core = core;
try {
this.newLine = System.getProperty("line.separator");
} catch (SecurityException var3) {
this.newLine = "\n";
}
}
}
public String getIndent() {
return this.indent;
}
public void setIndent(String indent) {
if (indent == null) {
throw new IllegalArgumentException();
} else {
this.indent = indent;
}
}
public String getNewLine() {
return this.newLine;
}
public void setNewLine(String newLine) {
if (newLine == null) {
throw new IllegalArgumentException();
} else {
this.newLine = newLine;
}
}
public void add(XMLEvent event) throws XMLStreamException {
switch (event.getEventType()) {
case 1:
this.newLine();
this.core.add(event);
this.hasText = false;
this.hasEndTag = false;
++this.depth;
return;
case 2:
--this.depth;
if (!this.hasText && this.hasEndTag) {
this.newLine();
}
this.core.add(event);
this.hasText = false;
this.hasEndTag = true;
return;
case 3:
case 5:
case 11:
if (!this.hasText) {
this.newLine();
}
this.core.add(event);
return;
case 4:
case 6:
case 12:
if (event.asCharacters().isWhiteSpace()) {
return;
}
this.hasText = true;
this.core.add(event);
return;
case 7:
case 9:
case 10:
default:
this.core.add(event);
return;
case 8:
this.core.add(event);
this.flush();
}
}
private void newLine() throws XMLStreamException {
this.core.add(this.newLineEvent);
for (int i = 0; i < this.depth; ++i) {
this.core.add(this.indentEvent);
}
}
public void add(XMLEventReader reader) throws XMLStreamException {
if (reader == null) {
throw new IllegalArgumentException();
} else {
while (reader.hasNext()) {
this.add(reader.nextEvent());
}
}
}
public void close() throws XMLStreamException {
this.core.close();
}
public void flush() throws XMLStreamException {
this.core.flush();
}
public NamespaceContext getNamespaceContext() {
return this.core.getNamespaceContext();
}
public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
this.core.setNamespaceContext(context);
}
public String getPrefix(String uri) throws XMLStreamException {
return this.core.getPrefix(uri);
}
public void setDefaultNamespace(String uri) throws XMLStreamException {
this.core.setDefaultNamespace(uri);
}
public void setPrefix(String prefix, String uri) throws XMLStreamException {
this.core.setPrefix(prefix, uri);
}
private abstract static class CharactersImpl implements Characters {
private CharactersImpl() {
}
public boolean isWhiteSpace() {
return true;
}
public boolean isCData() {
return false;
}
public boolean isIgnorableWhiteSpace() {
return true;
}
public int getEventType() {
return 4;
}
public Location getLocation() {
return null;
}
public boolean isStartElement() {
return false;
}
public boolean isAttribute() {
return false;
}
public boolean isNamespace() {
return false;
}
public boolean isEndElement() {
return false;
}
public boolean isEntityReference() {
return false;
}
public boolean isProcessingInstruction() {
return false;
}
public boolean isCharacters() {
return true;
}
public boolean isStartDocument() {
return false;
}
public boolean isEndDocument() {
return false;
}
public StartElement asStartElement() {
return null;
}
public EndElement asEndElement() {
return null;
}
public Characters asCharacters() {
return this;
}
public QName getSchemaType() {
return null;
}
public void writeAsEncodedUnicode(Writer writer) throws XMLStreamException {
try {
writer.write(this.getData());
} catch (IOException var3) {
throw new XMLStreamException(var3);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show more