Merge branch 'master' into develop

# Conflicts:
#	pom.xml
This commit is contained in:
Struchkov Mark 2022-02-14 10:30:18 +03:00
commit a8c4e828c2
9 changed files with 267 additions and 167 deletions

17
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,17 @@
image: maven:3.8.4-openjdk-11
variables:
MAVEN_OPTS: "-Dmaven.repo.local=./.m2/repository"
stages:
- deploy
deploy:
stage: deploy
only:
- /^v.*$/
except:
- branches
before_script:
- gpg --pinentry-mode loopback --passphrase $GPG_PASSPHRASE --import $GPG_PRIVATE_KEY
script:
- 'mvn --settings $MAVEN_SETTINGS -U -P ossrh,release clean deploy'

68
pom.xml
View File

@ -6,7 +6,7 @@
<groupId>dev.struchkov.haiti.filter</groupId>
<artifactId>haiti-filter-jooq</artifactId>
<version>0.3.0-SNAPSHOT</version>
<version>0.4.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Haiti Filter JOOQ</name>
@ -18,6 +18,10 @@
<url>https://raw.githubusercontent.com/haiti-projects/haiti-filter-jooq/master/LICENSE</url>
</license>
</licenses>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/haiti-projects/haiti-filter-jooq/issues</url>
</issueManagement>
<properties>
<maven.compiler.source>11</maven.compiler.source>
@ -36,7 +40,7 @@
<dependency>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-bom</artifactId>
<version>0.0.2</version>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -46,11 +50,11 @@
<dependencies>
<dependency>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-filter</artifactId>
<artifactId>haiti-utils</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-utils</artifactId>
<artifactId>haiti-exception</artifactId>
</dependency>
<dependency>
<groupId>org.jooq</groupId>
@ -59,28 +63,6 @@
</dependency>
</dependencies>
<scm>
<connection>scm:git:https://github.com/haiti-projects/haiti-filter-jooq.git</connection>
<url>https://github.com/haiti-projects/haiti-filter-jooq</url>
<developerConnection>scm:git:https://github.com/haiti-projects/haiti-filter-jooq.git</developerConnection>
</scm>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<developers>
<developer>
<id>uPagge</id>
<name>Struchkov Mark</name>
<url>https://mark.struchkov.dev</url>
<email>mark@struchkov.dev</email>
</developer>
</developers>
<build>
<pluginManagement>
<plugins>
@ -153,6 +135,14 @@
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
</plugins>
</build>
@ -171,15 +161,37 @@
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<artifactId>maven-gpg-plugin</artifactId>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<scm>
<connection>scm:git:https://github.com/haiti-projects/haiti-filter-jooq.git</connection>
<url>https://github.com/haiti-projects/haiti-filter-jooq</url>
<developerConnection>scm:git:https://github.com/haiti-projects/haiti-filter-jooq.git</developerConnection>
</scm>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<developers>
<developer>
<id>uPagge</id>
<name>Struchkov Mark</name>
<url>https://mark.struchkov.dev</url>
<email>mark@struchkov.dev</email>
</developer>
</developers>
</project>

View File

@ -1,12 +1,9 @@
package dev.struchkov.haiti.filter.jooq;
import dev.struchkov.haiti.filter.Filter;
import dev.struchkov.haiti.filter.FilterQuery;
import dev.struchkov.haiti.filter.jooq.exception.FilterJooqHaitiException;
import dev.struchkov.haiti.filter.jooq.page.PageableOffset;
import dev.struchkov.haiti.filter.jooq.page.PageableSeek;
import dev.struchkov.haiti.utils.Assert;
import lombok.NonNull;
import org.jooq.Condition;
import org.jooq.DSLContext;
import org.jooq.Operator;
@ -21,15 +18,16 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import static dev.struchkov.haiti.filter.jooq.exception.FilterJooqHaitiException.filterJooqException;
import static org.jooq.impl.DSL.condition;
import static org.jooq.impl.DSL.field;
public class CriteriaJooqFilter implements Filter {
public class CriteriaJooqFilter {
private final List<Condition> andConditions = new ArrayList<>();
private final List<Condition> orConditions = new ArrayList<>();
private final List<Condition> notConditions = new ArrayList<>();
private final List<JoinTable> joinTables = new ArrayList<>();
// private final List<JoinTable> joinTables = new ArrayList<>();
private final String table;
private final DSLContext dsl;
@ -47,84 +45,83 @@ public class CriteriaJooqFilter implements Filter {
return new CriteriaJooqFilter(table, dsl);
}
@Override
public Filter and(FilterQuery filterQuery) {
generateAnd((CriteriaJooqQuery) filterQuery);
public CriteriaJooqFilter and(CriteriaJooqQuery filterQuery) {
generateAnd(filterQuery);
return this;
}
@Override
public Filter and(Consumer<FilterQuery> query) {
public CriteriaJooqFilter and(Consumer<CriteriaJooqQuery> query) {
final CriteriaJooqQuery criteriaQuery = CriteriaJooqQuery.create();
query.accept(criteriaQuery);
generateAnd(criteriaQuery);
return this;
}
@Override
public Filter or(FilterQuery filterQuery) {
generateOr((CriteriaJooqQuery) filterQuery);
public CriteriaJooqFilter or(CriteriaJooqQuery filterQuery) {
generateOr(filterQuery);
return this;
}
public Filter or(Consumer<FilterQuery> query) {
public CriteriaJooqFilter or(Consumer<CriteriaJooqQuery> query) {
final CriteriaJooqQuery criteriaQuery = CriteriaJooqQuery.create();
query.accept(criteriaQuery);
generateOr(criteriaQuery);
return this;
}
@Override
public Filter not(FilterQuery filterQuery) {
// FIXME: Добавить поддержку
throw new IllegalStateException("Операция отрицания пока не поддерживается");
}
// FIXME: Добавить поддержку
// public CriteriaJooqFilter not(FilterQuery filterQuery) {
// throw new IllegalStateException("Операция отрицания пока не поддерживается");
// }
@Override
public Filter not(Consumer<FilterQuery> query) {
// FIXME: Добавить поддержку
throw new IllegalStateException("Операция отрицания пока не поддерживается");
}
public Filter page(@NonNull PageableOffset offset) {
Assert.isNull(seek, () -> new FilterJooqHaitiException("Нельзя установить два типа пагинации одновременно"));
// FIXME: Добавить поддержку
// public CriteriaJooqFilter not(Consumer<FilterQuery> query) {
// throw new IllegalStateException("Операция отрицания пока не поддерживается");
// }
public CriteriaJooqFilter page(PageableOffset offset) {
Assert.isNotNull(offset);
Assert.isNull(seek, filterJooqException("Нельзя установить два типа пагинации одновременно"));
this.offset = offset;
return this;
}
public Filter page(@NonNull PageableSeek seek) {
Assert.isNull(offset, () -> new FilterJooqHaitiException("Нельзя установить два типа пагинации одновременно"));
public CriteriaJooqFilter page(PageableSeek seek) {
Assert.isNotNull(seek);
Assert.isNull(offset, filterJooqException("Нельзя установить два типа пагинации одновременно"));
this.seek = seek;
return this;
}
public Filter sort(@NonNull SortContainer container) {
public CriteriaJooqFilter sort(SortContainer container) {
Assert.isNotNull(container);
if (container.getFieldName() != null) {
this.sorts.add(container);
}
return this;
}
public Filter sort(String field, SortType sortType) {
public CriteriaJooqFilter sort(String field, SortType sortType) {
if (field != null) {
this.sorts.add(SortContainer.of(field, sortType));
}
return this;
}
public Filter sort(String field) {
public CriteriaJooqFilter sort(String field) {
if (field != null) {
this.sorts.add(SortContainer.of(field));
}
return this;
}
public Filter join(@NonNull JoinTable... joinTables) {
// FIXME: Добавить поддержку
throw new IllegalStateException("Операция пока не поддерживается");
// FIXME: Добавить поддержку
// public CriteriaJooqFilter join(@NonNull JoinTable... joinTables) {
// throw new IllegalStateException("Операция пока не поддерживается");
// this.joinTables.addAll(Arrays.stream(joinTables).collect(Collectors.toList()));
// return this;
}
// }
private void generateAnd(CriteriaJooqQuery criteriaQuery) {
andConditions.addAll(criteriaQuery.getConditions());
@ -134,8 +131,38 @@ public class CriteriaJooqFilter implements Filter {
orConditions.addAll(criteriaQuery.getConditions());
}
@Override
public Query build() {
final List<Condition> conditions = getConditions();
SelectJoinStep<Record> from = dsl.select().from(table);
// if (!joinTables.isEmpty()) {
// for (JoinTable joinTable : joinTables) {
// final String tableName = joinTable.getTableName();
// final JoinTypeOperation joinType = joinTable.getJoinTypeOperation();
// final String fieldReference = joinTable.getFieldReference();
// final String fieldBase = joinTable.getFieldBase();
// final Condition on = field(fieldReference).eq(field(fieldBase));
// switch (joinType) {
// case LEFT:
// from = from.leftJoin(tableName).on(on);
// break;
// case INNER:
// from = from.innerJoin(tableName).on(on);
// break;
// case RIGHT:
// from = from.rightJoin(tableName).on(on);
// break;
// }
// }
// }
final SelectConditionStep<Record> where = from.where(conditions);
final SelectSeekStepN<? extends Record> sort = setSort(where);
setPaginationOffset(where);
setPaginationSeek(sort);
return where;
}
private List<Condition> getConditions() {
final List<Condition> conditions = new ArrayList<>();
if (!andConditions.isEmpty()) {
conditions.add(condition(Operator.AND, andConditions));
@ -143,35 +170,38 @@ public class CriteriaJooqFilter implements Filter {
if (!orConditions.isEmpty()) {
conditions.add(condition(Operator.OR, orConditions));
}
SelectJoinStep<Record> from = dsl.select().from(table);
if (!joinTables.isEmpty()) {
for (JoinTable joinTable : joinTables) {
final String tableName = joinTable.getTableName();
final JoinTypeOperation joinType = joinTable.getJoinTypeOperation();
final String fieldReference = joinTable.getFieldReference();
final String fieldBase = joinTable.getFieldBase();
final Condition on = field(fieldReference).eq(field(fieldBase));
switch (joinType) {
case LEFT:
from = from.leftJoin(tableName).on(on);
break;
case INNER:
from = from.innerJoin(tableName).on(on);
break;
case RIGHT:
from = from.rightJoin(tableName).on(on);
break;
}
}
}
final SelectConditionStep<Record> where = from.where(conditions);
final SelectSeekStepN<Record> sort = setSort(where);
setPaginationOffset(where);
setPaginationSeek(sort);
return conditions;
}
public Query count() {
final List<Condition> conditions = getConditions();
SelectJoinStep<? extends Record> from = dsl.selectCount().from(table);
// if (!joinTables.isEmpty()) {
// for (JoinTable joinTable : joinTables) {
// final String tableName = joinTable.getTableName();
// final JoinTypeOperation joinType = joinTable.getJoinTypeOperation();
// final String fieldReference = joinTable.getFieldReference();
// final String fieldBase = joinTable.getFieldBase();
// final Condition on = field(fieldReference).eq(field(fieldBase));
// switch (joinType) {
// case LEFT:
// from = from.leftJoin(tableName).on(on);
// break;
// case INNER:
// from = from.innerJoin(tableName).on(on);
// break;
// case RIGHT:
// from = from.rightJoin(tableName).on(on);
// break;
// }
// }
// }
final SelectConditionStep<? extends Record> where = from.where(conditions);
setSort(where);
return where;
}
private SelectSeekStepN<Record> setSort(SelectConditionStep<Record> where) {
private SelectSeekStepN<? extends Record> setSort(SelectConditionStep<? extends Record> where) {
if (!sorts.isEmpty()) {
final List<SortField<Object>> newSorts = new ArrayList<>();
for (SortContainer sort : sorts) {
@ -188,7 +218,7 @@ public class CriteriaJooqFilter implements Filter {
return null;
}
private void setPaginationSeek(SelectSeekStepN<Record> sort) {
private void setPaginationSeek(SelectSeekStepN<? extends Record> sort) {
if (seek != null) {
Assert.isNotNull(sort, () -> new FilterJooqHaitiException("При использовании пагинации типа seek необходимо указать сортировку"));
final Integer pageSize = seek.getPageSize();
@ -206,7 +236,7 @@ public class CriteriaJooqFilter implements Filter {
}
}
private void setPaginationOffset(SelectConditionStep<Record> where) {
private void setPaginationOffset(SelectConditionStep<? extends Record> where) {
if (offset != null) {
final int pageNumber = offset.getPageNumber();
final int pageSize = offset.getPageSize();
@ -214,4 +244,5 @@ public class CriteriaJooqFilter implements Filter {
where.limit(pageSize).offset(offsetNumber);
}
}
}

View File

@ -1,7 +1,6 @@
package dev.struchkov.haiti.filter.jooq;
import dev.struchkov.haiti.filter.FilterQuery;
import lombok.NonNull;
import dev.struchkov.haiti.utils.Assert;
import org.jooq.Condition;
import org.jooq.Field;
import org.jooq.impl.DSL;
@ -14,7 +13,7 @@ import java.util.Set;
import static org.jooq.impl.DSL.condition;
import static org.jooq.impl.DSL.field;
public class CriteriaJooqQuery implements FilterQuery {
public class CriteriaJooqQuery {
private final List<Condition> conditions = new ArrayList<>();
@ -22,12 +21,12 @@ public class CriteriaJooqQuery implements FilterQuery {
return new CriteriaJooqQuery();
}
protected List<Condition> getConditions() {
List<Condition> getConditions() {
return conditions;
}
@Override
public <Y extends Comparable<? super Y>> FilterQuery between(@NonNull String field, Y from, Y to) {
public <Y extends Comparable<? super Y>> CriteriaJooqQuery between(String field, Y from, Y to) {
Assert.isNotNull(field);
if (from != null && to != null) {
Condition condition = DSL.field(field).between(from, to);
conditions.add(condition);
@ -35,20 +34,8 @@ public class CriteriaJooqQuery implements FilterQuery {
return this;
}
@Override
public <Y extends Comparable<? super Y>> FilterQuery greaterThan(@NonNull String field, Y value) {
// FIXME: Добавить поддержку
throw new IllegalStateException("Операция пока не поддерживается");
}
@Override
public <Y extends Comparable<? super Y>> FilterQuery lessThan(@NonNull String field, Y value) {
// FIXME: Добавить поддержку
throw new IllegalStateException("Операция пока не поддерживается");
}
@Override
public FilterQuery matchPhrase(@NonNull String field, Object value) {
public CriteriaJooqQuery matchPhrase(String field, Object value) {
Assert.isNotNull(field);
if (value != null) {
final Condition condition = condition(Map.of(field(field), value));
conditions.add(condition);
@ -56,24 +43,23 @@ public class CriteriaJooqQuery implements FilterQuery {
return this;
}
@Override
public <U> FilterQuery matchPhrase(@NonNull String field, Set<U> values) {
public <U> CriteriaJooqQuery matchPhrase(String field, Set<U> values) {
Assert.isNotNull(field);
if (values != null && !values.isEmpty()) {
conditions.add(DSL.field(field).in(values));
}
return this;
}
@Override
public FilterQuery exists(String field) {
public CriteriaJooqQuery exists(String field) {
if (field != null) {
conditions.add(DSL.field(field).isNotNull());
}
return this;
}
@Override
public FilterQuery like(@NonNull String field, String value, boolean ignoreCase) {
public CriteriaJooqQuery like(String field, String value, boolean ignoreCase) {
Assert.isNotNull(field);
final Field<Object> query = field(field);
if (value != null) {
if (ignoreCase) {
@ -85,15 +71,4 @@ public class CriteriaJooqQuery implements FilterQuery {
return this;
}
@Override
public FilterQuery checkBoolInt(@NonNull String field, Boolean flag) {
// FIXME: Добавить поддержку
throw new IllegalStateException("Операция пока не поддерживается");
}
@Override
public List<Condition> build() {
return conditions;
}
}

View File

@ -1,17 +1,12 @@
package dev.struchkov.haiti.filter.jooq;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import dev.struchkov.haiti.utils.Assert;
/**
* Контейнер для соединения с таблицами.
*
* @author upagge 15.04.2021
*/
@Getter
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class JoinTable {
private final String tableName;
@ -19,12 +14,37 @@ public class JoinTable {
private final String fieldReference;
private final JoinTypeOperation joinTypeOperation;
public static JoinTable ofLeft(@NonNull String tableName, @NonNull String fieldBase, @NonNull String fieldReference) {
private JoinTable(String tableName, String fieldBase, String fieldReference, JoinTypeOperation joinTypeOperation) {
this.tableName = tableName;
this.fieldBase = fieldBase;
this.fieldReference = fieldReference;
this.joinTypeOperation = joinTypeOperation;
}
public static JoinTable ofLeft(String tableName, String fieldBase, String fieldReference) {
Assert.isNotNull(tableName, fieldBase, fieldReference);
return new JoinTable(tableName, fieldBase, fieldReference, JoinTypeOperation.LEFT);
}
public static JoinTable of(@NonNull String tableName, @NonNull String fieldBase, @NonNull String fieldReference, JoinTypeOperation joinType) {
public static JoinTable of(String tableName, String fieldBase, String fieldReference, JoinTypeOperation joinType) {
Assert.isNotNull(tableName, fieldBase, fieldReference);
return new JoinTable(tableName, fieldBase, fieldReference, joinType);
}
public String getTableName() {
return tableName;
}
public String getFieldBase() {
return fieldBase;
}
public String getFieldReference() {
return fieldReference;
}
public JoinTypeOperation getJoinTypeOperation() {
return joinTypeOperation;
}
}

View File

@ -1,29 +1,42 @@
package dev.struchkov.haiti.filter.jooq;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
import dev.struchkov.haiti.utils.Assert;
public class SortContainer {
private final String fieldName;
private SortType type = SortType.ASC;
private SortContainer(String fieldName) {
this.fieldName = fieldName;
}
private SortContainer(String fieldName, SortType type) {
this.fieldName = fieldName;
this.type = type;
}
public static SortContainer empty() {
return new SortContainer(null);
}
public static SortContainer of(@NonNull String fieldName) {
public static SortContainer of(String fieldName) {
Assert.isNotNull(fieldName);
return new SortContainer(fieldName);
}
public static SortContainer of(@NonNull String fieldName, SortType sortType) {
public static SortContainer of(String fieldName, SortType sortType) {
Assert.isNotNull(fieldName);
return new SortContainer(fieldName, sortType == null ? SortType.ASC : sortType);
}
public String getFieldName() {
return fieldName;
}
public SortType getType() {
return type;
}
}

View File

@ -1,11 +1,18 @@
package dev.struchkov.haiti.filter.jooq.exception;
import dev.struchkov.haiti.filter.exception.FilterException;
import dev.struchkov.haiti.context.exception.BasicException;
public class FilterJooqHaitiException extends FilterException {
import java.text.MessageFormat;
import java.util.function.Supplier;
public class FilterJooqHaitiException extends BasicException {
public FilterJooqHaitiException(String message) {
super(message);
}
public static Supplier<FilterJooqHaitiException> filterJooqException(String message, Object... objects) {
return () -> new FilterJooqHaitiException(MessageFormat.format(message, objects));
}
}

View File

@ -1,18 +1,19 @@
package dev.struchkov.haiti.filter.jooq.page;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class PageableOffset {
private final int pageNumber;
private int pageSize = 30;
private PageableOffset(int pageNumber) {
this.pageNumber = pageNumber;
}
private PageableOffset(int pageNumber, int pageSize) {
this.pageNumber = pageNumber;
this.pageSize = pageSize;
}
public static PageableOffset of(int pageNumber) {
return new PageableOffset(pageNumber);
}
@ -21,4 +22,16 @@ public class PageableOffset {
return new PageableOffset(pageNumber, pageSize);
}
public int getPageNumber() {
return pageNumber;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
}

View File

@ -1,19 +1,21 @@
package dev.struchkov.haiti.filter.jooq.page;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import dev.struchkov.haiti.utils.Assert;
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class PageableSeek {
private final Object lastId;
private int pageSize = 30;
private PageableSeek(Object lastId) {
this.lastId = lastId;
}
private PageableSeek(Object lastId, int pageSize) {
this.lastId = lastId;
this.pageSize = pageSize;
}
public static PageableSeek empty() {
return new PageableSeek(null);
}
@ -22,12 +24,22 @@ public class PageableSeek {
return new PageableSeek(null, pageSize);
}
public static PageableSeek of(@NonNull Object lastId) {
public static PageableSeek of(Object lastId) {
Assert.isNotNull(lastId);
return new PageableSeek(lastId);
}
public static PageableSeek of(@NonNull Object lastId, int pageSize) {
public static PageableSeek of(Object lastId, int pageSize) {
Assert.isNotNull(lastId);
return new PageableSeek(lastId, pageSize);
}
public Object getLastId() {
return lastId;
}
public int getPageSize() {
return pageSize;
}
}