Storage. Начало. Уже скомпилируется.
This commit is contained in:
parent
29828d8f07
commit
e3e2a27a82
46 changed files with 2264 additions and 4 deletions
37
clearing-classes/pom.xml
Normal file
37
clearing-classes/pom.xml
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>clearing-classes</artifactId>
|
||||||
|
<name>Clearing classes</name>
|
||||||
|
<description>Clearing classes module</description>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<artifactId>clearing</artifactId>
|
||||||
|
<groupId>ru.spcex.clearing</groupId>
|
||||||
|
<version>SPCEX-1.0.0.0</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>com.moex.platform</groupId>-->
|
||||||
|
<!-- <artifactId>platform-common</artifactId>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>com.moex.platform</groupId>-->
|
||||||
|
<!-- <artifactId>platform-errors</artifactId>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package ru.clearing.classes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* В случае любых изменений модуля classes необходимо изменить serialVersionUID++
|
||||||
|
*/
|
||||||
|
public interface ConstSerializable {
|
||||||
|
long serialVersionUID = 293236453420L;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
package ru.clearing.classes.StaticData.Company;
|
||||||
|
|
||||||
|
import ru.clearing.classes.ConstSerializable;
|
||||||
|
import ru.clearing.classes.objects.BusinessObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Company extends BusinessObject {
|
||||||
|
private static final long serialVersionUID = ConstSerializable.serialVersionUID;
|
||||||
|
|
||||||
|
private String clearingCode;
|
||||||
|
private String exchangeCode;
|
||||||
|
private String fullName;
|
||||||
|
// private CompanyInfo profile; // todo impl profile
|
||||||
|
private Long statusId; // WorkflowStatusDictionary
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Company{" +
|
||||||
|
"clearingCode='" + clearingCode + '\'' +
|
||||||
|
", exchangeCode='" + exchangeCode + '\'' +
|
||||||
|
", fullName='" + fullName + '\'' +
|
||||||
|
", statusId=" + statusId +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClearingCode() {
|
||||||
|
return clearingCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClearingCode(String clearingCode) {
|
||||||
|
this.clearingCode = clearingCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExchangeCode() {
|
||||||
|
return exchangeCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExchangeCode(String exchangeCode) {
|
||||||
|
this.exchangeCode = exchangeCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFullName() {
|
||||||
|
return fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFullName(String fullName) {
|
||||||
|
this.fullName = fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getStatusId() {
|
||||||
|
return statusId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatusId(Long statusId) {
|
||||||
|
this.statusId = statusId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package ru.clearing.classes.StaticData.Company;
|
||||||
|
|
||||||
|
import ru.clearing.classes.ConstSerializable;
|
||||||
|
import ru.clearing.classes.objects.ObjectBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DB: COMPANY_ROLE_SET
|
||||||
|
*/
|
||||||
|
public class CompanyRoleSet extends ObjectBase {
|
||||||
|
private static final long serialVersionUID = ConstSerializable.serialVersionUID;
|
||||||
|
|
||||||
|
private Long roleId;
|
||||||
|
private Long companyId;
|
||||||
|
|
||||||
|
public Long getRoleId() {
|
||||||
|
return roleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoleId(Long roleId) {
|
||||||
|
this.roleId = roleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCompanyId() {
|
||||||
|
return companyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCompanyId(Long companyId) {
|
||||||
|
this.companyId = companyId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package ru.clearing.classes.StaticData.User;
|
||||||
|
|
||||||
|
|
||||||
|
import ru.clearing.classes.ConstSerializable;
|
||||||
|
import ru.clearing.classes.objects.BusinessObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Database table: USER_CLEARING todo name for user ?
|
||||||
|
*/
|
||||||
|
public class ClearingUser extends BusinessObject {
|
||||||
|
private static final long serialVersionUID = ConstSerializable.serialVersionUID;
|
||||||
|
|
||||||
|
// private String idpUuid;
|
||||||
|
//
|
||||||
|
// public ClearingUser() {
|
||||||
|
// super();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public String toString() {
|
||||||
|
// return String.format("%s{id=%d, idpUuid='%s'}", getClass().getSimpleName(), getId(), getIdpUuid());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public String getIdpUuid() {
|
||||||
|
// return idpUuid;
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package ru.clearing.classes.objects;
|
||||||
|
|
||||||
|
import ru.clearing.classes.ConstSerializable;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class BusinessEvent extends ObjectBase {
|
||||||
|
static final long serialVersionUID = ConstSerializable.serialVersionUID;
|
||||||
|
|
||||||
|
private Date eventTime;
|
||||||
|
|
||||||
|
public BusinessEvent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getEventTime() {
|
||||||
|
return eventTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEventTime(Date eventTime) {
|
||||||
|
this.eventTime = eventTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package ru.clearing.classes.objects;
|
||||||
|
|
||||||
|
import ru.clearing.classes.ConstSerializable;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UUID - Long based with field object
|
||||||
|
*/
|
||||||
|
public abstract class BusinessObject extends ObjectBase {
|
||||||
|
static final long serialVersionUID = ConstSerializable.serialVersionUID;
|
||||||
|
|
||||||
|
private Instant created;
|
||||||
|
private Instant updated;
|
||||||
|
|
||||||
|
public Instant getCreated() {
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreated(Instant created) {
|
||||||
|
this.created = created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getUpdated() {
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdated(Instant updated) {
|
||||||
|
this.updated = updated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
package ru.clearing.classes.objects;
|
||||||
|
|
||||||
|
import ru.clearing.classes.ConstSerializable;
|
||||||
|
import ru.clearing.common.interfaces.WithId;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Long ID - based primary key object
|
||||||
|
*/
|
||||||
|
public abstract class ObjectBase implements WithId, Serializable {
|
||||||
|
static final long serialVersionUID = ConstSerializable.serialVersionUID;
|
||||||
|
|
||||||
|
protected Long id;
|
||||||
|
public ObjectBase(){
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectBase(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Long getIdOrNull(WithId o) {
|
||||||
|
return o == null ? null : o.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s{id=%d}", getClass().getSimpleName(), getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
ObjectBase otcObject = (ObjectBase) o;
|
||||||
|
|
||||||
|
return id.equals(otcObject.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id.hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package ru.clearing.common.interfaces;
|
||||||
|
|
||||||
|
public interface WithId {
|
||||||
|
Long getId();
|
||||||
|
}
|
||||||
BIN
clearing-classes/target/dfa-classes-DFA-1.0.0.0.jar
Normal file
BIN
clearing-classes/target/dfa-classes-DFA-1.0.0.0.jar
Normal file
Binary file not shown.
4
clearing-classes/target/maven-archiver/pom.properties
Normal file
4
clearing-classes/target/maven-archiver/pom.properties
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
#Created by Apache Maven 3.6.3
|
||||||
|
groupId=ru.spcex.clearing
|
||||||
|
artifactId=clearing-classes
|
||||||
|
version=SPCEX-1.0.0.0
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
ru\clearing\classes\objects\ObjectBase.class
|
||||||
|
ru\clearing\classes\ConstSerializable.class
|
||||||
|
ru\clearing\classes\StaticData\Company\CompanyRoleSet.class
|
||||||
|
ru\clearing\classes\objects\BusinessEvent.class
|
||||||
|
ru\clearing\classes\StaticData\Company\Company.class
|
||||||
|
ru\clearing\classes\StaticData\User\ClearingUser.class
|
||||||
|
ru\clearing\common\interfaces\WithId.class
|
||||||
|
ru\clearing\classes\objects\BusinessObject.class
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
E:\MFD_GIT_REPO\clearing\clearing-classes\src\main\java\ru\clearing\classes\StaticData\User\ClearingUser.java
|
||||||
|
E:\MFD_GIT_REPO\clearing\clearing-classes\src\main\java\ru\clearing\classes\objects\ObjectBase.java
|
||||||
|
E:\MFD_GIT_REPO\clearing\clearing-classes\src\main\java\ru\clearing\classes\ConstSerializable.java
|
||||||
|
E:\MFD_GIT_REPO\clearing\clearing-classes\src\main\java\ru\clearing\classes\StaticData\Company\Company.java
|
||||||
|
E:\MFD_GIT_REPO\clearing\clearing-classes\src\main\java\ru\clearing\classes\objects\BusinessEvent.java
|
||||||
|
E:\MFD_GIT_REPO\clearing\clearing-classes\src\main\java\ru\clearing\classes\objects\BusinessObject.java
|
||||||
|
E:\MFD_GIT_REPO\clearing\clearing-classes\src\main\java\ru\clearing\classes\StaticData\Company\CompanyRoleSet.java
|
||||||
|
E:\MFD_GIT_REPO\clearing\clearing-classes\src\main\java\ru\clearing\common\interfaces\WithId.java
|
||||||
12
clearing-dictionary/.gitignore
vendored
Normal file
12
clearing-dictionary/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
*.iml
|
||||||
|
target
|
||||||
|
lib
|
||||||
|
.idea
|
||||||
|
*.log
|
||||||
|
temp
|
||||||
|
otc.logs_IS_UNDEFINED
|
||||||
|
.gitconfig
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
*/otc-test/src/test/resources/dataForDb/*.sql
|
||||||
|
**/out
|
||||||
|
preview
|
||||||
3
clearing-dictionary/CHANGELOG.md
Normal file
3
clearing-dictionary/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
1.0.0
|
||||||
|
------------------------------
|
||||||
|
-
|
||||||
118
clearing-dictionary/pom.xml
Normal file
118
clearing-dictionary/pom.xml
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>clearing-dictionary</artifactId>
|
||||||
|
<name>PLATFORM dictionary</name>
|
||||||
|
<description>PLATFORM dictionary</description>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<version>SPCEX-1.0.0.0</version>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<artifactId>clearing</artifactId>
|
||||||
|
<groupId>ru.spcex.clearing</groupId>
|
||||||
|
<version>SPCEX-1.0.0.0</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<external_libraries.junit-jupiter.version>5.4.2</external_libraries.junit-jupiter.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<!-- TEST -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
<version>${external_libraries.junit-jupiter.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.junit.vintage</groupId>
|
||||||
|
<artifactId>junit-vintage-engine</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>3.7</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- TEST -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.7.0</version>
|
||||||
|
<configuration>
|
||||||
|
<source>${project.java.version}</source>
|
||||||
|
<target>${project.java.version}</target>
|
||||||
|
<encoding>${project.build.sourceEncoding}</encoding>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>3.0.0-M5</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<addClasspath>true</addClasspath>
|
||||||
|
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||||
|
</manifest>
|
||||||
|
<manifestEntries>
|
||||||
|
<Built-By>${built.by}</Built-By>
|
||||||
|
</manifestEntries>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>3.2.0</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<addClasspath>true</addClasspath>
|
||||||
|
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||||
|
</manifest>
|
||||||
|
<manifestEntries>
|
||||||
|
<Built-By>${built.by}</Built-By>
|
||||||
|
</manifestEntries>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package ru.clearing.platform.dictionary;
|
||||||
|
|
||||||
|
public abstract class AbstractDictionary implements Dictionary {
|
||||||
|
static final long serialVersionUID = ConstDictionarySerializable.serialVersionUID;
|
||||||
|
|
||||||
|
protected Long id;
|
||||||
|
protected String name;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package ru.clearing.platform.dictionary;
|
||||||
|
|
||||||
|
public interface ConstDictionarySerializable {
|
||||||
|
long serialVersionUID = 7020097431335696640L;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package ru.clearing.platform.dictionary;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Словарь.
|
||||||
|
*/
|
||||||
|
public interface Dictionary extends Serializable {
|
||||||
|
|
||||||
|
Long getId();
|
||||||
|
|
||||||
|
void setId(Long id);
|
||||||
|
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
void setName(String id);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package ru.clearing.platform.dictionary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Database table: WORKFLOW_STATUS_DICTIONARY
|
||||||
|
*/
|
||||||
|
public class WorkflowStatusDictionary extends AbstractDictionary {
|
||||||
|
private static final long serialVersionUID = ConstDictionarySerializable.serialVersionUID;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
package ru.clearing.platform.dictionary.special;
|
||||||
|
|
||||||
|
import ru.clearing.platform.dictionary.ConstDictionarySerializable;
|
||||||
|
import ru.clearing.platform.dictionary.Dictionary;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DB table: COUNTRY_CODE_DICTIONARY
|
||||||
|
* Dictionary
|
||||||
|
*/
|
||||||
|
public class CountryCode implements Serializable, Dictionary {
|
||||||
|
static final long serialVersionUID = ConstDictionarySerializable.serialVersionUID;
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
private String countryCode;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("CountryCode{id=%d, countryCode='%s'}", id, countryCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCountryCode() {
|
||||||
|
return countryCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCountryCode(String countryCode) {
|
||||||
|
this.countryCode = countryCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
pom.xml
5
pom.xml
|
|
@ -15,6 +15,8 @@
|
||||||
<module>frontendapi</module>
|
<module>frontendapi</module>
|
||||||
<module>storage</module>
|
<module>storage</module>
|
||||||
<module>db-scripts</module>
|
<module>db-scripts</module>
|
||||||
|
<module>clearing-classes</module>
|
||||||
|
<module>clearing-dictionary</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
@ -27,6 +29,9 @@
|
||||||
<global.project.version>SPCEX-1.0.0.0</global.project.version>
|
<global.project.version>SPCEX-1.0.0.0</global.project.version>
|
||||||
|
|
||||||
<spring-boot.version>2.3.12.RELEASE</spring-boot.version>
|
<spring-boot.version>2.3.12.RELEASE</spring-boot.version>
|
||||||
|
|
||||||
|
<!-- IMDG -->
|
||||||
|
<external_libraries.hazelcast.version>3.12.4</external_libraries.hazelcast.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,6 @@
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-jdbc</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter</artifactId>
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
|
@ -29,6 +25,38 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ru.spcex.clearing</groupId>
|
||||||
|
<artifactId>clearing-classes</artifactId>
|
||||||
|
<version>SPCEX-1.0.0.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ru.spcex.clearing</groupId>
|
||||||
|
<artifactId>clearing-dictionary</artifactId>
|
||||||
|
<version>SPCEX-1.0.0.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- JDBC -->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-jdbc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.mchange</groupId>
|
||||||
|
<artifactId>c3p0</artifactId>
|
||||||
|
<version>0.9.5.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- IMDG для MapStore -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.hazelcast</groupId>
|
||||||
|
<artifactId>hazelcast-all</artifactId>
|
||||||
|
<version>${external_libraries.hazelcast.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<finalName>jar/${project.artifactId}</finalName>
|
<finalName>jar/${project.artifactId}</finalName>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
package ru.spcex.clearing.storage.base;
|
||||||
|
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import ru.clearing.classes.objects.BusinessEvent;
|
||||||
|
import ru.clearing.classes.objects.BusinessObject;
|
||||||
|
import ru.spcex.clearing.storage.utils.TimeUtil;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public abstract class BusinessEventMapStore<T extends BusinessEvent> extends ObjectBaseMapStore<T> {
|
||||||
|
|
||||||
|
public BusinessEventMapStore(JdbcTemplate jdbcTemplate) {
|
||||||
|
super(jdbcTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Iterable<Long> loadAllKeys() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final T load(Long id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Collection<T> load(Collection<Long> keys) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Map<Long, T> loadAll(Collection<Long> keys) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Заполняет поля:<br>
|
||||||
|
* uuid<br>
|
||||||
|
* eventTime<br>
|
||||||
|
* ownerId<br>
|
||||||
|
* eventTypeId
|
||||||
|
*
|
||||||
|
* @param businessEvent объект для заполнения
|
||||||
|
* @param rs resultSet для выгрузки
|
||||||
|
*/
|
||||||
|
public void fillBusinessEventFields(BusinessEvent businessEvent, ResultSet rs) throws SQLException {
|
||||||
|
businessEvent.setEventTime(TimeUtil.toUtilDate(rs.getDate("eventtime")));
|
||||||
|
businessEvent.setId(getLong(rs, "id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fillBusinessObjectFieds(BusinessObject businessObject, ResultSet rs) throws SQLException {
|
||||||
|
businessObject.setId(rs.getObject("orderbondid", Long.class));
|
||||||
|
businessObject.setUpdated(TimeUtil.fromDate(rs.getDate("updated")));
|
||||||
|
businessObject.setCreated(TimeUtil.fromDate(rs.getDate("created")));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package ru.spcex.clearing.storage.base;
|
||||||
|
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import ru.clearing.classes.objects.BusinessObject;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Шаблон для загрузки <code>BusinessObject</code>-ов.
|
||||||
|
*/
|
||||||
|
public abstract class BusinessObjectMapStore<T extends BusinessObject> extends ObjectBaseMapStore<T> {
|
||||||
|
|
||||||
|
public BusinessObjectMapStore(JdbcTemplate jdbcTemplate) {
|
||||||
|
super(jdbcTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Заполняет стандартные поля для BusinessObject из ResultSet
|
||||||
|
*
|
||||||
|
* @param businessObject дозаполнить стандартные поля этому объекту
|
||||||
|
* @param rs из ResultSet
|
||||||
|
* @throws SQLException - error
|
||||||
|
*/
|
||||||
|
protected void fillBusinessObjectFields(BusinessObject businessObject, ResultSet rs) throws SQLException {
|
||||||
|
fillBusinessObjectFields(businessObject, rs, "id");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void fillBusinessObjectFields(BusinessObject businessObject, ResultSet rs, String idName) throws SQLException {
|
||||||
|
businessObject.setUpdated(getInstantFromTimestamp(rs, "updated"));
|
||||||
|
businessObject.setCreated(getInstantFromTimestamp(rs, "created"));
|
||||||
|
businessObject.setId(getLong(rs, idName));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
package ru.spcex.clearing.storage.base;
|
||||||
|
|
||||||
|
import com.hazelcast.core.MapLoader;
|
||||||
|
import ru.clearing.platform.dictionary.Dictionary;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.dao.support.DataAccessUtils;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static ru.spcex.clearing.storage.base.ObjectBaseMapStore.MAX_IN_CLAUSE_SIZE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store для словарей стандартных - из ID, NAME.
|
||||||
|
*/
|
||||||
|
public abstract class DictionaryMapStore<T extends Dictionary> implements MapLoader<Long, T> {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(DictionaryMapStore.class);
|
||||||
|
|
||||||
|
protected NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||||
|
|
||||||
|
protected final JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
protected DictionaryMapStore(JdbcTemplate jdbcTemplate) {
|
||||||
|
this.jdbcTemplate = jdbcTemplate;
|
||||||
|
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getTableName();
|
||||||
|
|
||||||
|
public abstract T getDictionaryObject();
|
||||||
|
|
||||||
|
protected T mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||||
|
T dictionary = getDictionaryObject();
|
||||||
|
dictionary.setId(rs.getLong("id"));
|
||||||
|
dictionary.setName(rs.getString("name"));
|
||||||
|
return dictionary;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<T> loadCollection(Collection<Long> keys) {
|
||||||
|
Map<String, Collection<Long>> paramMap = Collections.singletonMap("ids", keys);
|
||||||
|
return namedParameterJdbcTemplate.query("select * from " + getTableName() + " where id in (:ids)", paramMap, this::mapRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T load(Long id) {
|
||||||
|
Collection<T> rows;
|
||||||
|
List<Long> list = Collections.singletonList(id);
|
||||||
|
try {
|
||||||
|
rows = loadCollection(list);
|
||||||
|
} catch (Throwable e) { // one retry
|
||||||
|
log.trace("Retry load after {}", e.toString());
|
||||||
|
rows = loadCollection(list);
|
||||||
|
}
|
||||||
|
return DataAccessUtils.singleResult(rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Long, T> loadAll(Collection<Long> keys) {
|
||||||
|
log.trace("loadAll from dictionary {} {} keys", getTableName(), keys.size());
|
||||||
|
Map<Long, T> result = new HashMap<>();
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// загрузить данные по ключам частями, чтобы не выйти за ограничения базы по кол-ву элементов в in clause
|
||||||
|
List<Long> keysSubList = new ArrayList<>(MAX_IN_CLAUSE_SIZE);
|
||||||
|
for (Iterator<Long> iterator = keys.iterator(); iterator.hasNext(); ) {
|
||||||
|
Long key = iterator.next();
|
||||||
|
keysSubList.add(key);
|
||||||
|
if (keysSubList.size() == MAX_IN_CLAUSE_SIZE || !iterator.hasNext()) {
|
||||||
|
Collection<T> rows = loadCollection(keysSubList);
|
||||||
|
for (T row : rows) {
|
||||||
|
result.put(row.getId(), row);
|
||||||
|
}
|
||||||
|
keysSubList.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.trace("loadAll from dictionary {} {} keys done in {} ms", getTableName(), keys.size(), (System.currentTimeMillis() - start));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<Long> loadAllKeys() {
|
||||||
|
log.debug("loadAllKeys from " + getTableName());
|
||||||
|
return jdbcTemplate.query("select id from " + getTableName(), (rs, rowNum) -> rs.getLong("id"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
package ru.spcex.clearing.storage.base;
|
||||||
|
|
||||||
|
import com.hazelcast.core.HazelcastInstance;
|
||||||
|
import com.hazelcast.core.MapLoaderLifecycleSupport;
|
||||||
|
import com.hazelcast.core.MapStore;
|
||||||
|
//import com.opencsv.CSVWriter;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
import ru.clearing.classes.objects.ObjectBase;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MapStore записывающий изменения в файл
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
|
public abstract class LoggingMapStore<T extends ObjectBase> implements MapStore<Long, T>, MapLoaderLifecycleSupport {
|
||||||
|
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
// private CSVWriter csvWriter; todo подключить OpenCSV и настройку про логирование данных добавить
|
||||||
|
|
||||||
|
// private Supplier<String> recoveryPath = () -> DfaConfig.get().getRoot().getSettings().getRecoveryLogPath();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(HazelcastInstance hazelcastInstance, Properties properties, String mapName) {
|
||||||
|
// try {
|
||||||
|
// String recoveryLogPath = recoveryPath.get();
|
||||||
|
// if (recoveryLogPath != null) {
|
||||||
|
// SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||||
|
// File recoveryDir = new File(recoveryLogPath + File.separator + simpleDateFormat.format(new Date()));
|
||||||
|
// recoveryDir.mkdirs();
|
||||||
|
// File recoveryFile = new File(recoveryDir, getTableName() + ".csv");
|
||||||
|
// csvWriter = new CSVWriter(new BufferedWriter(new FileWriter(recoveryFile)), ';');
|
||||||
|
// log.info("recovery log started {}", recoveryFile);
|
||||||
|
// }
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// log.error("", e);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void setRecoveryPath(Supplier<String> recoveryPath) {
|
||||||
|
// this.recoveryPath = recoveryPath;
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
// try {
|
||||||
|
// if (csvWriter != null)
|
||||||
|
// csvWriter.close();
|
||||||
|
// } catch (IOException e) {
|
||||||
|
// log.error("", e);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getTableName();
|
||||||
|
|
||||||
|
protected void logHeaders(@NonNull String[] headers) {
|
||||||
|
try {
|
||||||
|
// if (csvWriter != null) {
|
||||||
|
// csvWriter.writeNext(headers);
|
||||||
|
// csvWriter.flush();
|
||||||
|
// }
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void logValues(@NonNull List<Object[]> valuesList) {
|
||||||
|
try {
|
||||||
|
// if (csvWriter != null) {
|
||||||
|
// for (Object[] values : valuesList) {
|
||||||
|
// String[] nextLine = new String[values.length];
|
||||||
|
// for (int i = 0; i < values.length; i++) {
|
||||||
|
// nextLine[i] = String.valueOf(values[i]);
|
||||||
|
// }
|
||||||
|
// csvWriter.writeNext(nextLine);
|
||||||
|
// }
|
||||||
|
// csvWriter.flush();
|
||||||
|
// }
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,174 @@
|
||||||
|
package ru.spcex.clearing.storage.base;
|
||||||
|
import org.springframework.dao.support.DataAccessUtils;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||||
|
import ru.clearing.classes.objects.ObjectBase;
|
||||||
|
import ru.spcex.clearing.storage.utils.DbUtilsHelper;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public abstract class ObjectBaseMapStore<T extends ObjectBase> extends SimpleObjectMapStore<T> {
|
||||||
|
/**
|
||||||
|
* См. legalEntityProfileToSQLArgs()
|
||||||
|
*/
|
||||||
|
protected static final String LEGAL_ENTITY_PROFILE_STATEMENT_ARGUMENT =
|
||||||
|
"description, domicilecountrycodeid, isprofessional, organizationtypeid, ogrn, name," +
|
||||||
|
" fullname, nameeng, fullnameeng, kpp, contactphone, contactemail, tsedallowedid, edomail," +
|
||||||
|
" nsdallowedid, otcmonitorallowedid, otcmonitorobligedid";
|
||||||
|
|
||||||
|
protected static final String insertChargeDefinitionStatement = DbUtilsHelper.fillValuesBlock(
|
||||||
|
"UPDATE OR INSERT INTO CHARGEDEFINITION (id, chargeamount, chargedirectionid, " +
|
||||||
|
" chargesettlementamount, chargetypeid, netincluded, currencycodeid, moexexchangecommission, userid, partyid)" +
|
||||||
|
" values %values_block% matching (id);"
|
||||||
|
);
|
||||||
|
public static final int MAX_IN_CLAUSE_SIZE = 1000;
|
||||||
|
|
||||||
|
protected NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||||
|
|
||||||
|
public ObjectBaseMapStore(JdbcTemplate jdbcTemplate) {
|
||||||
|
super(jdbcTemplate);
|
||||||
|
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
|
||||||
|
// this.jdbcTemplate = jdbcTemplate;
|
||||||
|
// this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T load(Long id) {
|
||||||
|
if (!isLoadable(id)) return null;
|
||||||
|
Collection<T> rows;
|
||||||
|
List<Long> list = Collections.singletonList(id);
|
||||||
|
try {
|
||||||
|
rows = load(list);
|
||||||
|
} catch (Throwable e) { // one retry
|
||||||
|
rows = load(list);
|
||||||
|
}
|
||||||
|
T obj = DataAccessUtils.singleResult(rows);
|
||||||
|
if (obj != null && isLoadable(obj))
|
||||||
|
return obj;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isLoadable(Long id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isLoadable(T obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Long, T> loadAll(Collection<Long> keys) {
|
||||||
|
log.debug("loadAll from " + getTableName() + " " + keys.size() + " keys");
|
||||||
|
Map<Long, T> result = new HashMap<>();
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// загрузить данные по ключам частями, чтобы не выйти за ограничения базы по кол-ву элементов в in clause
|
||||||
|
List<Long> keysSubList = new ArrayList<>(MAX_IN_CLAUSE_SIZE);
|
||||||
|
for (Iterator<Long> iterator = keys.iterator(); iterator.hasNext(); ) {
|
||||||
|
Long key = iterator.next();
|
||||||
|
keysSubList.add(key);
|
||||||
|
if (keysSubList.size() == MAX_IN_CLAUSE_SIZE || !iterator.hasNext()) {
|
||||||
|
Collection<T> rows = load(keysSubList);
|
||||||
|
for (T row : rows) {
|
||||||
|
result.put(row.getId(), row);
|
||||||
|
}
|
||||||
|
keysSubList.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("loadAll from " + getTableName() + " " + keys.size() + " keys done in " + (System.currentTimeMillis() - start) + "ms");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Collection<T> load(Collection<Long> keys);
|
||||||
|
|
||||||
|
protected Long getLong(ResultSet rs, String columnName) throws SQLException {
|
||||||
|
return rs.getObject(columnName, Long.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Instant getInstantFromTimestamp(ResultSet rs, String column) throws SQLException {
|
||||||
|
Timestamp date = rs.getTimestamp(column);
|
||||||
|
return date != null ? date.toInstant() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* todo реfакторинг:
|
||||||
|
protected LegalEntityProfile getLegalEntityProfile(Long id) {
|
||||||
|
if (id == null)
|
||||||
|
return null;
|
||||||
|
List<LegalEntityProfile> results = jdbcTemplate.query(
|
||||||
|
"SELECT * FROM legalentityprofile WHERE id = ?", new Object[]{id},
|
||||||
|
(rs, rowNum) -> {
|
||||||
|
LegalEntityProfile legalEntityProfile = new LegalEntityProfile();
|
||||||
|
legalEntityProfile.setDescription(rs.getString("description"));
|
||||||
|
legalEntityProfile.setDomicileCountryCodeId(rs.getObject("domicilecountrycodeid", Long.class));
|
||||||
|
legalEntityProfile.setProfessional(rs.getObject("isprofessional", Boolean.class));
|
||||||
|
legalEntityProfile.setOrganizationTypeId(rs.getObject("organizationtypeid", Long.class));
|
||||||
|
legalEntityProfile.setOgrn(rs.getString("ogrn"));
|
||||||
|
legalEntityProfile.setShortName(rs.getString("name"));
|
||||||
|
legalEntityProfile.setFullName(rs.getString("fullname"));
|
||||||
|
legalEntityProfile.setNameEng(rs.getString("nameeng"));
|
||||||
|
legalEntityProfile.setFullNameEng(rs.getString("fullnameeng"));
|
||||||
|
legalEntityProfile.setKpp(rs.getString("kpp"));
|
||||||
|
legalEntityProfile.setContactPhone(rs.getString("contactphone"));
|
||||||
|
legalEntityProfile.setContactEMail(rs.getString("contactemail"));
|
||||||
|
legalEntityProfile.setTsedAllowedId(rs.getObject("tsedallowedid", Long.class));
|
||||||
|
legalEntityProfile.setEdoMail(rs.getString("edomail"));
|
||||||
|
legalEntityProfile.setNsdAllowedId(rs.getObject("nsdallowedid", Long.class));
|
||||||
|
legalEntityProfile.setOtcMonitorAllowedId(rs.getObject("otcmonitorallowedid", Long.class));
|
||||||
|
legalEntityProfile.setOtcMonitorObligedId(rs.getObject("otcmonitorobligedid", Long.class));
|
||||||
|
legalEntityProfile.setId(getLong(rs, "id"));
|
||||||
|
return legalEntityProfile;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
LegalEntityProfile onceObject = DataAccessUtils.singleResult(results);
|
||||||
|
if (onceObject == null) {
|
||||||
|
log.warn("No row in table legalentityprofile where id={}. Create empty ", id);
|
||||||
|
onceObject = new LegalEntityProfile();
|
||||||
|
onceObject.setId(id); // чтобы не потерять id
|
||||||
|
}
|
||||||
|
return onceObject;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Без ID перечисление значений полей LegalEntityProfile.
|
||||||
|
// * См. LegalentityprofileStatementArgument
|
||||||
|
// *
|
||||||
|
// * @param legalEntityProfile
|
||||||
|
// * @return
|
||||||
|
// */
|
||||||
|
// protected List<Object> legalEntityProfileToSQLArgs(@NonNull LegalEntityProfile legalEntityProfile) {
|
||||||
|
// List<Object> legalEntityArgs = new ArrayList<>(Arrays.asList(
|
||||||
|
//// legalEntityProfile.getId(),
|
||||||
|
// legalEntityProfile.getDescription(),
|
||||||
|
// legalEntityProfile.getDomicileCountryCodeId(),
|
||||||
|
// legalEntityProfile.getProfessional(),
|
||||||
|
// legalEntityProfile.getOrganizationTypeId(),
|
||||||
|
// legalEntityProfile.getOgrn(),
|
||||||
|
// legalEntityProfile.getShortName(),
|
||||||
|
// legalEntityProfile.getFullName(),
|
||||||
|
// legalEntityProfile.getNameEng(),
|
||||||
|
// legalEntityProfile.getFullNameEng(),
|
||||||
|
// legalEntityProfile.getKpp(),
|
||||||
|
// legalEntityProfile.getContactPhone(),
|
||||||
|
// legalEntityProfile.getContactEMail(),
|
||||||
|
// legalEntityProfile.getTsedAllowedId(),
|
||||||
|
// legalEntityProfile.getEdoMail(),
|
||||||
|
// legalEntityProfile.getNsdAllowedId(),
|
||||||
|
// legalEntityProfile.getOtcMonitorAllowedId(),
|
||||||
|
// legalEntityProfile.getOtcMonitorObligedId()
|
||||||
|
// ));
|
||||||
|
// return legalEntityArgs;
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,200 @@
|
||||||
|
package ru.spcex.clearing.storage.base;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.SqlTypeValue;
|
||||||
|
import org.springframework.jdbc.core.StatementCreatorUtils;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
import ru.clearing.classes.objects.ObjectBase;
|
||||||
|
import ru.spcex.clearing.storage.utils.BigDecimalUtil;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.sql.Types;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MapStore для выгрузки обычных объектов
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
|
public abstract class SimpleObjectMapStore<T extends ObjectBase> extends LoggingMapStore<T>
|
||||||
|
{
|
||||||
|
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
protected SimpleDateFormat FIREBIRD_DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd"); // не делать static.
|
||||||
|
protected final JdbcTemplate jdbcTemplate;
|
||||||
|
private final int bathSize = 1000;
|
||||||
|
|
||||||
|
protected SimpleObjectMapStore(JdbcTemplate jdbcTemplate) {
|
||||||
|
this.jdbcTemplate = jdbcTemplate;
|
||||||
|
logHeaders(getFields());
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getTableName();
|
||||||
|
|
||||||
|
public abstract String[] getFields();
|
||||||
|
|
||||||
|
private boolean oidIsPresentInTheFields = Arrays.stream(getFields()).anyMatch(anotherString -> {
|
||||||
|
if (anotherString == null) return false;
|
||||||
|
return "oid".equalsIgnoreCase(anotherString.trim());
|
||||||
|
});
|
||||||
|
|
||||||
|
public boolean deleteIsSupported() {
|
||||||
|
return !oidIsPresentInTheFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void store(Long id, T o) {
|
||||||
|
log.debug("store {} {} {}", getTableName(), id, o);
|
||||||
|
Map<Long, T> map = new HashMap<>();
|
||||||
|
map.put(id, o);
|
||||||
|
store(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void storeAll(Map<Long, T> map) {
|
||||||
|
log.debug("storeAll {} {}", getTableName(), map);
|
||||||
|
store(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void store(Map<Long, T> map);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(Long id) {
|
||||||
|
if (deleteIsSupported()) {
|
||||||
|
defaultDelete(id);
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException("delete not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteAll(Collection<Long> collection) {
|
||||||
|
if (deleteIsSupported()) {
|
||||||
|
deleteAllShowNotDeleted(collection);
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException("deleteAll not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void defaultDelete(Long id) {
|
||||||
|
ArrayList<Long> list = new ArrayList<>();
|
||||||
|
list.add(id);
|
||||||
|
deleteAll(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteAllShowNotDeleted(Collection<Long> collection) {
|
||||||
|
List<Object[]> listOfID = new ArrayList<>(collection.size());
|
||||||
|
for (Long id : collection)
|
||||||
|
listOfID.add(new Object[]{id});
|
||||||
|
try {
|
||||||
|
jdbcTemplate.batchUpdate("DELETE FROM " + getTableName() + " WHERE id=?", listOfID);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("SQL error at batch DELETE FROM {}\n{}", getTableName(), ExceptionUtils.getStackTrace(e));
|
||||||
|
log.info("List of non deleted ID {}", collection); // показать список неудалённых UUID
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract T load(Long id);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Long, T> loadAll(Collection<Long> keys) {
|
||||||
|
Map<Long, T> result = new HashMap<>();
|
||||||
|
for (Long key : keys) {
|
||||||
|
result.put(key, load(key));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<Long> loadAllKeys() {
|
||||||
|
log.debug("loadAllKeys from " + getTableName());
|
||||||
|
List<Long> keys;
|
||||||
|
try {
|
||||||
|
keys = jdbcTemplate.query("select id from " + getTableName(), (resultSet, i) -> resultSet.getLong("id"));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
log.error("{}", ExceptionUtils.getStackTrace(e));
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Загружает ключи только за текущий день.
|
||||||
|
* <code>where CAST(tradingday as DATE) = ?</code>
|
||||||
|
* Осторожно со знаком: в некоторых случаях требуется за текущий и будущие дни, тогда этот метод не подходит.
|
||||||
|
* См. так же loadAllKeys().
|
||||||
|
*
|
||||||
|
* @return список id
|
||||||
|
*/
|
||||||
|
protected List<Long> defaultLoadAllKeysOnTradingDay() {
|
||||||
|
log.debug("loadAllKeys from " + getTableName());
|
||||||
|
return jdbcTemplate.query("select id from " + getTableName() + " where CAST(tradingday as DATE) = ?",
|
||||||
|
new Object[]{FIREBIRD_DATE_FORMATTER.format(new Date())},
|
||||||
|
(resultSet, i) -> resultSet.getObject("id", Long.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void batchInsertUpdate(@NonNull String insertStatement, @NonNull List<Object[]> args) {
|
||||||
|
try {
|
||||||
|
logValues(args);
|
||||||
|
int[][] ret = jdbcTemplate.batchUpdate(insertStatement, args, bathSize, (ps, params) -> {
|
||||||
|
for (int i = 0; i < params.length; i++) {
|
||||||
|
int type = ps.getParameterMetaData().getParameterType(i + 1);
|
||||||
|
Object value = params[i];
|
||||||
|
if (value != null) {
|
||||||
|
if ((type == Types.VARCHAR || type == Types.CHAR) && value instanceof String) {
|
||||||
|
String stringValue = (String) value;
|
||||||
|
int length = ps.getParameterMetaData().getPrecision(i + 1);
|
||||||
|
if (stringValue.length() > length) {
|
||||||
|
value = stringValue.substring(0, length);
|
||||||
|
log.error("String value for insert is too large [ insertSql: {}, params: {}, incorrect value : {}, normalized value: {} ]",
|
||||||
|
insertStatement, Arrays.toString(params), stringValue, value);
|
||||||
|
}
|
||||||
|
} else if ((type == Types.DECIMAL || type == Types.NUMERIC) && value instanceof BigDecimal) {
|
||||||
|
BigDecimal bigDecimalValue = (BigDecimal) value;
|
||||||
|
int dbScalePartLength = ps.getParameterMetaData().getScale(i + 1);
|
||||||
|
int precision = ps.getParameterMetaData().getPrecision(i + 1);
|
||||||
|
if (!BigDecimalUtil.checkSize(bigDecimalValue, precision, dbScalePartLength)) {
|
||||||
|
value = BigDecimalUtil.genMaxValueForInsert(precision, dbScalePartLength);
|
||||||
|
log.error("BigDecimal value for insert is too large [ insertSql: {}, params: {}, incorrect value : {}, normalized value: {} ]",
|
||||||
|
insertStatement, Arrays.toString(params), bigDecimalValue, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//в batchUpdate(String sql, List<Object[]> batchArgs), как типа поля всегда передавался SqlTypeValue.TYPE_UNKNOWN,
|
||||||
|
//см. BatchUpdateUtils.setStatementParameters
|
||||||
|
try {
|
||||||
|
StatementCreatorUtils.setParameterValue(ps, i + 1, SqlTypeValue.TYPE_UNKNOWN, value);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new SQLException("batchInsertUpdate, at prepare argument " + i + " value = " + value + "; SQL=" + insertStatement, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
int batchSize = ret.length > 0 ? ret[0].length : ret.length;
|
||||||
|
log.debug("{} {} rows stored", getTableName(), batchSize);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("SQL error at batch UPDATE OR INSERT INTO {}\n{}", getTableName(), ExceptionUtils.getStackTrace(e));
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Instant getInstantFromTimestamp(ResultSet rs, String column) throws SQLException {
|
||||||
|
Timestamp date = rs.getTimestamp(column);
|
||||||
|
return date != null ? date.toInstant() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Timestamp timestampFromInstant(Instant instant) {
|
||||||
|
if (instant == null) return null;
|
||||||
|
return Timestamp.from(instant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package ru.spcex.clearing.storage.config;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Корневой элемент конфигурации
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings("DefaultAnnotationParam")
|
||||||
|
public class ConfigurationRootElement /*extends ConfigurationRootBaseElement*/ {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Конфигурация БД
|
||||||
|
*/
|
||||||
|
// @JsonProperty(value = "Database", required = true)
|
||||||
|
private SettingsElementDatabase database = new SettingsElementDatabase();
|
||||||
|
|
||||||
|
// @JsonProperty(value = "Settings", required = false)
|
||||||
|
private SettingsElement settings = new SettingsElement();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Конфигурация Hazelcast
|
||||||
|
*/
|
||||||
|
// @JsonProperty(value = "HazelcastServer", required = true)
|
||||||
|
// private HazelcastServerElement hazelcast = new HazelcastServerElement();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Конфигурация сервисов Core
|
||||||
|
*/
|
||||||
|
// @JsonProperty(value = "Services")
|
||||||
|
private ServicesElement servicesElement = new ServicesElement();
|
||||||
|
|
||||||
|
public SettingsElementDatabase getDatabase() {
|
||||||
|
return database;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public HazelcastServerElement getHazelcast() {
|
||||||
|
// return hazelcast;
|
||||||
|
// }
|
||||||
|
|
||||||
|
public SettingsElement getSettings() {
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServicesElement getServicesElement() {
|
||||||
|
return servicesElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
package ru.spcex.clearing.storage.config;
|
||||||
|
|
||||||
|
import com.mchange.v2.c3p0.ComboPooledDataSource;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import ru.spcex.clearing.storage.error.ModuleInitializeException;
|
||||||
|
import ru.spcex.clearing.storage.utils.DbDefaultConfig;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.sql.Connection;
|
||||||
|
|
||||||
|
@SuppressWarnings("UnnecessaryLocalVariable")
|
||||||
|
@Configuration
|
||||||
|
public class DbConnectionConfig {
|
||||||
|
private Logger log = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
private ConfigurationRootElement configRoot = DfaConfig.get().getRoot();
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DataSource dataSource() /*fixme why: throws PropertyVetoException*/ {
|
||||||
|
DataSource result;
|
||||||
|
String login = configRoot.getDatabase().getLogin();
|
||||||
|
String password = configRoot.getDatabase().getPassword();
|
||||||
|
String logTimeoutPart = "";
|
||||||
|
String dbPath;
|
||||||
|
if (StringUtils.isEmpty(configRoot.getDatabase().getEmbeddedFilePath())) {
|
||||||
|
dbPath = configRoot.getDatabase().getJdbcConnectionString();
|
||||||
|
int timeoutSec = configRoot.getDatabase().getConnectionAcquireTimeoutSeconds();
|
||||||
|
ComboPooledDataSource cpds = new ComboPooledDataSource();
|
||||||
|
try {
|
||||||
|
cpds.setDriverClass(configRoot.getDatabase().getDriver());
|
||||||
|
} catch (Exception ue) { // fixme не компилится из-за PropertyVetoException
|
||||||
|
throw new RuntimeException(ue);
|
||||||
|
}
|
||||||
|
cpds.setJdbcUrl(dbPath);
|
||||||
|
cpds.setUser(login);
|
||||||
|
cpds.setPassword(password);
|
||||||
|
cpds.setInitialPoolSize(configRoot.getDatabase().getMinPoolSize());
|
||||||
|
cpds.setMinPoolSize(configRoot.getDatabase().getMinPoolSize());
|
||||||
|
cpds.setMaxPoolSize(configRoot.getDatabase().getMaxPoolSize());
|
||||||
|
cpds.setNumHelperThreads(configRoot.getDatabase().getNumHelperThreads());
|
||||||
|
cpds.setCheckoutTimeout(timeoutSec * 1000/*todo common 1000==ConstsCommon.SECOND*/);
|
||||||
|
logTimeoutPart = String.format(" (timeout=%ds)", timeoutSec);
|
||||||
|
result = cpds;
|
||||||
|
} else {
|
||||||
|
dbPath = configRoot.getDatabase().getEmbeddedFilePath();
|
||||||
|
result = DbDefaultConfig.getEmbeddedDatabase(dbPath);
|
||||||
|
}
|
||||||
|
String OPERATION_DATABASE_CONNECTION_CHECK = String.format("Database [%s] connection check", dbPath);
|
||||||
|
try {
|
||||||
|
Connection conn = result.getConnection();
|
||||||
|
conn.close();
|
||||||
|
log.info("{}: success", OPERATION_DATABASE_CONNECTION_CHECK);
|
||||||
|
return result;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
String msg = String.format("%s%s: failed: %s -> %s",
|
||||||
|
OPERATION_DATABASE_CONNECTION_CHECK, logTimeoutPart, e.getClass().getSimpleName(), e.getMessage());
|
||||||
|
log.error(msg);
|
||||||
|
throw new ModuleInitializeException(msg, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
|
||||||
|
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
|
||||||
|
return jdbcTemplate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package ru.spcex.clearing.storage.config;
|
||||||
|
|
||||||
|
|
||||||
|
public class DfaConfig {
|
||||||
|
protected static DfaConfig self;
|
||||||
|
|
||||||
|
|
||||||
|
ConfigurationRootElement root = new ConfigurationRootElement();
|
||||||
|
|
||||||
|
protected String defaultLogFileName() {
|
||||||
|
return "storage";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String appName() {
|
||||||
|
return "clearing-storage";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected Class parsedClazz() {
|
||||||
|
return ConfigurationRootElement.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DfaConfig get() {
|
||||||
|
if (self == null) {
|
||||||
|
self = new DfaConfig();
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigurationRootElement getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
package ru.spcex.clearing.storage.config;
|
||||||
|
|
||||||
|
import com.hazelcast.config.*;
|
||||||
|
import com.hazelcast.core.HazelcastInstance;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.hazelcast.HazelcastInstanceFactory;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class HazelcastConfiguration {
|
||||||
|
|
||||||
|
private ConfigurationRootElement configRoot = DfaConfig.get().getRoot();
|
||||||
|
private final PoolMapConfigs poolMapConfigs;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public HazelcastConfiguration(PoolMapConfigs poolMapConfigs) {
|
||||||
|
this.poolMapConfigs = poolMapConfigs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public HazelcastInstance hazelcastServerInstance(Config config) {
|
||||||
|
return (new HazelcastInstanceFactory(config)).getHazelcastInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Config hazelCastConfig() {
|
||||||
|
Config config = new Config();
|
||||||
|
config.setInstanceName("instance");
|
||||||
|
config.setGroupConfig(new GroupConfig()
|
||||||
|
// todo config .setName(configRoot.getHazelcast().getLogin())
|
||||||
|
// .setPassword(configRoot.getHazelcast().getPassword()
|
||||||
|
// )
|
||||||
|
);
|
||||||
|
// if (StringUtils.isEmpty(configRoot.getHazelcast().getMancenterUrl())) {
|
||||||
|
// config.setManagementCenterConfig(new ManagementCenterConfig()
|
||||||
|
// .setEnabled(false)
|
||||||
|
// );
|
||||||
|
// } else {
|
||||||
|
// config.setManagementCenterConfig(new ManagementCenterConfig()
|
||||||
|
// .setEnabled(true)
|
||||||
|
// .setUrl(configRoot.getHazelcast().getMancenterUrl())
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
config.setProperty("hazelcast.shutdownhook.enabled", "true");
|
||||||
|
config.setProperty("hazelcast.logging.type", "slf4j");
|
||||||
|
config.setProperty("hazelcast.operation.call.timeout.millis", "600000");
|
||||||
|
config.setNetworkConfig(new NetworkConfig()
|
||||||
|
// .setPort(configRoot.getHazelcast().getListenPort())
|
||||||
|
.setJoin(new JoinConfig()
|
||||||
|
.setMulticastConfig(new MulticastConfig()
|
||||||
|
.setEnabled(false))
|
||||||
|
.setTcpIpConfig(new TcpIpConfig()
|
||||||
|
.setEnabled(true)
|
||||||
|
// .setMembers(
|
||||||
|
// DfaConfig.get()
|
||||||
|
// .getRoot().getHazelcast().getClusterMembersList()
|
||||||
|
// )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
config.addMapConfig(poolMapConfigs.map_WorkflowStatusDictionary());
|
||||||
|
config.addMapConfig(poolMapConfigs.map_WorkflowStatusDictionary());
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package ru.spcex.clearing.storage.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ComponentScan(basePackages = "com.moex.platform.storage")
|
||||||
|
public class PlatformStorageBeans {
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
package ru.spcex.clearing.storage.config;
|
||||||
|
|
||||||
|
import com.hazelcast.config.*;
|
||||||
|
import com.hazelcast.core.MapLoader;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import ru.spcex.clearing.storage.dictionary.WorkflowStatusDictionaryMapStore;
|
||||||
|
import ru.spcex.clearing.storage.object.CompanyRoleSetMapStore;
|
||||||
|
import ru.spcex.clearing.storage.utils.IMDGDistributedNames;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class PoolMapConfigs {
|
||||||
|
|
||||||
|
private ConfigurationRootElement configRoot = DfaConfig.get().getRoot();
|
||||||
|
|
||||||
|
public PoolMapConfigs() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private MapStoreConfig makeDefaultMapStoreConfig(MapLoader<Long, ?> mapBean) {
|
||||||
|
return new MapStoreConfig()
|
||||||
|
.setImplementation(mapBean)
|
||||||
|
;//todo config: .setWriteDelaySeconds(configRoot.getHazelcast().getDbSyncSeconds());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScheduledExecutorConfig makeDefaultScheduledExecutorConfig(String name) {
|
||||||
|
return new ScheduledExecutorConfig()
|
||||||
|
.setName(name)
|
||||||
|
.setPoolSize(16)
|
||||||
|
.setDurability(1)
|
||||||
|
.setCapacity(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapConfig makeDefaultMapConfig(String mapName, MapLoader<Long, ?> mapBean) {
|
||||||
|
return new MapConfig()
|
||||||
|
.setName(mapName)
|
||||||
|
.setInMemoryFormat(InMemoryFormat.OBJECT)
|
||||||
|
.setMapStoreConfig(makeDefaultMapStoreConfig(mapBean))
|
||||||
|
//fixme config: .setBackupCount(configRoot.getHazelcast().getBackupCount())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
private NearCacheConfig makeDefaultNearCacheConfig() {
|
||||||
|
return new NearCacheConfig()
|
||||||
|
.setMaxIdleSeconds(3600)
|
||||||
|
.setInMemoryFormat(InMemoryFormat.OBJECT)
|
||||||
|
.setSerializeKeys(true)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MapIndexConfig makeMapIndexConfig(String attributeName, boolean ordered) {
|
||||||
|
return new MapIndexConfig()
|
||||||
|
.setAttribute(attributeName)
|
||||||
|
.setOrdered(ordered);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WorkflowStatusDictionaryMapStore workflowStatusDictionaryMapStore;
|
||||||
|
|
||||||
|
public MapConfig map_WorkflowStatusDictionary() {
|
||||||
|
return makeDefaultMapConfig(IMDGDistributedNames.Map_WorkflowStatusDictionary, workflowStatusDictionaryMapStore)
|
||||||
|
.setNearCacheConfig(makeDefaultNearCacheConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CompanyRoleSetMapStore companyRoleSetMapStore;
|
||||||
|
|
||||||
|
public MapConfig map_CompanyRoleSet() {
|
||||||
|
return makeDefaultMapConfig(IMDGDistributedNames.Map_CompanyRoleSet, companyRoleSetMapStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package ru.spcex.clearing.storage.config;
|
||||||
|
|
||||||
|
//import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
//import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Настройка сервисов
|
||||||
|
*/
|
||||||
|
public class ServicesElement implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Время, через которое выставленная заявка будет снята, в миллисекундах.
|
||||||
|
*/
|
||||||
|
// @JsonProperty(value = "ExpirationDelay")
|
||||||
|
private Integer ExpirationDelay = 5 * 60 * 1000;
|
||||||
|
|
||||||
|
public Integer getExpirationDelay() {
|
||||||
|
return ExpirationDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Время окончания торговой сессии
|
||||||
|
*/
|
||||||
|
// @JsonProperty(value = "SessionEndTime")
|
||||||
|
// @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm:ss", timezone = "Europe/Moscow")
|
||||||
|
private Date SessionEndTime = null;
|
||||||
|
|
||||||
|
public Date getSessionEndTime() {
|
||||||
|
return SessionEndTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package ru.spcex.clearing.storage.config;
|
||||||
|
|
||||||
|
//import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@SuppressWarnings({"DefaultAnnotationParam", "unused", "FieldCanBeLocal"})
|
||||||
|
public class SettingsElement implements Serializable {
|
||||||
|
// @JsonProperty(value = "InitHazelcastThreadMultiplier", required = false)
|
||||||
|
private int initHazelcastThreadMultiplier = 2;
|
||||||
|
|
||||||
|
// @JsonProperty(value = "RecoveryLogPath", required = false)
|
||||||
|
private String recoveryLogPath;
|
||||||
|
|
||||||
|
// @JsonProperty(value = "ExecutionLimitationPeriod", required = false)
|
||||||
|
private Integer executionLimitationPeriod = 10;
|
||||||
|
|
||||||
|
public int getInitHazelcastThreadMultiplier() {
|
||||||
|
return initHazelcastThreadMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getExecutionLimitationPeriod() {
|
||||||
|
return executionLimitationPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRecoveryLogPath() {
|
||||||
|
return recoveryLogPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
package ru.spcex.clearing.storage.config;
|
||||||
|
|
||||||
|
//import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@SuppressWarnings({"FieldCanBeLocal", "unused", "DefaultAnnotationParam"})
|
||||||
|
public class SettingsElementDatabase implements Serializable {
|
||||||
|
|
||||||
|
// @JsonProperty(value = "Driver")
|
||||||
|
private String driver = "org.firebirdsql.jdbc.FBDriver";
|
||||||
|
|
||||||
|
// @JsonProperty(value = "JdbcConnectionString", required = true)
|
||||||
|
private String jdbcConnectionString;
|
||||||
|
|
||||||
|
// @JsonProperty(value = "Login", required = true)
|
||||||
|
private String login;
|
||||||
|
|
||||||
|
// @JsonProperty(value = "Password", required = true)
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
// @JsonProperty(value = "MaxPoolSize")
|
||||||
|
private int maxPoolSize = 30;
|
||||||
|
|
||||||
|
// @JsonProperty(value = "MinPoolSize")
|
||||||
|
private int minPoolSize = 10;
|
||||||
|
|
||||||
|
// @JsonProperty(value = "EmbeddedFilePath", required = false)
|
||||||
|
private String embeddedFilePath;
|
||||||
|
|
||||||
|
// @JsonProperty(value = "NumHelperThreads", required = false)
|
||||||
|
private int numHelperThreads = Runtime.getRuntime().availableProcessors() * 2;
|
||||||
|
|
||||||
|
// @JsonProperty(value = "ConnectionAcquireTimeoutSeconds", required = false)
|
||||||
|
private int connectionAcquireTimeoutSeconds = 30;
|
||||||
|
|
||||||
|
public String getDriver() {
|
||||||
|
return driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJdbcConnectionString() {
|
||||||
|
return jdbcConnectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLogin() {
|
||||||
|
return login;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxPoolSize() {
|
||||||
|
return maxPoolSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMinPoolSize() {
|
||||||
|
return minPoolSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmbeddedFilePath() {
|
||||||
|
return embeddedFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumHelperThreads() {
|
||||||
|
return numHelperThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getConnectionAcquireTimeoutSeconds() {
|
||||||
|
return connectionAcquireTimeoutSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
// для поддержки интеграционных тестов otc-test:
|
||||||
|
public void setJdbcConnectionString(String jdbcConnectionString) {
|
||||||
|
this.jdbcConnectionString = jdbcConnectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogin(String login) {
|
||||||
|
this.login = login;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmbeddedFilePath(String embeddedFilePath) {
|
||||||
|
this.embeddedFilePath = embeddedFilePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package ru.spcex.clearing.storage.dictionary;
|
||||||
|
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import ru.clearing.platform.dictionary.WorkflowStatusDictionary;
|
||||||
|
import ru.spcex.clearing.storage.base.DictionaryMapStore;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class WorkflowStatusDictionaryMapStore extends DictionaryMapStore<WorkflowStatusDictionary> {
|
||||||
|
|
||||||
|
public WorkflowStatusDictionaryMapStore(JdbcTemplate jdbcTemplate) {
|
||||||
|
super(jdbcTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTableName() {
|
||||||
|
return "WORKFLOW_STATUS_DICTIONARY";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorkflowStatusDictionary getDictionaryObject() {
|
||||||
|
return new WorkflowStatusDictionary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package ru.spcex.clearing.storage.error;
|
||||||
|
|
||||||
|
public class ModuleInitializeException extends RuntimeException {
|
||||||
|
public ModuleInitializeException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModuleInitializeException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModuleInitializeException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModuleInitializeException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
package ru.spcex.clearing.storage.object;
|
||||||
|
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import ru.clearing.classes.StaticData.Company.Company;
|
||||||
|
import ru.clearing.classes.StaticData.Company.CompanyRoleSet;
|
||||||
|
import ru.spcex.clearing.storage.base.ObjectBaseMapStore;
|
||||||
|
import ru.spcex.clearing.storage.utils.DbUtilsHelper;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class CompanyRoleSetMapStore extends ObjectBaseMapStore<CompanyRoleSet> {
|
||||||
|
|
||||||
|
public CompanyRoleSetMapStore(JdbcTemplate jdbcTemplate) {
|
||||||
|
super(jdbcTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTableName() {
|
||||||
|
return "COMPANY_ROLE_SET";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getFields() {
|
||||||
|
return new String[]{"id", "roleid", "companyid"};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final String insertStatement = DbUtilsHelper.createUpdateOrInsert(getTableName(), getFields(), "id");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<CompanyRoleSet> load(Collection<Long> keys) {
|
||||||
|
Map<String, Collection<Long>> paramMap = Collections.singletonMap("ids", keys);
|
||||||
|
return namedParameterJdbcTemplate.query("select * from " + getTableName() + " where id in (:ids)", paramMap,
|
||||||
|
(resultSet, i) -> {
|
||||||
|
CompanyRoleSet companyRoleSet = new CompanyRoleSet();
|
||||||
|
companyRoleSet.setId(resultSet.getObject("id", Long.class));
|
||||||
|
companyRoleSet.setRoleId(resultSet.getObject("roleid", Long.class));
|
||||||
|
companyRoleSet.setCompanyId(resultSet.getObject("companyid", Long.class));
|
||||||
|
return companyRoleSet;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void store(Map<Long, CompanyRoleSet> map) {
|
||||||
|
List<Object[]> batchArgs = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Map.Entry<Long, CompanyRoleSet> entry : map.entrySet()) {
|
||||||
|
CompanyRoleSet partnerList = entry.getValue();
|
||||||
|
|
||||||
|
Object[] args = new Object[]{
|
||||||
|
partnerList.getId(),
|
||||||
|
partnerList.getRoleId(),
|
||||||
|
partnerList.getCompanyId(),
|
||||||
|
};
|
||||||
|
batchArgs.add(args);
|
||||||
|
}
|
||||||
|
batchInsertUpdate(insertStatement, batchArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
package ru.spcex.clearing.storage.utils;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.DecimalFormatSymbols;
|
||||||
|
|
||||||
|
public class BigDecimalUtil {
|
||||||
|
|
||||||
|
private static final DecimalFormat defaultDecimalFormat;
|
||||||
|
|
||||||
|
static {
|
||||||
|
DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols();
|
||||||
|
decimalFormatSymbols.setDecimalSeparator('.');
|
||||||
|
decimalFormatSymbols.setGroupingSeparator(' ');
|
||||||
|
defaultDecimalFormat = new DecimalFormat("#,###.00", decimalFormatSymbols);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BigDecimal sum(BigDecimal num1, BigDecimal num2) {
|
||||||
|
BigDecimal sum = BigDecimal.ZERO;
|
||||||
|
if (num1 != null)
|
||||||
|
sum = sum.add(num1);
|
||||||
|
if (num2 != null)
|
||||||
|
sum = sum.add(num2);
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param value
|
||||||
|
* @param dbSize общее кол-во позиций
|
||||||
|
* @param dbScale кол-во позиций под дробную часть
|
||||||
|
* @return true, если размер целой части не превышает значения, указанные в параметрах
|
||||||
|
*/
|
||||||
|
public static boolean checkSize(BigDecimal value, int dbSize, int dbScale) {
|
||||||
|
if (value == null)
|
||||||
|
return true;
|
||||||
|
return value.precision() - value.scale() <= dbSize - dbScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BigDecimal genMaxValueForInsert(int dbSize, int dbScale) {
|
||||||
|
int maxIntSizeForInsert = dbSize - dbScale;
|
||||||
|
long newLongValue = new BigDecimal(Math.pow(10, maxIntSizeForInsert)).longValue();
|
||||||
|
return new BigDecimal(newLongValue - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BigDecimal chooseHighest(BigDecimal oldPrice, BigDecimal newPrice) {
|
||||||
|
if (newPrice != null && (oldPrice == null || isLess(oldPrice, newPrice))) {
|
||||||
|
return newPrice;
|
||||||
|
} else {
|
||||||
|
return oldPrice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BigDecimal chooseSmallest(BigDecimal oldPrice, BigDecimal newPrice) {
|
||||||
|
if (newPrice != null && (oldPrice == null || isLess(newPrice, oldPrice))) {
|
||||||
|
return newPrice;
|
||||||
|
} else {
|
||||||
|
return oldPrice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Если bestPrice меньше price, то true, иначе false
|
||||||
|
*
|
||||||
|
* @param bestPrice
|
||||||
|
* @param price
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean isLess(BigDecimal bestPrice, BigDecimal price) {
|
||||||
|
return price != null && bestPrice != null && bestPrice.compareTo(price) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Integer nullSafeAdd(Integer a, Integer b) {
|
||||||
|
if (a == null) {
|
||||||
|
return b;
|
||||||
|
} else if (b == null) {
|
||||||
|
return a;
|
||||||
|
} else {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BigDecimal nullSafeAdd(BigDecimal a, BigDecimal b) {
|
||||||
|
if (a == null) {
|
||||||
|
return b;
|
||||||
|
} else if (b == null) {
|
||||||
|
return a;
|
||||||
|
} else {
|
||||||
|
return a.add(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Long nullSafeAdd(Long a, Long b) {
|
||||||
|
if (a == null) {
|
||||||
|
return b;
|
||||||
|
} else if (b == null) {
|
||||||
|
return a;
|
||||||
|
} else {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String defaultFormatValue(BigDecimal val) {
|
||||||
|
DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols();
|
||||||
|
decimalFormatSymbols.setDecimalSeparator('.');
|
||||||
|
decimalFormatSymbols.setGroupingSeparator(' ');
|
||||||
|
if (val == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return defaultDecimalFormat.format(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package ru.spcex.clearing.storage.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
public class DbDefaultConfig {
|
||||||
|
public static DataSource getEmbeddedDatabase(String embeddedFilePath) {
|
||||||
|
throw new UnsupportedOperationException("Are PostgreSQL not supported embedded DB?");//todo PsotgreSQL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
package ru.spcex.clearing.storage.utils;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class DbUtilsHelper {
|
||||||
|
|
||||||
|
private static String generateValuesBlock(int querySignCount) {
|
||||||
|
return StringUtils.rightPad("(?", querySignCount * 3 - 1, ", ?") + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Pattern pGetColumns = Pattern.compile("(?m)(?i)INTO\\s+[0-9a-z\" _$]+\\s+\\(\\s*([0-9a-z_\\- ,\"\\n+]*?)\\s*\\)");
|
||||||
|
|
||||||
|
public static String fillValuesBlock(String insertStatement) {
|
||||||
|
|
||||||
|
Matcher m = pGetColumns.matcher(insertStatement);
|
||||||
|
if (m.find()) {
|
||||||
|
String g = m.group(1);
|
||||||
|
String block = generateValuesBlock(g.split(",").length);
|
||||||
|
return insertStatement.replaceAll("%values_block%", block);
|
||||||
|
} else {
|
||||||
|
return insertStatement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String createInsert(String tableName, String[] fields) {
|
||||||
|
return "INSERT INTO " + tableName +
|
||||||
|
" (" + Arrays.stream(fields).map(f -> "\"" + f.toUpperCase() + "\"").collect(Collectors.joining(", ")) + ") values (" +
|
||||||
|
// Arrays.stream(fields).map(f -> "\"" + f.toUpperCase() + "\"").collect(Collectors.joining(", ", ":", ""));
|
||||||
|
String.join(", ", Collections.nCopies(fields.length, "?")) +
|
||||||
|
")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String createUpdateOrInsert(String tableName, String[] fields, String matchingKey) {
|
||||||
|
String updateOrInsert = "INSERT INTO " + tableName +
|
||||||
|
" (" + Arrays.stream(fields).map(f -> "\"" + f.toUpperCase() + "\"").collect(Collectors.joining(", ")) + ") values (" +
|
||||||
|
// Arrays.stream(fields).map(f -> "\"" + f.toUpperCase() + "\"").collect(Collectors.joining(", ", ":", ""));
|
||||||
|
String.join(", ", Collections.nCopies(fields.length, "?")) +
|
||||||
|
") WHERE ";
|
||||||
|
if (matchingKey != null) // PostgreSQL conflict_target fixme проверить мэтчинг
|
||||||
|
updateOrInsert += " " + matchingKey.toUpperCase();
|
||||||
|
updateOrInsert += " CONFLICT DO UPDATE";
|
||||||
|
|
||||||
|
return updateOrInsert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package ru.spcex.clearing.storage.utils;
|
||||||
|
|
||||||
|
//fixme перенести в новый модуль IMDGDistributedNames
|
||||||
|
public final class IMDGDistributedNames {
|
||||||
|
private IMDGDistributedNames() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String Map_WorkflowStatusDictionary = "Map_WorkflowStatusDictionary";
|
||||||
|
public static final String Map_CompanyRoleSet = "Map_CompanyRoleSet";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,288 @@
|
||||||
|
package ru.spcex.clearing.storage.utils;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.time.*;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Для работы с java.util.Date
|
||||||
|
* И конвертация в новый формат
|
||||||
|
* todo копипаст юниттеста нужен.
|
||||||
|
*/
|
||||||
|
public class TimeUtil {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(TimeUtil.class);
|
||||||
|
public static final ZoneId zone = ZoneId.systemDefault();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить дату без времени (начало дня)
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Date getDateOnStartOfDay(Date date) {
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTime(date);
|
||||||
|
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
|
calendar.set(Calendar.MINUTE, 0);
|
||||||
|
calendar.set(Calendar.SECOND, 0);
|
||||||
|
calendar.set(Calendar.MILLISECOND, 0);
|
||||||
|
return calendar.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить начало следующего дня
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Date getDateNextDay(Date date) {
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTime(date);
|
||||||
|
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
|
calendar.set(Calendar.MINUTE, 0);
|
||||||
|
calendar.set(Calendar.SECOND, 0);
|
||||||
|
calendar.set(Calendar.MILLISECOND, 0);
|
||||||
|
calendar.add(Calendar.DAY_OF_YEAR, 1);
|
||||||
|
return calendar.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalDateTime toDateTime(Date fromDate) {
|
||||||
|
if (fromDate == null)
|
||||||
|
return null;
|
||||||
|
if (fromDate instanceof java.sql.Timestamp)
|
||||||
|
return ((java.sql.Timestamp) fromDate).toLocalDateTime();
|
||||||
|
if (fromDate instanceof java.sql.Date || fromDate instanceof java.sql.Time)
|
||||||
|
log.debug("Warning at converting date/time: for class {} may not contain date or time. unixtime={}", fromDate.getClass(), fromDate.getTime());
|
||||||
|
return toDateTime0(fromDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LocalDateTime toDateTime0(Date fromDate) {
|
||||||
|
try {
|
||||||
|
if (fromDate instanceof java.sql.Date) {
|
||||||
|
Instant instant = Instant.now(); //can be LocalDateTime
|
||||||
|
ZoneId systemZone = ZoneId.systemDefault(); // my timezone
|
||||||
|
ZoneOffset currentOffsetForMyZone = systemZone.getRules().getOffset(instant);
|
||||||
|
return LocalDateTime.ofEpochSecond(fromDate.getTime() / 1000, 0, currentOffsetForMyZone);
|
||||||
|
}
|
||||||
|
return LocalDateTime.ofInstant(fromDate.toInstant(), ZoneId.systemDefault());
|
||||||
|
} catch (UnsupportedOperationException ue) {
|
||||||
|
log.warn("Error(warn) convert type of date/time: {}({}) class: {}. Retry", fromDate, fromDate.getTime(), fromDate.getClass());
|
||||||
|
try {
|
||||||
|
Instant instant = Instant.now(); //can be LocalDateTime
|
||||||
|
ZoneId systemZone = ZoneId.systemDefault(); // my timezone
|
||||||
|
ZoneOffset currentOffsetForMyZone = systemZone.getRules().getOffset(instant);
|
||||||
|
return LocalDateTime.ofEpochSecond(fromDate.getTime() / 1000, 0, currentOffsetForMyZone);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error convert type2 of date/time: {} class: {}\n{}", fromDate, fromDate.getClass(), ExceptionUtils.getStackTrace(ue));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalDate toDate(Date fromDate) {
|
||||||
|
if (fromDate == null)
|
||||||
|
return null;
|
||||||
|
if (fromDate instanceof java.sql.Date)
|
||||||
|
return ((java.sql.Date) fromDate).toLocalDate();
|
||||||
|
if (fromDate instanceof java.sql.Time)
|
||||||
|
log.debug("Warning at converting date/time: for class {} may not contain date. unixtime={}", fromDate.getClass(), fromDate.getTime());
|
||||||
|
return toDateTime0(fromDate).toLocalDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalTime toTime(Date fromDate) {
|
||||||
|
if (fromDate == null)
|
||||||
|
return null;
|
||||||
|
if (fromDate instanceof java.sql.Time)
|
||||||
|
return ((java.sql.Time) fromDate).toLocalTime();
|
||||||
|
if (fromDate instanceof java.sql.Date)
|
||||||
|
log.debug("Warning at converting date/time: for class {} may not contain time. unixtime={}", fromDate.getClass(), fromDate.getTime());
|
||||||
|
return toDateTime0(fromDate).toLocalTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Последовательный ряд дат дней между двумя датами.
|
||||||
|
*
|
||||||
|
* @param from с даты, включительно
|
||||||
|
* @param to по дату, включительно.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Date[] makeDateRange(Date from, Date to) {
|
||||||
|
ArrayList<Date> datesL = new ArrayList<Date>();
|
||||||
|
LocalDate fromDate = toDate(from);
|
||||||
|
LocalDate toDate = toDate(to);
|
||||||
|
datesL.add(from);
|
||||||
|
for (LocalDate dateI = fromDate.plusDays(1); dateI.isBefore(toDate); dateI = dateI.plusDays(1)) {
|
||||||
|
Date date = Date.from(dateI.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||||
|
datesL.add(date);
|
||||||
|
}
|
||||||
|
if (!fromDate.equals(toDate))
|
||||||
|
datesL.add(to);
|
||||||
|
Date[] dates = datesL.toArray(new Date[0]);
|
||||||
|
return dates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date fromInstant(Instant instant) {
|
||||||
|
if (instant == null) return null;
|
||||||
|
return Date.from(instant);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date from(LocalDateTime localDateTime) {
|
||||||
|
return localDateTime != null ? Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date from(LocalDate localDate) {
|
||||||
|
return localDate != null ? Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant()) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* иногда встречается java.sql.Date
|
||||||
|
* у них toInstant() не поддерживается
|
||||||
|
*/
|
||||||
|
public static Instant fromDate(Date dateToConvert) {
|
||||||
|
try {
|
||||||
|
if (dateToConvert == null) return null;
|
||||||
|
return dateToConvert.toInstant();
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// log.warn("java.sql.Date");
|
||||||
|
if (dateToConvert instanceof java.sql.Date) {
|
||||||
|
return ((java.sql.Date) dateToConvert).toLocalDate().atStartOfDay(ZoneId.systemDefault()).toInstant();
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Instant fromDate(LocalDate dateToConvert) {
|
||||||
|
return dateToConvert == null ? null : dateToConvert.atStartOfDay(ZoneId.systemDefault()).toInstant();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalDateTime toDateTime(Instant instant) {
|
||||||
|
if (instant == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date toUtilDate(java.sql.Date sqlDate) {
|
||||||
|
return sqlDate != null ? new Date(sqlDate.getTime()) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isCurrentTradingDay(Date date) {
|
||||||
|
Date tradingDay = getDateOnStartOfDay(date);
|
||||||
|
Date currentDay = getDateOnStartOfDay(new Date());
|
||||||
|
return currentDay.equals(tradingDay);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Начало дня по текущей временной зоне
|
||||||
|
*/
|
||||||
|
public static Instant startOfDayNow() {
|
||||||
|
ZonedDateTime zdtStart = ZonedDateTime.now();
|
||||||
|
zdtStart = zdtStart.truncatedTo(ChronoUnit.DAYS);
|
||||||
|
return zdtStart.toInstant();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Начало дня по текущей временной зоне.
|
||||||
|
*
|
||||||
|
* @param from
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Instant startOfDay(Instant from) {
|
||||||
|
ZonedDateTime zdtStart = from.atZone(ZoneId.systemDefault());
|
||||||
|
zdtStart = zdtStart.truncatedTo(ChronoUnit.DAYS);
|
||||||
|
return zdtStart.toInstant();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ZonedDateTime toZoned(Instant instant) {
|
||||||
|
if (instant == null) return null;
|
||||||
|
return instant.atZone(zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalDate toDate(Instant instant) {
|
||||||
|
ZonedDateTime zoned = toZoned(instant);
|
||||||
|
if (zoned == null) return null;
|
||||||
|
return zoned.toLocalDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Сегодня (от начала дня) или позднее
|
||||||
|
*
|
||||||
|
* @param instant дата, может ыть null
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean afterToday(Instant instant) {
|
||||||
|
LocalDate localDate = toDate(instant);
|
||||||
|
return afterToday(localDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Сегодня (от начала дня) или позднее
|
||||||
|
*
|
||||||
|
* @param date дата, может ыть null
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean afterToday(Date date) {
|
||||||
|
LocalDate localDate = toDate(date);
|
||||||
|
return afterToday(localDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Сегодня (от начала дня) или позднее
|
||||||
|
*
|
||||||
|
* @param localDate дата, может ыть null
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean afterToday(LocalDate localDate) {
|
||||||
|
if (localDate == null) return false;
|
||||||
|
return !localDate.isBefore(LocalDate.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isToday(Instant instant) {
|
||||||
|
LocalDate localDate = toDate(instant);
|
||||||
|
return isToday(localDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isToday(Date date) {
|
||||||
|
LocalDate localDate = toDate(date);
|
||||||
|
return isToday(localDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isToday(LocalDate localDate) {
|
||||||
|
if (localDate == null) return false;
|
||||||
|
return localDate.equals(LocalDate.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Если instant без даты (1970 год), то берёт из него время и добавляет текущую дату.
|
||||||
|
*
|
||||||
|
* @param time может быть null
|
||||||
|
* @return time, или если не указана дата, то текущая дата + время из <code>time</code>
|
||||||
|
*/
|
||||||
|
public static Instant addDateTodayToTimeIfNeeded(Instant time) {
|
||||||
|
if (time == null)
|
||||||
|
return null;
|
||||||
|
LocalDateTime ldt = TimeUtil.toDateTime(time);
|
||||||
|
if (ldt.getYear() == 1970 && ldt.getMonth() == Month.JANUARY && ldt.getDayOfMonth() == 1) {
|
||||||
|
// time without date
|
||||||
|
ldt = LocalDateTime.of(LocalDate.now(), ldt.toLocalTime());
|
||||||
|
return ldt.atZone(ZoneId.systemDefault()).toInstant();
|
||||||
|
}
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatInstantToString(DateTimeFormatter formatter, Instant date) {
|
||||||
|
if (formatter == null || date == null) return "";
|
||||||
|
return formatter.format(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue