io.vertx.up.uca.jooq.JoinStore Maven / Gradle / Ivy
package io.vertx.up.uca.jooq;
import io.vertx.core.json.JsonObject;
import io.vertx.tp.plugin.jooq.JooqDsl;
import io.vertx.tp.plugin.jooq.JooqInfix;
import io.vertx.up.atom.Kv;
import io.vertx.up.exception.web._501NotSupportException;
import io.vertx.up.unity.Ux;
import org.jooq.Field;
import org.jooq.Record;
import org.jooq.Table;
import org.jooq.impl.DSL;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
/**
* @author Lang
*/
@SuppressWarnings("all")
class JoinStore {
/*
* Class -> Analyzer
* Here each Dao class contain only one JqAnalyzer for deep analyzing
* and future usage.
*/
private transient final ConcurrentMap, JqAnalyzer> daoAnalyzer
= new ConcurrentHashMap<>();
/*
* Table prefix: Name -> Prefix.Name
* Here the system append prefix to table name for duplicated column issue.
*/
private transient final ConcurrentMap tablePrefix
= new ConcurrentHashMap<>();
/*
* Mapping assist for calculation
* Class> -> Table Name
* Table Name -> Class>
*/
private transient final ConcurrentMap, String> daoTable
= new ConcurrentHashMap<>();
private transient final ConcurrentMap> tableDao
= new ConcurrentHashMap<>();
/*
* Next table ( exclude the first added table here )
*/
private transient final List tableList = new ArrayList<>();
private transient final List edgeList = new ArrayList<>();
private transient final JoinAlias alias;
private transient Kv first;
private transient JqAnalyzer firstAnalyzer;
private transient Class> firstDao;
JoinStore() {
this.alias = new JoinAlias();
}
void join(final Class> daoCls, final String field) {
/*
* Support three tables only as max table here
* It means that if there exist more than 3 tables, we recommend
* to re-design database instead of using `JOIN`
* Because multi tables join may caused performance issue.
*/
if (2 < this.daoAnalyzer.size()) {
throw new RuntimeException("Join table counter limitation! ");
}
/*
* Stored analyzer by daoCls
*/
this.addDao(daoCls);
/*
* Build Relation
*/
final String toTable = this.daoTable.get(daoCls);
this.tableList.add(toTable);
/*
* JqEdge
*/
{
final JqEdge edge = new JqEdge();
edge.setFrom(this.first.getKey(), this.first.getValue());
edge.setTo(toTable, field);
this.edgeList.add(edge);
}
}
void add(final Class> daoCls, final String field) {
/*
* Stored analyzer by daoCls
*/
this.addDao(daoCls);
/*
* The first
*/
final String firstTable = this.daoTable.get(daoCls);
this.first = Kv.create(firstTable, field);
/*
* Assist for joining here
*/
this.firstDao = daoCls;
this.firstAnalyzer = this.daoAnalyzer.get(daoCls);
}
void alias(final Class> daoCls, final String field, final String alias) {
final String tableName = this.daoTable.getOrDefault(daoCls, null);
if (Objects.nonNull(tableName)) {
final JqAnalyzer analyzer = this.daoAnalyzer.get(daoCls);
this.alias.addAlias(analyzer, tableName, field, alias);
}
}
/*
* Bind pojo file to dao class
* This step could be done one by one here, this operation could not
* be done in banch.
*/
void pojo(final Class> daoCls, final String pojo) {
final JqAnalyzer analyzer = this.daoAnalyzer.get(daoCls);
if (Objects.nonNull(analyzer)) {
analyzer.on(pojo, daoCls);
}
}
// -------------------- Meta data processing -----------
Set metaFirstField() {
return this.firstAnalyzer.fieldSet();
}
String metaTable(final String field) {
return this.alias.table(field);
}
Field metaColumn(final String field) {
return this.alias.field(field);
}
JooqDsl metaDsl() {
return this.firstAnalyzer.dsl();
}
String metaPrefix(final String table) {
Objects.requireNonNull(table);
return this.tablePrefix.get(table);
}
// -------------------- Spec Meta Operation -----------
boolean noPrefix() {
return this.tablePrefix.isEmpty();
}
boolean hasTable() {
return this.tableList.isEmpty();
}
JqAnalyzer analyzer(final String name) {
final Class> daoCls = this.tableDao.get(name);
return this.daoAnalyzer.get(daoCls);
}
UxJooq jooq() {
return Ux.Jooq.on(this.firstDao);
}
UxJooq childJooq() {
final Set> analyzers = this.daoAnalyzer.keySet()
.stream().filter(item -> !item.equals(this.firstDao))
.collect(Collectors.toSet());
if (1 == analyzers.size()) {
final Class> daoCls = analyzers.iterator().next();
return Ux.Jooq.on(daoCls);
} else {
throw new _501NotSupportException(this.getClass());
}
}
Set childKeySet() {
final Collection analyzers = this.daoAnalyzer.values()
.stream().filter(item -> !item.equals(this.firstAnalyzer))
.collect(Collectors.toSet());
if (1 == analyzers.size()) {
final JqAnalyzer analyzer = analyzers.iterator().next();
return analyzer.primarySet();
} else {
throw new _501NotSupportException(this.getClass());
}
}
ConcurrentMap> mapColumn() {
return this.alias.mapColumn();
}
Field field(final String field) {
final String prefix = this.tablePrefix.get(this.first.getKey());
return this.alias.field(field, prefix);
}
Field field() {
return this.field(this.first.getValue());
}
JqEdge edge(final int index) {
return this.edgeList.get(index);
}
List tables() {
return this.tableList;
}
Table tableRecord() {
return this.tableRecord(this.first.getKey());
}
Table tableRecord(final int index) {
final String table = this.tableList.get(index);
return this.tableRecord(table);
}
Table tableRecord(final String tableName) {
final String alias = this.tablePrefix.get(tableName);
return DSL.table(DSL.name(tableName)).as(DSL.name(alias));
}
// -------------------- Data Operation -----------
/*
* The record is `firstAnalyzer` data record
* 1) Extract primary key value ( Joined )
*/
JsonObject dataJoin(final JsonObject record) {
Objects.requireNonNull(record);
final JsonObject joined = new JsonObject();
final String firstField = this.first.getValue();
final Object value = record.getValue(firstField);
if (Objects.nonNull(value)) {
this.edgeList.forEach(edge -> {
final String toField = edge.getToField();
if (Objects.nonNull(toField)) {
joined.put(toField, value);
}
});
}
return joined;
}
// -------------------- Private Operation -----------
private void addDao(final Class daoCls) {
/*
* Analyzer building
*/
final JooqDsl dsl = JooqInfix.getDao(daoCls);
final JqAnalyzer analyzer = JqAnalyzer.create(dsl);
final String tableName = analyzer.table().getName();
this.daoAnalyzer.put(daoCls, analyzer);
{
this.daoTable.put(daoCls, tableName);
this.tableDao.put(tableName, daoCls);
}
/*
* Table Name -> Table Alias mapping
*/
final int size = this.daoAnalyzer.size();
final String tableAlias = "T" + size;
this.tablePrefix.put(tableName, DSL.table(tableAlias).getName());
// Alias Reference
this.alias.addDao(analyzer, tableName, tableAlias);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy