All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.topia.service.script.table.TopiaSqlTables Maven / Gradle / Ivy

package org.nuiton.topia.service.script.table;

/*
 * #%L
 * ObServe Toolkit :: ToPIA Script service
 * %%
 * Copyright (C) 2017 - 2018 IRD, Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.topia.persistence.TopiaEntityEnum;
import org.nuiton.topia.persistence.metadata.TopiaMetadataEntity;
import org.nuiton.topia.persistence.metadata.TopiaMetadataModel;

/**
 * A container of {@link TopiaSqlTable}.
 * 

* Created on 01/01/16. * * @author Tony Chemit - [email protected] * @since 3.0.1 */ public class TopiaSqlTables implements Iterable { /** Logger. */ private static final Log log = LogFactory.getLog(TopiaSqlTables.class); private ImmutableMap tablesByFullyTableName; private ImmutableSet orderedTables; public TopiaSqlTables(ImmutableMap tablesByFullyTableName, ImmutableSet orderedTables) { this.tablesByFullyTableName = tablesByFullyTableName; this.orderedTables = orderedTables; } public static Builder builder(TopiaMetadataModel metadataModel, TopiaMetadataEntity metadataEntity) { return new BuilderImpl(metadataModel, metadataEntity); } public TopiaSqlTable getTable(String key) { return tablesByFullyTableName.get(key); } @SuppressWarnings("NullableProblems") @Override public Iterator iterator() { return orderedTables.iterator(); } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("orderedTables", orderedTables) .toString(); } public TopiaSqlTables reverse() { List reverseList = new LinkedList<>(); for (TopiaSqlTable orderedTable : orderedTables) { reverseList.add(0, orderedTable); } ImmutableSet reverseSet = ImmutableSet.copyOf(reverseList); return new TopiaSqlTables(tablesByFullyTableName, reverseSet); } public void replaceTable(String tableName, TopiaSqlTable table) { ImmutableMap.Builder tablesByFullyTableName2 = ImmutableMap.builder(); ImmutableSet.Builder orderedTables2 = ImmutableSet.builder(); for (Map.Entry entry : tablesByFullyTableName.entrySet()) { String name = entry.getKey(); TopiaSqlTable topiaSqlTable = entry.getValue(); if (tableName.equals(name)) { topiaSqlTable = table; } tablesByFullyTableName2.put(name, topiaSqlTable); } for (TopiaSqlTable orderedTable : orderedTables) { if (tableName.equals(orderedTable.getFullyTableName())) { orderedTable = table; } orderedTables2.add(orderedTable); } tablesByFullyTableName = tablesByFullyTableName2.build(); orderedTables = orderedTables2.build(); } public int size() { return tablesByFullyTableName.size(); } /** * Created on 02/01/16. * * @author Tony Chemit - [email protected] */ public interface Builder { BuilderStepOnTable addMainTable(TopiaEntityEnum entityEnum); TopiaSqlTables build(); } public interface BuilderStepOnTable extends Builder { BuilderStepOnTable addJoinTable(TopiaEntityEnum entityEnum); BuilderStepOnTable addAndEnterJoinTable(TopiaEntityEnum entityEnum); BuilderStepOnTable addReverseJoinTable(TopiaEntityEnum entityEnum); BuilderStepOnTable addAndEnterReverseJoinTable(TopiaEntityEnum entityEnum); BuilderStepOnTable addAssociationTable(TopiaEntityEnum entityEnum, String associationName); BuilderStepOnTable backToParent(); BuilderStepOnTable backToTable(TopiaEntityEnum entityEnum); BuilderStepOnTable checkCurrentTable(TopiaEntityEnum entityEnum); } /** * Created on 01/01/16. * * @author Tony Chemit - [email protected] */ protected static class BuilderImpl implements Builder { private final TreeMap tablesByFullyTableName; private final TreeMap tablesByOrder; private final TopiaMetadataModel metadataModel; private final TopiaMetadataEntity metadataEntity; private int internalOrder; BuilderImpl(TopiaMetadataModel metadataModel, TopiaMetadataEntity metadataEntity) { this.metadataModel = metadataModel; this.metadataEntity = metadataEntity; this.tablesByFullyTableName = new TreeMap<>(); this.tablesByOrder = new TreeMap<>(); } @Override public BuilderStepOnTable addMainTable(TopiaEntityEnum entityEnum) { String schemaName = entityEnum.dbSchemaName().toLowerCase(); String tableName = entityEnum.dbTableName().toLowerCase(); //TODO check that this table is not already registred String whereClauseAlias = tableName + ".topiaid"; String fromClause = schemaName + "." + tableName + " " + tableName; registerTable(entityEnum, schemaName, tableName, whereClauseAlias, fromClause, ImmutableSet.of()); return new BuilderStepOnTableImpl(null, entityEnum); } @Override public TopiaSqlTables build() { List orders = Lists.newArrayList(tablesByOrder.keySet()); Collections.sort(orders); ImmutableSet.Builder orderedTablesBuilder = ImmutableSet.builder(); for (Integer order : orders) { orderedTablesBuilder.add(tablesByOrder.get(order)); } return new TopiaSqlTables(ImmutableMap.copyOf(tablesByFullyTableName), orderedTablesBuilder.build()); } Builder registerTable(TopiaEntityEnum entityEnum, String schemaName, String tableName, String whereClauseAlias, String fromClause, ImmutableSet joinClauses) { return registerTable(entityEnum, null, schemaName, tableName, whereClauseAlias, fromClause, joinClauses, null); } Builder registerAssociationTable(TopiaEntityEnum entityEnum, TopiaMetadataEntity associationEntityEnum, String schemaName, String tableName, String whereClauseAlias, String fromClause, ImmutableSet joinClauses, String joinColumnName) { return registerTable(entityEnum, associationEntityEnum, schemaName, tableName, whereClauseAlias, fromClause, joinClauses, joinColumnName); } private Builder registerTable(TopiaEntityEnum entityEnum, TopiaMetadataEntity associationMetadataEntity, String schemaName, String tableName, String whereClauseAlias, String fromClause, ImmutableSet joinClauses, String joinColumnName) { //TODO check that this table is not already registered TopiaMetadataEntity metadataEntity = metadataModel.getEntity(entityEnum.name()); TopiaSqlTable table = new TopiaSqlTable( metadataEntity, associationMetadataEntity, schemaName, tableName, fromClause, whereClauseAlias, joinClauses, joinColumnName); log.debug("new TopiaTable: " + table); tablesByFullyTableName.put(table.getFullyTableName(), table); tablesByOrder.put(internalOrder++, table); return this; } protected TopiaSqlTable getTable(String key) { return tablesByFullyTableName.get(key); } protected TopiaSqlTable getTable(TopiaEntityEnum entityEnum) { String key = getFullyTableName(entityEnum); return tablesByFullyTableName.get(key); } String getFullyTableName(TopiaEntityEnum entityEnum) { return entityEnum.dbSchemaName().toLowerCase() + "." + entityEnum.dbTableName().toLowerCase(); } String getAssociationTableName(String tableName, String parentTableName) { String associationTableName; if (tableName.compareTo(parentTableName) < 0) { associationTableName = tableName + "_" + parentTableName; } else { associationTableName = parentTableName + "_" + tableName; } return associationTableName; } protected class BuilderStepOnTableImpl implements Builder, BuilderStepOnTable { protected final BuilderStepOnTableImpl parent; final TopiaEntityEnum tableEntityEnum; BuilderStepOnTableImpl(BuilderStepOnTableImpl parent, TopiaEntityEnum tableEntityEnum) { this.parent = parent; this.tableEntityEnum = tableEntityEnum; } @Override public BuilderStepOnTable addMainTable(TopiaEntityEnum entityEnum) { return BuilderImpl.this.addMainTable(entityEnum); } @Override public TopiaSqlTables build() { return BuilderImpl.this.build(); } @Override public BuilderStepOnTable addJoinTable(TopiaEntityEnum entityEnum) { TopiaSqlTable parentTable = getTable(); String schemaName = entityEnum.dbSchemaName().toLowerCase(); String tableName = entityEnum.dbTableName().toLowerCase(); String parentTableName = parentTable.getTableName(); String whereClauseAlias; String fromClause; ImmutableSet joinClauses; if (parent == null) { // parent table is main (no join on it) // we can directly use the target table to join whereClauseAlias = tableName + "." + parentTableName; fromClause = schemaName + "." + tableName + " " + tableName; joinClauses = ImmutableSet.of(); } else { // simple join table whereClauseAlias = parentTable.getWhereClauseAlias(); fromClause = parentTable.getFromClause(); String joinClause = " INNER JOIN " + schemaName + "." + tableName + " " + tableName + " ON " + tableName + "." + parentTableName + " = " + parentTableName + ".topiaId"; joinClauses = addJoinCause(parentTable.getJoinClauses(), joinClause); } registerTable(entityEnum, schemaName, tableName, whereClauseAlias, fromClause, joinClauses); return this; } @Override public BuilderStepOnTable addAndEnterJoinTable(TopiaEntityEnum entityEnum) { addJoinTable(entityEnum); return new BuilderStepOnTableImpl(this, entityEnum); } @Override public BuilderStepOnTable addReverseJoinTable(TopiaEntityEnum entityEnum) { TopiaSqlTable parentTable = getTable(); String schemaName = entityEnum.dbSchemaName().toLowerCase(); String tableName = entityEnum.dbTableName().toLowerCase(); String whereClauseAlias = parentTable.getWhereClauseAlias(); String fromClause = parentTable.getFromClause(); String parentTableName = parentTable.getTableName(); String joinClause = " INNER JOIN " + schemaName + "." + tableName + " " + tableName + " ON " + tableName + ".topiaId = " + parentTableName + "." + tableName; ImmutableSet joinClauses = addJoinCause(parentTable.getJoinClauses(), joinClause); registerTable(entityEnum, schemaName, tableName, whereClauseAlias, fromClause, joinClauses); invertOrderWithParent(parentTable, entityEnum); return this; } @Override public BuilderStepOnTable addAndEnterReverseJoinTable(TopiaEntityEnum entityEnum) { addReverseJoinTable(entityEnum); return new BuilderStepOnTableImpl(this, entityEnum); } @Override public BuilderStepOnTable addAssociationTable(TopiaEntityEnum entityEnum, String associationName) { TopiaSqlTable parentTable = getTable(); String schemaName = tableEntityEnum.dbSchemaName().toLowerCase(); String tableName = getAssociationTableName(associationName.toLowerCase(), parentTable.getTableName()); String whereClauseAlias = parentTable.getWhereClauseAlias(); String fromClause = parentTable.getFromClause(); if (parentTable.getJoinClauses().isEmpty()) { fromClause = schemaName + "." + tableName; } ImmutableSet joinClauses; boolean addInnerJoin = parent != null; if (addInnerJoin) { String parentTableName = parentTable.getTableName(); String joinClause = " INNER JOIN " + schemaName + "." + tableName + " " + tableName + " ON " + tableName + "." + parentTableName + " = " + parentTableName + ".topiaId"; joinClauses = addJoinCause(parentTable.getJoinClauses(), joinClause); } else { joinClauses = parentTable.getJoinClauses(); } String joinColumnName = parentTable.getTableName(); registerAssociationTable(entityEnum, parentTable.getMetadataEntity(), schemaName, tableName, whereClauseAlias, fromClause, joinClauses, joinColumnName); return this; } @Override public BuilderStepOnTable backToParent() { Preconditions.checkState(parent != null, "Could not find a parent table"); return parent; } @Override public BuilderStepOnTable backToTable(TopiaEntityEnum entityEnum) { BuilderStepOnTable table; if (Objects.equals(tableEntityEnum, entityEnum)) { table = this; } else { Preconditions.checkState(parent != null, "Could not find a perent table of type: " + entityEnum); table = parent.backToTable(entityEnum); } return table; } @Override public BuilderStepOnTable checkCurrentTable(TopiaEntityEnum entityEnum) { Preconditions.checkState(tableEntityEnum.equals(entityEnum), "Current table should be " + entityEnum + ", but was " + tableEntityEnum); return this; } protected TopiaSqlTable getTable() { return BuilderImpl.this.getTable(tableEntityEnum); } int getTableOrder(TopiaSqlTable table) { for (Map.Entry entry : tablesByOrder.entrySet()) { if (table.equals(entry.getValue())) { return entry.getKey(); } } throw new IllegalStateException("Could not find table " + table.getFullyTableName()); } void invertOrderWithParent(TopiaSqlTable parentTable, TopiaEntityEnum entityEnum) { int parentTableOrder = getTableOrder(parentTable); TopiaSqlTable table = BuilderImpl.this.getTable(entityEnum); int tableOrder = getTableOrder(table); tablesByOrder.put(parentTableOrder, table); tablesByOrder.put(tableOrder, parentTable); } ImmutableSet addJoinCause(ImmutableSet joinClauses, String joinClause) { return ImmutableSet .builder() .addAll(joinClauses) .add(joinClause) .build(); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy