package io.ebeaninternal.server.query;
import io.ebean.util.SplitName;
import io.ebeaninternal.api.SpiQuery;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
class SqlTreeAlias {
private final SpiQuery.TemporalMode temporalMode;
private int counter;
private int manyWhereCounter;
private final TreeSet<String> joinProps = new TreeSet<>();
private HashSet<String> embeddedPropertyJoins;
private final TreeSet<String> manyWhereJoinProps = new TreeSet<>();
private final HashMap<String, String> aliasMap = new HashMap<>();
private final HashMap<String, String> manyWhereAliasMap = new HashMap<>();
private final String rootTableAlias;
SqlTreeAlias(String rootTableAlias, SpiQuery.TemporalMode temporalMode) {
this.rootTableAlias = rootTableAlias;
this.temporalMode = temporalMode;
}
void addManyWhereJoins(Set<String> manyWhereJoins) {
if (manyWhereJoins != null) {
for (String include : manyWhereJoins) {
addPropertyJoin(include, manyWhereJoinProps);
}
}
}
private void addEmbeddedPropertyJoin(String embProp) {
if (embeddedPropertyJoins == null) {
embeddedPropertyJoins = new HashSet<>();
}
embeddedPropertyJoins.add(embProp);
}
public void addJoin(Set<String> propJoins, STreeType desc) {
if (propJoins != null) {
for (String propJoin : propJoins) {
if (desc.isEmbeddedPath(propJoin)) {
addEmbeddedPropertyJoin(propJoin);
} else {
addPropertyJoin(propJoin, joinProps);
}
}
}
}
private void addPropertyJoin(String include, TreeSet<String> set) {
if (set.add(include)) {
String[] split = SplitName.split(include);
if (split[0] != null) {
addPropertyJoin(split[0], set);
}
}
}
void buildAlias() {
for (String joinProp : joinProps) {
calcAlias(joinProp);
}
for (String joinProp : manyWhereJoinProps) {
calcAliasManyWhere(joinProp);
}
mapEmbeddedPropertyAlias();
}
private void mapEmbeddedPropertyAlias() {
if (embeddedPropertyJoins != null) {
for (String propJoin : embeddedPropertyJoins) {
String[] split = SplitName.split(propJoin);
String alias = getTableAlias(split[0]);
aliasMap.put(propJoin, alias);
}
}
}
private String calcAlias(String prefix) {
String alias = nextTableAlias();
aliasMap.put(prefix, alias);
return alias;
}
private void calcAliasManyWhere(String prefix) {
String alias = nextManyWhereTableAlias();
manyWhereAliasMap.put(prefix, alias);
}
String getTableAlias(String prefix) {
if (prefix == null) {
return rootTableAlias;
} else {
String s = aliasMap.get(prefix);
if (s == null) {
return calcAlias(prefix);
}
return s;
}
}
String getTableAliasManyWhere(String prefix) {
if (prefix == null) {
return rootTableAlias;
}
String s = manyWhereAliasMap.get(prefix);
if (s == null) {
s = aliasMap.get(prefix);
}
if (s == null) {
String msg = "Could not determine table alias for [" + prefix + "] manyMap[" + manyWhereAliasMap + "] aliasMap[" + aliasMap + "]";
throw new RuntimeException(msg);
}
return s;
}
String parseWhere(String clause) {
clause = parseRootAlias(clause);
clause = parseAliasMap(clause, manyWhereAliasMap);
return parseAliasMap(clause, aliasMap);
}
public String parse(String clause) {
clause = parseRootAlias(clause);
return parseAliasMap(clause, aliasMap);
}
String parseRootAlias(String clause) {
if (rootTableAlias == null) {
return clause.replace("${}", "");
} else {
return clause.replace("${}", rootTableAlias + ".");
}
}
private String parseAliasMap(String clause, HashMap<String, String> parseAliasMap) {
for (Map.Entry<String, String> e : parseAliasMap.entrySet()) {
String k = "${" + e.getKey() + "}";
clause = clause.replace(k, e.getValue() + ".");
}
return clause;
}
private String nextTableAlias() {
return "t" + (++counter);
}
private String nextManyWhereTableAlias() {
return "u" + (++manyWhereCounter);
}
boolean isIncludeJoins() {
return !aliasMap.isEmpty() || !manyWhereAliasMap.isEmpty();
}
boolean isIncludeSoftDelete() {
return temporalMode == SpiQuery.TemporalMode.SOFT_DELETED;
}
}