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

de.akquinet.jbosscc.guttenbase.tools.TableOrderTool Maven / Gradle / Ivy

There is a newer version: 2.1.0
Show newest version
package de.akquinet.jbosscc.guttenbase.tools;

import de.akquinet.jbosscc.guttenbase.meta.ForeignKeyMetaData;
import de.akquinet.jbosscc.guttenbase.meta.TableMetaData;

import java.sql.SQLException;
import java.util.*;

/**
 * Order tables by foreign key constraints, i.e. the foreign keys of a database schema spawn an directed (possibly cyclic!) graph
 * of dependencies. The tool tries to create of sequential order either in top-down (starting at the root nodes) or bottom-up
 * (starting at the leaves) manner. 
* If there are cycles in the dependencies, we choose the node with the fewest incoming/outgoing edges. *

* © 2012-2020 akquinet tech@spree *

* * @author M. Dahm */ @SuppressWarnings("RedundantThrows") public class TableOrderTool { public List getOrderedTables(final List tableMetaData, final boolean topDown) throws SQLException { final Map tableNodes = createGraph(tableMetaData); return orderTables(tableNodes, topDown); } private List orderTables(final Map tableNodes, final boolean topDown) throws SQLException { final List result = new ArrayList<>(); while (!tableNodes.isEmpty()) { final TableNode tableNode = findMatchingNode(new ArrayList<>(tableNodes.values()), topDown); for (final TableNode referencingTable : tableNode.getReferencedByTables()) { referencingTable.removeReferencedTable(tableNode); } for (final TableNode referencedTable : tableNode.getReferencedTables()) { referencedTable.removeReferencedByTable(tableNode); } result.add(tableNode.getTableMetaData()); tableNodes.remove(tableNode.getTableMetaData().getTableName().toUpperCase()); } return result; } private TableNode findMatchingNode(final List tableNodes, final boolean topDown) { tableNodes.sort((tn1, tn2) -> { if (topDown) { return tn1.getReferencedTables().size() - tn2.getReferencedTables().size(); } else { return tn1.getReferencedByTables().size() - tn2.getReferencedByTables().size(); } }); return tableNodes.get(0); } private Map createGraph(final List tableMetaData) { final Map tableNodes = new LinkedHashMap<>(); for (final TableMetaData table : tableMetaData) { final List importedForeignKeys = table.getImportedForeignKeys(); final TableNode tableNode = getTableNode(tableNodes, table); for (final ForeignKeyMetaData foreignKeyMetaData : importedForeignKeys) { final TableNode referencingTable = getTableNode(tableNodes, foreignKeyMetaData.getReferencingColumn().getTableMetaData()); final TableNode referencedTable = getTableNode(tableNodes, foreignKeyMetaData.getReferencedColumn().getTableMetaData()); assert tableNode.equals(referencingTable); referencingTable.addReferencedTable(referencedTable); referencedTable.addReferencedByTable(referencingTable); } } return tableNodes; } private TableNode getTableNode(final Map tableNodes, final TableMetaData table) { final String tableName = table.getTableName().toUpperCase(); if (tableNodes.containsKey(tableName)) { return tableNodes.get(tableName); } else { final TableNode result = new TableNode(table); tableNodes.put(tableName, result); return result; } } private static class TableNode { private final TableMetaData _tableMetaData; private final List _referencedTables = new ArrayList<>(); private final List _referencedByTables = new ArrayList<>(); public TableNode(final TableMetaData tableMetaData) { _tableMetaData = tableMetaData; } public void addReferencedTable(final TableNode tableMetaData) { _referencedTables.add(tableMetaData); } public void removeReferencedTable(final TableNode tableMetaData) { _referencedTables.remove(tableMetaData); } public void addReferencedByTable(final TableNode tableMetaData) { _referencedByTables.add(tableMetaData); } public void removeReferencedByTable(final TableNode tableMetaData) { _referencedByTables.remove(tableMetaData); } public List getReferencedTables() { return _referencedTables; } public List getReferencedByTables() { return _referencedByTables; } public TableMetaData getTableMetaData() { return _tableMetaData; } @Override public int hashCode() { return _tableMetaData.hashCode(); } @Override public boolean equals(final Object obj) { final TableNode that = (TableNode) obj; return this.getTableMetaData().equals(that.getTableMetaData()); } @Override public String toString() { return _tableMetaData.getTableName() + "::referencedTables:" + toString(getReferencedTables()) + ", referencedByTables: " + toString(getReferencedByTables()); } private static String toString(final List referencedTables) { List result = new ArrayList<>(); for (TableNode tableNode : referencedTables) { result.add(tableNode.getTableMetaData().getTableName()); } return result.toString(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy