Revision: 3351
Author: [email protected]
Date: Wed Mar  3 14:14:30 2010
Log: This is the major portion of work for pushing the events of the SQLObjects to the foreground thread.
This includes:
-The architect project was previously firing all events on the current thread and not using the correct session to forward events to the foreground. Now the correct session is being used, which initially caused problems during populate. -The SQLObjects now have a map of exceptions that occurred per child type. This lets places like the SQLTable contain one
exception per child type.

More work on the SQLObjects in the library and testing is needed.
http://code.google.com/p/power-architect/source/detail?r=3351

Modified:
/branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/ArchitectProjectTest.java /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/profile/ProfileManagerImplTest.java /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/profile/TestProfileBase.java /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/swingui/TestSwingUIProject.java /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/swingui/TestingArchitectSwingSession.java /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/util/ArchitectNewValueMaker.java /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/ArchitectProject.java /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/ArchitectSessionImpl.java /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/ProjectLoader.java /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/messages.properties /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/profile/ProfileManagerImpl.java /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/ArchitectSwingSessionImpl.java /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/DBTree.java /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/PlayPen.java /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/SwingUIProjectLoader.java /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/dbtree/DBTreeCellRenderer.java /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/dbtree/DBTreeModel.java

=======================================
--- /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/ArchitectProjectTest.java Tue Feb 16 14:02:41 2010 +++ /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/ArchitectProjectTest.java Wed Mar 3 14:14:30 2010
@@ -38,7 +38,7 @@
         super.setUp();
         ArchitectSession session = new StubArchitectSession();
         objectUnderTest = new ArchitectProject();
-        objectUnderTest.init(session);
+        objectUnderTest.setSession(session);
         getRootObject().addChild(objectUnderTest, 0);
     }

=======================================
--- /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/profile/ProfileManagerImplTest.java Wed Feb 17 15:05:17 2010 +++ /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/profile/ProfileManagerImplTest.java Wed Mar 3 14:14:30 2010
@@ -41,9 +41,14 @@
         super.setUp();

         profileManager = new ProfileManagerImpl();
- ArchitectProject project = (ArchitectProject) new ArchitectNewValueMaker( + final ArchitectProject project = (ArchitectProject) new ArchitectNewValueMaker( getRootObject(), getPLIni()).makeNewValue(ArchitectProject.class, null, "");
-        project.init(new StubArchitectSession());
+        project.setSession(new StubArchitectSession() {
+            @Override
+            public ArchitectProject getWorkspace() {
+                return project;
+            }
+        });
         project.setProfileManager(profileManager);

         getRootObject().addChild(project, 0);
=======================================
--- /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/profile/TestProfileBase.java Fri Feb 12 07:43:48 2010 +++ /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/profile/TestProfileBase.java Wed Mar 3 14:14:30 2010
@@ -176,7 +176,6 @@
             assertNotNull(t3);

             pm = new ProfileManagerImpl();
-            ((ProfileManagerImpl) pm).setUserPrompterFactory(session);
             session.getWorkspace().setProfileManager(pm);
             pm.getDefaultProfileSettings().setFindingAvg(true);
             pm.getDefaultProfileSettings().setFindingMin(true);
=======================================
--- /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/swingui/TestSwingUIProject.java Wed Mar 3 12:03:13 2010 +++ /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/swingui/TestSwingUIProject.java Wed Mar 3 14:14:30 2010
@@ -483,7 +483,7 @@
// grab the second database in the dbtree's model (the first is the play pen) db = (SQLDatabase) session2.getSourceDatabases().getDatabaseList().get(1);

- System.out.println("DB has child exception " + db.getChildrenInaccessibleReason()); + System.out.println("DB has child exception " + db.getChildrenInaccessibleReasons());

                Map<String, Object> newDescription =
ca.sqlpower.testutil.TestUtils.getAllInterestingProperties(db, propertiesToIgnore);
=======================================
--- /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/swingui/TestingArchitectSwingSession.java Thu Feb 25 09:46:15 2010 +++ /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/swingui/TestingArchitectSwingSession.java Wed Mar 3 14:14:30 2010
@@ -41,7 +41,6 @@
 import ca.sqlpower.architect.olap.OLAPRootObject;
 import ca.sqlpower.architect.olap.OLAPSession;
 import ca.sqlpower.architect.profile.ProfileManager;
-import ca.sqlpower.architect.profile.ProfileManagerImpl;
import ca.sqlpower.architect.swingui.ArchitectSwingSessionImpl.ColumnVisibility;
 import ca.sqlpower.architect.swingui.olap.OLAPEditSession;
 import ca.sqlpower.architect.undo.ArchitectUndoManager;
@@ -98,7 +97,7 @@
             }
         };
         this.delegateSession = new ArchitectSessionImpl(context, "test");
- ((ProfileManagerImpl) delegateSession.getProfileManager()).setUserPrompterFactory(this);
+        delegateSession.getWorkspace().setSession(this);
         project = new SwingUIProjectLoader(this);
         userSettings = context.getUserSettings();
         sourceDatabases = new DBTree(this);
@@ -384,18 +383,15 @@
     }

     public boolean isForegroundThread() {
-        // TODO Auto-generated method stub
-        return false;
+        return true;
     }

     public void runInBackground(Runnable runner) {
-        // TODO Auto-generated method stub
-
+        runner.run();
     }

     public void runInForeground(Runnable runner) {
-        // TODO Auto-generated method stub
-
+        runner.run();
     }

     public void addPropertyChangeListener(PropertyChangeListener l) {
=======================================
--- /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/util/ArchitectNewValueMaker.java Thu Feb 18 07:51:21 2010 +++ /branches/sqlobject-foreground-events/regress/ca/sqlpower/architect/util/ArchitectNewValueMaker.java Wed Mar 3 14:14:30 2010
@@ -31,7 +31,6 @@
 import ca.sqlpower.sqlobject.SQLObjectException;
 import ca.sqlpower.sqlobject.SQLTable;
 import ca.sqlpower.testutil.GenericNewValueMaker;
-import ca.sqlpower.util.SPSession;

 public class ArchitectNewValueMaker extends GenericNewValueMaker {

@@ -69,12 +68,7 @@
             ArchitectProject project;
             final SPObject rootObject = getRootObject();
             try {
-                project = new ArchitectProject() {
-                    @Override
-                    public SPSession getSession() {
-                        return rootObject.getSession();
-                    }
-                };
+                project = new ArchitectProject();
             } catch (SQLObjectException e) {
                 throw new RuntimeException(e);
             }
=======================================
--- /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/ArchitectProject.java Tue Feb 16 14:02:41 2010 +++ /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/ArchitectProject.java Wed Mar 3 14:14:30 2010
@@ -31,6 +31,7 @@
 import ca.sqlpower.object.annotation.Accessor;
 import ca.sqlpower.object.annotation.Constructor;
 import ca.sqlpower.object.annotation.ConstructorParameter;
+import ca.sqlpower.object.annotation.Mutator;
 import ca.sqlpower.object.annotation.NonBound;
 import ca.sqlpower.object.annotation.NonProperty;
 import ca.sqlpower.object.annotation.Transient;
@@ -40,7 +41,7 @@
 import ca.sqlpower.sqlobject.SQLObject;
 import ca.sqlpower.sqlobject.SQLObjectException;
 import ca.sqlpower.sqlobject.SQLObjectRoot;
-import ca.sqlpower.util.SPSession;
+import ca.sqlpower.util.SessionNotFoundException;

 /**
  *
@@ -68,6 +69,11 @@
     private final SQLObjectRoot rootObject;
     private ProfileManager profileManager;

+    /**
+     * The current integrity watcher on the project.
+     */
+    private SourceObjectIntegrityWatcher currentWatcher;
+
     /**
* Constructs an architect project. The init method must be called immediately
      * after creating a project.
@@ -93,16 +99,24 @@
public ArchitectProject(@ConstructorParameter(isProperty=ParameterType.CHILD, propertyName="rootObject") SQLObjectRoot rootObject)
             throws SQLObjectException {
         this.rootObject = rootObject;
+        rootObject.setParent(this);
+        setName("Architect Project");
     }

     /**
      * Call this to initialize the session and the children of the project.
      */
-    public void init(ArchitectSession session) {
+    @Transient @Mutator
+    public void setSession(ArchitectSession session) {
+        if (this.session != null) {
+            rootObject.removeSQLObjectPreEventListener(currentWatcher);
+            currentWatcher = null;
+        }
         this.session = session;
- rootObject.addSQLObjectPreEventListener(new SourceObjectIntegrityWatcher(session));
-        rootObject.setParent(this);
-        setName("Architect Project");
+        if (this.session != null) {
+            currentWatcher = new SourceObjectIntegrityWatcher(session);
+            rootObject.addSQLObjectPreEventListener(currentWatcher);
+        }
     }

     /**
@@ -187,8 +201,13 @@
     }

     @Transient @Accessor
-    public SPSession getSession() {
-        return session;
+    public ArchitectSession getSession() throws SessionNotFoundException {
+        if (session != null) {
+            return session;
+        } else {
+ throw new SessionNotFoundException("The project has not been given a session yet. " + + "This should only happen during the construction of the project.");
+        }
     }

     public boolean allowsChildren() {
=======================================
--- /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/ArchitectSessionImpl.java Thu Feb 25 09:46:15 2010 +++ /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/ArchitectSessionImpl.java Wed Mar 3 14:14:30 2010
@@ -87,9 +87,8 @@

            this.context = context;
            this.project = new ArchitectProject();
-           project.init(this);
+           project.setSession(this);
            ProfileManagerImpl manager = new ProfileManagerImpl();
-           manager.setUserPrompterFactory(this);
            this.project.setProfileManager(manager);
            this.name = name;
         this.projectLoader = new ProjectLoader(this);
@@ -210,7 +209,7 @@
     public void runInForeground(Runnable runner) {
         runner.run();
     }
-
+
     public void addPropertyChangeListener(PropertyChangeListener l) {
         pcs.addPropertyChangeListener(l);
     }
=======================================
--- /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/ProjectLoader.java Thu Feb 25 09:46:15 2010 +++ /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/ProjectLoader.java Wed Mar 3 14:14:30 2010
@@ -64,6 +64,7 @@
 import ca.sqlpower.sqlobject.SQLIndex.AscendDescend;
 import ca.sqlpower.sqlobject.SQLIndex.Column;
 import ca.sqlpower.sqlobject.SQLRelationship.Deferrability;
+import ca.sqlpower.sqlobject.SQLRelationship.SQLImportedKey;
 import ca.sqlpower.sqlobject.SQLRelationship.UpdateDeleteRule;
 import ca.sqlpower.xml.UnescapingSaxParser;

@@ -88,7 +89,7 @@
         String message = attr.getValue("sql-exception");
         if (message != null) {
             try {
- obj.setChildrenInaccessibleReason(new SQLObjectException(message), false); + obj.setChildrenInaccessibleReason(new SQLObjectException(message), SQLObject.class, false);
             } catch (SQLObjectException e) {
                 throw new AssertionError("Unreachable code");
             }
@@ -570,10 +571,10 @@
             return tab;
         }
     }
-
+
     /**
- * XXX Temporary factory for folders until the file format changes and the folders
-     * are removed permanently.
+ * XXX Temporary factory for folders until the file format changes and the
+     * folders are removed permanently.
      */
     private class SQLFolderFactory extends AbstractObjectCreationFactory {
         @Override
@@ -581,14 +582,48 @@
String type = attributes.getValue("type"); //1=col, 2=import, 3=export, 4=index boolean isPopulated = Boolean.valueOf(attributes.getValue("populated"));

+            String message = attributes.getValue("sql-exception");
+
             if (type.equals("1")) {
                 currentTable.setColumnsPopulated(isPopulated);
+                if (message != null) {
+                    try {
+ currentTable.setChildrenInaccessibleReason(new SQLObjectException(message),
+                                SQLColumn.class, false);
+                    } catch (SQLObjectException e) {
+                        throw new AssertionError("Unreachable code");
+                    }
+                }
             } else if (type.equals("2")) {
                 currentTable.setImportedKeysPopulated(isPopulated);
+                if (message != null) {
+                    try {
+ currentTable.setChildrenInaccessibleReason(new SQLObjectException(message),
+                                SQLImportedKey.class, false);
+                    } catch (SQLObjectException e) {
+                        throw new AssertionError("Unreachable code");
+                    }
+                }
             } else if (type.equals("3")) {
                 currentTable.setExportedKeysPopulated(isPopulated);
+                if (message != null) {
+                    try {
+ currentTable.setChildrenInaccessibleReason(new SQLObjectException(message),
+                                SQLRelationship.class, false);
+                    } catch (SQLObjectException e) {
+                        throw new AssertionError("Unreachable code");
+                    }
+                }
             } else if (type.equals("4")) {
                 currentTable.setIndicesPopulated(isPopulated);
+                if (message != null) {
+                    try {
+ currentTable.setChildrenInaccessibleReason(new SQLObjectException(message),
+                                SQLIndex.class, false);
+                    } catch (SQLObjectException e) {
+                        throw new AssertionError("Unreachable code");
+                    }
+                }
             }

             return currentTable;
=======================================
--- /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/messages.properties Thu Aug 7 09:26:17 2008 +++ /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/messages.properties Wed Mar 3 14:14:30 2010
@@ -1,4 +1,8 @@
 cancel=Cancel
+columnsUnpopulatedOnLoad=The columns of this table were not populated in the loaded file. To populate these columns refresh the data source. +importedKeysUnpopulatedOnLoad=The imported keys of this table were not populated in the loaded file. To populate these columns refresh the data source. +exportedKeysUnpopulatedOnLoad=The exported keys of this table were not populated in the loaded file. To populate these columns refresh the data source. +indicesUnpopulatedOnLoad=The indices of this table were not populated in the loaded file. To populate these columns refresh the data source.
 ok=OK
 SourceObjectIntegrityWatcher.forgetLineageOption=Forget Lineage
SourceObjectIntegrityWatcher.keepSourceConnectionOption=Keep Source Connection
=======================================
--- /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/profile/ProfileManagerImpl.java Thu Feb 18 13:18:27 2010 +++ /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/profile/ProfileManagerImpl.java Wed Mar 3 14:14:30 2010
@@ -32,7 +32,6 @@
 import org.apache.log4j.Logger;

 import ca.sqlpower.architect.ArchitectProject;
-import ca.sqlpower.architect.ArchitectSession;
 import ca.sqlpower.architect.profile.event.ProfileChangeEvent;
 import ca.sqlpower.architect.profile.event.ProfileChangeListener;
 import ca.sqlpower.object.AbstractSPObject;
@@ -50,7 +49,6 @@
 import ca.sqlpower.sqlobject.SQLObjectPreEventListener;
 import ca.sqlpower.sqlobject.SQLTable;
 import ca.sqlpower.util.UserPrompter;
-import ca.sqlpower.util.UserPrompterFactory;
 import ca.sqlpower.util.UserPrompter.UserPromptOptions;
 import ca.sqlpower.util.UserPrompter.UserPromptResponse;
 import ca.sqlpower.util.UserPrompterFactory.UserPromptType;
@@ -82,7 +80,7 @@

         public void dbChildrenPreRemove(SQLObjectPreEvent e) {
             logger.debug("Pre-remove on profile manager");
-            UserPrompter up = session.createUserPrompter(
+            UserPrompter up = getParent().getSession().createUserPrompter(
"{0} tables have been profiled from the database {1}.\n" +
                     "\n" +
"If you proceed, the profiling information from the database" +
@@ -130,11 +128,6 @@
      */
private final List<TableProfileResult> results = new ArrayList<TableProfileResult>();

-    /**
-     * The user prompter for the profile manager.
-     */
-    private UserPrompterFactory session;
-
     /**
      * The defaults that new profile results will be created with.
      * XXX these are specific to the remote database profiler!
@@ -202,11 +195,6 @@
         defaultProfileSettings.setParent(this);
         setName("Profile Manager");
     }
-
-    @Transient @Mutator
-    public void setUserPrompterFactory(ArchitectSession session) {
-        this.session = session;
-    }

     @Override @Mutator
     public void setParent(SPObject parent) {
@@ -215,8 +203,9 @@
((ArchitectProject) getParent()).getRootObject().removeSQLObjectPreEventListener(databaseRemovalWatcher);
         }
         super.setParent(parent);
- if (parent != null && ((ArchitectProject) parent).getRootObject() != null) { - ((ArchitectProject) parent).getRootObject().addSQLObjectPreEventListener(databaseRemovalWatcher); + final ArchitectProject architectProject = (ArchitectProject) parent;
+        if (parent != null && architectProject.getRootObject() != null) {
+ architectProject.getRootObject().addSQLObjectPreEventListener(databaseRemovalWatcher);
         }
         firePropertyChange("parent", oldParent, parent);
     }
=======================================
--- /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/ArchitectSwingSessionImpl.java Wed Mar 3 12:03:13 2010 +++ /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/ArchitectSwingSessionImpl.java Wed Mar 3 14:14:30 2010
@@ -260,9 +260,9 @@
         this.isNew = true;
         this.context = context;
         this.delegateSession = delegateSession;
+        delegateSession.getWorkspace().setSession(this);
         this.olapRootObject = new OLAPRootObject(delegateSession);
         ProfileManagerImpl profileManager = new ProfileManagerImpl();
-        profileManager.setUserPrompterFactory(this);
((ArchitectSessionImpl)delegateSession).setProfileManager(profileManager); ((ArchitectSessionImpl)delegateSession).setUserPrompterFactory(this);
         this.recent = new RecentMenu(this.getClass()) {
@@ -1082,7 +1082,13 @@
     }

     public boolean isForegroundThread() {
-        return SwingUtilities.isEventDispatchThread();
+ //Until the GUI is initialized we may be running headless in which case
+        //we will not be using the EDT.
+        if (frame != null) {
+            return SwingUtilities.isEventDispatchThread();
+        } else {
+            return true;
+        }
     }

     public void runInBackground(final Runnable runner) {
@@ -1103,13 +1109,15 @@
     }

     public void runInForeground(Runnable runner) {
-        if (SwingUtilities.isEventDispatchThread()) {
+ //Until the GUI is initialized we may be running headless in which case
+        //we will not be using the EDT.
+        if (frame == null || SwingUtilities.isEventDispatchThread()) {
             runner.run();
         } else {
             SwingUtilities.invokeLater(runner);
         }
     }
-
+
     public void addPropertyChangeListener(PropertyChangeListener l) {
         delegateSession.addPropertyChangeListener(l);
     }
=======================================
--- /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/DBTree.java Fri Jan 15 15:02:04 2010 +++ /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/DBTree.java Wed Mar 3 14:14:30 2010
@@ -160,9 +160,12 @@
             public void mouseReleased(MouseEvent e) {
                 if (getPathForLocation(e.getX(), e.getY()) != null) {
Object node = getPathForLocation(e.getX(), e.getY()).getLastPathComponent(); - if (e.getClickCount() == 2 && node instanceof SQLObject && ((SQLObject) node).getChildrenInaccessibleReason() != null) { + if (e.getClickCount() == 2 && node instanceof SQLObject && + !((SQLObject) node).getChildrenInaccessibleReasons().isEmpty()) {
+                        Throwable firstException = ((SQLObject) node).
+ getChildrenInaccessibleReasons().entrySet().iterator().next().getValue(); SPSUtils.showExceptionDialogNoReport(session.getArchitectFrame(), - Messages.getString("DBTree.exceptionNodeReport"), ((SQLObject) node).getChildrenInaccessibleReason()); //$NON-NLS-1$ + Messages.getString("DBTree.exceptionNodeReport"), firstException); //$NON-NLS-1$
                     }
                 }
             }
@@ -570,7 +573,7 @@
                                //tree only has one child
if (!tempDB.isCatalogContainer() && !tempDB.isSchemaContainer() &&
                                        (!(tempDB.getChildCount() == 1) ||
-                                               
tempDB.getChildrenInaccessibleReason() == null))
+ tempDB.getChildrenInaccessibleReasons().isEmpty()))
                                {
                                    //a new action is needed to maintain the 
database variable
CompareToCurrentAction compareToCurrentAction = new CompareToCurrentAction();
@@ -633,18 +636,21 @@
                }

// Show exception details (SQLException node can appear anywhere in the hierarchy) - if (p != null && p.getLastPathComponent() instanceof SQLObject && ((SQLObject) p.getLastPathComponent()).getChildrenInaccessibleReason() != null) {
+               if (p != null && p.getLastPathComponent() instanceof SQLObject 
&&
+ !((SQLObject) p.getLastPathComponent()).getChildrenInaccessibleReasons().isEmpty()) {
                        newMenu.addSeparator();
             final SQLObject node = (SQLObject) p.getLastPathComponent();
newMenu.add(new JMenuItem(new AbstractAction(Messages.getString("DBTree.showExceptionDetails")) { //$NON-NLS-1$
                 public void actionPerformed(ActionEvent e) {
+                    Throwable firstException = ((SQLObject) node).
+ getChildrenInaccessibleReasons().entrySet().iterator().next().getValue(); SPSUtils.showExceptionDialogNoReport(session.getArchitectFrame(), - Messages.getString("DBTree.exceptionNodeReport"), node.getChildrenInaccessibleReason()); //$NON-NLS-1$ + Messages.getString("DBTree.exceptionNodeReport"), firstException); //$NON-NLS-1$
                 }
             }));

// If the sole child is an exception node, we offer the user a way to re-try the operation
-            if (node.getChildrenInaccessibleReason() != null) {
+            if (!node.getChildrenInaccessibleReasons().isEmpty()) {
newMenu.add(new JMenuItem(new AbstractAction(Messages.getString("DBTree.retryActionName")) { //$NON-NLS-1$
                     public void actionPerformed(ActionEvent e) {
                         node.setPopulated(false);
=======================================
--- /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/PlayPen.java Wed Mar 3 12:03:13 2010 +++ /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/PlayPen.java Wed Mar 3 14:14:30 2010
@@ -1523,24 +1523,45 @@
                public void doStuff() {
logger.info("AddObjectsTask starting on thread "+Thread.currentThread().getName()); //$NON-NLS-1$ session.getArchitectFrame().getContentPane().setCursor(new Cursor(Cursor.WAIT_CURSOR));
+
                        try {
-                               int tableCount = 0;
-
-                               Iterator<SQLObject> soIt = 
sqlObjects.iterator();
-                               // first pass: figure out how much work we need 
to do...
-                               while (soIt.hasNext() && !isCancelled()) {
-                                       SQLObject so = soIt.next();
-                    tableCount += SQLObjectUtils.countTablesSnapshot(so);
-                               }
-                               setJobSize(new Integer(tableCount));
-
-                               ensurePopulated(sqlObjects);
-
+                           Iterator<SQLObject> soIt = sqlObjects.iterator();
+                           // first pass: Cause all of the SQLObjects between 
the given
+                           // ones and the table descendents to populate...
+                           while (soIt.hasNext() && !isCancelled()) {
+                               SQLObject so = soIt.next();
+                               SQLObjectUtils.countTablesSnapshot(so);
+                           }
                        } catch (SQLObjectException e) {
-                               logger.error("Unexpected exception during 
populate", e); //$NON-NLS-1$
+ logger.error("Unexpected exception during populate", e); //$NON-NLS-1$
                 setDoStuffException(e);
- errorMessage = "Unexpected exception during populate: " + e.getMessage(); //$NON-NLS-1$
-                       }
+ errorMessage = "Unexpected exception during populate: " + e.getMessage(); //$NON-NLS-1$
+            }
+
+                       //Second pass: count the tables. Done in the foreground 
to
+                       //wait for the objects to be fully populated by pass 1.
+                       session.runInForeground(new Runnable() {
+                           public void run() {
+                               try {
+                                   int tableCount = 0;
+                                   Iterator<SQLObject> soIt = 
sqlObjects.iterator();
+                                   while (soIt.hasNext() && !isCancelled()) {
+                                       SQLObject so = soIt.next();
+                                       tableCount += 
SQLObjectUtils.countTablesSnapshot(so);
+                                   }
+                                   setJobSize(new Integer(tableCount));
+                               } catch (SQLObjectException e) {
+ logger.error("Unexpected exception, objects should be populated by " +
+                                               "this pass.", e); //$NON-NLS-1$
+                                   setDoStuffException(e);
+ errorMessage = "Unexpected exception, objects should be populated " +
+                                               "by this pass: " + 
e.getMessage(); //$NON-NLS-1$
+                               }
+                           }
+                       });
+
+                       ensurePopulated(sqlObjects);
+
                        logger.info("AddObjectsTask done"); //$NON-NLS-1$
                }

@@ -1555,7 +1576,15 @@
                private void ensurePopulated(List<? extends SQLObject> soList) {
                        for (SQLObject so : soList) {
                                if (isCancelled()) break;
-                               if (so instanceof SQLTable) 
setProgress(getProgress() + 1);
+                               if (so instanceof SQLTable) {
+ //pushing updates to foreground as population happens on the foreground + //and this will keep the progress bar more honest with what is happening.
+                                   session.runInForeground(new Runnable(){
+                        public void run() {
+                            setProgress(getProgress() + 1);
+                        }
+                    });
+                               }
                 ensurePopulated(so.getChildren());
                        }
                }
=======================================
--- /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/SwingUIProjectLoader.java Wed Mar 3 12:03:13 2010 +++ /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/SwingUIProjectLoader.java Wed Mar 3 14:14:30 2010
@@ -80,6 +80,7 @@
 import ca.sqlpower.sqlobject.SQLRelationship;
 import ca.sqlpower.sqlobject.SQLSchema;
 import ca.sqlpower.sqlobject.SQLTable;
+import ca.sqlpower.sqlobject.SQLRelationship.SQLImportedKey;
 import ca.sqlpower.util.ExceptionReport;
 import ca.sqlpower.util.SQLPowerUtils;
 import ca.sqlpower.util.UserPrompter;
@@ -1241,8 +1242,11 @@
propNames.put("name", o.getName()); // note: there was no name attrib for SQLDatabase, SQLRelationship.ColumnMapping, and SQLExceptionNode //$NON-NLS-1$
         propNames.put("UUID", o.getUUID());

-        if (o.getChildrenInaccessibleReason() != null) {
- propNames.put("sql-exception", o.getChildrenInaccessibleReason().getMessage()); //$NON-NLS-1$
+        if (!o.getChildrenInaccessibleReasons().isEmpty()) {
+            //Only storing the top exception to prevent file format changes
+ //Only the SQLTable should have multiple children inaccessible reasons. + Throwable topException = o.getChildrenInaccessibleReason(SQLObject.class);
+            propNames.put("sql-exception", topException); //$NON-NLS-1$
         }

         if (o instanceof SQLDatabase) {
@@ -1370,20 +1374,47 @@
             String indicesFolder = null;
             if (o instanceof SQLTable) {
                 SQLTable table = (SQLTable) o;
+                String exception;
+ if (table.getChildrenInaccessibleReason(SQLColumn.class) != null) {
+                    exception = "sql-exception=\"" +
+ table.getChildrenInaccessibleReason(SQLColumn.class) + "\" ";
+                } else {
+                    exception = "";
+                }
ioo.println(out, "<folder id=\"FOL" + id + "1\" populated=\"" + table.isColumnsPopulated() + "\" name=\"Columns\" " +
-                                       "physicalName=\"Columns\" type=\"1\">");
+ "physicalName=\"Columns\" " + exception + "type=\"1\">");
                 ioo.indent++;

+ if (table.getChildrenInaccessibleReason(SQLImportedKey.class) != null) {
+                    exception = "sql-exception=\"" +
+ table.getChildrenInaccessibleReason(SQLImportedKey.class) + "\" ";
+                } else {
+                    exception = "";
+                }
importedKeysFolder = "<folder id=\"FOL" + id + "2\" populated=\"" + table.isImportedKeysPopulated() + "\" name=\"Imported Keys\" " +
-                    "physicalName=\"Imported Keys\" type=\"2\">";
+ "physicalName=\"Imported Keys\" " + exception + "type=\"2\">";
+
+ if (table.getChildrenInaccessibleReason(SQLRelationship.class) != null) {
+                    exception = "sql-exception=\"" +
+ table.getChildrenInaccessibleReason(SQLRelationship.class) + "\" ";
+                } else {
+                    exception = "";
+                }
exportedKeysFolder = "<folder id=\"FOL" + id + "3\" populated=\"" + table.isExportedKeysPopulated() + "\" name=\"Exported Keys\" " +
-                    "physicalName=\"Exported Keys\" type=\"3\">";
+ "physicalName=\"Exported Keys\" " + exception + "type=\"3\">";
+
+ if (table.getChildrenInaccessibleReason(SQLIndex.class) != null) {
+                    exception = "sql-exception=\"" +
+ table.getChildrenInaccessibleReason(SQLIndex.class) + "\" ";
+                } else {
+                    exception = "";
+                }
indicesFolder = "<folder id=\"FOL" + id + "4\" populated=\"" +
                     table.isIndicesPopulated() + "\" name=\"Indices\" " +
-                    "physicalName=\"Indices\" type=\"4\">";
+ "physicalName=\"Indices\" " + exception + "type=\"4\">";
             }
             while (children.hasNext()) {
                 SQLObject child = (SQLObject) children.next();
=======================================
--- /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/dbtree/DBTreeCellRenderer.java Tue Dec 22 12:38:24 2009 +++ /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/dbtree/DBTreeCellRenderer.java Wed Mar 3 14:14:30 2010
@@ -147,14 +147,14 @@
                        setIcon(null);
                }

- if (value instanceof SQLObject && ((SQLObject) value).getChildrenInaccessibleReason() != null) { + if (value instanceof SQLObject && !((SQLObject) value).getChildrenInaccessibleReasons().isEmpty()) { logger.debug("Children are not accessible from the node " + ((SQLObject) value).getName());
             if (getIcon() == null) {
                 setIcon(ERROR_BADGE);
             } else {
setIcon(new ComposedIcon(Arrays.asList(getIcon(), ERROR_BADGE)));
             }
- setToolTipText("Inaccessible: " + ((SQLObject) value).getChildrenInaccessibleReason()); + setToolTipText("Inaccessible: " + ((SQLObject) value).getChildrenInaccessibleReasons());
         }

                this.selected = sel;
=======================================
--- /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/dbtree/DBTreeModel.java Wed Feb 17 08:55:16 2010 +++ /branches/sqlobject-foreground-events/src/ca/sqlpower/architect/swingui/dbtree/DBTreeModel.java Wed Mar 3 14:14:30 2010
@@ -177,6 +177,15 @@
                 throw new RuntimeException(e);
             }
         }
+
+        @Override
+ public Throwable getChildrenInaccessibleReason(Class<? extends SQLObject> childType) { + if (childType == containingChildType || childType == SQLObject.class) { + return parentTable.getChildrenInaccessibleReason(containingChildType);
+            } else {
+                return null;
+            }
+        }

        }

Reply via email to