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;
+ }
+ }
}