Revision: 3368
Author: [email protected]
Date: Tue Mar  9 09:19:08 2010
Log: The DBTreeModel now pools events from the tree model and fires tree model changes when transactions end. This prevents the tree model from trying to repopulate the objects in an infinite loop. To help prevent additional populating the SQLTable now overrides getChildren(Class) so only the children of interest and the children necessary are populated.

The DBTree and model have been updated to allow the Copy Table Data panel to expand the tree.

More testing is needed to ensure this issue has been resolved.
http://code.google.com/p/power-architect/source/detail?r=3368

Modified:
/branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/DBTree.java /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/dbtree/DBTreeModel.java

=======================================
--- /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/DBTree.java Wed Mar 3 14:14:30 2010 +++ /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/DBTree.java Tue Mar 9 09:19:08 2010
@@ -282,9 +282,6 @@
        public void expandPath(TreePath tp) {
                try {
                        session.getArchitectFrame().setCursor(new 
Cursor(Cursor.WAIT_CURSOR));
-                       if (tp.getLastPathComponent() instanceof SQLObject) {
-                           ((SQLObject) tp.getLastPathComponent()).populate();
-                       }
                        super.expandPath(tp);
                } catch (Exception ex) {
logger.warn("Unexpected exception while expanding path "+tp, ex); //$NON-NLS-1$
@@ -293,18 +290,6 @@
                }
        }

-       @Override
-       public void expandRow(int row) {
-           if (getPathForRow(row).getLastPathComponent() instanceof SQLObject) 
{
-               try {
- ((SQLObject) getPathForRow(row).getLastPathComponent()).populate();
-            } catch (SQLObjectException e) {
-                throw new RuntimeException(e);
-            }
-           }
-           super.expandRow(row);
-       }
-
        // ---------- methods of DragSourceListener -----------
        public void dragEnter(DragSourceDragEvent dsde) {
                logger.debug("DBTree: got dragEnter event"); //$NON-NLS-1$
=======================================
--- /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/dbtree/DBTreeModel.java Wed Mar 3 14:14:30 2010 +++ /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/dbtree/DBTreeModel.java Tue Mar 9 09:19:08 2010
@@ -188,6 +188,15 @@
         }

        }
