Revision: 3848
Author: mo.jeff
Date: Fri Aug 6 16:17:03 2010
Log: Added support so that type snapshots get created from reverse
engineering. This required combining the setting of the upstream type to a
system type, and then to a snapshot type to occur in the same transaction,
so modifications to the SPObjectSnapshotHierarchyListener were made to
accomodate this. Also removed the UpstreamTypeUpdateListener since reverse
engineered columns use snapshots right away, so it is no longer necessary.
One issue that remains is that when loading a project, the update listeners
appear to be not attached or not working as changes to domains and types
will not result in a refresh icon appearing over the used types in the
project in the dbtree. However, you can still rightclick and update to
retrieve changes.
http://code.google.com/p/power-architect/source/detail?r=3848
Modified:
/trunk/src/main/java/ca/sqlpower/architect/ArchitectSessionImpl.java
/trunk/src/main/java/ca/sqlpower/architect/SPObjectSnapshotHierarchyListener.java
=======================================
--- /trunk/src/main/java/ca/sqlpower/architect/ArchitectSessionImpl.java
Wed Aug 4 13:00:45 2010
+++ /trunk/src/main/java/ca/sqlpower/architect/ArchitectSessionImpl.java
Fri Aug 6 16:17:03 2010
@@ -26,7 +26,6 @@
import ca.sqlpower.architect.ddl.DDLGenerator;
import ca.sqlpower.architect.ddl.GenericDDLGenerator;
-import ca.sqlpower.architect.enterprise.UpstreamTypeUpdaterListener;
import ca.sqlpower.architect.profile.ProfileManager;
import ca.sqlpower.architect.profile.ProfileManagerImpl;
import ca.sqlpower.architect.swingui.LiquibaseSettings;
@@ -42,9 +41,9 @@
import ca.sqlpower.swingui.event.SessionLifecycleListener;
import ca.sqlpower.util.DefaultUserPrompterFactory;
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;
/**
* The ArchitectSession class represents a single user's session with
@@ -110,7 +109,6 @@
throw new SQLObjectException("SQL Error in ddlGenerator",e);
}
- project.addSPListener(new UpstreamTypeUpdaterListener(this));
}
// --------------- accessors and mutators ------------------
=======================================
---
/trunk/src/main/java/ca/sqlpower/architect/SPObjectSnapshotHierarchyListener.java
Thu Aug 5 12:09:29 2010
+++
/trunk/src/main/java/ca/sqlpower/architect/SPObjectSnapshotHierarchyListener.java
Fri Aug 6 16:17:03 2010
@@ -21,8 +21,11 @@
import java.beans.PropertyChangeEvent;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import org.apache.log4j.Logger;
+
import ca.sqlpower.architect.enterprise.ArchitectClientSideSession;
import ca.sqlpower.architect.enterprise.DomainCategory;
import ca.sqlpower.architect.enterprise.DomainCategorySnapshot;
@@ -36,6 +39,7 @@
import ca.sqlpower.sqlobject.UserDefinedSQLType;
import ca.sqlpower.sqlobject.UserDefinedSQLTypeSnapshot;
import ca.sqlpower.util.SQLPowerUtils;
+import ca.sqlpower.util.TransactionEvent;
/**
* Add this listener to a SQLDatabase to have its columns have correct
snapshot listeners
@@ -43,12 +47,38 @@
*/
public class SPObjectSnapshotHierarchyListener extends AbstractSPListener {
+ private static final Logger logger =
Logger.getLogger(SPObjectSnapshotHierarchyListener.class);
+
/**
* This project holds all of the snapshots of the {...@link
UserDefinedSQLType}
* objects.
*/
private final ArchitectClientSideSession session;
+ /**
+ * How many levels of transactions the object
+ * being watched is in. Currently only being used
+ * if the TransactionEvent source is a UserDefinedSQLType
+ */
+ private int transactionCount = 0;
+
+ /**
+ * A reference to a property change event kept during
+ * a transaction to change a UserDefinedSQLType's upstream
+ * type so that the event details can be used to create a
+ * new snapshot.
+ */
+ private PropertyChangeEvent upstreamTypeChangeEvent;
+
+ /**
+ * True if this listener is in the middle of
+ * setting a snapshot. False otherwise. Used
+ * to prevent an 'echo' event from causing
+ * extra commit() calls when setting the upstream
+ * type to use a snapshot.
+ */
+ private boolean settingSnapshot = false;
+
/**
* This map tracks all of the listeners that have been attached to
system
* workspace types and domains to the snapshot that they were attached
for.
@@ -65,14 +95,14 @@
@Override
public void childAdded(SPChildEvent e) {
if (e.getChild() instanceof SQLTable) {
- e.getChild().addSPListener(this);
+ SQLTable table = (SQLTable) e.getChild();
+ table.addSPListener(this);
+ for (SQLColumn sqlColumn :
table.getChildren(SQLColumn.class)) {
+
sqlColumn.getUserDefinedSQLType().addSPListener(this);
+ }
} else if (e.getChild() instanceof SQLColumn) {
SQLColumn sqlColumn = (SQLColumn) e.getChild();
- if (sqlColumn.getUserDefinedSQLType() != null) {
- sqlColumn.getUserDefinedSQLType().addSPListener(this);
- createSPObjectSnapshot(sqlColumn.getUserDefinedSQLType(),
sqlColumn.getUserDefinedSQLType().getUpstreamType());
-
addUpdateListener(sqlColumn.getUserDefinedSQLType().getUpstreamType());
- }
+ sqlColumn.getUserDefinedSQLType().addSPListener(this);
}
}
@@ -99,17 +129,14 @@
public void propertyChanged(PropertyChangeEvent e) {
if (e.getSource() instanceof UserDefinedSQLType
&& e.getPropertyName().equals("upstreamType")) {
-
- if (e.getNewValue() instanceof UserDefinedSQLType) {
- createSPObjectSnapshot((UserDefinedSQLType) e.getSource(),
(UserDefinedSQLType) e.getNewValue());
- }
-
- if (e.getOldValue() != null && ((UserDefinedSQLType)
e.getSource()).isMagicEnabled()) {
- cleanupSnapshot((UserDefinedSQLType) e.getOldValue());
- }
-
- UserDefinedSQLType columnProxyType =
(UserDefinedSQLType) e.getSource();
- addUpdateListener(columnProxyType.getUpstreamType());
+ if (upstreamTypeChangeEvent == null &&
+ !(e.getNewValue() instanceof UserDefinedSQLType &&
+ ((UserDefinedSQLType)e.getNewValue()).getParent() ==
session.getWorkspace().getSnapshotCollection())) {
+ logger.debug("Got a property change event for
upstreamType!");
+ upstreamTypeChangeEvent = e;
+ } else {
+ logger.debug("Got another upstreamType change event in the
middle of another");
+ }
}
}
@@ -232,11 +259,33 @@
SnapshotCollection collection =
session.getWorkspace().getSnapshotCollection();
+ // Check if the upstream type is a system type by checking if it's
not
+ // parented by this session's workspace.
if (upstreamTypeParent != null
&& !upstreamTypeParent.equals(collection) &&
!(upstreamTypeParent instanceof DomainCategory &&
upstreamTypeParent.getParent().equals(collection))) {
+
+ // Check if a snapshot for the upstreamType already exists. If
so, just use that.
+ boolean snapshotExists = false;
+ List<UserDefinedSQLTypeSnapshot> typeSnapshots =
+
session.getWorkspace().getSnapshotCollection().getChildren(UserDefinedSQLTypeSnapshot.class);
+ for (UserDefinedSQLTypeSnapshot typeSnapshot : typeSnapshots) {
+ // If the snapshot is a domain snapshot, but the upstream
type
+ // is not a domain, then move on to the next snapshot.
+ if (typeSnapshot.isDomainSnapshot() &&
+ !(upstreamType.getParent() instanceof
DomainCategory)) continue;
+
+ if
(upstreamType.getUUID().equals(typeSnapshot.getOriginalUUID())) {
+ typeProxy.setUpstreamType(typeSnapshot.getSPObject());
+
typeSnapshot.setSnapshotUseCount(typeSnapshot.getSnapshotUseCount() + 1);
+ snapshotExists = true;
+ break;
+ }
+ }
+ if (snapshotExists) return; // If snapshot already existed,
then nothing else needs to be done
+
+ // Otherwise, we have to create a new snapshot
int systemRevision =
session.getSystemSession().getCurrentRevisionNumber();
-
boolean isDomainSnapshot = upstreamType.getParent() instanceof
DomainCategory;
UserDefinedSQLTypeSnapshot snapshot;
if (upstreamType.getUpstreamType() != null) {
@@ -295,4 +344,50 @@
}
}
}
-}
+
+ @Override
+ public void transactionStarted(TransactionEvent e) {
+ if (e.getSource() instanceof UserDefinedSQLType) {
+ UserDefinedSQLType udt = (UserDefinedSQLType) e.getSource();
+ transactionCount++;
+ logger.debug("Incremented transaction counter to " +
transactionCount);
+ if (transactionCount == 1) {
+ udt.begin("setting upstream type (snapshot)");
+ }
+ }
+ }
+
+ @Override
+ public void transactionEnded(TransactionEvent e) {
+ if (e.getSource() instanceof UserDefinedSQLType) {
+ UserDefinedSQLType udt = (UserDefinedSQLType) e.getSource();
+
+ transactionCount--;
+ logger.debug("Decremented transaction counter to " +
transactionCount);
+ if (transactionCount == 1) {
+ if (upstreamTypeChangeEvent != null) {
+ UserDefinedSQLType newValue = (UserDefinedSQLType)
upstreamTypeChangeEvent.getNewValue();
+ UserDefinedSQLType source = (UserDefinedSQLType)
upstreamTypeChangeEvent.getSource();
+ UserDefinedSQLType oldValue = (UserDefinedSQLType)
upstreamTypeChangeEvent.getOldValue();
+ upstreamTypeChangeEvent = null;
+
+ logger.debug("Replacing upstreamType with snapshot!");
+ settingSnapshot = true;
+ createSPObjectSnapshot(source, newValue);
+
+ if (oldValue != null && source.isMagicEnabled()) {
+ cleanupSnapshot(oldValue);
+ }
+
+ UserDefinedSQLType columnProxyType = source;
+ addUpdateListener(columnProxyType.getUpstreamType());
+ }
+ if (!settingSnapshot) {
+ udt.commit();
+ } else {
+ settingSnapshot = false;
+ }
+ }
+ }
+ }
+}