First Version

This commit is contained in:
Struchkov Mark 2022-01-12 16:39:10 +03:00
commit e264d7751c
6 changed files with 419 additions and 0 deletions

85
.gitignore vendored Normal file
View File

@ -0,0 +1,85 @@
*.class
*.log
*.ctxt
.mtj.tmp/
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
hs_err_pid*
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
.idea/**/contentModel.xml
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
.idea/**/gradle.xml
.idea/**/libraries
cmake-build-*/
.idea/**/mongoSettings.xml
*.iws
out/
.idea_modules/
atlassian-ide-plugin.xml
.idea/replstate.xml
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
.idea/httpRequests
.idea/caches/build_file_checksums.ser
*~
.fuse_hidden*
.directory
.Trash-*
.nfs*
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
*.stackdump
[Dd]esktop.ini
$RECYCLE.BIN/
*.cab
*.msi
*.msix
*.msm
*.msp
*.lnk
.DS_Store
.AppleDouble
.LSOverride
Icon
._*
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

47
pom.xml Normal file
View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>dev.struchkov.haiti.filter</groupId>
<artifactId>haiti-filter-jooq</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Haiti Filter JOOQ</name>
<description>JOOQ based filtering module</description>
<url>https://github.com/haiti-projects/haiti-filter-jooq</url>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<jooq.version>3.15.5</jooq.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-bom</artifactId>
<version>0.0.1-RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-filter</artifactId>
</dependency>
<dependency>
<groupId>org.jooq</groupId>
<artifactId>jooq</artifactId>
<version>${jooq.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,147 @@
package dev.struchkov.haiti.filter.jooq;
import dev.struchkov.haiti.filter.Filter;
import dev.struchkov.haiti.filter.FilterQuery;
import lombok.NonNull;
import org.jooq.Condition;
import org.jooq.DSLContext;
import org.jooq.Operator;
import org.jooq.Query;
import org.jooq.Record;
import org.jooq.SelectConditionStep;
import org.jooq.SelectJoinStep;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import static org.jooq.impl.DSL.condition;
import static org.jooq.impl.DSL.field;
public class CriteriaJooqFilter implements Filter {
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 String fieldOrder;
private Object lastId;
private Integer pageSize;
private final String table;
private final DSLContext dsl;
protected CriteriaJooqFilter(String table, DSLContext dsl) {
this.table = table;
this.dsl = dsl;
}
public static CriteriaJooqFilter create(String table, DSLContext dsl) {
return new CriteriaJooqFilter(table, dsl);
}
@Override
public Filter and(FilterQuery filterQuery) {
generateAnd((CriteriaJooqQuery) filterQuery);
return this;
}
@Override
public Filter and(Consumer<FilterQuery> query) {
final CriteriaJooqQuery criteriaQuery = CriteriaJooqQuery.create();
query.accept(criteriaQuery);
generateAnd(criteriaQuery);
return this;
}
@Override
public Filter or(FilterQuery filterQuery) {
generateOr((CriteriaJooqQuery) filterQuery);
return this;
}
public Filter or(Consumer<FilterQuery> query) {
final CriteriaJooqQuery criteriaQuery = CriteriaJooqQuery.create();
query.accept(criteriaQuery);
generateOr(criteriaQuery);
return this;
}
@Override
public Filter not(FilterQuery filterQuery) {
return null;
}
@Override
public Filter not(Consumer<FilterQuery> query) {
return null;
}
public Filter page(@NonNull String fieldOrder, Object id, int pageSize) {
this.fieldOrder = fieldOrder;
this.lastId = id;
this.pageSize = pageSize;
return this;
}
public Filter join(@NonNull JoinTable... joinTables) {
this.joinTables.addAll(Arrays.stream(joinTables).collect(Collectors.toList()));
return this;
}
private void generateAnd(CriteriaJooqQuery criteriaQuery) {
andConditions.addAll(criteriaQuery.getConditions());
}
private void generateOr(CriteriaJooqQuery criteriaQuery) {
orConditions.addAll(criteriaQuery.getConditions());
}
@Override
public Query build() {
final List<Condition> conditions = new ArrayList<>();
if (!andConditions.isEmpty()) {
conditions.add(condition(Operator.AND, andConditions));
}
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);
if (pageSize != null && fieldOrder != null) {
if (lastId != null) {
where.orderBy(field(fieldOrder))
.seek(lastId)
.limit(pageSize);
} else {
where.orderBy(field(fieldOrder))
.limit(pageSize);
}
}
return where;
}
}

View File

@ -0,0 +1,96 @@
package dev.struchkov.haiti.filter.jooq;
import dev.struchkov.haiti.filter.FilterQuery;
import lombok.NonNull;
import org.jooq.Condition;
import org.jooq.Field;
import org.jooq.impl.DSL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.jooq.impl.DSL.condition;
import static org.jooq.impl.DSL.field;
public class CriteriaJooqQuery implements FilterQuery {
private final List<Condition> conditions = new ArrayList<>();
public static CriteriaJooqQuery create() {
return new CriteriaJooqQuery();
}
protected List<Condition> getConditions() {
return conditions;
}
@Override
public <Y extends Comparable<? super Y>> FilterQuery between(@NonNull String field, Y from, Y to) {
if (from != null && to != null) {
Condition condition = DSL.field(field).between(from, to);
conditions.add(condition);
}
return this;
}
@Override
public <Y extends Comparable<? super Y>> FilterQuery greaterThan(@NonNull String field, Y value) {
return this;
}
@Override
public <Y extends Comparable<? super Y>> FilterQuery lessThan(@NonNull String field, Y value) {
return this;
}
@Override
public FilterQuery matchPhrase(@NonNull String field, Object value) {
if (value != null) {
final Condition condition = condition(Map.of(field(field), value));
conditions.add(condition);
}
return this;
}
@Override
public <U> FilterQuery matchPhrase(@NonNull String field, Set<U> values) {
if (values != null && !values.isEmpty()) {
conditions.add(DSL.field(field).in(values));
}
return this;
}
@Override
public FilterQuery 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) {
final Field<Object> query = field(field);
if (value != null) {
if (ignoreCase) {
conditions.add(query.like(value));
} else {
conditions.add(query.likeIgnoreCase(value));
}
}
return this;
}
@Override
public FilterQuery checkBoolInt(@NonNull String field, Boolean flag) {
return this;
}
@Override
public List<Condition> build() {
return conditions;
}
}

View File

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

View File

@ -0,0 +1,14 @@
package dev.struchkov.haiti.filter.jooq;
/**
* Разрешенные типы операции JOIN.
*
* @author upagge 24.02.2021
*/
public enum JoinTypeOperation {
LEFT,
RIGHT,
INNER
}