+
+       /**
+        * For use in the {...@link DBTreeSPListener}.
+        */
+       private enum EventType {
+           INSERT,
+           REMOVE,
+           CHANGE
+       }

        /**
* A {...@link SPListener} implementation that will fire tree events as the underlying
@@ -195,6 +204,39 @@
         */
        private class DBTreeSPListener implements SPListener {

+           /**
+ * Small inner class to group the tree event with the type of event it is.
+            */
+           private class TreeEventWithType {
+               private final TreeModelEvent evt;
+               private final EventType type;
+
+               public TreeEventWithType(TreeModelEvent evt, EventType type) {
+                this.evt = evt;
+                this.type = type;
+               }
+
+               public TreeModelEvent getEvt() {
+                return evt;
+            }
+
+               public EventType getType() {
+                return type;
+            }
+           }
+
+        /**
+ * List to hold all of the events. The events are to be pooled during a + * transaction and only acted upon when the transaction is complete. + * This gives methods like populate the ability to fire multiple child
+         * events but not cause the tree model to get the children of the
+ * objects it is looking at which would cause populate to start over
+         * again when it is already in the middle of populating.
+         */
+ private List<TreeEventWithType> allEvents = new ArrayList<TreeEventWithType>();
+
+           private int transactionCount = 0;
+
         public void childAdded(SPChildEvent e) {
             if (logger.isDebugEnabled()) {
logger.debug("dbChildrenInserted. source="+e.getSource() //$NON-NLS-1$
@@ -207,7 +249,11 @@

             Set<TreeModelEvent> events = createTreeEvents(e);
             for (TreeModelEvent evt : events) {
-                fireTreeNodesInserted(evt);
+                if (transactionCount > 0) {
+ allEvents.add(new TreeEventWithType(evt, EventType.INSERT));
+                } else {
+                    fireTreeNodesInserted(evt);
+                }
             }

if (e.getChild() instanceof SQLTable && foldersInTables.get(e.getChild()) == null) {
@@ -218,8 +264,13 @@
                 for (int i = 0; i < folderList.size(); i++) {
                     positions[i] = i;
                 }
- fireTreeNodesInserted(new TreeModelEvent(table, getPathToNode(table),
-                        positions, folderList.toArray()));
+ final TreeModelEvent evt = new TreeModelEvent(table, getPathToNode(table),
+                        positions, folderList.toArray());
+                if (transactionCount > 0) {
+ allEvents.add(new TreeEventWithType(evt, EventType.INSERT));
+                } else {
+                    fireTreeNodesInserted(evt);
+                }
             } else {
                 setupTreeForNode((SQLObject) e.getChild());
             }
@@ -240,20 +291,42 @@

             Set<TreeModelEvent> events = createTreeEvents(e);
             for (TreeModelEvent evt : events) {
-                fireTreeNodesRemoved(evt);
+                if (transactionCount > 0) {
+ allEvents.add(new TreeEventWithType(evt, EventType.REMOVE));
+                } else {
+                    fireTreeNodesRemoved(evt);
+                }
             }
         }

         public void transactionEnded(TransactionEvent e) {
-            //do nothing
+            if (transactionCount == 0) {
+ throw new IllegalStateException("Transaction ended outside of a transaction.");
+            }
+            transactionCount--;
+            if (transactionCount == 0) {
+                for (TreeEventWithType evt : allEvents) {
+                    if (evt.getType() == EventType.INSERT) {
+                        fireTreeNodesInserted(evt.getEvt());
+                    } else if (evt.getType() == EventType.REMOVE) {
+                        fireTreeNodesRemoved(evt.getEvt());
+                    } else if (evt.getType() == EventType.CHANGE) {
+                        fireTreeNodesChanged(evt.getEvt());
+                    } else {
+ throw new IllegalStateException("Unknown event type " + evt.getType());
+                    }
+                }
+                allEvents.clear();
+            }
         }

         public void transactionRollback(TransactionEvent e) {
-            //do nothing
+            transactionCount = 0;
+            allEvents.clear();
         }

         public void transactionStarted(TransactionEvent e) {
-            //do nothing
+            transactionCount++;
         }

         public void propertyChanged(PropertyChangeEvent e) {
@@ -301,7 +374,12 @@
                 refreshTreeStructure();
logger.info("Changing a UUID. This should only be done during load.");
             } else {
- fireTreeNodesChanged(new TreeModelEvent(this, getPathToNode(source))); + final TreeModelEvent evt = new TreeModelEvent(this, getPathToNode(source));
+                if (transactionCount > 0) {
+ allEvents.add(new TreeEventWithType(evt, EventType.CHANGE));
+                } else {
+                    fireTreeNodesChanged(evt);
+                }
             }
         }

@@ -392,8 +470,8 @@

                SQLObject sqlParent = (SQLObject) parent;
                try {
- if (logger.isDebugEnabled()) logger.debug("returning "+sqlParent.getChildrenWithoutPopulating().size()); //$NON-NLS-1$
-                       return sqlParent.getChildrenWithoutPopulating().size();
+ if (logger.isDebugEnabled()) logger.debug("returning "+sqlParent.getChildren().size()); //$NON-NLS-1$
+                       return sqlParent.getChildren().size();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
@@ -412,16 +490,17 @@
        }

        public int getIndexOfChild(Object parent, Object child) {
- if (logger.isDebugEnabled()) logger.debug("DBTreeModel.getIndexOfChild("+parent+","+child+"): returning "+((SQLObject) parent).getChildren().indexOf(child)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+           SPObject spChild = (SPObject) child;
+ if (logger.isDebugEnabled()) logger.debug("DBTreeModel.getIndexOfChild("+parent+","+child+"): returning "+((SQLObject) parent).getChildren(spChild.getClass()).indexOf(child)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

                if (parent instanceof FolderNode) {
-            return ((FolderNode) parent).getChildren().indexOf(child);
+ return ((FolderNode) parent).getChildren(spChild.getClass()).indexOf(child);
         } else if (parent instanceof SQLTable) {
             if (foldersInTables.get((SQLTable) parent) == null) return -1;
             return foldersInTables.get((SQLTable) parent).indexOf(child);
         }

- return ((SQLObject) parent).getChildrenWithoutPopulating().indexOf(child); + return ((SQLObject) parent).getChildren(spChild.getClass()).indexOf(child);
        }

        // -------------- treeModel event source support -----------------

Reply via email to