Compare commits
12 Commits
master
...
fix/readme
| Author | SHA1 | Date |
|---|---|---|
|
|
c5a175f2dc | |
|
|
9c66f3819c | |
|
|
24aed8cc8b | |
|
|
78008a9325 | |
|
|
fc8fbc68c3 | |
|
|
c89de4c548 | |
|
|
2771e92e77 | |
|
|
1771271789 | |
|
|
73d7a2325d | |
|
|
28355a9341 | |
|
|
2dae5f7a77 | |
|
|
5f6adc97fe |
117
README.md
117
README.md
|
|
@ -19,19 +19,6 @@
|
||||||
implementation("ru.touchin:common")
|
implementation("ru.touchin:common")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Project Gradle tasks
|
|
||||||
### Detekt:
|
|
||||||
- `gradle $project:detekt` - detect not formatted, complex code.
|
|
||||||
|
|
||||||
Reports are stored in "$pwd/build/reports/kotlin-detekt-${project.name}.html".
|
|
||||||
|
|
||||||
### DiKTat:
|
|
||||||
- `gradle :diktatCheck` - detect not formatted code of "kt", "kts" files;
|
|
||||||
- `gradle :diktatFix` - if possible, fix not formatted code. Known issues: full fix may require 1+ launch in order to apply all rules; some rules potentially may break code syntax.
|
|
||||||
|
|
||||||
By setting environment variable `TASKS_FILE_REPORT_ENABLED`(true, false) you may configure raw console output or html file as report.
|
|
||||||
Reports are stored in "$pwd/build/reports/diktat-report.html".
|
|
||||||
|
|
||||||
## common
|
## common
|
||||||
|
|
||||||
|
|
@ -81,106 +68,6 @@ Reports are stored in "$pwd/build/reports/diktat-report.html".
|
||||||
|
|
||||||
Утилиты для тестирования репозиториев
|
Утилиты для тестирования репозиториев
|
||||||
|
|
||||||
## codestyle-archunit
|
|
||||||
|
|
||||||
Набор правил для поддержки оформления архитектуры.
|
|
||||||
|
|
||||||
#### Список доступных правил
|
|
||||||
- `ru.touchin.codestyle.archunit.rules.ClassNamingArchRules`
|
|
||||||
- `ru.touchin.codestyle.archunit.rules.ClassPackagingArchRules`
|
|
||||||
|
|
||||||
|
|
||||||
#### Gradle plugin
|
|
||||||
Настройка и применение совместно с [ArchUnit Gradle Plugin](https://github.com/societe-generale/arch-unit-gradle-plugin).
|
|
||||||
|
|
||||||
Действие `checkRules` для проверки соответствие правилам запускается при операциях сборки, по умолчанию.
|
|
||||||
Вручную можно вызвать командой ``gradle :checkRules`` для нужного модуля.
|
|
||||||
Добавить его можно следующим образом на примере установки в рутовый gradle.build проекта:
|
|
||||||
|
|
||||||
Groovy DSL:
|
|
||||||
```groovy
|
|
||||||
buildscript {
|
|
||||||
dependencies {
|
|
||||||
classpath "com.societegenerale.commons:arch-unit-gradle-plugin:3.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
subprojects {
|
|
||||||
dependencyManagement {
|
|
||||||
dependencies {
|
|
||||||
dependency "com.tngtech.archunit:archunit:1.0.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
apply plugin: "java"
|
|
||||||
apply plugin: "com.societegenerale.commons.arch-unit-gradle-plugin"
|
|
||||||
|
|
||||||
archUnit {
|
|
||||||
mainScopePath = "/classes/kotlin/main" // or "/classes/java/main"
|
|
||||||
testScopePath = "/classes/kotlin/test" // or "/classes/java/test"
|
|
||||||
|
|
||||||
var applyType = applyOn("ru.touchin", "main")
|
|
||||||
configurableRules = [
|
|
||||||
configurableRule(
|
|
||||||
"ru.touchin.codestyle.archunit.rules.ClassNamingArchRules",
|
|
||||||
applyType,
|
|
||||||
),
|
|
||||||
configurableRule(
|
|
||||||
"ru.touchin.codestyle.archunit.rules.ClassPackagingArchRules",
|
|
||||||
applyType,
|
|
||||||
),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
archUnitExtraLib "ru.touchin:codestyle-archunit" // or archUnitExtraLib project(":codestyle-archunit")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Kotlin DSL:
|
|
||||||
```kotlin
|
|
||||||
plugins {
|
|
||||||
id("com.societegenerale.commons.arch-unit-gradle-plugin") version "3.0.0"
|
|
||||||
}
|
|
||||||
subprojects {
|
|
||||||
configure<DependencyManagementExtension> {
|
|
||||||
dependencies {
|
|
||||||
dependency("com.tngtech.archunit:archunit:1.0.1")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
apply(plugin = "java")
|
|
||||||
apply(plugin = "com.societegenerale.commons.arch-unit-gradle-plugin")
|
|
||||||
|
|
||||||
archUnit {
|
|
||||||
mainScopePath = "/classes/kotlin/main" // or "/classes/java/main"
|
|
||||||
testScopePath = "/classes/kotlin/test" // or "/classes/java/test"
|
|
||||||
|
|
||||||
configurableRules = listOf(
|
|
||||||
"ru.touchin.codestyle.archunit.rules.ClassNamingArchRules",
|
|
||||||
"ru.touchin.codestyle.archunit.rules.ClassPackagingArchRules"
|
|
||||||
).map { package ->
|
|
||||||
configurableRule(
|
|
||||||
package,
|
|
||||||
applyOn("ru.touchin", "main")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
archUnitExtraLib("ru.touchin:codestyle-archunit") // or archUnitExtraLib(project(":codestyle-archunit"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Отключить проверки на таске помимо конфигурирования `configurableRule` можно также таким образом:
|
|
||||||
```kotlin
|
|
||||||
// clear action launch for root project to avoid exception
|
|
||||||
tasks.checkRules.configure {
|
|
||||||
actions.clear()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## logger
|
## logger
|
||||||
|
|
||||||
Основные компоненты логирования:
|
Основные компоненты логирования:
|
||||||
|
|
@ -329,7 +216,7 @@ server.info:
|
||||||
|
|
||||||
## push-message-provider
|
## push-message-provider
|
||||||
|
|
||||||
Интерфейсы и компоненты для модулей по обеспечению интеграции с сервисами отправки пуш-уведомлений. Является необходимой зависимостью для использования провайдеров.
|
Интерфейсы и компоненты для модулей по обеспечению интеграции с сервисами отправки пуш-уведомлений. Является необходимой для подключения зависимостью для использования провайдеров.
|
||||||
|
|
||||||
Далее рассматривается пример использования подключаемых модулей-провайдеров.
|
Далее рассматривается пример использования подключаемых модулей-провайдеров.
|
||||||
``` kotlin
|
``` kotlin
|
||||||
|
|
@ -429,7 +316,7 @@ C) Данные из файла консоли Firebase, добавляемые
|
||||||
Модуль по обеспечению интеграции с Huawei Push Kit.
|
Модуль по обеспечению интеграции с Huawei Push Kit.
|
||||||
|
|
||||||
1) Подключение нового провайдера осуществляется при помощи аннотации `@EnablePushMessageProviderHpk`.
|
1) Подключение нового провайдера осуществляется при помощи аннотации `@EnablePushMessageProviderHpk`.
|
||||||
2) Для логирования запросов к сервису HPK нужно встроить в контейнер Spring собственный `WebClientLogger` из модуля `logger-spring-web` или же использовать стандартный посредством импорта конфигурации:
|
2) Для логирования запросов к сервису HPK нужно встроить в контейнер Spring собственный `WebClientLogger` из пакета `common-spring-web` или же использовать стандартный посредством импорта конфигурации:
|
||||||
``` kotlin
|
``` kotlin
|
||||||
@Import(
|
@Import(
|
||||||
SpringLoggerConfiguration::class,
|
SpringLoggerConfiguration::class,
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension
|
import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension
|
||||||
import io.gitlab.arturbosch.detekt.extensions.DetektExtension
|
|
||||||
import org.jetbrains.kotlin.cli.common.toBooleanLenient
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm")
|
kotlin("jvm")
|
||||||
id("org.springframework.boot") apply false
|
id ("org.springframework.boot") apply false
|
||||||
|
|
||||||
// IntelliJ
|
// IntelliJ
|
||||||
idea
|
idea
|
||||||
|
|
@ -17,9 +15,6 @@ plugins {
|
||||||
// A Gradle plugin that provides Maven-like dependency management and exclusions
|
// A Gradle plugin that provides Maven-like dependency management and exclusions
|
||||||
// https://docs.spring.io/dependency-management-plugin/docs/current/reference/html/
|
// https://docs.spring.io/dependency-management-plugin/docs/current/reference/html/
|
||||||
id("io.spring.dependency-management")
|
id("io.spring.dependency-management")
|
||||||
|
|
||||||
id("io.gitlab.arturbosch.detekt")
|
|
||||||
id("org.cqfn.diktat.diktat-gradle-plugin")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
|
|
@ -35,30 +30,6 @@ allprojects {
|
||||||
apply(plugin = "idea")
|
apply(plugin = "idea")
|
||||||
}
|
}
|
||||||
|
|
||||||
diktat {
|
|
||||||
inputs {
|
|
||||||
include(
|
|
||||||
"**/src/**/*.kt",
|
|
||||||
"*.kts",
|
|
||||||
"**/*.kts",
|
|
||||||
"**/src/**/*.kts",
|
|
||||||
)
|
|
||||||
exclude(
|
|
||||||
"**/build/**",
|
|
||||||
"build/**",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val tasksFileReportEnabled = project.properties["TASKS_FILE_REPORT_ENABLED"]
|
|
||||||
?.let { it.toString().toBooleanLenient() }
|
|
||||||
?: true
|
|
||||||
|
|
||||||
reporter = if (tasksFileReportEnabled) "html" else "plain"
|
|
||||||
output = if (tasksFileReportEnabled) "${project.buildDir}/reports/diktat-report.html" else String()
|
|
||||||
diktatConfigFile = file("$rootDir/diktat-analysis.yml")
|
|
||||||
ignoreFailures = true
|
|
||||||
debug = false
|
|
||||||
}
|
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
println("Enabling Kotlin JVM plugin in project ${project.name}...")
|
println("Enabling Kotlin JVM plugin in project ${project.name}...")
|
||||||
apply(plugin = "org.jetbrains.kotlin.jvm")
|
apply(plugin = "org.jetbrains.kotlin.jvm")
|
||||||
|
|
@ -69,26 +40,6 @@ subprojects {
|
||||||
println("Enabling Spring Boot Dependency Management in project ${project.name}...")
|
println("Enabling Spring Boot Dependency Management in project ${project.name}...")
|
||||||
apply(plugin = "io.spring.dependency-management")
|
apply(plugin = "io.spring.dependency-management")
|
||||||
|
|
||||||
println("Enabling Detekt support in project ${project.name}...")
|
|
||||||
apply(plugin = "io.gitlab.arturbosch.detekt")
|
|
||||||
|
|
||||||
detekt {
|
|
||||||
config = files("$rootDir/detekt-config.yml")
|
|
||||||
source = files(
|
|
||||||
DetektExtension.Companion.DEFAULT_SRC_DIR_JAVA,
|
|
||||||
DetektExtension.Companion.DEFAULT_SRC_DIR_KOTLIN,
|
|
||||||
)
|
|
||||||
reports {
|
|
||||||
txt.enabled = false
|
|
||||||
xml.enabled = false
|
|
||||||
html {
|
|
||||||
enabled = true
|
|
||||||
destination = file("${project.buildDir}/reports/kotlin-detekt-${project.name}.html")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configure<DependencyManagementExtension> {
|
configure<DependencyManagementExtension> {
|
||||||
imports {
|
imports {
|
||||||
mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
|
mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
|
||||||
|
|
@ -99,15 +50,13 @@ subprojects {
|
||||||
dependency("ch.qos.logback.contrib:logback-json-classic:0.1.5")
|
dependency("ch.qos.logback.contrib:logback-json-classic:0.1.5")
|
||||||
dependency("ch.qos.logback.contrib:logback-jackson:0.1.5")
|
dependency("ch.qos.logback.contrib:logback-jackson:0.1.5")
|
||||||
|
|
||||||
dependency("org.testcontainers:testcontainers:1.18.3")
|
dependency("org.testcontainers:testcontainers:1.15.1")
|
||||||
dependency("org.testcontainers:postgresql:1.18.3")
|
dependency("org.testcontainers:postgresql:1.15.1")
|
||||||
dependency("org.testcontainers:junit-jupiter:1.18.3")
|
dependency("org.testcontainers:junit-jupiter:1.15.1")
|
||||||
dependency("org.junit.jupiter:junit-jupiter-api:5.4.2")
|
dependency("org.junit.jupiter:junit-jupiter-api:5.4.2")
|
||||||
dependency("org.junit.jupiter:junit-jupiter-params:5.4.2")
|
dependency("org.junit.jupiter:junit-jupiter-params:5.4.2")
|
||||||
dependency("org.junit.jupiter:junit-jupiter-engine:5.4.2")
|
dependency("org.junit.jupiter:junit-jupiter-engine:5.4.2")
|
||||||
|
|
||||||
dependency("com.tngtech.archunit:archunit:1.0.1")
|
|
||||||
|
|
||||||
dependency("org.liquibase:liquibase-core:4.4.0")
|
dependency("org.liquibase:liquibase-core:4.4.0")
|
||||||
|
|
||||||
dependency("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0")
|
dependency("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0")
|
||||||
|
|
@ -133,7 +82,7 @@ subprojects {
|
||||||
dependencies {
|
dependencies {
|
||||||
// use for @ConstructorBinding
|
// use for @ConstructorBinding
|
||||||
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
||||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
implementation ("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||||
|
|
||||||
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
|
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
plugins {
|
|
||||||
id("kotlin")
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(project(":common"))
|
|
||||||
implementation("com.tngtech.archunit:archunit")
|
|
||||||
}
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
package ru.touchin.codestyle.archunit.rules
|
|
||||||
|
|
||||||
import com.tngtech.archunit.lang.ArchRule
|
|
||||||
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes
|
|
||||||
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition.methods
|
|
||||||
import ru.touchin.common.exceptions.CommonException
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set of rules that defines constraint for classes naming.
|
|
||||||
*/
|
|
||||||
@Suppress("unused")
|
|
||||||
object ClassNamingArchRules {
|
|
||||||
|
|
||||||
|
|
||||||
val CLASSES_WHICH_HAVE_SCHEDULED_METHODS_MUST_HAVE_SUFFIX: ArchRule = methods()
|
|
||||||
.that()
|
|
||||||
.areAnnotatedWith("org.springframework.scheduling.annotation.Scheduled")
|
|
||||||
.should().beDeclaredInClassesThat().haveSimpleNameEndingWith("Job")
|
|
||||||
.allowEmptyShould(true)
|
|
||||||
.because("Classes that use 'Scheduled' annotation must have name with 'Job' suffix")
|
|
||||||
|
|
||||||
val ANNOTATED_SERVICE_CLASSES_MUST_HAVE_SUFFIX: ArchRule = methods()
|
|
||||||
.that().areAnnotatedWith("org.springframework.stereotype.Service")
|
|
||||||
.should().beDeclaredInClassesThat().haveSimpleNameContaining("Service")
|
|
||||||
.allowEmptyShould(true)
|
|
||||||
.because("Classes that use 'Service' annotation are assignable to class with `Service` suffix")
|
|
||||||
|
|
||||||
val ANNOTATED_ENTITY_CLASSES_MUST_HAVE_SUFFIX: ArchRule = classes()
|
|
||||||
.that().areAnnotatedWith("javax.persistence.Entity")
|
|
||||||
.should().haveSimpleNameEndingWith("Entity")
|
|
||||||
.allowEmptyShould(true)
|
|
||||||
.because("Hibernate 'Entity' classes must have name with 'Entity' suffix")
|
|
||||||
|
|
||||||
val EXCEPTION_CLASSES_MUST_HAVE_SUFFIX: ArchRule = classes()
|
|
||||||
.that().areAssignableTo(Exception::class.java)
|
|
||||||
.or().areAssignableTo(CommonException::class.java)
|
|
||||||
.should().haveSimpleNameEndingWith("Exception")
|
|
||||||
.allowEmptyShould(true)
|
|
||||||
.because("'Exception' classes must have name with 'Exception' suffix")
|
|
||||||
|
|
||||||
val JPAREPOSITORY_CLASSES_MUST_HAVE_SUFFIX: ArchRule = classes()
|
|
||||||
.that().areAssignableTo("org.springframework.data.jpa.repository.JpaRepository")
|
|
||||||
.should().haveSimpleNameEndingWith("Repository")
|
|
||||||
.allowEmptyShould(true)
|
|
||||||
.because("Classes that use 'JpaRepository' must have name with 'Repository' suffix")
|
|
||||||
|
|
||||||
val WEBCLIENT_CLASSES_MUST_HAVE_SUFFIX: ArchRule = classes()
|
|
||||||
.that().haveFullyQualifiedName("org.springframework.web.reactive.valction.client.WebClient")
|
|
||||||
.should().onlyBeAccessed().byClassesThat().haveSimpleNameEndingWith("WebClient")
|
|
||||||
.allowEmptyShould(true)
|
|
||||||
.because("Classes that use Spring 'WebClient' must have name with 'WebClient' suffix")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
package ru.touchin.codestyle.archunit.rules
|
|
||||||
|
|
||||||
import com.tngtech.archunit.lang.ArchRule
|
|
||||||
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set of rules that defines constraint for classes placement.
|
|
||||||
*/
|
|
||||||
@Suppress("unused")
|
|
||||||
object ClassPackagingArchRules {
|
|
||||||
|
|
||||||
|
|
||||||
val IMPL_CLASSES_ARE_IN_CORRESPONDING_PACKAGE: ArchRule = classes()
|
|
||||||
.that().haveSimpleNameEndingWith("Impl")
|
|
||||||
.should().resideInAPackage("..impl..")
|
|
||||||
.allowEmptyShould(true)
|
|
||||||
.because("Implementations of interfaces must reside in package 'impl'")
|
|
||||||
|
|
||||||
|
|
||||||
val ENTITIES_ARE_IN_CORRESPONDING_PACKAGE: ArchRule = classes()
|
|
||||||
.that().haveSimpleNameEndingWith("Entity")
|
|
||||||
.should().resideInAPackage("..models..")
|
|
||||||
.allowEmptyShould(true)
|
|
||||||
.because("'Entity' must reside in package 'models'")
|
|
||||||
|
|
||||||
val REPOSITORIES_ARE_IN_CORRESPONDING_PACKAGE: ArchRule = classes()
|
|
||||||
.that().haveSimpleNameEndingWith("Repository")
|
|
||||||
.should().resideInAPackage("..repositories..")
|
|
||||||
.allowEmptyShould(true)
|
|
||||||
.because("'Repository' must reside in package 'repositories'")
|
|
||||||
|
|
||||||
val CORE_SERVICES_ARE_IN_CORRESPONDING_PACKAGE: ArchRule = classes()
|
|
||||||
.that().haveSimpleNameEndingWith("CoreService")
|
|
||||||
.should().resideInAPackage("..services..")
|
|
||||||
.allowEmptyShould(true)
|
|
||||||
.because("'CoreService' must reside in package 'services'")
|
|
||||||
|
|
||||||
val CONVERTERS_ARE_IN_CORRESPONDING_PACKAGE: ArchRule = classes()
|
|
||||||
.that().haveSimpleNameEndingWith("Converter")
|
|
||||||
.should().resideInAPackage("..converters..")
|
|
||||||
.allowEmptyShould(true)
|
|
||||||
.because("'Converter' must reside in package 'converters'")
|
|
||||||
|
|
||||||
val EXCEPTIONS_ARE_IN_CORRESPONDING_PACKAGE: ArchRule = classes()
|
|
||||||
.that().haveSimpleNameEndingWith("Exception")
|
|
||||||
.should().resideInAPackage("..exceptions..")
|
|
||||||
.allowEmptyShould(true)
|
|
||||||
.because("'Exception' must reside in package 'exceptions'")
|
|
||||||
|
|
||||||
val ENUM_CLASSES_ARE_IN_CORRESPONDING_PACKAGE: ArchRule = classes()
|
|
||||||
.that().areEnums()
|
|
||||||
.should().resideInAPackage("..enums..")
|
|
||||||
.allowEmptyShould(true)
|
|
||||||
.because("'Enum' must reside in package 'enums'")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -13,7 +13,7 @@ import javax.persistence.MappedSuperclass
|
||||||
@MappedSuperclass
|
@MappedSuperclass
|
||||||
abstract class BaseEntity : Serializable {
|
abstract class BaseEntity : Serializable {
|
||||||
|
|
||||||
@CreatedDate(updatable = false)
|
@CreatedDate
|
||||||
lateinit var createdAt: ZonedDateTime
|
lateinit var createdAt: ZonedDateTime
|
||||||
|
|
||||||
@LastModifiedDate
|
@LastModifiedDate
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,5 @@ abstract class BaseUuidIdEntity : BaseEntity() {
|
||||||
@GeneratedValue(generator = "uuid")
|
@GeneratedValue(generator = "uuid")
|
||||||
@GenericGenerator(name = "uuid", strategy = "uuid2")
|
@GenericGenerator(name = "uuid", strategy = "uuid2")
|
||||||
open var id: UUID? = null
|
open var id: UUID? = null
|
||||||
@Suppress("RedundantSetter")
|
|
||||||
protected set(id) {
|
|
||||||
field = id
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
package ru.touchin.common.spring.annotations
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Import
|
|
||||||
import ru.touchin.common.spring.processors.RequiredByBeanDefinitionPostProcessor
|
|
||||||
|
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS)
|
|
||||||
@Import(RequiredByBeanDefinitionPostProcessor::class)
|
|
||||||
annotation class RequiredBy(vararg val value: String)
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
package ru.touchin.common.spring.processors
|
|
||||||
|
|
||||||
import org.springframework.beans.BeansException
|
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
|
|
||||||
import org.springframework.stereotype.Component
|
|
||||||
import ru.touchin.common.spring.annotations.RequiredBy
|
|
||||||
|
|
||||||
@Component
|
|
||||||
class RequiredByBeanDefinitionPostProcessor : BeanDefinitionRegistryPostProcessor {
|
|
||||||
|
|
||||||
@Throws(BeansException::class)
|
|
||||||
override fun postProcessBeanDefinitionRegistry(registry: BeanDefinitionRegistry) {
|
|
||||||
for (beanName in registry.beanDefinitionNames) {
|
|
||||||
val beanClassName = registry.getBeanDefinition(beanName).beanClassName?:continue
|
|
||||||
|
|
||||||
getDependantBeanNames(beanClassName).forEach { dependantBeanName ->
|
|
||||||
registry.getBeanDefinition(dependantBeanName).setDependsOn(beanName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(BeansException::class)
|
|
||||||
override fun postProcessBeanFactory(beanFactory: ConfigurableListableBeanFactory) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getDependantBeanNames(beanClassName: String): List<String> {
|
|
||||||
val beanClass = Class.forName(beanClassName)
|
|
||||||
var dependantBeans = emptyList<String>()
|
|
||||||
|
|
||||||
if (beanClass.isAnnotationPresent(RequiredBy::class.java)) {
|
|
||||||
dependantBeans = beanClass.getAnnotation(RequiredBy::class.java).value.toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
return dependantBeans
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -19,12 +19,12 @@ object StringUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
nextUpperCase -> {
|
nextUpperCase -> {
|
||||||
this.append(char.uppercase())
|
this.append(char.toUpperCase())
|
||||||
nextUpperCase = false
|
nextUpperCase = false
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
!nextUpperCase -> {
|
||||||
this.append(char.lowercase())
|
this.append(char.toLowerCase())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -34,8 +34,8 @@ object StringUtils {
|
||||||
fun String.removeNonPrintableCharacters(): String {
|
fun String.removeNonPrintableCharacters(): String {
|
||||||
return this
|
return this
|
||||||
.transliterateCyrillic()
|
.transliterateCyrillic()
|
||||||
.replace("\\p{Cntrl}&&[^\r\n\t]".toRegex(), "") // erases all the ASCII control characters
|
.replace("[\\p{Cntrl}&&[^\r\n\t]]".toRegex(), "")// erases all the ASCII control characters
|
||||||
.replace("\\p{C}".toRegex(), "") // removes non-printable characters from Unicode
|
.replace("\\p{C}".toRegex(), "")// removes non-printable characters from Unicode
|
||||||
.trim()
|
.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,402 +0,0 @@
|
||||||
build:
|
|
||||||
maxIssues: 0
|
|
||||||
weights:
|
|
||||||
# complexity: 2
|
|
||||||
# LongParameterList: 1
|
|
||||||
# style: 1
|
|
||||||
# comments: 1
|
|
||||||
|
|
||||||
processors:
|
|
||||||
active: true
|
|
||||||
exclude:
|
|
||||||
# - 'FunctionCountProcessor'
|
|
||||||
# - 'PropertyCountProcessor'
|
|
||||||
# - 'ClassCountProcessor'
|
|
||||||
# - 'PackageCountProcessor'
|
|
||||||
# - 'KtFileCountProcessor'
|
|
||||||
|
|
||||||
formatting:
|
|
||||||
active: true
|
|
||||||
android: true
|
|
||||||
autoCorrect: true
|
|
||||||
MaximumLineLength:
|
|
||||||
active: true
|
|
||||||
|
|
||||||
console-reports:
|
|
||||||
active: false
|
|
||||||
exclude:
|
|
||||||
# - 'ProjectStatisticsReport'
|
|
||||||
# - 'ComplexityReport'
|
|
||||||
# - 'NotificationReport'
|
|
||||||
# - 'FindingsReport'
|
|
||||||
# - 'BuildFailureReport'
|
|
||||||
|
|
||||||
comments:
|
|
||||||
active: false
|
|
||||||
CommentOverPrivateFunction:
|
|
||||||
active: false
|
|
||||||
CommentOverPrivateProperty:
|
|
||||||
active: false
|
|
||||||
EndOfSentenceFormat:
|
|
||||||
active: false
|
|
||||||
endOfSentenceFormat: ([.?!][ \t\n\r\f<])|([.?!]$)
|
|
||||||
UndocumentedPublicClass:
|
|
||||||
active: false
|
|
||||||
searchInNestedClass: true
|
|
||||||
searchInInnerClass: true
|
|
||||||
searchInInnerObject: true
|
|
||||||
searchInInnerInterface: true
|
|
||||||
UndocumentedPublicFunction:
|
|
||||||
active: false
|
|
||||||
|
|
||||||
complexity:
|
|
||||||
active: true
|
|
||||||
ComplexCondition:
|
|
||||||
active: true
|
|
||||||
threshold: 5
|
|
||||||
ComplexInterface:
|
|
||||||
active: false
|
|
||||||
threshold: 10
|
|
||||||
includeStaticDeclarations: false
|
|
||||||
ComplexMethod:
|
|
||||||
active: true
|
|
||||||
threshold: 10
|
|
||||||
ignoreSingleWhenExpression: true
|
|
||||||
ignoreSimpleWhenEntries: true
|
|
||||||
LabeledExpression:
|
|
||||||
active: true
|
|
||||||
LargeClass:
|
|
||||||
active: true
|
|
||||||
threshold: 800
|
|
||||||
LongMethod:
|
|
||||||
active: true
|
|
||||||
threshold: 40
|
|
||||||
LongParameterList:
|
|
||||||
active: true
|
|
||||||
functionThreshold: 10
|
|
||||||
ignoreDefaultParameters: false
|
|
||||||
MethodOverloading:
|
|
||||||
active: false
|
|
||||||
threshold: 5
|
|
||||||
NamedArguments:
|
|
||||||
active: false
|
|
||||||
threshold: 2
|
|
||||||
NestedBlockDepth:
|
|
||||||
active: true
|
|
||||||
threshold: 4
|
|
||||||
StringLiteralDuplication:
|
|
||||||
active: true
|
|
||||||
threshold: 3
|
|
||||||
ignoreAnnotation: true
|
|
||||||
excludeStringsWithLessThan5Characters: true
|
|
||||||
ignoreStringsRegex: '$^'
|
|
||||||
TooManyFunctions:
|
|
||||||
active: true
|
|
||||||
thresholdInFiles: 20
|
|
||||||
thresholdInClasses: 20
|
|
||||||
thresholdInInterfaces: 20
|
|
||||||
thresholdInObjects: 20
|
|
||||||
thresholdInEnums: 20
|
|
||||||
ignoreDeprecated: false
|
|
||||||
ignorePrivate: false
|
|
||||||
|
|
||||||
empty-blocks:
|
|
||||||
active: true
|
|
||||||
EmptyCatchBlock:
|
|
||||||
active: true
|
|
||||||
allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
|
|
||||||
EmptyClassBlock:
|
|
||||||
active: true
|
|
||||||
EmptyDefaultConstructor:
|
|
||||||
active: false
|
|
||||||
EmptyDoWhileBlock:
|
|
||||||
active: true
|
|
||||||
EmptyElseBlock:
|
|
||||||
active: true
|
|
||||||
EmptyFinallyBlock:
|
|
||||||
active: true
|
|
||||||
EmptyForBlock:
|
|
||||||
active: true
|
|
||||||
EmptyFunctionBlock:
|
|
||||||
active: true
|
|
||||||
ignoreOverridden: false
|
|
||||||
EmptyIfBlock:
|
|
||||||
active: true
|
|
||||||
EmptyInitBlock:
|
|
||||||
active: true
|
|
||||||
EmptyKtFile:
|
|
||||||
active: true
|
|
||||||
EmptySecondaryConstructor:
|
|
||||||
active: true
|
|
||||||
EmptyWhenBlock:
|
|
||||||
active: true
|
|
||||||
EmptyWhileBlock:
|
|
||||||
active: true
|
|
||||||
|
|
||||||
exceptions:
|
|
||||||
active: true
|
|
||||||
ExceptionRaisedInUnexpectedLocation:
|
|
||||||
active: true
|
|
||||||
methodNames: 'toString,hashCode,equals,finalize'
|
|
||||||
InstanceOfCheckForException:
|
|
||||||
active: false
|
|
||||||
NotImplementedDeclaration:
|
|
||||||
active: true
|
|
||||||
PrintStackTrace:
|
|
||||||
active: true
|
|
||||||
RethrowCaughtException:
|
|
||||||
active: false
|
|
||||||
ReturnFromFinally:
|
|
||||||
active: false
|
|
||||||
SwallowedException:
|
|
||||||
active: false
|
|
||||||
ThrowingExceptionFromFinally:
|
|
||||||
active: false
|
|
||||||
ThrowingExceptionInMain:
|
|
||||||
active: false
|
|
||||||
ThrowingExceptionsWithoutMessageOrCause:
|
|
||||||
active: true
|
|
||||||
exceptions: 'IllegalArgumentException,IllegalStateException,IOException'
|
|
||||||
ThrowingNewInstanceOfSameException:
|
|
||||||
active: false
|
|
||||||
TooGenericExceptionCaught:
|
|
||||||
active: false
|
|
||||||
exceptionNames:
|
|
||||||
- ArrayIndexOutOfBoundsException
|
|
||||||
- Error
|
|
||||||
- Exception
|
|
||||||
- IllegalMonitorStateException
|
|
||||||
- NullPointerException
|
|
||||||
- IndexOutOfBoundsException
|
|
||||||
- RuntimeException
|
|
||||||
- Throwable
|
|
||||||
allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
|
|
||||||
TooGenericExceptionThrown:
|
|
||||||
active: true
|
|
||||||
exceptionNames:
|
|
||||||
- Error
|
|
||||||
- Exception
|
|
||||||
- Throwable
|
|
||||||
- RuntimeException
|
|
||||||
|
|
||||||
naming:
|
|
||||||
active: true
|
|
||||||
ClassNaming:
|
|
||||||
active: true
|
|
||||||
classPattern: '[A-Z$][a-zA-Z0-9$]*'
|
|
||||||
ConstructorParameterNaming:
|
|
||||||
active: true
|
|
||||||
parameterPattern: '[a-z][A-Za-z0-9]*'
|
|
||||||
privateParameterPattern: '[a-z][A-Za-z0-9]*'
|
|
||||||
excludeClassPattern: '$^'
|
|
||||||
EnumNaming:
|
|
||||||
active: true
|
|
||||||
enumEntryPattern: '^[A-Z][_a-zA-Z0-9]*'
|
|
||||||
ForbiddenClassName:
|
|
||||||
active: false
|
|
||||||
forbiddenName: ''
|
|
||||||
FunctionMaxLength:
|
|
||||||
active: false
|
|
||||||
maximumFunctionNameLength: 30
|
|
||||||
FunctionMinLength:
|
|
||||||
active: false
|
|
||||||
minimumFunctionNameLength: 3
|
|
||||||
FunctionNaming:
|
|
||||||
active: true
|
|
||||||
functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$'
|
|
||||||
excludeClassPattern: '$^'
|
|
||||||
ignoreOverridden: true
|
|
||||||
FunctionParameterNaming:
|
|
||||||
active: true
|
|
||||||
parameterPattern: '[a-z][A-Za-z0-9]*'
|
|
||||||
excludeClassPattern: '$^'
|
|
||||||
ignoreOverridden: true
|
|
||||||
MatchingDeclarationName:
|
|
||||||
active: true
|
|
||||||
MemberNameEqualsClassName:
|
|
||||||
active: false
|
|
||||||
ignoreOverridden: true
|
|
||||||
ObjectPropertyNaming:
|
|
||||||
active: true
|
|
||||||
constantPattern: '[A-Za-z][_A-Za-z0-9]*'
|
|
||||||
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
|
|
||||||
privatePropertyPattern: '[A-Za-z][_A-Za-z0-9]*'
|
|
||||||
PackageNaming:
|
|
||||||
active: false
|
|
||||||
packagePattern: '^[a-z]+(\.[a-z][a-z0-9]*)*$'
|
|
||||||
TopLevelPropertyNaming:
|
|
||||||
active: true
|
|
||||||
constantPattern: '[A-Z][_A-Z0-9]*'
|
|
||||||
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
|
|
||||||
privatePropertyPattern: '[A-Za-z][_A-Za-z0-9]*'
|
|
||||||
VariableMaxLength:
|
|
||||||
active: false
|
|
||||||
maximumVariableNameLength: 64
|
|
||||||
VariableMinLength:
|
|
||||||
active: false
|
|
||||||
minimumVariableNameLength: 1
|
|
||||||
VariableNaming:
|
|
||||||
active: true
|
|
||||||
variablePattern: '[a-z][A-Za-z0-9]*'
|
|
||||||
privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
|
|
||||||
excludeClassPattern: '$^'
|
|
||||||
ignoreOverridden: true
|
|
||||||
|
|
||||||
performance:
|
|
||||||
active: true
|
|
||||||
ArrayPrimitive:
|
|
||||||
active: false
|
|
||||||
ForEachOnRange:
|
|
||||||
active: true
|
|
||||||
SpreadOperator:
|
|
||||||
active: false
|
|
||||||
UnnecessaryTemporaryInstantiation:
|
|
||||||
active: true
|
|
||||||
|
|
||||||
potential-bugs:
|
|
||||||
active: true
|
|
||||||
DuplicateCaseInWhenExpression:
|
|
||||||
active: true
|
|
||||||
EqualsAlwaysReturnsTrueOrFalse:
|
|
||||||
active: false
|
|
||||||
EqualsWithHashCodeExist:
|
|
||||||
active: true
|
|
||||||
ExplicitGarbageCollectionCall:
|
|
||||||
active: true
|
|
||||||
InvalidRange:
|
|
||||||
active: true
|
|
||||||
IteratorHasNextCallsNextMethod:
|
|
||||||
active: false
|
|
||||||
IteratorNotThrowingNoSuchElementException:
|
|
||||||
active: false
|
|
||||||
LateinitUsage:
|
|
||||||
active: false
|
|
||||||
excludeAnnotatedProperties: ""
|
|
||||||
ignoreOnClassesPattern: ""
|
|
||||||
UnconditionalJumpStatementInLoop:
|
|
||||||
active: false
|
|
||||||
UnreachableCode:
|
|
||||||
active: true
|
|
||||||
UnsafeCallOnNullableType:
|
|
||||||
active: false
|
|
||||||
UnsafeCast:
|
|
||||||
active: false
|
|
||||||
UselessPostfixExpression:
|
|
||||||
active: false
|
|
||||||
WrongEqualsTypeParameter:
|
|
||||||
active: false
|
|
||||||
|
|
||||||
style:
|
|
||||||
active: true
|
|
||||||
CollapsibleIfStatements:
|
|
||||||
active: false
|
|
||||||
DataClassContainsFunctions:
|
|
||||||
active: false
|
|
||||||
conversionFunctionPrefix: 'to'
|
|
||||||
DestructuringDeclarationWithTooManyEntries:
|
|
||||||
active: true
|
|
||||||
maxDestructuringEntries: 5
|
|
||||||
EqualsNullCall:
|
|
||||||
active: true
|
|
||||||
ExplicitItLambdaParameter:
|
|
||||||
active: true
|
|
||||||
ExpressionBodySyntax:
|
|
||||||
active: false
|
|
||||||
includeLineWrapping: false
|
|
||||||
ForbiddenComment:
|
|
||||||
active: true
|
|
||||||
values: 'STOPSHIP:'
|
|
||||||
ForbiddenImport:
|
|
||||||
active: false
|
|
||||||
imports: ''
|
|
||||||
ForbiddenVoid:
|
|
||||||
active: false
|
|
||||||
FunctionOnlyReturningConstant:
|
|
||||||
active: false
|
|
||||||
ignoreOverridableFunction: true
|
|
||||||
excludedFunctions: 'describeContents'
|
|
||||||
LoopWithTooManyJumpStatements:
|
|
||||||
active: false
|
|
||||||
maxJumpCount: 1
|
|
||||||
MagicNumber:
|
|
||||||
active: false
|
|
||||||
ignoreNumbers: '-1,0,1,2'
|
|
||||||
ignoreHashCodeFunction: true
|
|
||||||
ignorePropertyDeclaration: false
|
|
||||||
ignoreConstantDeclaration: true
|
|
||||||
ignoreCompanionObjectPropertyDeclaration: true
|
|
||||||
ignoreAnnotation: false
|
|
||||||
ignoreNamedArgument: true
|
|
||||||
ignoreEnums: false
|
|
||||||
MandatoryBracesIfStatements:
|
|
||||||
active: true
|
|
||||||
MaxLineLength:
|
|
||||||
active: true
|
|
||||||
maxLineLength: 150
|
|
||||||
excludePackageStatements: true
|
|
||||||
excludeImportStatements: true
|
|
||||||
excludeCommentStatements: false
|
|
||||||
MayBeConst:
|
|
||||||
active: true
|
|
||||||
ModifierOrder:
|
|
||||||
active: true
|
|
||||||
NestedClassesVisibility:
|
|
||||||
active: false
|
|
||||||
NewLineAtEndOfFile:
|
|
||||||
active: true
|
|
||||||
NoTabs:
|
|
||||||
active: true
|
|
||||||
OptionalAbstractKeyword:
|
|
||||||
active: true
|
|
||||||
OptionalUnit:
|
|
||||||
active: false
|
|
||||||
OptionalWhenBraces:
|
|
||||||
active: false
|
|
||||||
PreferToOverPairSyntax:
|
|
||||||
active: true
|
|
||||||
ProtectedMemberInFinalClass:
|
|
||||||
active: true
|
|
||||||
RedundantVisibilityModifierRule:
|
|
||||||
active: true
|
|
||||||
ReturnCount:
|
|
||||||
active: true
|
|
||||||
max: 3
|
|
||||||
excludedFunctions: "equals"
|
|
||||||
SafeCast:
|
|
||||||
active: true
|
|
||||||
SerialVersionUIDInSerializableClass:
|
|
||||||
active: false
|
|
||||||
SpacingBetweenPackageAndImports:
|
|
||||||
active: true
|
|
||||||
ThrowsCount:
|
|
||||||
active: true
|
|
||||||
max: 3
|
|
||||||
TrailingWhitespace:
|
|
||||||
active: true
|
|
||||||
UnnecessaryAbstractClass:
|
|
||||||
active: false
|
|
||||||
excludeAnnotatedClasses: "dagger.Module"
|
|
||||||
UnnecessaryApply:
|
|
||||||
active: true
|
|
||||||
UnnecessaryInheritance:
|
|
||||||
active: true
|
|
||||||
UnnecessaryLet:
|
|
||||||
active: true
|
|
||||||
UnnecessaryParentheses:
|
|
||||||
active: true
|
|
||||||
UntilInsteadOfRangeTo:
|
|
||||||
active: true
|
|
||||||
UnusedImports:
|
|
||||||
active: true
|
|
||||||
UnusedPrivateClass:
|
|
||||||
active: true
|
|
||||||
UnusedPrivateMember:
|
|
||||||
active: true
|
|
||||||
allowedNames: "(_|ignored|expected|serialVersionUID)"
|
|
||||||
UtilityClassWithPublicConstructor:
|
|
||||||
active: false
|
|
||||||
VarCouldBeVal:
|
|
||||||
active: true
|
|
||||||
WildcardImport:
|
|
||||||
active: true
|
|
||||||
excludeImports: 'java.util.*,kotlinx.android.synthetic.*'
|
|
||||||
|
|
@ -1,536 +0,0 @@
|
||||||
#### ENABLED RULES ####
|
|
||||||
|
|
||||||
# Checks that there is no more than one statement per line
|
|
||||||
- name: MORE_THAN_ONE_STATEMENT_PER_LINE
|
|
||||||
enabled: true
|
|
||||||
# Checks that line breaks follow code style guide: rule 3.6
|
|
||||||
- name: WRONG_NEWLINES
|
|
||||||
enabled: true
|
|
||||||
configuration:
|
|
||||||
# If the number of parameters on one line is more than this threshold, all parameters will be placed on separate lines.
|
|
||||||
maxParametersInOneLine: 2
|
|
||||||
# 3 by default.
|
|
||||||
maxCallsInOneLine: 2
|
|
||||||
# Checks that indentation is correct
|
|
||||||
- name: WRONG_INDENTATION
|
|
||||||
enabled: true
|
|
||||||
configuration:
|
|
||||||
# Is newline at the end of a file needed
|
|
||||||
newlineAtEnd: true
|
|
||||||
# If true: in parameter list when parameters are split by newline they are indented with two indentations instead of one
|
|
||||||
extendedIndentOfParameters: false
|
|
||||||
# If true: if first parameter in parameter list is on the same line as opening parenthesis, then other parameters can be aligned with it
|
|
||||||
alignedParameters: true
|
|
||||||
# If true, expression bodies which begin on a separate line are indented
|
|
||||||
# using a continuation indent. The default is false.
|
|
||||||
#
|
|
||||||
# This flag is called CONTINUATION_INDENT_FOR_EXPRESSION_BODIES in IDEA and
|
|
||||||
# ij_kotlin_continuation_indent_for_expression_bodies in .editorconfig.
|
|
||||||
extendedIndentForExpressionBodies: false
|
|
||||||
# If true: if expression is split by newline after operator like +/-/`*`, then the next line is indented with two indentations instead of one
|
|
||||||
extendedIndentAfterOperators: true
|
|
||||||
# If true: when dot qualified expression starts on a new line, this line will be indented with two indentations instead of one
|
|
||||||
extendedIndentBeforeDot: false
|
|
||||||
# The indentation size for each file
|
|
||||||
indentationSize: 4
|
|
||||||
# Checks that braces are used in if, else, when, for, do, and while statements. Exception: single line ternary operator statement
|
|
||||||
- name: NO_BRACES_IN_CONDITIONALS_AND_LOOPS
|
|
||||||
enabled: true
|
|
||||||
# Checks that annotation is on a single line
|
|
||||||
- name: ANNOTATION_NEW_LINE
|
|
||||||
enabled: true
|
|
||||||
# Checks that the long lambda has parameters
|
|
||||||
- name: TOO_MANY_LINES_IN_LAMBDA
|
|
||||||
enabled: true
|
|
||||||
configuration:
|
|
||||||
maxLambdaLength: 1 # max length of lambda without parameters
|
|
||||||
# Checks that the line length is < lineLength parameter
|
|
||||||
- name: LONG_LINE
|
|
||||||
enabled: true
|
|
||||||
configuration:
|
|
||||||
lineLength: '120'
|
|
||||||
# Checks trailing comma
|
|
||||||
- name: TRAILING_COMMA
|
|
||||||
enabled: true
|
|
||||||
configuration:
|
|
||||||
# VALUE_ARGUMENT
|
|
||||||
valueArgument: true
|
|
||||||
# VALUE_PARAMETER
|
|
||||||
valueParameter: true
|
|
||||||
# REFERENCE_EXPRESSION
|
|
||||||
indices: true
|
|
||||||
# WHEN_CONDITION_WITH_EXPRESSION
|
|
||||||
whenConditions: true
|
|
||||||
# STRING_TEMPLATE
|
|
||||||
collectionLiteral: true
|
|
||||||
# TYPE_PROJECTION
|
|
||||||
typeArgument: true
|
|
||||||
# TYPE_PARAMETER
|
|
||||||
typeParameter: true
|
|
||||||
# DESTRUCTURING_DECLARATION_ENTRY
|
|
||||||
destructuringDeclaration: true
|
|
||||||
|
|
||||||
#### DISABLED DEFAULT RULES ####
|
|
||||||
|
|
||||||
# Checks that the Class/Enum/Interface name matches Pascal case
|
|
||||||
- name: CLASS_NAME_INCORRECT
|
|
||||||
enabled: false
|
|
||||||
# all code blocks with MyAnnotation will be ignored and not checked
|
|
||||||
ignoreAnnotated: [ MyAnnotation ]
|
|
||||||
# Checks that CONSTANT (treated as const val from companion object or class level) is in non UPPER_SNAKE_CASE
|
|
||||||
- name: CONSTANT_UPPERCASE
|
|
||||||
enabled: false
|
|
||||||
# Checks that enum value is in upper SNAKE_CASE or in PascalCase depending on the config. UPPER_SNAKE_CASE is the default, but can be changed by 'enumStyle' config
|
|
||||||
- name: ENUM_VALUE
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
# Two options: SNAKE_CASE (default), PascalCase
|
|
||||||
enumStyle: SNAKE_CASE
|
|
||||||
# Checks that class which extends any Exception class has Exception suffix
|
|
||||||
- name: EXCEPTION_SUFFIX
|
|
||||||
enabled: false
|
|
||||||
# Checks that file name has extension
|
|
||||||
- name: FILE_NAME_INCORRECT
|
|
||||||
enabled: false
|
|
||||||
# Checks that file name matches class name, if it is only one class in file
|
|
||||||
- name: FILE_NAME_MATCH_CLASS
|
|
||||||
enabled: false
|
|
||||||
# Checks that functions/methods which return boolean have special prefix like "is/should/e.t.c"
|
|
||||||
- name: FUNCTION_BOOLEAN_PREFIX
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
allowedPrefixes: "" # A list of functions that return boolean and are allowed to use. Input is in a form "foo, bar".
|
|
||||||
# Checks that function/method name is in lowerCamelCase
|
|
||||||
- name: FUNCTION_NAME_INCORRECT_CASE
|
|
||||||
enabled: false
|
|
||||||
# Checks that typealias name is in PascalCase
|
|
||||||
- name: TYPEALIAS_NAME_INCORRECT_CASE
|
|
||||||
enabled: false
|
|
||||||
# Checks that generic name doesn't contain more than 1 letter (capital). It can be followed by numbers, example: T12, T
|
|
||||||
- name: GENERIC_NAME
|
|
||||||
enabled: false
|
|
||||||
# Identifier length should be in range [2,64] except names that used in industry like {i, j} and 'e' for catching exceptions
|
|
||||||
- name: IDENTIFIER_LENGTH
|
|
||||||
enabled: false
|
|
||||||
# Checks that the object matches PascalCase
|
|
||||||
- name: OBJECT_NAME_INCORRECT
|
|
||||||
enabled: false
|
|
||||||
# Checks that package name is in correct (lower) case
|
|
||||||
- name: PACKAGE_NAME_INCORRECT_CASE
|
|
||||||
enabled: false
|
|
||||||
# Checks that package name starts with the company's domain
|
|
||||||
- name: PACKAGE_NAME_INCORRECT_PREFIX
|
|
||||||
enabled: false
|
|
||||||
# Checks that package name does not have incorrect symbols like underscore or non-ASCII letters/digits
|
|
||||||
- name: PACKAGE_NAME_INCORRECT_SYMBOLS
|
|
||||||
enabled: false
|
|
||||||
# Checks that the path for a file matches with a package name
|
|
||||||
- name: PACKAGE_NAME_INCORRECT_PATH
|
|
||||||
enabled: false
|
|
||||||
# Checks that package name is in the file
|
|
||||||
- name: PACKAGE_NAME_MISSING
|
|
||||||
enabled: false
|
|
||||||
# Checks that variable does not have prefix (like mVariable or M_VARIABLE)
|
|
||||||
- name: VARIABLE_HAS_PREFIX
|
|
||||||
enabled: false
|
|
||||||
# Checks that variable does not contain one single letter, only exceptions are fixed names that used in industry like {i, j}
|
|
||||||
- name: VARIABLE_NAME_INCORRECT
|
|
||||||
enabled: false
|
|
||||||
# Checks that the name of variable is in lowerCamelCase and contains only ASCII letters
|
|
||||||
- name: VARIABLE_NAME_INCORRECT_FORMAT
|
|
||||||
enabled: false
|
|
||||||
# Checks that functions have kdoc
|
|
||||||
- name: MISSING_KDOC_ON_FUNCTION
|
|
||||||
enabled: false
|
|
||||||
# Checks that on file level internal or public class or function has missing KDoc
|
|
||||||
- name: MISSING_KDOC_TOP_LEVEL
|
|
||||||
enabled: false
|
|
||||||
# Checks that accessible internal elements (protected, public, internal) in a class are documented
|
|
||||||
- name: MISSING_KDOC_CLASS_ELEMENTS
|
|
||||||
enabled: false
|
|
||||||
# Checks that accessible method parameters are documented in KDoc
|
|
||||||
- name: KDOC_WITHOUT_PARAM_TAG
|
|
||||||
enabled: false
|
|
||||||
# Checks that accessible method explicit return type is documented in KDoc
|
|
||||||
- name: KDOC_WITHOUT_RETURN_TAG
|
|
||||||
enabled: false
|
|
||||||
# Checks that accessible method throw keyword is documented in KDoc
|
|
||||||
- name: KDOC_WITHOUT_THROWS_TAG
|
|
||||||
enabled: false
|
|
||||||
# Checks that KDoc is not empty
|
|
||||||
- name: KDOC_EMPTY_KDOC
|
|
||||||
enabled: false
|
|
||||||
# Checks that underscore is correctly used to split package naming
|
|
||||||
- name: INCORRECT_PACKAGE_SEPARATOR
|
|
||||||
enabled: false
|
|
||||||
# Checks that code block doesn't contain kdoc comments
|
|
||||||
- name: COMMENTED_BY_KDOC
|
|
||||||
enabled: false
|
|
||||||
# Checks that there is no @deprecated tag in kdoc
|
|
||||||
- name: KDOC_NO_DEPRECATED_TAG
|
|
||||||
enabled: false
|
|
||||||
# Checks that there is no empty content in kdoc tags
|
|
||||||
- name: KDOC_NO_EMPTY_TAGS
|
|
||||||
enabled: false
|
|
||||||
# Checks that there is only one space after kdoc tag
|
|
||||||
- name: KDOC_WRONG_SPACES_AFTER_TAG
|
|
||||||
enabled: false
|
|
||||||
# Checks tags order in kDoc. `@param`, `@return`, `@throws`
|
|
||||||
- name: KDOC_WRONG_TAGS_ORDER
|
|
||||||
enabled: false
|
|
||||||
# Checks that there is no newline of empty KDoc line (with leading asterisk) between `@param`, `@return`, `@throws` tags
|
|
||||||
- name: KDOC_NO_NEWLINES_BETWEEN_BASIC_TAGS
|
|
||||||
enabled: false
|
|
||||||
# Checks that block of tags @param, @return, @throws is separated from previous part of KDoc by exactly one empty line
|
|
||||||
- name: KDOC_NEWLINES_BEFORE_BASIC_TAGS
|
|
||||||
enabled: false
|
|
||||||
# Checks that special tags `@apiNote`, `@implNote`, `@implSpec` have exactly one empty line after
|
|
||||||
- name: KDOC_NO_NEWLINE_AFTER_SPECIAL_TAGS
|
|
||||||
enabled: false
|
|
||||||
# Checks that kdoc does not contain @author tag or date
|
|
||||||
- name: KDOC_CONTAINS_DATE_OR_AUTHOR
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
versionRegex: \d+\.\d+\.\d+[-.\w\d]*
|
|
||||||
# Checks that KDoc does not contain single line with words 'return', 'get' or 'set'
|
|
||||||
- name: KDOC_TRIVIAL_KDOC_ON_FUNCTION
|
|
||||||
enabled: false
|
|
||||||
# Checks that there is newline after header KDoc
|
|
||||||
- name: HEADER_WRONG_FORMAT
|
|
||||||
enabled: false
|
|
||||||
# Checks that file with zero or >1 classes has header KDoc
|
|
||||||
- name: HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE
|
|
||||||
enabled: false
|
|
||||||
# Checks that copyright exists on top of file and is properly formatted (as a block comment)
|
|
||||||
- name: HEADER_MISSING_OR_WRONG_COPYRIGHT
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
isCopyrightMandatory: false
|
|
||||||
copyrightText: 'Copyright (c) Your Company Name Here. 2010-;@currYear;'
|
|
||||||
# Checks that header kdoc is located before package directive
|
|
||||||
- name: HEADER_NOT_BEFORE_PACKAGE
|
|
||||||
enabled: false
|
|
||||||
# Checks that file does not contain lines > maxSize
|
|
||||||
- name: FILE_IS_TOO_LONG
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
# number of lines
|
|
||||||
maxSize: '2000'
|
|
||||||
# Checks that file does not contain commented out code
|
|
||||||
- name: COMMENTED_OUT_CODE
|
|
||||||
enabled: false
|
|
||||||
# Checks that file does not contain only comments, imports and package directive
|
|
||||||
- name: FILE_CONTAINS_ONLY_COMMENTS
|
|
||||||
enabled: false
|
|
||||||
# Orders imports alphabetically
|
|
||||||
- name: FILE_UNORDERED_IMPORTS
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
# use logical imports grouping with sorting inside of a group
|
|
||||||
useRecommendedImportsOrder: true
|
|
||||||
# Checks that general order of code parts is right
|
|
||||||
- name: FILE_INCORRECT_BLOCKS_ORDER
|
|
||||||
enabled: false
|
|
||||||
# Checks that there is exactly one line between code blocks
|
|
||||||
- name: FILE_NO_BLANK_LINE_BETWEEN_BLOCKS
|
|
||||||
enabled: false
|
|
||||||
# Checks that there is no wildcard imports. Exception: allowedWildcards
|
|
||||||
- name: FILE_WILDCARD_IMPORTS
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
allowedWildcards: "" # Allowed wildcards for imports (e.g. "import org.cqfn.diktat.*, import org.jetbrains.kotlin.*")
|
|
||||||
useRecommendedImportsOrder: true
|
|
||||||
# Checks unused imports
|
|
||||||
- name: UNUSED_IMPORT
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
deleteUnusedImport: true
|
|
||||||
# Checks that the declaration part of a class-like code structures (class/interface/etc.) is in the proper order
|
|
||||||
- name: WRONG_ORDER_IN_CLASS_LIKE_STRUCTURES
|
|
||||||
enabled: false
|
|
||||||
# Checks that properties with comments are separated by a blank line
|
|
||||||
- name: BLANK_LINE_BETWEEN_PROPERTIES
|
|
||||||
enabled: false
|
|
||||||
# Checks top level order
|
|
||||||
- name: TOP_LEVEL_ORDER
|
|
||||||
enabled: false
|
|
||||||
# Checks that non-empty code blocks with braces follow the K&R style (1TBS or OTBS style)
|
|
||||||
- name: BRACES_BLOCK_STRUCTURE_ERROR
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
openBraceNewline: 'True'
|
|
||||||
closeBraceNewline: 'True'
|
|
||||||
# Checks that there is no empty blocks in a file.
|
|
||||||
# If allowEmptyBlocks is true, checks that it follows correct style (have a newline)
|
|
||||||
- name: EMPTY_BLOCK_STRUCTURE_ERROR
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
# Whether a newline after `{` is required in an empty block
|
|
||||||
styleEmptyBlockWithNewline: 'True'
|
|
||||||
allowEmptyBlocks: 'False'
|
|
||||||
# Checks that semicolons are not used at the end of a line
|
|
||||||
- name: REDUNDANT_SEMICOLON
|
|
||||||
enabled: false
|
|
||||||
# Checks that there are not too many consecutive spaces in line
|
|
||||||
- name: TOO_MANY_CONSECUTIVE_SPACES
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
# Maximum allowed number of consecutive spaces (not counting indentation)
|
|
||||||
maxSpaces: '1'
|
|
||||||
# Whether formatting for enums should be kept without checking
|
|
||||||
saveInitialFormattingForEnums: false
|
|
||||||
# Inspection that checks if a long dot qualified expression is used in condition or as an argument
|
|
||||||
- name: COMPLEX_EXPRESSION
|
|
||||||
enabled: false
|
|
||||||
# Checks that blank lines are used correctly.
|
|
||||||
# For example: triggers when there are too many blank lines between function declaration
|
|
||||||
- name: TOO_MANY_BLANK_LINES
|
|
||||||
enabled: false
|
|
||||||
# Checks that usage of horizontal spaces doesn't violate code style guide
|
|
||||||
- name: WRONG_WHITESPACE
|
|
||||||
enabled: false
|
|
||||||
# Checks that backticks (``) are not used in the identifier name, except the case when it is test method (marked with @Test annotation)
|
|
||||||
- name: BACKTICKS_PROHIBITED
|
|
||||||
enabled: false
|
|
||||||
# Checks that a single line concatenation of strings is not used
|
|
||||||
- name: STRING_CONCATENATION
|
|
||||||
enabled: false
|
|
||||||
# Checks that each when statement have else in the end
|
|
||||||
- name: WHEN_WITHOUT_ELSE
|
|
||||||
enabled: false
|
|
||||||
# Checks that enum structure is correct: enum entries should be separated by comma and line break and last entry should have semicolon in the end.
|
|
||||||
- name: ENUMS_SEPARATED
|
|
||||||
enabled: false
|
|
||||||
# Checks that value on integer or float constant is not too big
|
|
||||||
- name: LONG_NUMERICAL_VALUES_SEPARATED
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
# Maximum number of digits which are not split
|
|
||||||
maxNumberLength: '5'
|
|
||||||
# Maximum number of digits between separators
|
|
||||||
maxBlockLength: '3'
|
|
||||||
# Checks magic number
|
|
||||||
- name: MAGIC_NUMBER
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
# Ignore numbers from test
|
|
||||||
ignoreTest: "true"
|
|
||||||
# Ignore numbers
|
|
||||||
ignoreNumbers: "-1, 1, 0, 2, 0U, 1U, 2U, -1L, 0L, 1L, 2L, 0UL, 1UL, 2UL"
|
|
||||||
# Is ignore override hashCode function
|
|
||||||
ignoreHashCodeFunction: "true"
|
|
||||||
# Is ignore property
|
|
||||||
ignorePropertyDeclaration: "false"
|
|
||||||
# Is ignore local variable
|
|
||||||
ignoreLocalVariableDeclaration: "false"
|
|
||||||
# Is ignore constant
|
|
||||||
ignoreConstantDeclaration: "true"
|
|
||||||
# Is ignore property in companion object
|
|
||||||
ignoreCompanionObjectPropertyDeclaration: "true"
|
|
||||||
# Is ignore numbers in enum
|
|
||||||
ignoreEnums: "false"
|
|
||||||
# Is ignore number in ranges
|
|
||||||
ignoreRanges: "false"
|
|
||||||
# Is ignore number in extension function
|
|
||||||
ignoreExtensionFunctions: "false"
|
|
||||||
# Checks that order of enum values or constant property inside companion is correct
|
|
||||||
- name: WRONG_DECLARATIONS_ORDER
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
# Whether enum members should be sorted alphabetically
|
|
||||||
sortEnum: true
|
|
||||||
# Whether class properties should be sorted alphabetically
|
|
||||||
sortProperty: true
|
|
||||||
# Checks that multiple modifiers sequence is in the correct order
|
|
||||||
- name: WRONG_MULTIPLE_MODIFIERS_ORDER
|
|
||||||
enabled: false
|
|
||||||
# Checks that identifier has appropriate name (See table of rule 1.2 part 6)
|
|
||||||
- name: CONFUSING_IDENTIFIER_NAMING
|
|
||||||
enabled: false
|
|
||||||
# Checks year in the copyright
|
|
||||||
- name: WRONG_COPYRIGHT_YEAR
|
|
||||||
enabled: false
|
|
||||||
# Inspection that checks if local variables are declared close to the first usage site
|
|
||||||
- name: LOCAL_VARIABLE_EARLY_DECLARATION
|
|
||||||
enabled: false
|
|
||||||
# Try to avoid initialize val by null (e.g. val a: Int? = null -> val a: Int = 0)
|
|
||||||
- name: NULLABLE_PROPERTY_TYPE
|
|
||||||
enabled: false
|
|
||||||
# Inspection that checks if there is a blank line before kDoc and none after
|
|
||||||
- name: WRONG_NEWLINES_AROUND_KDOC
|
|
||||||
enabled: false
|
|
||||||
# Inspection that checks if there is no blank lines before first comment
|
|
||||||
- name: FIRST_COMMENT_NO_BLANK_LINE
|
|
||||||
enabled: false
|
|
||||||
# Inspection that checks if there are blank lines between code and comment and between code start token and comment's text
|
|
||||||
- name: COMMENT_WHITE_SPACE
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
maxSpacesBeforeComment: 2
|
|
||||||
maxSpacesInComment: 1
|
|
||||||
# Inspection that checks if all comment's are inside if-else code blocks. Exception is general if comment
|
|
||||||
- name: IF_ELSE_COMMENTS
|
|
||||||
enabled: false
|
|
||||||
# Type aliases provide alternative names for existing types when type's reference text is longer 25 chars
|
|
||||||
- name: TYPE_ALIAS
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
typeReferenceLength: '25' # max length of type reference
|
|
||||||
# Checks if casting can be omitted
|
|
||||||
- name: SMART_CAST_NEEDED
|
|
||||||
enabled: false
|
|
||||||
# Checks that variables of generic types have explicit type declaration
|
|
||||||
- name: GENERIC_VARIABLE_WRONG_DECLARATION
|
|
||||||
enabled: false
|
|
||||||
# Inspection that checks if string template has redundant curly braces
|
|
||||||
- name: STRING_TEMPLATE_CURLY_BRACES
|
|
||||||
enabled: false
|
|
||||||
# Variables with `val` modifier - are immutable (read-only). Usage of such variables instead of `var` variables increases
|
|
||||||
# robustness and readability of code, because `var` variables can be reassigned several times in the business logic.
|
|
||||||
# This rule prohibits usage of `var`s as local variables - the only exception is accumulators and counters
|
|
||||||
- name: SAY_NO_TO_VAR
|
|
||||||
enabled: false
|
|
||||||
# Inspection that checks if string template has redundant quotes
|
|
||||||
- name: STRING_TEMPLATE_QUOTES
|
|
||||||
enabled: false
|
|
||||||
# Check if there are redundant nested if-statements, which could be collapsed into a single one by concatenating their conditions
|
|
||||||
- name: COLLAPSE_IF_STATEMENTS
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
startCollapseFromNestedLevel: 2
|
|
||||||
# Checks that floating-point values are not used in arithmetic expressions
|
|
||||||
- name: FLOAT_IN_ACCURATE_CALCULATIONS
|
|
||||||
enabled: false
|
|
||||||
# Checks that function length isn't too long
|
|
||||||
- name: TOO_LONG_FUNCTION
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
maxFunctionLength: '30' # max length of function
|
|
||||||
isIncludeHeader: 'false' # count function's header
|
|
||||||
# Warns if there are nested functions
|
|
||||||
- name: AVOID_NESTED_FUNCTIONS
|
|
||||||
enabled: false
|
|
||||||
# Checks that lambda inside function parameters is in the end
|
|
||||||
- name: LAMBDA_IS_NOT_LAST_PARAMETER
|
|
||||||
enabled: false
|
|
||||||
# Checks that function doesn't contains too many parameters
|
|
||||||
- name: TOO_MANY_PARAMETERS
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
maxParameterListSize: '5' # max parameters size
|
|
||||||
# Checks that function doesn't have too many nested blocks
|
|
||||||
- name: NESTED_BLOCK
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
maxNestedBlockQuantity: '4'
|
|
||||||
# Checks that function use default values, instead overloading
|
|
||||||
- name: WRONG_OVERLOADING_FUNCTION_ARGUMENTS
|
|
||||||
enabled: false
|
|
||||||
# Checks that using runBlocking inside async block code
|
|
||||||
- name: RUN_BLOCKING_INSIDE_ASYNC
|
|
||||||
enabled: false
|
|
||||||
# Checks that property in constructor doesn't contain comment
|
|
||||||
- name: KDOC_NO_CONSTRUCTOR_PROPERTY
|
|
||||||
enabled: false
|
|
||||||
# Checks that using unnecessary, custom label
|
|
||||||
- name: CUSTOM_LABEL
|
|
||||||
enabled: false
|
|
||||||
# Check that lambda with inner lambda doesn't use implicit parameter
|
|
||||||
- name: PARAMETER_NAME_IN_OUTER_LAMBDA
|
|
||||||
enabled: false
|
|
||||||
# Checks that property in KDoc present in class
|
|
||||||
- name: KDOC_EXTRA_PROPERTY
|
|
||||||
enabled: false
|
|
||||||
# There's a property in KDoc which is already present
|
|
||||||
- name: KDOC_DUPLICATE_PROPERTY
|
|
||||||
enabled: false
|
|
||||||
# Checks that KDoc in constructor has property tag but with comment inside constructor
|
|
||||||
- name: KDOC_NO_CONSTRUCTOR_PROPERTY_WITH_COMMENT
|
|
||||||
enabled: false
|
|
||||||
# if a class has single constructor, it should be converted to a primary constructor
|
|
||||||
- name: SINGLE_CONSTRUCTOR_SHOULD_BE_PRIMARY
|
|
||||||
enabled: false
|
|
||||||
# Checks if class can be made as data class
|
|
||||||
- name: USE_DATA_CLASS
|
|
||||||
enabled: false
|
|
||||||
# Checks that never use the name of a variable in the custom getter or setter
|
|
||||||
- name: WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR
|
|
||||||
enabled: false
|
|
||||||
# Checks that classes have only one init block
|
|
||||||
- name: MULTIPLE_INIT_BLOCKS
|
|
||||||
enabled: false
|
|
||||||
# Checks that there are abstract functions in abstract class
|
|
||||||
- name: CLASS_SHOULD_NOT_BE_ABSTRACT
|
|
||||||
enabled: false
|
|
||||||
# Checks if there are any trivial getters or setters
|
|
||||||
- name: TRIVIAL_ACCESSORS_ARE_NOT_RECOMMENDED
|
|
||||||
enabled: false
|
|
||||||
# Checks that no custom getters and setters are used for properties. It is a more wide rule than TRIVIAL_ACCESSORS_ARE_NOT_RECOMMENDED
|
|
||||||
# Kotlin compiler automatically generates `get` and `set` methods for properties and also lets the possibility to override it.
|
|
||||||
# But in all cases it is very confusing when `get` and `set` are overridden for a developer who uses this particular class.
|
|
||||||
# Developer expects to get the value of the property, but receives some unknown value and some extra side effect hidden by the custom getter/setter.
|
|
||||||
# Use extra functions for it instead.
|
|
||||||
- name: CUSTOM_GETTERS_SETTERS
|
|
||||||
enabled: false
|
|
||||||
# Checks if null-check was used explicitly (for example: if (a == null))
|
|
||||||
# Try to avoid explicit null checks (explicit comparison with `null`)
|
|
||||||
# Kotlin is declared as [Null-safe](https://kotlinlang.org/docs/reference/null-safety.html) language.
|
|
||||||
# But Kotlin architects wanted Kotlin to be fully compatible with Java, that's why `null` keyword was also introduced in Kotlin.
|
|
||||||
# There are several code-structures that can be used in Kotlin to avoid null-checks. For example: `?:`, `.let {}`, `.also {}`, e.t.c
|
|
||||||
- name: AVOID_NULL_CHECKS
|
|
||||||
enabled: false
|
|
||||||
# Checks if class instantiation can be wrapped in `apply` for better readability
|
|
||||||
- name: COMPACT_OBJECT_INITIALIZATION
|
|
||||||
enabled: false
|
|
||||||
# Checks explicit supertype qualification
|
|
||||||
- name: USELESS_SUPERTYPE
|
|
||||||
enabled: false
|
|
||||||
# Checks if extension function with the same signature don't have related classes
|
|
||||||
- name: EXTENSION_FUNCTION_SAME_SIGNATURE
|
|
||||||
enabled: false
|
|
||||||
# Checks if there is empty primary constructor
|
|
||||||
- name: EMPTY_PRIMARY_CONSTRUCTOR
|
|
||||||
enabled: false
|
|
||||||
# In case of not using field keyword in property accessors,
|
|
||||||
# there should be explicit backing property with the name of real property
|
|
||||||
# Example: val table get() {if (_table == null) ...} -> table should have _table
|
|
||||||
- name: NO_CORRESPONDING_PROPERTY
|
|
||||||
enabled: false
|
|
||||||
# Checks if there is class/object that can be replace with extension function
|
|
||||||
- name: AVOID_USING_UTILITY_CLASS
|
|
||||||
enabled: false
|
|
||||||
# If there is stateless class it is preferred to use object
|
|
||||||
- name: OBJECT_IS_PREFERRED
|
|
||||||
enabled: false
|
|
||||||
# If there exists negated version of function you should prefer it instead of !functionCall
|
|
||||||
- name: INVERSE_FUNCTION_PREFERRED
|
|
||||||
enabled: false
|
|
||||||
# Checks if class can be converted to inline class
|
|
||||||
- name: INLINE_CLASS_CAN_BE_USED
|
|
||||||
enabled: false
|
|
||||||
# If file contains class, then it can't contain extension functions for the same class
|
|
||||||
- name: EXTENSION_FUNCTION_WITH_CLASS
|
|
||||||
enabled: false
|
|
||||||
# Check if kts script contains other functions except run code
|
|
||||||
- name: RUN_IN_SCRIPT
|
|
||||||
enabled: false
|
|
||||||
# Check if boolean expression can be simplified
|
|
||||||
- name: COMPLEX_BOOLEAN_EXPRESSION
|
|
||||||
enabled: false
|
|
||||||
# Check if range can replace with until or `rangeTo` function with range
|
|
||||||
- name: CONVENTIONAL_RANGE
|
|
||||||
enabled: false
|
|
||||||
configuration:
|
|
||||||
isRangeToIgnore: false
|
|
||||||
# Check if there is a call of print()\println() or console.log(). Assumption that it's a debug print
|
|
||||||
- name: DEBUG_PRINT
|
|
||||||
enabled: false
|
|
||||||
# Check that typealias name is in PascalCase
|
|
||||||
- name: TYPEALIAS_NAME_INCORRECT_CASE
|
|
||||||
enabled: false
|
|
||||||
# Should change property length - 1 to property lastIndex
|
|
||||||
- name: USE_LAST_INDEX
|
|
||||||
enabled: false
|
|
||||||
# Only properties from the primary constructor should be documented in a @property tag in class KDoc
|
|
||||||
- name: KDOC_NO_CLASS_BODY_PROPERTIES_IN_HEADER
|
|
||||||
enabled: false
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
package ru.touchin.exception.handler.spring.configurations
|
package ru.touchin.exception.handler.spring.configurations
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean
|
import org.springframework.context.annotation.Bean
|
||||||
import org.springframework.context.annotation.ComponentScan
|
import org.springframework.context.annotation.ComponentScan
|
||||||
import org.springframework.context.annotation.Configuration
|
import org.springframework.context.annotation.Configuration
|
||||||
|
|
|
||||||
|
|
@ -33,14 +33,10 @@ class ExceptionHandlerAdvice(
|
||||||
|
|
||||||
val body = exceptionResponseBodyCreator(result.apiError)
|
val body = exceptionResponseBodyCreator(result.apiError)
|
||||||
|
|
||||||
val headers = if (exceptionResolverProperties.includeHeaders) {
|
val headers = if (exceptionResolverProperties.includeHeaders) HttpHeaders().apply {
|
||||||
HttpHeaders().apply {
|
set("X-Error-Code", result.apiError.errorCode.toString())
|
||||||
set("X-Error-Code", result.apiError.errorCode.toString())
|
set("X-Error-Message", result.apiError.errorMessage)
|
||||||
set("X-Error-Message", result.apiError.errorMessage)
|
} else null
|
||||||
}
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
return ResponseEntity(body, headers, result.status)
|
return ResponseEntity(body, headers, result.status)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
springBootVersion=2.5.3
|
springBootVersion=2.5.3
|
||||||
springDependencyManagementVersion=1.0.11.RELEASE
|
springDependencyManagementVersion=1.0.11.RELEASE
|
||||||
detektGradlePluginVersion=1.18.0
|
kotlinVersion=1.5.21
|
||||||
diktatGradlePluginVersion=1.2.5
|
|
||||||
kotlinVersion=1.6.21
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import org.aspectj.lang.ProceedingJoinPoint
|
||||||
import org.aspectj.lang.annotation.Around
|
import org.aspectj.lang.annotation.Around
|
||||||
import org.aspectj.lang.annotation.Aspect
|
import org.aspectj.lang.annotation.Aspect
|
||||||
import org.aspectj.lang.reflect.MethodSignature
|
import org.aspectj.lang.reflect.MethodSignature
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
import ru.touchin.logger.spring.annotations.AutoLogging
|
import ru.touchin.logger.spring.annotations.AutoLogging
|
||||||
import ru.touchin.logger.spring.annotations.LogValue
|
import ru.touchin.logger.spring.annotations.LogValue
|
||||||
import ru.touchin.logger.builder.LogDataItem
|
import ru.touchin.logger.builder.LogDataItem
|
||||||
|
|
@ -23,7 +22,6 @@ class LogAspect(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@Around("@annotation(autoLoggingAnnotation)")
|
@Around("@annotation(autoLoggingAnnotation)")
|
||||||
@Suppress("TooGenericExceptionCaught")
|
|
||||||
fun logInvocation(pjp: ProceedingJoinPoint, autoLoggingAnnotation: AutoLogging): Any? {
|
fun logInvocation(pjp: ProceedingJoinPoint, autoLoggingAnnotation: AutoLogging): Any? {
|
||||||
val duration = LogDuration()
|
val duration = LogDuration()
|
||||||
|
|
||||||
|
|
@ -48,11 +46,8 @@ class LogAspect(
|
||||||
.build()
|
.build()
|
||||||
.error()
|
.error()
|
||||||
} catch (logError: Throwable) {
|
} catch (logError: Throwable) {
|
||||||
LoggerFactory.getLogger(this::class.java)
|
error.printStackTrace()
|
||||||
.let { logger ->
|
logError.printStackTrace()
|
||||||
logger.error("Cannot build logger", error)
|
|
||||||
logger.error("Cannot create logger", logError)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ interface LogBuilder<T> {
|
||||||
fun addData(vararg items: LogDataItem): LogBuilder<T>
|
fun addData(vararg items: LogDataItem): LogBuilder<T>
|
||||||
fun setMethod(method: String): LogBuilder<T>
|
fun setMethod(method: String): LogBuilder<T>
|
||||||
fun setContext(context: LogExecutionContextData): LogBuilder<LogData>
|
fun setContext(context: LogExecutionContextData): LogBuilder<LogData>
|
||||||
fun setContext(): LogBuilder<LogData>
|
|
||||||
fun build(): Log<T>
|
fun build(): Log<T>
|
||||||
fun isEnabled(logLevel: LogLevel): Boolean
|
fun isEnabled(logLevel: LogLevel): Boolean
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,8 @@ class LogBuilderImpl(
|
||||||
logData.method = method
|
logData.method = method
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setContext(): LogBuilder<LogData> = also {
|
|
||||||
logData.ctx = LoggerExecutionContext.current.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setContext(context: LogExecutionContextData): LogBuilder<LogData> = also {
|
override fun setContext(context: LogExecutionContextData): LogBuilder<LogData> = also {
|
||||||
logData.ctx = context
|
logData.ctx = LoggerExecutionContext.current.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun build(): Log<LogData> {
|
override fun build(): Log<LogData> {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package ru.touchin.logger.context
|
package ru.touchin.logger.context
|
||||||
|
|
||||||
@Suppress("unused", "EnumEntryName", "EnumNaming")
|
@Suppress("unused", "EnumEntryName")
|
||||||
enum class DefaultContextFields {
|
enum class DefaultContextFields {
|
||||||
id,
|
id,
|
||||||
host,
|
host,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
package ru.touchin.logger.dto
|
package ru.touchin.logger.dto
|
||||||
|
|
||||||
enum class LogLevel {
|
enum class LogLevel {
|
||||||
Trace, Debug, Info, Error
|
Trace, Info, Error
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,5 @@
|
||||||
package ru.touchin.logger.log
|
package ru.touchin.logger.log
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature
|
|
||||||
import com.fasterxml.jackson.databind.json.JsonMapper
|
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
|
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import ru.touchin.logger.dto.LogLevel
|
import ru.touchin.logger.dto.LogLevel
|
||||||
import ru.touchin.logger.dto.LogData
|
import ru.touchin.logger.dto.LogData
|
||||||
|
|
@ -31,14 +26,6 @@ abstract class AbstractLog(clazz: Class<*>) : Log<LogData> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun debug() {
|
|
||||||
if (logger.isDebugEnabled) {
|
|
||||||
val logMessage = getMessage()
|
|
||||||
|
|
||||||
logger.debug(logMessage.message, logMessage.error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun info() {
|
override fun info() {
|
||||||
if (logger.isInfoEnabled) {
|
if (logger.isInfoEnabled) {
|
||||||
val logMessage = getMessage()
|
val logMessage = getMessage()
|
||||||
|
|
@ -66,20 +53,9 @@ abstract class AbstractLog(clazz: Class<*>) : Log<LogData> {
|
||||||
override fun isEnabled(level: LogLevel): Boolean {
|
override fun isEnabled(level: LogLevel): Boolean {
|
||||||
return when(level) {
|
return when(level) {
|
||||||
LogLevel.Trace -> logger.isTraceEnabled
|
LogLevel.Trace -> logger.isTraceEnabled
|
||||||
LogLevel.Debug -> logger.isDebugEnabled
|
|
||||||
LogLevel.Info -> logger.isInfoEnabled
|
LogLevel.Info -> logger.isInfoEnabled
|
||||||
LogLevel.Error -> logger.isErrorEnabled
|
LogLevel.Error -> logger.isErrorEnabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun objectMapper() = objectMapper
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val objectMapper: ObjectMapper = JsonMapper.builder()
|
|
||||||
.addModule(JavaTimeModule())
|
|
||||||
.build()
|
|
||||||
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
|
|
||||||
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,33 @@
|
||||||
package ru.touchin.logger.log
|
package ru.touchin.logger.log
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude
|
||||||
import com.fasterxml.jackson.databind.JsonNode
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature
|
||||||
|
import com.fasterxml.jackson.databind.json.JsonMapper
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode
|
import com.fasterxml.jackson.databind.node.ObjectNode
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
|
||||||
import ru.touchin.logger.dto.LogError
|
import ru.touchin.logger.dto.LogError
|
||||||
import ru.touchin.logger.dto.LogError.Companion.stackTraceAsString
|
import ru.touchin.logger.dto.LogError.Companion.stackTraceAsString
|
||||||
import ru.touchin.logger.dto.LogError.Companion.toLogError
|
import ru.touchin.logger.dto.LogError.Companion.toLogError
|
||||||
|
|
||||||
open class JsonLogImpl(clazz: Class<*>) : AbstractLog(clazz) {
|
open class JsonLogImpl(clazz: Class<*>) : AbstractLog(clazz) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val objectMapper: ObjectMapper = JsonMapper.builder()
|
||||||
|
.addModule(JavaTimeModule())
|
||||||
|
.build()
|
||||||
|
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
|
||||||
|
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
||||||
|
}
|
||||||
|
|
||||||
private fun toJson(): JsonNode {
|
private fun toJson(): JsonNode {
|
||||||
val result = objectMapper().convertValue(logData, ObjectNode::class.java)
|
val result = objectMapper.convertValue(logData, ObjectNode::class.java)
|
||||||
|
|
||||||
logData.error
|
logData.error
|
||||||
?.toLogError()
|
?.toLogError()
|
||||||
?.let {
|
?.let {
|
||||||
objectMapper().convertValue(it, JsonNode::class.java)
|
objectMapper.convertValue(it, JsonNode::class.java)
|
||||||
}
|
}
|
||||||
?.let {
|
?.let {
|
||||||
result.remove("error")
|
result.remove("error")
|
||||||
|
|
@ -26,7 +39,7 @@ open class JsonLogImpl(clazz: Class<*>) : AbstractLog(clazz) {
|
||||||
|
|
||||||
override fun getMessage(): LogMessage {
|
override fun getMessage(): LogMessage {
|
||||||
val message = runCatching {
|
val message = runCatching {
|
||||||
objectMapper().writeValueAsString(toJson())
|
objectMapper.writeValueAsString(toJson())
|
||||||
}.getOrElse { throwable ->
|
}.getOrElse { throwable ->
|
||||||
"""
|
"""
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ import ru.touchin.logger.dto.LogLevel
|
||||||
interface Log<T> {
|
interface Log<T> {
|
||||||
|
|
||||||
var logData: T
|
var logData: T
|
||||||
|
|
||||||
fun trace()
|
fun trace()
|
||||||
fun debug()
|
|
||||||
fun info()
|
fun info()
|
||||||
fun error()
|
fun error()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ class SimpleLogImpl(clazz: Class<*>): AbstractLog(clazz) {
|
||||||
|
|
||||||
override fun getMessage(): LogMessage {
|
override fun getMessage(): LogMessage {
|
||||||
val builder = StringBuilder()
|
val builder = StringBuilder()
|
||||||
val pretty = objectMapper().writerWithDefaultPrettyPrinter()
|
|
||||||
|
|
||||||
builder.append("\n\ttags: ${logData.tags.joinToString(",")}")
|
builder.append("\n\ttags: ${logData.tags.joinToString(",")}")
|
||||||
|
|
||||||
|
|
@ -12,18 +11,6 @@ class SimpleLogImpl(clazz: Class<*>): AbstractLog(clazz) {
|
||||||
builder.append("\n\tduration: ${logData.duration}ms")
|
builder.append("\n\tduration: ${logData.duration}ms")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logData.method != null) {
|
|
||||||
builder.append("\n\tmethod: ${logData.method}")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!logData.ctx.isNullOrEmpty()) {
|
|
||||||
builder.append("\n\tcontext:\n${pretty.writeValueAsString(logData.ctx)}")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logData.data.isNotEmpty()) {
|
|
||||||
builder.append("\n\tdata:\n${pretty.writeValueAsString(logData.data)}")
|
|
||||||
}
|
|
||||||
|
|
||||||
return LogMessage(
|
return LogMessage(
|
||||||
message = builder.toString(),
|
message = builder.toString(),
|
||||||
error = logData.error
|
error = logData.error
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import com.google.firebase.messaging.AndroidNotification
|
||||||
import com.google.firebase.messaging.ApnsConfig
|
import com.google.firebase.messaging.ApnsConfig
|
||||||
import com.google.firebase.messaging.Aps
|
import com.google.firebase.messaging.Aps
|
||||||
import com.google.firebase.messaging.Message
|
import com.google.firebase.messaging.Message
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier
|
||||||
import org.springframework.stereotype.Component
|
import org.springframework.stereotype.Component
|
||||||
import ru.touchin.push.message.provider.dto.PushMessageNotification
|
import ru.touchin.push.message.provider.dto.PushMessageNotification
|
||||||
import ru.touchin.push.message.provider.dto.request.PushTokenMessage
|
import ru.touchin.push.message.provider.dto.request.PushTokenMessage
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,7 @@ internal open class ConditionalResponse<S, F>(
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// Only one value should be present
|
// Only one value should be present
|
||||||
val hasSuccessValue = success != null
|
check((success == null) != (failure == null))
|
||||||
val hasFailureValue = failure != null
|
|
||||||
|
|
||||||
check(hasSuccessValue != hasFailureValue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val isSuccess: Boolean = success != null
|
val isSuccess: Boolean = success != null
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import org.springframework.web.reactive.function.client.WebClient
|
||||||
import ru.touchin.common.spring.web.webclient.dto.RequestLogData
|
import ru.touchin.common.spring.web.webclient.dto.RequestLogData
|
||||||
import ru.touchin.common.spring.web.webclient.logger.WebClientLogger
|
import ru.touchin.common.spring.web.webclient.logger.WebClientLogger
|
||||||
import ru.touchin.push.message.provider.hpk.base.clients.ConfigurableWebClient
|
import ru.touchin.push.message.provider.hpk.base.clients.ConfigurableWebClient
|
||||||
|
import ru.touchin.push.message.provider.hpk.clients.hms_hpk.bodies.HmsHpkMessagesSendBody
|
||||||
import ru.touchin.push.message.provider.hpk.clients.hms_hpk.requests.HmsHpkMessagesSendRequest
|
import ru.touchin.push.message.provider.hpk.clients.hms_hpk.requests.HmsHpkMessagesSendRequest
|
||||||
import ru.touchin.push.message.provider.hpk.clients.hms_hpk.responses.HmsHpkResponse
|
import ru.touchin.push.message.provider.hpk.clients.hms_hpk.responses.HmsHpkResponse
|
||||||
import ru.touchin.push.message.provider.hpk.properties.HpkProperties
|
import ru.touchin.push.message.provider.hpk.properties.HpkProperties
|
||||||
|
|
@ -18,7 +19,6 @@ import ru.touchin.push.message.provider.hpk.properties.HpkProperties
|
||||||
* Client for Huawei Push Kit.
|
* Client for Huawei Push Kit.
|
||||||
* @see <a href="https://developer.huawei.com/consumer/en/doc/development/HMSCore-References/https-send-api-0000001050986197">Documentation</a>
|
* @see <a href="https://developer.huawei.com/consumer/en/doc/development/HMSCore-References/https-send-api-0000001050986197">Documentation</a>
|
||||||
*/
|
*/
|
||||||
@Suppress("LongLine")
|
|
||||||
@Component
|
@Component
|
||||||
class HmsHpkWebClient(
|
class HmsHpkWebClient(
|
||||||
webClientLogger: WebClientLogger,
|
webClientLogger: WebClientLogger,
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,7 @@ internal data class AndroidConfig private constructor(
|
||||||
*
|
*
|
||||||
* 1-100: message cache group ID. Messages are cached by group. Each group can cache only one message for each app.
|
* 1-100: message cache group ID. Messages are cached by group. Each group can cache only one message for each app.
|
||||||
*
|
*
|
||||||
* For example, if you send 10 messages and set collapse_key to 1 for the first five messages and to 2 for the rest,
|
* For example, if you send 10 messages and set collapse_key to 1 for the first five messages and to 2 for the rest, the latest message whose value of collapse_key is 1 and the latest message whose value of collapse_key is 2 are sent to the user after the user's device goes online.
|
||||||
* the latest message whose value of collapse_key is 1 and
|
|
||||||
* the latest message whose value of collapse_key is 2 are sent to the user after the user's device goes online.
|
|
||||||
*
|
*
|
||||||
* The default value is -1.
|
* The default value is -1.
|
||||||
* */
|
* */
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,11 @@ internal data class Message private constructor(
|
||||||
val notification: Notification?,
|
val notification: Notification?,
|
||||||
/** Android message push control. */
|
/** Android message push control. */
|
||||||
@JsonProperty("android")
|
@JsonProperty("android")
|
||||||
val androidConfig: AndroidConfig?,
|
val android: AndroidConfig?,
|
||||||
@JsonProperty("apns")
|
@JsonProperty("apns")
|
||||||
val apnsConfig: ApnsConfig?,
|
val apns: ApnsConfig?,
|
||||||
@JsonProperty("webpush")
|
@JsonProperty("webpush")
|
||||||
val webPushConfig: WebPushConfig?,
|
val webpush: WebPushConfig?,
|
||||||
/** Push token of the target user of a message. */
|
/** Push token of the target user of a message. */
|
||||||
val token: Collection<String>?,
|
val token: Collection<String>?,
|
||||||
/** Topic subscribed by the target user of a message. */
|
/** Topic subscribed by the target user of a message. */
|
||||||
|
|
@ -42,9 +42,9 @@ internal data class Message private constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
notification?.also { Notification.validator.check(it) }
|
notification?.also { Notification.validator.check(it) }
|
||||||
androidConfig?.also { AndroidConfig.validator.check(it, notification) }
|
android?.also { AndroidConfig.validator.check(it, notification) }
|
||||||
apnsConfig?.also { ApnsConfig.validator.check(it) }
|
apns?.also { ApnsConfig.validator.check(it) }
|
||||||
webPushConfig?.also { WebPushConfig.validator.check(it) }
|
webpush?.also { WebPushConfig.validator.check(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,8 +64,8 @@ internal data class Message private constructor(
|
||||||
private var data: String? = null
|
private var data: String? = null
|
||||||
private var notification: Notification? = null
|
private var notification: Notification? = null
|
||||||
private var androidConfig: AndroidConfig? = null
|
private var androidConfig: AndroidConfig? = null
|
||||||
private var apnsConfig: ApnsConfig? = null
|
private var apns: ApnsConfig? = null
|
||||||
private var webPushConfig: WebPushConfig? = null
|
private var webpush: WebPushConfig? = null
|
||||||
private val token: MutableList<String> = mutableListOf()
|
private val token: MutableList<String> = mutableListOf()
|
||||||
private var topic: String? = null
|
private var topic: String? = null
|
||||||
private var condition: String? = null
|
private var condition: String? = null
|
||||||
|
|
@ -85,13 +85,13 @@ internal data class Message private constructor(
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setApns(apnsConfig: ApnsConfig): Builder {
|
fun setApns(apns: ApnsConfig): Builder {
|
||||||
this.apnsConfig = apnsConfig
|
this.apns = apns
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setWebpush(webPushConfig: WebPushConfig): Builder {
|
fun setWebpush(webpush: WebPushConfig): Builder {
|
||||||
this.webPushConfig = webPushConfig
|
this.webpush = webpush
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,9 +114,9 @@ internal data class Message private constructor(
|
||||||
return Message(
|
return Message(
|
||||||
data = data,
|
data = data,
|
||||||
notification = notification,
|
notification = notification,
|
||||||
androidConfig = androidConfig,
|
android = androidConfig,
|
||||||
apnsConfig = apnsConfig,
|
apns = apns,
|
||||||
webPushConfig = webPushConfig,
|
webpush = webpush,
|
||||||
topic = topic,
|
topic = topic,
|
||||||
condition = condition,
|
condition = condition,
|
||||||
token = token.takeIf(Collection<*>::isNotEmpty),
|
token = token.takeIf(Collection<*>::isNotEmpty),
|
||||||
|
|
|
||||||
|
|
@ -30,13 +30,13 @@ internal data class WebPushConfig private constructor(
|
||||||
|
|
||||||
class Builder : Buildable {
|
class Builder : Buildable {
|
||||||
|
|
||||||
private var webPushHeaders: WebPushHeaders? = null
|
private var headers: WebPushHeaders? = null
|
||||||
private var data: String? = null
|
private var data: String? = null
|
||||||
private var webNotification: WebNotification? = null
|
private var notification: WebNotification? = null
|
||||||
private var webHmsOptions: WebHmsOptions? = null
|
private var webHmsOptions: WebHmsOptions? = null
|
||||||
|
|
||||||
fun setHeaders(webPushHeaders: WebPushHeaders): Builder {
|
fun setHeaders(webPushHeaders: WebPushHeaders): Builder {
|
||||||
this.webPushHeaders = webPushHeaders
|
this.headers = webPushHeaders
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,20 +46,20 @@ internal data class WebPushConfig private constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setNotification(webNotification: WebNotification): Builder {
|
fun setNotification(webNotification: WebNotification): Builder {
|
||||||
this.webNotification = webNotification
|
this.notification = notification
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setWebHmsOptions(webHmsOptions: WebHmsOptions): Builder {
|
fun setWebHmsOptions(webHmsOptions: WebHmsOptions): Builder {
|
||||||
this.webHmsOptions = webHmsOptions
|
this.webHmsOptions
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun build(): WebPushConfig {
|
fun build(): WebPushConfig {
|
||||||
return WebPushConfig(
|
return WebPushConfig(
|
||||||
webPushHeaders = webPushHeaders,
|
webPushHeaders = headers,
|
||||||
data = data,
|
data = data,
|
||||||
webNotification = webNotification,
|
webNotification = notification,
|
||||||
webHmsOptions = webHmsOptions,
|
webHmsOptions = webHmsOptions,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,6 @@ internal data class AndroidNotificationConfig private constructor(
|
||||||
|
|
||||||
class Validator {
|
class Validator {
|
||||||
|
|
||||||
@Suppress("ComplexMethod")
|
|
||||||
fun check(androidNotificationConfig: AndroidNotificationConfig, notification: Notification?) {
|
fun check(androidNotificationConfig: AndroidNotificationConfig, notification: Notification?) {
|
||||||
with(androidNotificationConfig) {
|
with(androidNotificationConfig) {
|
||||||
androidBadgeNotification?.let { AndroidBadgeNotification.validator.check(it) }
|
androidBadgeNotification?.let { AndroidBadgeNotification.validator.check(it) }
|
||||||
|
|
@ -119,11 +118,9 @@ internal data class AndroidNotificationConfig private constructor(
|
||||||
if (!color.isNullOrBlank()) {
|
if (!color.isNullOrBlank()) {
|
||||||
require(color.matches(COLOR_PATTERN)) { "Wrong color format, color must be in the form #RRGGBB" }
|
require(color.matches(COLOR_PATTERN)) { "Wrong color format, color must be in the form #RRGGBB" }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!image.isNullOrBlank()) {
|
if (!image.isNullOrBlank()) {
|
||||||
require(image.startsWith(HTTPS_URL_PATTERN)) { "notifyIcon must start with $HTTPS_URL_PATTERN" }
|
require(image.startsWith(HTTPS_URL_PATTERN)) { "notifyIcon must start with $HTTPS_URL_PATTERN" }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (androidStyleType != null) {
|
if (androidStyleType != null) {
|
||||||
when (androidStyleType) {
|
when (androidStyleType) {
|
||||||
AndroidStyleType.DEFAULT -> {
|
AndroidStyleType.DEFAULT -> {
|
||||||
|
|
@ -140,14 +137,12 @@ internal data class AndroidNotificationConfig private constructor(
|
||||||
require(
|
require(
|
||||||
!inboxContent.isNullOrEmpty()
|
!inboxContent.isNullOrEmpty()
|
||||||
) { "inboxContent is required when style is $androidStyleType" }
|
) { "inboxContent is required when style is $androidStyleType" }
|
||||||
|
|
||||||
require(
|
require(
|
||||||
inboxContent.size <= INBOX_CONTENT_MAX_ITEMS
|
inboxContent.size <= INBOX_CONTENT_MAX_ITEMS
|
||||||
) { "inboxContent must have at most $INBOX_CONTENT_MAX_ITEMS items" }
|
) { "inboxContent must have at most $INBOX_CONTENT_MAX_ITEMS items" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profileId != null) {
|
if (profileId != null) {
|
||||||
require(
|
require(
|
||||||
profileId.length <= PROFILE_ID_MAX_LENGTH
|
profileId.length <= PROFILE_ID_MAX_LENGTH
|
||||||
|
|
@ -167,7 +162,6 @@ internal data class AndroidNotificationConfig private constructor(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("TooManyFunctions")
|
|
||||||
class Builder : Buildable {
|
class Builder : Buildable {
|
||||||
|
|
||||||
private var title: String? = null
|
private var title: String? = null
|
||||||
|
|
@ -201,7 +195,7 @@ internal data class AndroidNotificationConfig private constructor(
|
||||||
private var androidLightSettings: AndroidLightSettings? = null
|
private var androidLightSettings: AndroidLightSettings? = null
|
||||||
private var foregroundShow = false
|
private var foregroundShow = false
|
||||||
private val inboxContent: MutableList<String> = mutableListOf()
|
private val inboxContent: MutableList<String> = mutableListOf()
|
||||||
private val androidButtons: MutableList<AndroidButton> = mutableListOf()
|
private val buttons: MutableList<AndroidButton> = mutableListOf()
|
||||||
private var profileId: String? = null
|
private var profileId: String? = null
|
||||||
|
|
||||||
fun setTitle(title: String): Builder {
|
fun setTitle(title: String): Builder {
|
||||||
|
|
@ -359,8 +353,8 @@ internal data class AndroidNotificationConfig private constructor(
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addButton(vararg androidButton: AndroidButton): Builder {
|
fun addButton(vararg button: AndroidButton): Builder {
|
||||||
androidButtons.addAll(androidButton)
|
buttons.addAll(button)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -405,7 +399,7 @@ internal data class AndroidNotificationConfig private constructor(
|
||||||
androidLightSettings = androidLightSettings,
|
androidLightSettings = androidLightSettings,
|
||||||
foregroundShow = foregroundShow,
|
foregroundShow = foregroundShow,
|
||||||
inboxContent = inboxContent.takeIf(Collection<*>::isNotEmpty),
|
inboxContent = inboxContent.takeIf(Collection<*>::isNotEmpty),
|
||||||
androidButtons = androidButtons.takeIf(Collection<*>::isNotEmpty),
|
androidButtons = buttons.takeIf(Collection<*>::isNotEmpty),
|
||||||
profileId = profileId,
|
profileId = profileId,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ internal data class ApnsHmsOptions private constructor(
|
||||||
|
|
||||||
class Validator {
|
class Validator {
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
fun check(apnsHmsOptions: ApnsHmsOptions) {
|
fun check(apnsHmsOptions: ApnsHmsOptions) {
|
||||||
// no validation
|
// no validation
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import ru.touchin.push.message.provider.hpk.base.builders.Buildable
|
||||||
@JsonNaming(PropertyNamingStrategies.KebabCaseStrategy::class)
|
@JsonNaming(PropertyNamingStrategies.KebabCaseStrategy::class)
|
||||||
internal class Aps private constructor(
|
internal class Aps private constructor(
|
||||||
@JsonProperty("alert")
|
@JsonProperty("alert")
|
||||||
val apnsAlert: ApnsAlert?,
|
val alert: ApnsAlert?,
|
||||||
val badge: Int?,
|
val badge: Int?,
|
||||||
val sound: String?,
|
val sound: String?,
|
||||||
val contentAvailable: Int?,
|
val contentAvailable: Int?,
|
||||||
|
|
@ -20,8 +20,8 @@ internal class Aps private constructor(
|
||||||
|
|
||||||
fun check(aps: Aps) {
|
fun check(aps: Aps) {
|
||||||
with(aps) {
|
with(aps) {
|
||||||
if (apnsAlert != null) {
|
if (alert != null) {
|
||||||
ApnsAlert.validator.check(apnsAlert)
|
ApnsAlert.validator.check(alert)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -30,7 +30,7 @@ internal class Aps private constructor(
|
||||||
|
|
||||||
class Builder : Buildable {
|
class Builder : Buildable {
|
||||||
|
|
||||||
private var apnsAlert: ApnsAlert? = null
|
private var alert: ApnsAlert? = null
|
||||||
private var badge: Int? = null
|
private var badge: Int? = null
|
||||||
private var sound: String? = null
|
private var sound: String? = null
|
||||||
private var contentAvailable: Int? = null
|
private var contentAvailable: Int? = null
|
||||||
|
|
@ -38,7 +38,7 @@ internal class Aps private constructor(
|
||||||
private var threadId: String? = null
|
private var threadId: String? = null
|
||||||
|
|
||||||
fun setAlert(alert: ApnsAlert): Builder {
|
fun setAlert(alert: ApnsAlert): Builder {
|
||||||
this.apnsAlert = alert
|
this.alert = alert
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,7 +69,7 @@ internal class Aps private constructor(
|
||||||
|
|
||||||
fun build(): Aps {
|
fun build(): Aps {
|
||||||
return Aps(
|
return Aps(
|
||||||
apnsAlert = apnsAlert,
|
alert = alert,
|
||||||
badge = badge,
|
badge = badge,
|
||||||
sound = sound,
|
sound = sound,
|
||||||
contentAvailable = contentAvailable,
|
contentAvailable = contentAvailable,
|
||||||
|
|
|
||||||
|
|
@ -14,19 +14,18 @@ internal data class WebNotification private constructor(
|
||||||
val tag: String?,
|
val tag: String?,
|
||||||
val badge: String?,
|
val badge: String?,
|
||||||
@JsonProperty("dir")
|
@JsonProperty("dir")
|
||||||
val webDir: WebDir?,
|
val dir: WebDir?,
|
||||||
val vibrate: Collection<Int>?,
|
val vibrate: Collection<Int>?,
|
||||||
val renotify: Boolean,
|
val renotify: Boolean,
|
||||||
val requireInteraction: Boolean,
|
val requireInteraction: Boolean,
|
||||||
val silent: Boolean,
|
val silent: Boolean,
|
||||||
val timestamp: Long?,
|
val timestamp: Long?,
|
||||||
@JsonProperty("actions")
|
@JsonProperty("actions")
|
||||||
val webActions: Collection<WebActions>?,
|
val actions: Collection<WebActions>?,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
class Validator {
|
class Validator {
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
fun check(webNotification: WebNotification) {
|
fun check(webNotification: WebNotification) {
|
||||||
// no verification required
|
// no verification required
|
||||||
}
|
}
|
||||||
|
|
@ -42,13 +41,13 @@ internal data class WebNotification private constructor(
|
||||||
private var lang: String? = null
|
private var lang: String? = null
|
||||||
private var tag: String? = null
|
private var tag: String? = null
|
||||||
private var badge: String? = null
|
private var badge: String? = null
|
||||||
private var webDir: WebDir? = null
|
private var dir: WebDir? = null
|
||||||
private val vibrate: MutableList<Int> = mutableListOf()
|
private val vibrate: MutableList<Int> = mutableListOf()
|
||||||
private var renotify = false
|
private var renotify = false
|
||||||
private var requireInteraction = false
|
private var requireInteraction = false
|
||||||
private var silent = false
|
private var silent = false
|
||||||
private var timestamp: Long? = null
|
private var timestamp: Long? = null
|
||||||
private val webActions: MutableList<WebActions> = mutableListOf()
|
private val actions: MutableList<WebActions> = mutableListOf()
|
||||||
|
|
||||||
fun setTitle(title: String): Builder {
|
fun setTitle(title: String): Builder {
|
||||||
this.title = title
|
this.title = title
|
||||||
|
|
@ -71,7 +70,7 @@ internal data class WebNotification private constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setLang(lang: String): Builder {
|
fun setLang(lang: String): Builder {
|
||||||
this.lang = lang
|
this.lang
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,8 +84,8 @@ internal data class WebNotification private constructor(
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setDir(webDir: WebDir): Builder {
|
fun setDir(dir: WebDir): Builder {
|
||||||
this.webDir = webDir
|
this.dir = dir
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,7 +115,7 @@ internal data class WebNotification private constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addActions(vararg webActions: WebActions): Builder {
|
fun addActions(vararg webActions: WebActions): Builder {
|
||||||
this.webActions.addAll(webActions)
|
this.actions.addAll(webActions)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,13 +128,13 @@ internal data class WebNotification private constructor(
|
||||||
lang = lang,
|
lang = lang,
|
||||||
tag = tag,
|
tag = tag,
|
||||||
badge = badge,
|
badge = badge,
|
||||||
webDir = webDir,
|
dir = dir,
|
||||||
vibrate = vibrate.takeIf(Collection<*>::isNotEmpty),
|
vibrate = vibrate.takeIf(Collection<*>::isNotEmpty),
|
||||||
renotify = renotify,
|
renotify = renotify,
|
||||||
requireInteraction = requireInteraction,
|
requireInteraction = requireInteraction,
|
||||||
silent = silent,
|
silent = silent,
|
||||||
timestamp = timestamp,
|
timestamp = timestamp,
|
||||||
webActions = webActions.takeIf(Collection<*>::isNotEmpty),
|
actions = actions.takeIf(Collection<*>::isNotEmpty),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ internal data class WebPushHeaders private constructor(
|
||||||
val ttl: String?,
|
val ttl: String?,
|
||||||
val topic: String?,
|
val topic: String?,
|
||||||
@JsonProperty("urgency")
|
@JsonProperty("urgency")
|
||||||
val webUrgency: WebUrgency?,
|
val urgency: WebUrgency?,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
class Validator {
|
class Validator {
|
||||||
|
|
@ -54,7 +54,7 @@ internal data class WebPushHeaders private constructor(
|
||||||
return WebPushHeaders(
|
return WebPushHeaders(
|
||||||
ttl = ttl,
|
ttl = ttl,
|
||||||
topic = topic,
|
topic = topic,
|
||||||
webUrgency = urgency,
|
urgency = urgency,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import ru.touchin.push.message.provider.dto.result.SendPushResult
|
||||||
import ru.touchin.push.message.provider.dto.result.SendPushTokenMessageTraceableResult
|
import ru.touchin.push.message.provider.dto.result.SendPushTokenMessageTraceableResult
|
||||||
import ru.touchin.push.message.provider.enums.PlatformType
|
import ru.touchin.push.message.provider.enums.PlatformType
|
||||||
import ru.touchin.push.message.provider.enums.PushMessageProviderType
|
import ru.touchin.push.message.provider.enums.PushMessageProviderType
|
||||||
import ru.touchin.push.message.provider.enums.PushTokenStatus
|
|
||||||
import ru.touchin.push.message.provider.factories.PushMessageProviderServiceFactory
|
import ru.touchin.push.message.provider.factories.PushMessageProviderServiceFactory
|
||||||
import ru.touchin.push.message.provider.mock.properties.PushMessageProviderMockProperties
|
import ru.touchin.push.message.provider.mock.properties.PushMessageProviderMockProperties
|
||||||
import ru.touchin.push.message.provider.services.PushMessageProviderService
|
import ru.touchin.push.message.provider.services.PushMessageProviderService
|
||||||
|
|
@ -49,7 +48,7 @@ class PushMessageProviderMockServiceFactoryImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun check(request: PushTokenCheck): CheckPushTokenResult {
|
override fun check(request: PushTokenCheck): CheckPushTokenResult {
|
||||||
return CheckPushTokenResult(PushTokenStatus.VALID)
|
throw NotImplementedError()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ internal class ScopeRepositoryTest {
|
||||||
val savedScope = scopeRepository.findByIdOrThrow(scope.name)
|
val savedScope = scopeRepository.findByIdOrThrow(scope.name)
|
||||||
|
|
||||||
assertTrue(
|
assertTrue(
|
||||||
ReflectionEquals(scope, "createdAt", "users").matches(savedScope)
|
ReflectionEquals(scope, "createdAt").matches(savedScope)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ internal class UserRepositoryTest {
|
||||||
|
|
||||||
val savedUser = userRepository.findByIdOrThrow(user.id!!)
|
val savedUser = userRepository.findByIdOrThrow(user.id!!)
|
||||||
|
|
||||||
assertTrue(ReflectionEquals(user, "createdAt", "confirmedAt").matches(savedUser))
|
assertTrue(ReflectionEquals(user, "createdAt").matches(savedUser))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package ru.touchin.auth.security.jwks.controllers
|
package ru.touchin.auth.security.jwks.controllers
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
import org.springframework.web.bind.annotation.RequestMapping
|
||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package ru.touchin.server.info.services
|
package ru.touchin.server.info.services
|
||||||
|
|
||||||
|
import org.springframework.util.MultiValueMap
|
||||||
|
|
||||||
interface ServerInfoHeader {
|
interface ServerInfoHeader {
|
||||||
|
|
||||||
fun getHeaders(): Map<String, String>
|
fun getHeaders(): Map<String, String>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
package ru.touchin.server.info.services.version
|
package ru.touchin.server.info.services.version
|
||||||
|
|
||||||
import org.springframework.stereotype.Component
|
import org.springframework.stereotype.Component
|
||||||
import ru.touchin.server.info.services.ServerInfoHeader
|
import org.springframework.util.LinkedMultiValueMap
|
||||||
|
import org.springframework.util.MultiValueMap
|
||||||
import ru.touchin.server.info.services.version.properties.ServerInfoProperties
|
import ru.touchin.server.info.services.version.properties.ServerInfoProperties
|
||||||
|
import ru.touchin.server.info.services.ServerInfoHeader
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
class BuildVersionHeader(
|
class BuildVersionHeader(
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,11 @@ pluginManagement {
|
||||||
val kotlinVersion: String by settings
|
val kotlinVersion: String by settings
|
||||||
val springBootVersion: String by settings
|
val springBootVersion: String by settings
|
||||||
val springDependencyManagementVersion: String by settings
|
val springDependencyManagementVersion: String by settings
|
||||||
val detektGradlePluginVersion: String by settings
|
|
||||||
val diktatGradlePluginVersion: String by settings
|
|
||||||
|
|
||||||
val versions = listOf(
|
val versions = listOf(
|
||||||
"org.jetbrains.kotlin" to kotlinVersion,
|
"org.jetbrains.kotlin" to kotlinVersion,
|
||||||
"org.springframework.boot" to springBootVersion,
|
"org.springframework.boot" to springBootVersion,
|
||||||
"io.spring.dependency-management" to springDependencyManagementVersion,
|
"io.spring.dependency-management" to springDependencyManagementVersion
|
||||||
"io.gitlab.arturbosch.detekt" to detektGradlePluginVersion,
|
|
||||||
"org.cqfn.diktat.diktat-gradle-plugin" to diktatGradlePluginVersion,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
eachPlugin {
|
eachPlugin {
|
||||||
|
|
@ -39,7 +35,6 @@ include("common-geo")
|
||||||
include("common-geo-spatial4j-spring")
|
include("common-geo-spatial4j-spring")
|
||||||
include("common-messaging")
|
include("common-messaging")
|
||||||
include("captcha")
|
include("captcha")
|
||||||
include("codestyle-archunit")
|
|
||||||
include("logger")
|
include("logger")
|
||||||
include("logger-spring")
|
include("logger-spring")
|
||||||
include("logger-spring-web")
|
include("logger-spring-web")
|
||||||
|
|
@ -65,5 +60,3 @@ include("s3-storage")
|
||||||
include("server-info-spring-web")
|
include("server-info-spring-web")
|
||||||
include("geoip-core")
|
include("geoip-core")
|
||||||
include("user-agent")
|
include("user-agent")
|
||||||
include("smart-migration")
|
|
||||||
include("telegram-bot-spring")
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
plugins {
|
|
||||||
id("kotlin")
|
|
||||||
id("kotlin-spring")
|
|
||||||
id("maven-publish")
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
|
||||||
implementation("org.springframework.boot:spring-boot")
|
|
||||||
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
|
||||||
implementation project(":common-spring")
|
|
||||||
}
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
@file:Suppress("unused")
|
|
||||||
package ru.touchin.smartmigration
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Component
|
|
||||||
import ru.touchin.common.spring.annotations.RequiredBy
|
|
||||||
import ru.touchin.smartmigration.logic.DataSourceSQL
|
|
||||||
import ru.touchin.smartmigration.logic.factory.DataSourceSqlFactoryImpl
|
|
||||||
import java.sql.Date
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import javax.annotation.PostConstruct
|
|
||||||
import javax.sql.DataSource
|
|
||||||
|
|
||||||
private val SQL_DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
|
|
||||||
|
|
||||||
private val CURRENT_TIME_SQL: String
|
|
||||||
get() = SQL_DATE_FORMAT.format(Date(System.currentTimeMillis()))
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@RequiredBy("liquibase")
|
|
||||||
class BeforeLiquibase(
|
|
||||||
private val dataSource: DataSource
|
|
||||||
) {
|
|
||||||
|
|
||||||
val dataSourceSql: DataSourceSQL = DataSourceSqlFactoryImpl()
|
|
||||||
.getDataSourceSql(dataSource.connection.metaData.databaseProductName)
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
fun doAction() {
|
|
||||||
val buildNumber = System.getenv("BUILD_NUMBER")
|
|
||||||
?: return
|
|
||||||
|
|
||||||
checkMigrationTable()
|
|
||||||
|
|
||||||
if (checkBuildMigrationExecuted(buildNumber)) {
|
|
||||||
System.setProperty("spring.liquibase.enabled", "false")
|
|
||||||
} else {
|
|
||||||
insertMigration(buildNumber)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkBuildMigrationExecuted(buildNumber: String): Boolean {
|
|
||||||
return dataSourceSql.getMigrationCheckSQL(buildNumber).let {
|
|
||||||
dataSource.connection.createStatement().executeQuery(it).next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkMigrationTable() {
|
|
||||||
dataSourceSql.getTableCheckSQL().let {
|
|
||||||
dataSource.connection.createStatement().execute(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun insertMigration(buildNumber: String) {
|
|
||||||
dataSourceSql.getInsertMigrationSQL(buildNumber, CURRENT_TIME_SQL).let {
|
|
||||||
dataSource.connection.createStatement().execute(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
package ru.touchin.smartmigration
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.ComponentScan
|
|
||||||
import org.springframework.context.annotation.Configuration
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@ComponentScan("ru.touchin.smartmigration")
|
|
||||||
open class SmartMigrationConfig
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
package ru.touchin.smartmigration.annotation
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Import
|
|
||||||
import ru.touchin.smartmigration.SmartMigrationConfig
|
|
||||||
|
|
||||||
@Import(SmartMigrationConfig::class)
|
|
||||||
annotation class EnableSmartMigration
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
package ru.touchin.smartmigration.logic
|
|
||||||
|
|
||||||
interface DataSourceSQL {
|
|
||||||
|
|
||||||
fun getTableCheckSQL(): String
|
|
||||||
|
|
||||||
fun getMigrationCheckSQL(buildNumber: String): String
|
|
||||||
|
|
||||||
fun getInsertMigrationSQL(buildNumber: String, formattedTime: String): String
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
package ru.touchin.smartmigration.logic
|
|
||||||
|
|
||||||
import org.intellij.lang.annotations.Language
|
|
||||||
|
|
||||||
private const val MIGRATION_TABLE_NAME = "SMART_MIGRATION"
|
|
||||||
|
|
||||||
class PostgresDataSourceImpl: DataSourceSQL {
|
|
||||||
|
|
||||||
@Language("SQL")
|
|
||||||
override fun getTableCheckSQL(): String {
|
|
||||||
return """
|
|
||||||
CREATE TABLE IF NOT EXISTS smart_migration (
|
|
||||||
ID BIGSERIAL PRIMARY KEY,
|
|
||||||
BUILD_NUMBER VARCHAR(255) NOT NULL,
|
|
||||||
DATE timestamp NOT NULL
|
|
||||||
);
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
|
|
||||||
@Language("SQL")
|
|
||||||
override fun getMigrationCheckSQL(buildNumber: String): String {
|
|
||||||
return "SELECT * FROM $MIGRATION_TABLE_NAME WHERE BUILD_NUMBER = '$buildNumber'"
|
|
||||||
}
|
|
||||||
|
|
||||||
@Language("SQL")
|
|
||||||
override fun getInsertMigrationSQL(buildNumber: String, formattedTime: String): String {
|
|
||||||
return """
|
|
||||||
INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE)
|
|
||||||
VALUES ('$buildNumber', '$formattedTime');
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
package ru.touchin.smartmigration.logic
|
|
||||||
|
|
||||||
import org.intellij.lang.annotations.Language
|
|
||||||
|
|
||||||
private const val MIGRATION_TABLE_NAME = "SMART_MIGRATION"
|
|
||||||
|
|
||||||
class SqlDatasourceImpl:DataSourceSQL {
|
|
||||||
|
|
||||||
@Language("TSQL")
|
|
||||||
override fun getTableCheckSQL(): String {
|
|
||||||
return """
|
|
||||||
IF NOT EXISTS (
|
|
||||||
SELECT * FROM sysobjects WHERE name = '$MIGRATION_TABLE_NAME' and xtype='U'
|
|
||||||
)
|
|
||||||
CREATE TABLE SMART_MIGRATION (
|
|
||||||
ID BIGINT PRIMARY KEY IDENTITY ,
|
|
||||||
BUILD_NUMBER VARCHAR(255) NOT NULL,
|
|
||||||
DATE DATETIME NOT NULL
|
|
||||||
);
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
|
|
||||||
@Language("TSQL")
|
|
||||||
override fun getMigrationCheckSQL(buildNumber: String): String {
|
|
||||||
return "SELECT * FROM $MIGRATION_TABLE_NAME WHERE BUILD_NUMBER = '$buildNumber'"
|
|
||||||
}
|
|
||||||
|
|
||||||
@Language("TSQL")
|
|
||||||
override fun getInsertMigrationSQL(buildNumber: String, formattedTime: String): String {
|
|
||||||
return """
|
|
||||||
INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE)
|
|
||||||
VALUES ('$buildNumber', '$formattedTime');
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
package ru.touchin.smartmigration.logic.factory
|
|
||||||
|
|
||||||
import ru.touchin.smartmigration.logic.DataSourceSQL
|
|
||||||
|
|
||||||
interface DataSourceSqlFactory {
|
|
||||||
|
|
||||||
fun getDataSourceSql(driverName: String): DataSourceSQL
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
package ru.touchin.smartmigration.logic.factory
|
|
||||||
|
|
||||||
import ru.touchin.smartmigration.logic.DataSourceSQL
|
|
||||||
import ru.touchin.smartmigration.logic.PostgresDataSourceImpl
|
|
||||||
import ru.touchin.smartmigration.logic.SqlDatasourceImpl
|
|
||||||
|
|
||||||
class DataSourceSqlFactoryImpl: DataSourceSqlFactory {
|
|
||||||
|
|
||||||
override fun getDataSourceSql(driverName: String): DataSourceSQL {
|
|
||||||
return when(driverName){
|
|
||||||
"Microsoft SQL Server" -> SqlDatasourceImpl()
|
|
||||||
"PostgresSQL" -> PostgresDataSourceImpl()
|
|
||||||
else -> {
|
|
||||||
PostgresDataSourceImpl()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
HELP.md
|
|
||||||
.gradle
|
|
||||||
build/
|
|
||||||
!gradle/wrapper/gradle-wrapper.jar
|
|
||||||
!**/src/main/**/build/
|
|
||||||
!**/src/test/**/build/
|
|
||||||
|
|
||||||
### STS ###
|
|
||||||
.apt_generated
|
|
||||||
.classpath
|
|
||||||
.factorypath
|
|
||||||
.project
|
|
||||||
.settings
|
|
||||||
.springBeans
|
|
||||||
.sts4-cache
|
|
||||||
bin/
|
|
||||||
!**/src/main/**/bin/
|
|
||||||
!**/src/test/**/bin/
|
|
||||||
|
|
||||||
### IntelliJ IDEA ###
|
|
||||||
.idea
|
|
||||||
*.iws
|
|
||||||
*.iml
|
|
||||||
*.ipr
|
|
||||||
out/
|
|
||||||
!**/src/main/**/out/
|
|
||||||
!**/src/test/**/out/
|
|
||||||
|
|
||||||
### NetBeans ###
|
|
||||||
/nbproject/private/
|
|
||||||
/nbbuild/
|
|
||||||
/dist/
|
|
||||||
/nbdist/
|
|
||||||
/.nb-gradle/
|
|
||||||
|
|
||||||
### VS Code ###
|
|
||||||
.vscode/
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
## Библиотека написания телеграмм-ботов
|
|
||||||
|
|
||||||
```kotlin
|
|
||||||
@Component
|
|
||||||
class MyTelegramBot(
|
|
||||||
private val messageHandlers: List<MessageHandler>,
|
|
||||||
) : TelegramLongPollingBot() {
|
|
||||||
|
|
||||||
override fun onUpdateReceived(update: Update?) {
|
|
||||||
// create MessageContext
|
|
||||||
// messageHandlers.takeWhile { it.process(ctx, this) }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component
|
|
||||||
class HelloMessageHandler: AbstractMessageHandler {
|
|
||||||
|
|
||||||
override fun isSupported(ctx: MessageContext): Booleat {
|
|
||||||
ctx.messageCommand.message.equals("hi")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun process(ctx: MessageContext, sender: AbsSender): Boolean {
|
|
||||||
val message = SendMessage().apply {
|
|
||||||
this.chatId = ctx.chatId
|
|
||||||
this.text = "Hello"
|
|
||||||
}
|
|
||||||
|
|
||||||
sender.execute(message)
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
plugins {
|
|
||||||
id 'kotlin'
|
|
||||||
id 'kotlin-spring'
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
api 'org.telegram:telegrambots-spring-boot-starter:6.3.0'
|
|
||||||
|
|
||||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
|
|
||||||
implementation 'com.fasterxml.jackson.core:jackson-databind'
|
|
||||||
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
|
|
||||||
implementation 'org.springframework.boot:spring-boot'
|
|
||||||
|
|
||||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
|
||||||
testImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin")
|
|
||||||
testImplementation("org.mockito:mockito-inline")
|
|
||||||
testImplementation 'junit:junit'
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
package ru.touchin.spring.telegram.bot
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Import
|
|
||||||
|
|
||||||
@Import(value = [TelegramBotConfiguration::class])
|
|
||||||
annotation class EnableSpringTelegramBot
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
package ru.touchin.spring.telegram.bot
|
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationPropertiesScan
|
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties
|
|
||||||
import org.springframework.context.annotation.ComponentScan
|
|
||||||
import org.springframework.context.annotation.Configuration
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableConfigurationProperties
|
|
||||||
@ConfigurationPropertiesScan
|
|
||||||
@ComponentScan
|
|
||||||
class TelegramBotConfiguration
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package ru.touchin.spring.telegram.bot.messages
|
|
||||||
|
|
||||||
import org.telegram.telegrambots.meta.bots.AbsSender
|
|
||||||
import ru.touchin.spring.telegram.bot.messages.dto.MessageContext
|
|
||||||
|
|
||||||
abstract class AbstractMessageHandler<C: MessageContext<U, S>, U, S>:
|
|
||||||
MessageHandler<C, U, S>,
|
|
||||||
MessageFilter<C, U, S>,
|
|
||||||
HelpMessage
|
|
||||||
{
|
|
||||||
|
|
||||||
override fun process(context: C, sender: AbsSender): Boolean {
|
|
||||||
if (!isSupported(context)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return internalProcess(context, sender)
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun internalProcess(context: C, sender: AbsSender): Boolean
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
package ru.touchin.spring.telegram.bot.messages
|
|
||||||
|
|
||||||
interface HelpMessage {
|
|
||||||
|
|
||||||
fun helpMessage(): String? = null
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
package ru.touchin.spring.telegram.bot.messages
|
|
||||||
|
|
||||||
import ru.touchin.spring.telegram.bot.messages.dto.MessageContext
|
|
||||||
|
|
||||||
interface MessageFilter<C: MessageContext<U, S>, U, S> {
|
|
||||||
|
|
||||||
fun isSupported(context: C): Boolean
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
package ru.touchin.spring.telegram.bot.messages
|
|
||||||
|
|
||||||
import org.telegram.telegrambots.meta.bots.AbsSender
|
|
||||||
import ru.touchin.spring.telegram.bot.messages.dto.MessageContext
|
|
||||||
|
|
||||||
interface MessageHandler<C: MessageContext<U, S>, U, S> {
|
|
||||||
|
|
||||||
fun process(context: C, sender: AbsSender): Boolean
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
package ru.touchin.spring.telegram.bot.messages
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
object Order {
|
|
||||||
const val HIGH_PRIORITY = 1024
|
|
||||||
const val NORMAL_PRIORITY = 2048
|
|
||||||
const val LOW_PRIORITY = 3072
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
package ru.touchin.spring.telegram.bot.messages.dto
|
|
||||||
|
|
||||||
data class MessageCommand(
|
|
||||||
val command: String,
|
|
||||||
val message: String
|
|
||||||
) {
|
|
||||||
|
|
||||||
fun hasCommand() = command != NO_COMMAND
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val NO_COMMAND = ""
|
|
||||||
|
|
||||||
fun createNoCommandMessage(message: String) = MessageCommand(
|
|
||||||
command = NO_COMMAND,
|
|
||||||
message = message
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
package ru.touchin.spring.telegram.bot.messages.dto
|
|
||||||
|
|
||||||
import org.telegram.telegrambots.meta.api.objects.Update
|
|
||||||
|
|
||||||
open class MessageContext<U, S>(
|
|
||||||
val origin: Update,
|
|
||||||
val user: U,
|
|
||||||
val messageCommand: MessageCommand,
|
|
||||||
val state: S
|
|
||||||
) {
|
|
||||||
|
|
||||||
fun hasCommand(command: String) = messageCommand.command == command
|
|
||||||
|
|
||||||
val chatId: String
|
|
||||||
get() = origin.message?.chatId?.toString()
|
|
||||||
?: origin.callbackQuery.message.chatId.toString()
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
package ru.touchin.spring.telegram.bot.messages.services
|
|
||||||
|
|
||||||
import ru.touchin.spring.telegram.bot.messages.dto.MessageCommand
|
|
||||||
|
|
||||||
interface TelegramMessageCommandResolver {
|
|
||||||
|
|
||||||
fun resolve(rawMessage: String): MessageCommand
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
package ru.touchin.spring.telegram.bot.messages.services.impl
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service
|
|
||||||
import ru.touchin.spring.telegram.bot.messages.dto.MessageCommand
|
|
||||||
import ru.touchin.spring.telegram.bot.messages.services.TelegramMessageCommandResolver
|
|
||||||
|
|
||||||
@Service
|
|
||||||
class TelegramMessageCommandResolverImpl : TelegramMessageCommandResolver {
|
|
||||||
|
|
||||||
override fun resolve(rawMessage: String): MessageCommand {
|
|
||||||
val message = rawMessage.trim()
|
|
||||||
|
|
||||||
if (message.isBlank() || !message.startsWith("/")) {
|
|
||||||
return MessageCommand.createNoCommandMessage(rawMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
return MessageCommand(
|
|
||||||
command = message.substringBefore(' ').trim().lowercase(),
|
|
||||||
message = message.substringAfter(' ', missingDelimiterValue = "")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
package ru.touchin.spring.telegram.bot
|
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
|
||||||
|
|
||||||
@SpringBootApplication
|
|
||||||
open class TestApplication
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
package ru.touchin.spring.telegram.bot.messages.services.impl
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest
|
|
||||||
import org.springframework.test.context.ActiveProfiles
|
|
||||||
import org.junit.jupiter.api.Assertions.*
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import ru.touchin.spring.telegram.bot.messages.services.TelegramMessageCommandResolver
|
|
||||||
|
|
||||||
@ActiveProfiles("test")
|
|
||||||
@SpringBootTest
|
|
||||||
internal class TelegramMessageCommandResolverImplTest {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private lateinit var telegramMessageCommandResolver: TelegramMessageCommandResolver
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun shouldBeEmptyCommand() {
|
|
||||||
telegramMessageCommandResolver.resolve("hello").also {
|
|
||||||
assertFalse(it.hasCommand())
|
|
||||||
assertEquals("hello", it.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
telegramMessageCommandResolver.resolve("").also {
|
|
||||||
assertFalse(it.hasCommand())
|
|
||||||
assertEquals("", it.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
telegramMessageCommandResolver.resolve(" ").also {
|
|
||||||
assertFalse(it.hasCommand())
|
|
||||||
assertEquals(" ", it.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
telegramMessageCommandResolver.resolve("hello world").also {
|
|
||||||
assertFalse(it.hasCommand())
|
|
||||||
assertEquals("hello world", it.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun shouldResolveCommand() {
|
|
||||||
telegramMessageCommandResolver.resolve("/hello").also {
|
|
||||||
assertTrue(it.hasCommand())
|
|
||||||
assertEquals("/hello", it.command)
|
|
||||||
assertEquals("", it.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
telegramMessageCommandResolver.resolve("/hello world").also {
|
|
||||||
assertTrue(it.hasCommand())
|
|
||||||
assertEquals("/hello", it.command)
|
|
||||||
assertEquals("world", it.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
telegramMessageCommandResolver.resolve("/hello /world").also {
|
|
||||||
assertTrue(it.hasCommand())
|
|
||||||
assertEquals("/hello", it.command)
|
|
||||||
assertEquals("/world", it.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
telegramMessageCommandResolver.resolve(" /hello /world").also {
|
|
||||||
assertTrue(it.hasCommand())
|
|
||||||
assertEquals("/hello", it.command)
|
|
||||||
assertEquals(" /world", it.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -16,7 +16,6 @@ class EmailValidator(
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
private const val DEFAULT_EMAIL_REGEX = "^((([A-Za-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`\\{\\|\\}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([A-Za-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`\\{\\|\\}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([A-Za-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([A-Za-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([A-Za-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([A-Za-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([A-Za-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([A-Za-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([A-Za-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([A-Za-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))$"
|
private const val DEFAULT_EMAIL_REGEX = "^((([A-Za-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`\\{\\|\\}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([A-Za-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`\\{\\|\\}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([A-Za-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([A-Za-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([A-Za-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([A-Za-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([A-Za-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([A-Za-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([A-Za-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([A-Za-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))$"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue