public List sortTablesByRI(Collection recursiveConstraints) throws SQLException, IOException {
public List sortTablesByRI(Collection recursiveConstraints) {
    public List sortTablesByRI(Collection recursiveConstraints) throws SQLException, IOException {        final List heads = new ArrayList();        final List tails = new ArrayList();        final List remainingTables = new ArrayList(getDatabase().getTables());        List unattached = new ArrayList();        // first pass to gather the 'low hanging fruit'        for (Iterator iter = remainingTables.iterator(); iter.hasNext(); ) {            Table table = (Table)iter.next();            if (table.isLeaf() && table.isRoot()) {                unattached.add(table);                iter.remove();            }        }        unattached = sortTrimmedLevel(unattached);        while (!remainingTables.isEmpty()) {            int tablesLeft = remainingTables.size();            tails.addAll(0, trimLeaves(remainingTables));            heads.addAll(trimRoots(remainingTables));            // if we could't trim anything then there's recursion....            // resolve it by removing a constraint, one by one, 'till the tables are all trimmed            if (tablesLeft == remainingTables.size()) {                boolean foundSimpleRecursion = false;                for (Iterator iter = remainingTables.iterator(); iter.hasNext(); ) {                    Table potentialRecursiveTable = (Table)iter.next();                    ForeignKeyConstraint recursiveConstraint = potentialRecursiveTable.removeSelfReferencingConstraint();                    if (recursiveConstraint != null) {                        recursiveConstraints.add(recursiveConstraint);                        foundSimpleRecursion = true;                    }                }                if (!foundSimpleRecursion) {                    // expensive comparison, but we're down to the end of the tables so it shouldn't really matter                    Set byParentChildDelta = new TreeSet(new Comparator() {                        // sort on the delta between number of parents and kids so we can                        // target the tables with the biggest delta and therefore the most impact                        // on reducing the smaller of the two                        public int compare(Object object1, Object object2) {                            Table table1 = (Table)object1;                            Table table2 = (Table)object2;                            int rc = Math.abs(table2.getNumChildren() - table2.getNumParents()) - Math.abs(table1.getNumChildren() - table1.getNumParents());                            if (rc == 0)                                rc = table1.getName().compareTo(table2.getName());                            return rc;                        }                    });                    byParentChildDelta.addAll(remainingTables);                    Table recursiveTable = (Table)byParentChildDelta.iterator().next(); // this one has the largest delta                    ForeignKeyConstraint removedConstraint = recursiveTable.removeAForeignKeyConstraint();                    recursiveConstraints.add(removedConstraint);                }            }        }        // we've gathered all the heads and tails, so combine them here moving 'unattached' tables to the end        List ordered = new ArrayList(heads.size() + tails.size());        for (Iterator iter = heads.iterator(); iter.hasNext(); )            ordered.add(iter.next());        for (Iterator iter = tails.iterator(); iter.hasNext(); )            ordered.add(iter.next());        for (Iterator iter = unattached.iterator(); iter.hasNext(); )            ordered.add(iter.next());        return ordered;    }