dev.struchkov

This commit is contained in:
Struchkov Mark 2021-10-20 21:22:45 +03:00
parent 703f308785
commit cf68f1738e
50 changed files with 934 additions and 271 deletions

View File

@ -4,64 +4,110 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.sadtech.haiti</groupId>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-bom</artifactId>
<version>0.0.1-RELEASE</version>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Haiti BOM</name>
<description>Current versions of the framework dependencies</description>
<url>https://github.com/haiti-projects/haiti-framework</url>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<comments>
Copyright 2010 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.
</comments>
</license>
</licenses>
<organization>
<name>SADTECH</name>
<url>https://sadtech.org</url>
<name>Struchkov Inc.</name>
<url>https://mark.struchkov.dev</url>
</organization>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<scm>
<connection>scm:git:https://github.com/haiti-projects/haiti-framework.git</connection>
<url>https://github.com/haiti-projects/haiti-framework</url>
<developerConnection>scm:git:https://github.com/haiti-projects/haiti-framework.git</developerConnection>
</scm>
<sadtech.haiti.context.version>0.0.1-RELEASE</sadtech.haiti.context.version>
<sadtech.haiti.core.version>0.0.1-RELEASE</sadtech.haiti.core.version>
<sadtech.haiti.filter.version>0.0.1-RELEASE</sadtech.haiti.filter.version>
<sadtech.haiti.filter.api.version>0.0.1-RELEASE</sadtech.haiti.filter.api.version>
<sadtech.haiti.filter.criteria.version>0.0.1-RELEASE</sadtech.haiti.filter.criteria.version>
<sadtech.haiti.database.version>0.0.1-RELEASE</sadtech.haiti.database.version>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/haiti-projects/haiti-framework/issues</url>
</issueManagement>
<properties>
<java.version>16</java.version>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<haiti.context.version>0.0.1-SNAPSHOT</haiti.context.version>
<haiti.core.version>0.0.1-SNAPSHOT</haiti.core.version>
<haiti.filter.api.version>0.0.1-SNAPSHOT</haiti.filter.api.version>
<haiti.filter.criteria.version>0.0.1-SNAPSHOT</haiti.filter.criteria.version>
<haiti.database.version>0.0.1-RELEASE</haiti.database.version>
<haiti.utils.version>0.0.1-SNAPSHOT</haiti.utils.version>
<spring.data.elasticsearch.version>4.1.0</spring.data.elasticsearch.version>
<spring.data.jpa.version>2.4.0</spring.data.jpa.version>
<spring.data.commons.version>2.4.0</spring.data.commons.version>
<elasticsearch.version>7.9.3</elasticsearch.version>
<lombok.version>1.18.16</lombok.version>
<lombok.version>1.18.22</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.sadtech.haiti</groupId>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-context</artifactId>
<version>${sadtech.haiti.context.version}</version>
<version>${haiti.context.version}</version>
</dependency>
<dependency>
<groupId>org.sadtech.haiti</groupId>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-core</artifactId>
<version>${sadtech.haiti.core.version}</version>
<version>${haiti.core.version}</version>
</dependency>
<dependency>
<groupId>org.sadtech.haiti</groupId>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-filter</artifactId>
<version>${sadtech.haiti.filter.api.version}</version>
<version>${haiti.filter.api.version}</version>
</dependency>
<dependency>
<groupId>org.sadtech.haiti</groupId>
<groupId>dev.struchkov.haiti.filter</groupId>
<artifactId>haiti-filter-criteria</artifactId>
<version>0.0.1-RELEASE</version>
<version>${haiti.filter.criteria.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-utils</artifactId>
<version>${haiti.utils.version}</version>
</dependency>
<dependency>
@ -105,6 +151,67 @@
</dependencies>
</dependencyManagement>
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.7</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
@ -123,12 +230,12 @@
<developer>
<id>uPagge</id>
<name>Struchkov Mark</name>
<email>upagge@ya.ru</email>
<organization>SADTECH</organization>
<organizationUrl>https://sadtech.org</organizationUrl>
<url>https://uPagge.sadtech.org</url>
<email>mark@struchkov.dev</email>
<organization>Struchkov Inc.</organization>
<organizationUrl>https://struchkov.dev</organizationUrl>
<url>https://mark.struchkov.dev</url>
<roles>
<role>Project lead</role>
<role>Project Lead</role>
</roles>
<timezone>+3</timezone>
</developer>

View File

@ -4,23 +4,18 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sadtech.haiti</groupId>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti</artifactId>
<version>0.0.1-RELEASE</version>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>haiti-context</artifactId>
<version>0.0.1-RELEASE</version>
<version>0.0.1-SNAPSHOT</version>
<name>Haiti Context</name>
<description>Basic framework classes</description>
<url>https://github.com/haiti-projects/haiti-framework</url>
<organization>
<name>SADTECH</name>
<url>https://sadtech.org</url>
</organization>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
@ -32,12 +27,12 @@
<developer>
<id>uPagge</id>
<name>Struchkov Mark</name>
<email>upagge@ya.ru</email>
<organization>SADTECH</organization>
<organizationUrl>https://sadtech.org</organizationUrl>
<url>https://uPagge.sadtech.org</url>
<email>mark@struchkov.dev</email>
<organization>Struchkov Inc.</organization>
<organizationUrl>https://struchkov.dev</organizationUrl>
<url>https://mark.struchkov.dev</url>
<roles>
<role>Project lead</role>
<role>Project Lead</role>
</roles>
<timezone>+3</timezone>
</developer>

View File

@ -1,4 +1,4 @@
package org.sadtech.haiti.context.anotation;
package dev.struchkov.haiti.context.anotation;
/**
* Маркер для разграничения политик валидации.

View File

@ -0,0 +1,12 @@
package dev.struchkov.haiti.context.domain;
/**
* // TODO: 14.01.2021 Добавить описание.
*
* @author upagge 14.01.2021
*/
public interface BasicEntity<K> {
K getId();
}

View File

@ -0,0 +1,33 @@
package dev.struchkov.haiti.context.domain;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
/**
* Контейнер для возврата результата сервисных методов exists.
*
* @author upagge 11.01.2021
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class ExistsContainer<T, K> implements Serializable {
protected final Collection<T> container;
protected final boolean allFound;
protected final Collection<K> idNoFound;
public static <T, K> ExistsContainer<T, K> allFind(@NonNull Collection<T> container) {
return new ExistsContainer<>(container, true, Collections.emptyList());
}
public static <T, K> ExistsContainer<T, K> notAllFind(@NonNull Collection<T> container, @NonNull Collection<K> idNoFound) {
return new ExistsContainer<>(container, false, idNoFound);
}
}

View File

@ -1,4 +1,4 @@
package org.sadtech.haiti.context.enums;
package dev.struchkov.haiti.context.enums;
/**
* Допустимые типы сортировки.

View File

@ -1,4 +1,4 @@
package org.sadtech.haiti.context.exception;
package dev.struchkov.haiti.context.exception;
/**
* Исключения связанные с доступом.

View File

@ -1,4 +1,4 @@
package org.sadtech.haiti.context.exception;
package dev.struchkov.haiti.context.exception;
/**
* Общий класс для всех ошибок приложения.

View File

@ -1,4 +1,4 @@
package org.sadtech.haiti.context.exception;
package dev.struchkov.haiti.context.exception;
/**
* Исключение при конвертации.

View File

@ -0,0 +1,19 @@
package dev.struchkov.haiti.context.exception;
import java.text.MessageFormat;
import java.util.function.Supplier;
/**
* @author upagge 17.12.2019
*/
public class CreateException extends BasicException {
public CreateException(String message) {
super(message);
}
public static Supplier<CreateException> supplier(String message, Object... objects) {
return () -> new CreateException(MessageFormat.format(message, objects));
}
}

View File

@ -0,0 +1,21 @@
package dev.struchkov.haiti.context.exception;
import java.text.MessageFormat;
import java.util.function.Supplier;
/**
* Исключения, возникающие, когда необходимые данные не были найдены.
*
* @author upagge 17.12.2019
*/
public class NotFoundException extends BasicException {
public NotFoundException(String message) {
super(message);
}
public static Supplier<NotFoundException> supplier(String message, Object... objects) {
return () -> new NotFoundException(MessageFormat.format(message, objects));
}
}

View File

@ -1,6 +1,6 @@
package org.sadtech.haiti.context.page;
package dev.struchkov.haiti.context.page;
import org.sadtech.haiti.context.enums.TypeSort;
import dev.struchkov.haiti.context.enums.TypeSort;
public interface Pagination {

View File

@ -1,4 +1,4 @@
package org.sadtech.haiti.context.page;
package dev.struchkov.haiti.context.page;
import java.util.List;
import java.util.function.Function;

View File

@ -0,0 +1,11 @@
package dev.struchkov.haiti.context.repository;
import dev.struchkov.haiti.context.repository.simple.CrudOperation;
import dev.struchkov.haiti.context.repository.simple.MultipleOperation;
import dev.struchkov.haiti.context.repository.simple.PagingOperation;
import dev.struchkov.haiti.context.domain.BasicEntity;
public interface SimpleManagerRepository<T extends BasicEntity<K>, K>
extends CrudOperation<T, K>, MultipleOperation<T, K>, PagingOperation<T> {
}

View File

@ -1,4 +1,4 @@
package org.sadtech.haiti.context.repository.simple;
package dev.struchkov.haiti.context.repository.simple;
import lombok.NonNull;

View File

@ -0,0 +1,17 @@
package dev.struchkov.haiti.context.repository.simple;
import lombok.NonNull;
import dev.struchkov.haiti.context.domain.BasicEntity;
import java.util.Collection;
import java.util.List;
public interface MultipleOperation<T extends BasicEntity<K>, K> {
List<T> saveAll(@NonNull Collection<T> entities);
void deleteAllById(@NonNull Collection<K> primaryKeys);
List<T> findAllById(@NonNull Collection<K> ids);
}

View File

@ -0,0 +1,11 @@
package dev.struchkov.haiti.context.repository.simple;
import lombok.NonNull;
import dev.struchkov.haiti.context.page.Pagination;
import dev.struchkov.haiti.context.page.Sheet;
public interface PagingOperation<T> {
Sheet<T> findAll(@NonNull Pagination pagination);
}

View File

@ -0,0 +1,10 @@
package dev.struchkov.haiti.context.service;
import dev.struchkov.haiti.context.domain.BasicEntity;
import dev.struchkov.haiti.context.service.simple.MultipleService;
import dev.struchkov.haiti.context.service.simple.PagingService;
import dev.struchkov.haiti.context.service.simple.SimpleService;
public interface SimpleManagerService<T extends BasicEntity<K>, K> extends SimpleService<T, K>, MultipleService<T, K>, PagingService<T> {
}

View File

@ -0,0 +1,40 @@
package dev.struchkov.haiti.context.service.simple;
import lombok.NonNull;
import dev.struchkov.haiti.context.page.Pagination;
import dev.struchkov.haiti.context.page.Sheet;
import java.util.Optional;
public interface FilterService<T, F> {
/**
* Получить все элементы по заданному фильтру.
*
* @param filter Фильтр
* @param pagination Пагинация
*/
Sheet<T> getAll(@NonNull F filter, @NonNull Pagination pagination);
/**
* Возвращает первый найденный объект по фильтру.
*
* @param filter Объект фильтра
*/
Optional<T> getFirst(@NonNull F filter);
/**
* Проверка на наличие хотя бы одной сущности, которая удовлетворяет определенному набору параметров.
*
* @param filter Набор параметров
*/
boolean exists(@NonNull F filter);
/**
* Получить количество сущностей, которые удовлетворяют определенному набору параметров.
*
* @param filter Набор параметров
*/
long count(@NonNull F filter);
}

View File

@ -0,0 +1,20 @@
package dev.struchkov.haiti.context.service.simple;
import dev.struchkov.haiti.context.domain.BasicEntity;
import dev.struchkov.haiti.context.domain.ExistsContainer;
import lombok.NonNull;
import java.util.Collection;
import java.util.List;
public interface MultipleService<T extends BasicEntity<K>, K> {
List<T> createAll(@NonNull Collection<T> entities);
List<T> updateAll(@NonNull Collection<T> entities);
void deleteAllById(@NonNull Collection<K> ids);
ExistsContainer<T, K> existsById(@NonNull Collection<K> ids);
}

View File

@ -1,8 +1,8 @@
package org.sadtech.haiti.context.service.simple;
package dev.struchkov.haiti.context.service.simple;
import lombok.NonNull;
import org.sadtech.haiti.context.page.Pagination;
import org.sadtech.haiti.context.page.Sheet;
import dev.struchkov.haiti.context.page.Pagination;
import dev.struchkov.haiti.context.page.Sheet;
/**
* Расширение базового контракта сервисов с добавлением пагинации.

View File

@ -1,4 +1,4 @@
package org.sadtech.haiti.context.service.simple;
package dev.struchkov.haiti.context.service.simple;
import lombok.NonNull;
@ -17,6 +17,8 @@ public interface SimpleService<T, K> {
Optional<T> getById(@NonNull K primaryKey);
T getByIdOrThrow(@NonNull K primaryKey);
boolean existsById(@NonNull K primaryKey);
void deleteById(@NonNull K primaryKey);

View File

@ -1,14 +0,0 @@
package org.sadtech.haiti.context.exception;
/**
* Исключения, возникающиек, когда необходимые данные не были найдены.
*
* @author upagge 17.12.2019
*/
public class NotFoundException extends BasicException {
public NotFoundException(String message) {
super(message);
}
}

View File

@ -1,8 +0,0 @@
package org.sadtech.haiti.context.repository;
import org.sadtech.haiti.context.repository.simple.CrudOperation;
import org.sadtech.haiti.context.repository.simple.MultipleOperation;
import org.sadtech.haiti.context.repository.simple.PagingOperation;
public interface SimpleManagerRepository<T, K> extends CrudOperation<T, K>, MultipleOperation<T, K>, PagingOperation<T> {
}

View File

@ -1,14 +0,0 @@
package org.sadtech.haiti.context.repository.simple;
import lombok.NonNull;
import java.util.Collection;
import java.util.List;
public interface MultipleOperation<T, K> {
List<T> saveAll(@NonNull Collection<T> entities);
void deleteAllById(@NonNull Collection<K> primaryKeys);
}

View File

@ -1,11 +0,0 @@
package org.sadtech.haiti.context.repository.simple;
import lombok.NonNull;
import org.sadtech.haiti.context.page.Pagination;
import org.sadtech.haiti.context.page.Sheet;
public interface PagingOperation<T> {
Sheet<T> findAll(@NonNull Pagination pagination);
}

View File

@ -1,9 +0,0 @@
package org.sadtech.haiti.context.service;
import org.sadtech.haiti.context.service.simple.MultipleService;
import org.sadtech.haiti.context.service.simple.PagingService;
import org.sadtech.haiti.context.service.simple.SimpleService;
public interface SimpleManagerService<T, K> extends SimpleService<T, K>, MultipleService<T, K>, PagingService<T> {
}

View File

@ -1,16 +0,0 @@
package org.sadtech.haiti.context.service.simple;
import lombok.NonNull;
import java.util.Collection;
import java.util.List;
public interface MultipleService<T, K> {
List<T> createAll(@NonNull Collection<T> entities);
List<T> updateAll(@NonNull Collection<T> entities);
void deleteAllById(@NonNull Collection<K> ids);
}

View File

@ -4,50 +4,45 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sadtech.haiti</groupId>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti</artifactId>
<version>0.0.1-RELEASE</version>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>haiti-core</artifactId>
<version>0.0.1-RELEASE</version>
<version>0.0.1-SNAPSHOT</version>
<name>Haiti Core</name>
<description>Implementation of the main classes of the framework</description>
<url>https://github.com/haiti-projects/haiti-framework</url>
<organization>
<name>SADTECH</name>
<url>https://sadtech.org</url>
</organization>
<dependencies>
<dependency>
<groupId>org.sadtech.haiti</groupId>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-context</artifactId>
</dependency>
<dependency>
<groupId>org.sadtech.haiti</groupId>
<artifactId>haiti-filter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-filter</artifactId>
</dependency>
</dependencies>
<developers>
<developer>
<id>uPagge</id>
<name>Struchkov Mark</name>
<email>upagge@ya.ru</email>
<organization>SADTECH</organization>
<organizationUrl>https://sadtech.org</organizationUrl>
<url>https://uPagge.sadtech.org</url>
<email>mark@struchkov.dev</email>
<organization>Struchkov Inc.</organization>
<organizationUrl>https://struchkov.dev</organizationUrl>
<url>https://mark.struchkov.dev</url>
<roles>
<role>Project lead</role>
<role>Project Lead</role>
</roles>
<timezone>+3</timezone>
</developer>

View File

@ -1,8 +1,8 @@
package org.sadtech.haiti.core.page;
package dev.struchkov.haiti.core.page;
import dev.struchkov.haiti.context.enums.TypeSort;
import dev.struchkov.haiti.context.page.Pagination;
import lombok.Getter;
import org.sadtech.haiti.context.enums.TypeSort;
import org.sadtech.haiti.context.page.Pagination;
@Getter
public class PaginationImpl implements Pagination {

View File

@ -1,12 +1,14 @@
package org.sadtech.haiti.core.page;
package dev.struchkov.haiti.core.page;
import dev.struchkov.haiti.context.page.Sheet;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import org.sadtech.haiti.context.page.Sheet;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@Getter
@ -20,11 +22,6 @@ public class SheetImpl<T> implements Sheet<T> {
private final int totalPage;
private final List<T> content;
@Override
public boolean hasContent() {
return content != null && !content.isEmpty();
}
@Override
public <U> Sheet<U> map(Function<? super T, ? extends U> function) {
return new SheetImpl<>(
@ -36,5 +33,29 @@ public class SheetImpl<T> implements Sheet<T> {
);
}
public static <T> Sheet<T> empty() {
return new SheetImpl<>(
0,
0,
0L,
0,
Collections.emptyList()
);
}
public Sheet<T> filter(Predicate<? super T> predicate) {
final List<T> filterContent = content.stream().filter(predicate).collect(Collectors.toList());
return new SheetImpl<>(
this.number,
this.size,
this.totalElement,
this.totalPage,
filterContent
);
}
public boolean hasContent() {
return content != null && !content.isEmpty();
}
}

View File

@ -1,19 +1,19 @@
package org.sadtech.haiti.core.service;
package dev.struchkov.haiti.core.service;
import dev.struchkov.haiti.context.page.Pagination;
import dev.struchkov.haiti.context.page.Sheet;
import dev.struchkov.haiti.context.service.simple.FilterService;
import dev.struchkov.haiti.filter.Filter;
import dev.struchkov.haiti.filter.FilterOperation;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.sadtech.haiti.context.page.Pagination;
import org.sadtech.haiti.context.page.Sheet;
import org.sadtech.haiti.filter.Filter;
import org.sadtech.haiti.filter.FilterOperation;
import org.sadtech.haiti.filter.FilterService;
import java.util.Optional;
@RequiredArgsConstructor
public abstract class AbstractFilterService<T, F> implements FilterService<T, F> {
private final FilterOperation<T> filterOperation;
protected final FilterOperation<T> filterOperation;
@Override
public Sheet<T> getAll(@NonNull F filter, Pagination pagination) {

View File

@ -1,17 +1,20 @@
package org.sadtech.haiti.core.service;
package dev.struchkov.haiti.core.service;
import dev.struchkov.haiti.context.domain.BasicEntity;
import dev.struchkov.haiti.context.domain.ExistsContainer;
import dev.struchkov.haiti.context.repository.simple.MultipleOperation;
import dev.struchkov.haiti.context.service.simple.MultipleService;
import dev.struchkov.haiti.context.service.simple.SimpleService;
import dev.struchkov.haiti.core.util.ServiceOperation;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.sadtech.haiti.context.repository.simple.MultipleOperation;
import org.sadtech.haiti.context.service.simple.MultipleService;
import org.sadtech.haiti.context.service.simple.SimpleService;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@RequiredArgsConstructor
public abstract class AbstractMultipleService<T, K> implements MultipleService<T, K> {
public abstract class AbstractMultipleService<T extends BasicEntity<K>, K> implements MultipleService<T, K> {
private final SimpleService<T, K> simpleService;
private final MultipleOperation<T, K> multipleOperation;
@ -31,4 +34,9 @@ public abstract class AbstractMultipleService<T, K> implements MultipleService<T
return entities.stream().map(simpleService::update).collect(Collectors.toList());
}
@Override
public ExistsContainer<T, K> existsById(@NonNull Collection<K> ids) {
return ServiceOperation.existsContainerById(multipleOperation, ids);
}
}

View File

@ -1,11 +1,11 @@
package org.sadtech.haiti.core.service;
package dev.struchkov.haiti.core.service;
import dev.struchkov.haiti.context.page.Pagination;
import dev.struchkov.haiti.context.page.Sheet;
import dev.struchkov.haiti.context.repository.simple.PagingOperation;
import dev.struchkov.haiti.context.service.simple.PagingService;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.sadtech.haiti.context.page.Pagination;
import org.sadtech.haiti.context.page.Sheet;
import org.sadtech.haiti.context.repository.simple.PagingOperation;
import org.sadtech.haiti.context.service.simple.PagingService;
@RequiredArgsConstructor
public abstract class AbstractPagingService<T> implements PagingService<T> {

View File

@ -1,12 +1,15 @@
package org.sadtech.haiti.core.service;
package dev.struchkov.haiti.core.service;
import dev.struchkov.haiti.context.domain.BasicEntity;
import dev.struchkov.haiti.context.domain.ExistsContainer;
import dev.struchkov.haiti.context.exception.NotFoundException;
import dev.struchkov.haiti.context.page.Pagination;
import dev.struchkov.haiti.context.page.Sheet;
import dev.struchkov.haiti.context.repository.SimpleManagerRepository;
import dev.struchkov.haiti.context.service.SimpleManagerService;
import dev.struchkov.haiti.core.util.ServiceOperation;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.sadtech.haiti.context.page.Pagination;
import org.sadtech.haiti.context.page.Sheet;
import org.sadtech.haiti.context.repository.SimpleManagerRepository;
import org.sadtech.haiti.context.service.SimpleManagerService;
import org.sadtech.haiti.core.util.ServiceOperation;
import java.util.Collection;
import java.util.List;
@ -14,9 +17,9 @@ import java.util.Optional;
import java.util.stream.Collectors;
@RequiredArgsConstructor
public abstract class AbstractSimpleManagerService<T, K> implements SimpleManagerService<T, K> {
public abstract class AbstractSimpleManagerService<T extends BasicEntity<K>, K> implements SimpleManagerService<T, K> {
private final SimpleManagerRepository<T, K> repository;
protected final SimpleManagerRepository<T, K> repository;
@Override
public void deleteAllById(@NonNull Collection<K> primaryKeys) {
@ -33,6 +36,11 @@ public abstract class AbstractSimpleManagerService<T, K> implements SimpleManage
return ServiceOperation.getById(repository, primaryKey);
}
@Override
public T getByIdOrThrow(@NonNull K primaryKey) {
return getById(primaryKey).orElseThrow(NotFoundException.supplier("Объект не найден. Идентификатор: ", primaryKey));
}
@Override
public boolean existsById(@NonNull K primaryKey) {
return ServiceOperation.existsById(repository, primaryKey);
@ -53,4 +61,9 @@ public abstract class AbstractSimpleManagerService<T, K> implements SimpleManage
return entities.stream().map(this::update).collect(Collectors.toList());
}
@Override
public ExistsContainer<T, K> existsById(@NonNull Collection<K> ids) {
return ServiceOperation.existsContainerById(repository, ids);
}
}

View File

@ -1,9 +1,10 @@
package org.sadtech.haiti.core.service;
package dev.struchkov.haiti.core.service;
import dev.struchkov.haiti.context.repository.simple.CrudOperation;
import dev.struchkov.haiti.context.service.simple.SimpleService;
import dev.struchkov.haiti.core.util.ServiceOperation;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.sadtech.haiti.context.repository.simple.CrudOperation;
import org.sadtech.haiti.context.service.simple.SimpleService;
import java.util.Optional;
@ -14,17 +15,17 @@ public abstract class AbstractSimpleService<T, K> implements SimpleService<T, K>
@Override
public Optional<T> getById(@NonNull K primaryKey) {
return crudOperation.findById(primaryKey);
return ServiceOperation.getById(crudOperation, primaryKey);
}
@Override
public boolean existsById(@NonNull K primaryKey) {
return crudOperation.existsById(primaryKey);
return ServiceOperation.existsById(crudOperation, primaryKey);
}
@Override
public void deleteById(@NonNull K primaryKey) {
crudOperation.deleteById(primaryKey);
ServiceOperation.deleteById(crudOperation, primaryKey);
}
}

View File

@ -0,0 +1,55 @@
package dev.struchkov.haiti.core.util;
import dev.struchkov.haiti.context.domain.BasicEntity;
import dev.struchkov.haiti.context.domain.ExistsContainer;
import dev.struchkov.haiti.context.page.Pagination;
import dev.struchkov.haiti.context.page.Sheet;
import dev.struchkov.haiti.context.repository.simple.CrudOperation;
import dev.struchkov.haiti.context.repository.simple.MultipleOperation;
import dev.struchkov.haiti.context.repository.simple.PagingOperation;
import lombok.experimental.UtilityClass;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@UtilityClass
public final class ServiceOperation {
public static <T extends BasicEntity<K>, K> void deleteAllById(MultipleOperation<T, K> repository, Collection<K> primaryKeys) {
repository.deleteAllById(primaryKeys);
}
public static <T> Sheet<T> getAll(PagingOperation<T> repository, Pagination pagination) {
return repository.findAll(pagination);
}
public static <T, K> Optional<T> getById(CrudOperation<T, K> repository, K primaryKey) {
return repository.findById(primaryKey);
}
public static <T, K> boolean existsById(CrudOperation<T, K> repository, K primaryKey) {
return repository.existsById(primaryKey);
}
public static <T, K> void deleteById(CrudOperation<T, K> repository, K primaryKey) {
repository.deleteById(primaryKey);
}
public static <K, T extends BasicEntity<K>> ExistsContainer<T, K> existsContainerById(MultipleOperation<T, K> multipleOperation, Collection<K> ids) {
final List<T> existsEntity = multipleOperation.findAllById(ids);
final Set<K> existsIds = existsEntity.stream()
.map(BasicEntity::getId)
.collect(Collectors.toSet());
if (existsIds.containsAll(ids)) {
return ExistsContainer.allFind(existsEntity);
} else {
final Set<K> noExistsId = ids.stream()
.filter(id -> !existsIds.contains(id))
.collect(Collectors.toSet());
return ExistsContainer.notAllFind(existsEntity, noExistsId);
}
}
}

View File

@ -1,23 +0,0 @@
package org.sadtech.haiti.core.util;
/**
* // TODO: 06.09.2020 Добавить описание.
*
* @author upagge 06.09.2020
*/
public final class Assert {
public static void isNull(Object object, String message) {
if (object != null) {
throw new IllegalStateException(message);
}
}
public static void isNotNull(Object object, String message) {
if (object == null) {
throw new IllegalStateException(message);
}
}
}

View File

@ -1,37 +0,0 @@
package org.sadtech.haiti.core.util;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.sadtech.haiti.context.page.Pagination;
import org.sadtech.haiti.context.page.Sheet;
import org.sadtech.haiti.context.repository.simple.CrudOperation;
import org.sadtech.haiti.context.repository.simple.MultipleOperation;
import org.sadtech.haiti.context.repository.simple.PagingOperation;
import java.util.Collection;
import java.util.Optional;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class ServiceOperation {
public static <T, K> void deleteAllById(MultipleOperation<T, K> repository, Collection<K> primaryKeys) {
repository.deleteAllById(primaryKeys);
}
public static <T> Sheet<T> getAll(PagingOperation<T> repository, Pagination pagination) {
return repository.findAll(pagination);
}
public static <T, K> Optional<T> getById(CrudOperation<T, K> repository, K primaryKey) {
return repository.findById(primaryKey);
}
public static <T, K> boolean existsById(CrudOperation<T, K> repository, K primaryKey) {
return repository.existsById(primaryKey);
}
public static <T, K> void deleteById(CrudOperation<T, K> repository, K primaryKey) {
repository.deleteById(primaryKey);
}
}

View File

@ -4,23 +4,18 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sadtech.haiti</groupId>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti</artifactId>
<version>0.0.1-RELEASE</version>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>haiti-filter</artifactId>
<version>0.0.1-RELEASE</version>
<version>0.0.1-SNAPSHOT</version>
<name>Haiti Filter</name>
<description>Fast and convenient filtering requests to data warehouses.</description>
<url>https://github.com/haiti-projects/haiti-framework</url>
<organization>
<name>SADTECH</name>
<url>https://sadtech.org</url>
</organization>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
@ -28,7 +23,7 @@
</dependency>
<dependency>
<groupId>org.sadtech.haiti</groupId>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-context</artifactId>
</dependency>
</dependencies>
@ -37,12 +32,12 @@
<developer>
<id>uPagge</id>
<name>Struchkov Mark</name>
<email>upagge@ya.ru</email>
<organization>SADTECH</organization>
<organizationUrl>https://sadtech.org</organizationUrl>
<url>https://uPagge.sadtech.org</url>
<email>mark@struchkov.dev</email>
<organization>Struchkov Inc.</organization>
<organizationUrl>https://struchkov.dev</organizationUrl>
<url>https://mark.struchkov.dev</url>
<roles>
<role>Project lead</role>
<role>Project Lead</role>
</roles>
<timezone>+3</timezone>
</developer>

View File

@ -0,0 +1,13 @@
package dev.struchkov.haiti.filter;
public interface Filter {
Filter and(FilterQuery filterQuery);
Filter or(FilterQuery filterQuery);
Filter not(FilterQuery filterQuery);
<Q> Q build();
}

View File

@ -0,0 +1,19 @@
package dev.struchkov.haiti.filter;
import lombok.NonNull;
import dev.struchkov.haiti.context.page.Pagination;
import dev.struchkov.haiti.context.page.Sheet;
import java.util.Optional;
public interface FilterOperation<T> {
Sheet<T> findAll(@NonNull Filter filter, @NonNull Pagination pagination);
Optional<T> findFirst(@NonNull Filter filter);
boolean exists(@NonNull Filter filter);
long count(@NonNull Filter filter);
}

View File

@ -0,0 +1,63 @@
package dev.struchkov.haiti.filter;
import lombok.NonNull;
import java.util.Set;
public interface FilterQuery {
/**
* Добавляет в запрос поиск по диапазону.
*
* @param field Название поля в elasticsearch
* @param from Начало интервала
* @param to Конец интервала
*/
<Y extends Comparable<? super Y>> FilterQuery between(@NonNull String field, Y from, Y to);
<Y extends Comparable<? super Y>> FilterQuery greaterThan(@NonNull String field, Y value);
<Y extends Comparable<? super Y>> FilterQuery lessThan(@NonNull String field, Y value);
/**
* Добавляет в запрос проверку по значению поля
*
* @param field Название поля
* @param value Значение поля для проверки
*/
FilterQuery matchPhrase(@NonNull String field, Object value);
/**
* Добавляет в запрос проверку по нескольким значениям одного поля
*
* @param field Название поля
* @param value Значения поля
*/
<U> FilterQuery matchPhrase(@NonNull String field, Set<U> value);
/**
* Добавляет в запрос проверку на NULL значение поля
*
* @param field Наименование поля
*/
FilterQuery exists(String field);
/**
* Поиск подстрок
*
* @param field Названия поля
* @param value Часть искомого значения
*/
FilterQuery like(@NonNull String field, String value, boolean ignoreCase);
/**
* Добавляет в запрос поиск по флагу, который конвертируется в диапазон
*
* @param flag Значение флага
* @param field Поле для проверки
*/
FilterQuery checkBoolInt(@NonNull String field, Boolean flag);
<Q> Q build();
}

View File

@ -0,0 +1,9 @@
package dev.struchkov.haiti.filter.exception;
public class BadFilterConstructorException extends FilterException {
public BadFilterConstructorException(String s) {
super(s);
}
}

View File

@ -0,0 +1,20 @@
package dev.struchkov.haiti.filter.exception;
import dev.struchkov.haiti.context.exception.BasicException;
/**
* // TODO: 09.11.2020 Добавить описание.
*
* @author upagge 09.11.2020
*/
public class FilterException extends BasicException {
protected FilterException(String message) {
super(message);
}
protected FilterException(String message, Throwable cause) {
super(message, cause);
}
}

42
haiti-utils/pom.xml Normal file
View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>haiti-utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-context</artifactId>
</dependency>
</dependencies>
<developers>
<developer>
<id>uPagge</id>
<name>Struchkov Mark</name>
<email>mark@struchkov.dev</email>
<organization>Struchkov Inc.</organization>
<organizationUrl>https://struchkov.dev</organizationUrl>
<url>https://mark.struchkov.dev</url>
<roles>
<role>Project Lead</role>
</roles>
<timezone>+3</timezone>
</developer>
</developers>
</project>

View File

@ -0,0 +1,72 @@
package dev.struchkov.haiti.utils;
import lombok.experimental.UtilityClass;
import java.util.function.Supplier;
/**
* // TODO: 06.09.2020 Добавить описание.
*
* @author upagge 06.09.2020
*/
@UtilityClass
public final class Assert {
/**
* Проверка на null значение с возвращением исключения, если объект не null.
*
* @param object Проверяемый объект
* @param exception Возвращаемое исключение
*/
public static void isNull(Object object, Supplier<? extends RuntimeException> exception) {
if (object != null) {
throw exception.get();
}
}
/**
* Проверка на null значение с возвращением исключения, если объект null.
*
* @param object Проверяемый объект
* @param exception Возвращаемое исключение
*/
public static void isNotNull(Object object, Supplier<? extends RuntimeException> exception) {
if (object == null) {
throw exception.get();
}
}
/**
* Проверка на true значение с возвращением исключения, если flag не true.
*
* @param flag Проверяемое значение
* @param exception Возвращаемое исключение
*/
public static void isTrue(boolean flag, Supplier<? extends RuntimeException> exception) {
if (!flag) {
throw exception.get();
}
}
/**
* Проверка на false значение с возвращением исключения, если flag не false.
*
* @param flag Проверяемое значение
* @param exception Возвращаемое исключение
*/
public static void isFalse(boolean flag, Supplier<? extends RuntimeException> exception) {
if (flag) {
throw exception.get();
}
}
@UtilityClass
public static final class Utils {
public static Supplier<NullPointerException> nullPointer(String fieldName) {
return () -> new NullPointerException(fieldName + " is marked non-null but is null");
}
}
}

View File

@ -0,0 +1,155 @@
package dev.struchkov.haiti.utils;
import dev.struchkov.haiti.context.exception.ConvertException;
import lombok.NonNull;
import lombok.experimental.UtilityClass;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* // TODO: 07.03.2021 Добавить описание.
*
* @author upagge 07.03.2021
*/
@UtilityClass
public class ObjectUtils {
/**
* <p>Позволяет получить значение вложенного в объект поля по названию поля.</p>
* <p></p>
* <p><b>При этом у поля должен быть доступен get-метод</b></p>
* <p></p>
* <p>Поддерживаются воженные объекты, чтобы задать такой объект, необходимо прописать путь до него от переданного объекта через '.'. У всех объектов на пути должны быть get-методы.</p>
*
* @param fieldName Имя поля в объекте или цепь имен
* @param object Объект
* @return Значение поля из объекта
*/
public static Object getFieldValue(@NonNull Object object, @NonNull String fieldName) {
int firstNameIndex = fieldName.indexOf(".");
String firstName;
if (firstNameIndex != -1) {
firstName = fieldName.substring(0, firstNameIndex);
} else {
firstName = fieldName;
}
for (Method method : object.getClass().getMethods()) {
if (isGetMethod(firstName, method)) {
try {
final Object invoke = method.invoke(object);
if (firstNameIndex == -1) {
return invoke;
} else {
return getFieldValue(invoke, fieldName.substring(firstNameIndex + 1));
}
} catch (IllegalAccessException | InvocationTargetException e) {
throw new ConvertException("Не удалось определить метод " + method.getName());
}
}
}
throw new ConvertException("Метод у объекта не найден");
}
public static void setFieldValue(@NonNull Object object, @NonNull String fieldName, Object fieldValue) {
int firstNameIndex = fieldName.indexOf(".");
if (firstNameIndex != -1) {
final String[] split = fieldName.split("\\.");
final String fieldNameToObject = String.join(".", Arrays.copyOf(split, split.length - 1));
fieldName = split[split.length - 1];
object = getFieldValue(object, fieldNameToObject);
}
boolean flag = true;
for (Method method : object.getClass().getMethods()) {
if (isSetMethod(fieldName, method)) {
try {
Class<?> parameterType = method.getParameterTypes()[0];
method.invoke(object, convertFieldValue(fieldValue, parameterType));
flag = false;
break;
} catch (IllegalAccessException | InvocationTargetException e) {
throw new ConvertException("Не удалось определить метод " + method.getName());
}
}
}
Assert.isFalse(flag, () -> new ConvertException("Метод у объекта не найден"));
}
private static Object convertFieldValue(Object fieldValue, Class<?> parameterType) {
if (String.class.equals(fieldValue.getClass())) {
final String value = (String) fieldValue;
if ("null".equalsIgnoreCase(value)) {
return null;
}
if (Long.class.equals(parameterType)) {
return Long.valueOf(value);
}
if (Integer.class.equals(parameterType)) {
return Integer.valueOf(value);
}
if (Double.class.equals(parameterType)) {
return Double.valueOf(value);
}
if (Float.class.equals(parameterType)) {
return Float.valueOf(value);
}
if (BigDecimal.class.equals(parameterType)) {
return BigDecimal.valueOf(Long.parseLong(value));
}
if (BigInteger.class.equals(parameterType)) {
return BigInteger.valueOf(Long.parseLong(value));
}
}
return fieldValue;
}
/**
* Определяет что метод является геттером поля.
*
* @param fieldName Поле
* @param method Метод
* @return true если метод является геттером для fieldName, false в противном случае
*/
public static boolean isGetMethod(@NonNull String fieldName, Method method) {
return (method.getName().startsWith("get"))
&& (method.getName().length() == (fieldName.length() + 3))
&& method.getName().toLowerCase().endsWith(fieldName.toLowerCase());
}
/**
* Определяет что метод является сеттером поля.
*
* @param fieldName Поле
* @param method Метод
* @return true если метод является сеттером для fieldName, false в противном случае
*/
public static boolean isSetMethod(@NonNull String fieldName, Method method) {
return (method.getName().startsWith("set"))
&& (method.getName().length() == (fieldName.length() + 3))
&& method.getName().toLowerCase().endsWith(fieldName.toLowerCase());
}
public static <T> Collection<T> toCollect(T... t) {
return Arrays.stream(t).collect(Collectors.toList());
}
public static <T> Collection<T> toCollect(Collection<T> collection, T... t) {
return Stream.concat(
collection.stream(), Arrays.stream(t)
).collect(Collectors.toList());
}
public static <T> Collection<T> toCollect(Collection<T> collectionOne, Collection<T> collectionTwo) {
return Stream.concat(
collectionOne.stream(), collectionTwo.stream()
).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,15 @@
package dev.struchkov.haiti.utils;
import lombok.experimental.UtilityClass;
/**
* // TODO: 07.03.2021 Добавить описание.
*
* @author upagge 07.03.2021
*/
@UtilityClass
public class Strings {
public static final String EMPTY = "";
}

23
pom.xml
View File

@ -4,9 +4,9 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.sadtech.haiti</groupId>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti</artifactId>
<version>0.0.1-RELEASE</version>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
@ -14,6 +14,7 @@
<module>haiti-core</module>
<module>haiti-filter</module>
<module>haiti-bom</module>
<module>haiti-utils</module>
</modules>
<name>Haiti Framework</name>
@ -43,8 +44,8 @@
</licenses>
<organization>
<name>SADTECH</name>
<url>https://sadtech.org</url>
<name>Struchkov Inc.</name>
<url>https://mark.struchkov.dev</url>
</organization>
<scm>
@ -129,9 +130,9 @@
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.sadtech.haiti</groupId>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-bom</artifactId>
<version>0.0.1-RELEASE</version>
<version>0.0.1-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -156,12 +157,12 @@
<developer>
<id>uPagge</id>
<name>Struchkov Mark</name>
<email>upagge@ya.ru</email>
<organization>SADTECH</organization>
<organizationUrl>https://sadtech.org</organizationUrl>
<url>https://uPagge.sadtech.org</url>
<email>mark@struchkov.dev</email>
<organization>Struchkov Inc.</organization>
<organizationUrl>https://struchkov.dev</organizationUrl>
<url>https://mark.struchkov.dev</url>
<roles>
<role>Project lead</role>
<role>Project Lead</role>
</roles>
<timezone>+3</timezone>
</developer>