package net.sf.minuteProject.plugin.database;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import net.sf.minuteProject.configuration.bean.model.data.Database;
import net.sf.minuteProject.configuration.bean.model.data.Reference;
import net.sf.minuteProject.configuration.bean.model.data.Table;
import net.sf.minuteProject.utils.TableUtils;
/**
* @author florian
*
*/
public class SchemaUtils {
private List<Table> deleteOrder;
private List<Table> insertOrder;
private Map<Table, List<Table>> distinctDependencies;
/**
* get the order of tables in delete order
* @param database
* @return List<Table>
*/
public List<Table> getTableDeleteOrder (Database database) {
if (deleteOrder==null)
deleteOrder = getTableDeleteOrderList(database);
return deleteOrder;
}
private List<Table> getTableDeleteOrderList (Database database) {
List<Table> workingSet = getTables(database); //copy of the tables + ref
List<Table> deleteOrderList = getNonReferencedTable(workingSet);
// int nbInDeleteOrderList = deleteOrderList.size();
int deleteOrderListLastSize = 0;
int twiceDeleteOrderListLastSize = 0;//init
while (workingSet.size()>0 && deleteOrderList.size()>twiceDeleteOrderListLastSize) {
deleteOrderListLastSize = deleteOrderList.size();
getTableDeleteOrder(workingSet, deleteOrderList);
if (deleteOrderListLastSize == deleteOrderList.size()) {
// no further delete order where found for this pass
if (twiceDeleteOrderListLastSize<deleteOrderListLastSize)
//so lets iterate again to be sure
twiceDeleteOrderListLastSize = deleteOrderList.size();
else
twiceDeleteOrderListLastSize++;
}
// } else ;// add the last elements
//addLastTables (workingSet, deleteOrderList);
}
if (workingSet.size()>0) {
//recursivity
}
return deleteOrderList;
}
private void addLastTables (List<Table> workingSet, List<Table> deleteOrderList) {
for (Table table : workingSet) {
deleteOrderList.add(table);
}
}
/**
* get the order of tables in insert order
* @param database
* @return List<Table>
*/
public List<Table> getTableInsertOrder (Database database) {
if (insertOrder==null)
insertOrder = getTableInsertOrderList(database);
return insertOrder;
}
private List<Table> getTableInsertOrderList (Database database) {
List<Table> deleteOrder = getTableDeleteOrderList(database);
Collections.reverse(deleteOrder);
return deleteOrder;
}
/**
* the list of tables that an input tables depends on
* @param table, database
* @return List<Table>
*/
public List<Table> getDistinctTransitiveDependencies (Table table) {
if (table==null)
return new ArrayList<Table>();
if (!getDistinctDependencies().containsKey(table))
addDistinctDependencies(table, getDistinctTransitiveDependenciesForTable(table));
return getDistinctDependencies().get(table);
}
private List<Table> getDistinctTransitiveDependenciesForTable (Table table) {
Map<String, Table> distinctDep = new Hashtable<String, Table>();
populateDistinctTransitiveDependencies(table, distinctDep);
return new ArrayList<Table>(distinctDep.values());
}
private void populateDistinctTransitiveDependencies (Table table, Map<String, Table> distinctDep) {
List<Table> parents = TableUtils.getParents(table);
for (Table parent : parents) {
String parentName = parent.getName();
if (!parentName.equals(table.getName()) && !distinctDep.containsKey(parentName)) {
distinctDep.put(parentName, parent);
populateDistinctTransitiveDependencies(parent, distinctDep);
}
}
}
/**
* @param workingSet
* @param deleteOrderList
*/
public void getTableDeleteOrder (List<Table> workingSet, List<Table> deleteOrderList) {
List<Table> tablesToRemove = new ArrayList<Table>();
for (Table table : workingSet) {
if (table.getChildren()==null || table.getChildren().length==0 || areAllReferenceInDeleteOrderList(table, deleteOrderList)) {
deleteOrderList.add(table);
tablesToRemove.add(table);
}
}
for (Table table : tablesToRemove) {
workingSet.remove(table);
}
// return deleteOrderList;
}
private boolean areAllReferenceInDeleteOrderList (Table table, List<Table> deleteOrderList) {
for (Reference reference : table.getChildren()) {
if (isStillReferenceInWorkingSet(reference, deleteOrderList))
return false;
}
return true;
}
private boolean isStillReferenceInWorkingSet (Reference reference, List<Table> deleteOrderList) {
return !isNotReferenceInDeleteOrderList(reference, deleteOrderList);
}
private boolean isNotReferenceInDeleteOrderList (Reference reference, List<Table> deleteOrderList) {
for (Table tableDelete : deleteOrderList) {
if (reference.getForeignTableName().equals(tableDelete.getName()))
return true;
}
return false;
}
private List<Table> getTables (Database database) {
List<Table> tables = new ArrayList<Table>();
for (int i = 0; i < database.getTables().length; i++) {
tables.add(database.getTables()[i]);
}
return tables;
}
private List<Table> getNonReferencedTable (List<Table> tables) {
List<Table> nonReferencedTables = new ArrayList<Table>();
List<Table> tablesToRemove = new ArrayList<Table>();
for (Table table : tables) {
if (table.getChildren()==null || table.getChildren().length==0) {
nonReferencedTables.add(table);
tablesToRemove.add(table);
}
}
for (Table table : tablesToRemove) {
tables.remove(table);
}
return nonReferencedTables;
}
public Map<Table, List<Table>> getDistinctDependencies() {
if (distinctDependencies==null)
distinctDependencies = new Hashtable<Table, List<Table>>();
return distinctDependencies;
}
public void addDistinctDependencies(Table table, List<Table> distinctDependencies) {
getDistinctDependencies().put(table, distinctDependencies);
}
}