Revision: 3864
Author: [email protected]
Date: Tue Aug 10 13:58:36 2010
Log: Adding in a stop-gap solution for moving columns in a table with snapshots.

The problem is moving a column causes a remove and an add. The remove will cause the listener to update the use count of the snapshot to 0 in some cases and remove the snapshot and UDT. When the column is added back in the UDT upstream of the column proxy UDT the old snapshot is snapshotted and a listener is attempted to be added to it as though it is a system snapshot and causes an NPE.

Now the use count is only updated at the end of a transaction which works for now because all moves happen in a transaction. A better solution would involve merging the snapshot object with the snapshotted UDT.
http://code.google.com/p/power-architect/source/detail?r=3864

Modified:
/trunk/src/main/java/ca/sqlpower/architect/SPObjectSnapshotHierarchyListener.java

=======================================
--- /trunk/src/main/java/ca/sqlpower/architect/SPObjectSnapshotHierarchyListener.java Tue Aug 10 09:28:49 2010 +++ /trunk/src/main/java/ca/sqlpower/architect/SPObjectSnapshotHierarchyListener.java Tue Aug 10 13:58:36 2010
@@ -69,7 +69,20 @@
      * type so that the event details can be used to create a
      * new snapshot.
      */
- private Map<UserDefinedSQLType, PropertyChangeEvent> upstreamTypeChangeEventMap = new HashMap<UserDefinedSQLType, PropertyChangeEvent>();; + private Map<UserDefinedSQLType, PropertyChangeEvent> upstreamTypeChangeEventMap = new HashMap<UserDefinedSQLType, PropertyChangeEvent>();
+
+    /**
+ * Each type that needs to be cleaned up is mapped to a count of how many
+     * times the clean up method should be called on it.
+     * <p>
+ * XXX This is a stop-gap for being able to move a column as a remove and + * add since the column will be pointing at the snapshot and not a system
+     * type. In the future we need to have the snapshot object override
+ * {...@link UserDefinedSQLType} so it is the same object. That change will
+     * also simplify the model.
+     */
+    private final Map<UserDefinedSQLType, Integer> typesToCleanup =
+        new HashMap<UserDefinedSQLType, Integer>();

     /**
      * True if this listener is in the middle of
@@ -135,14 +148,24 @@
                        for (SQLColumn col : 
e.getChild().getChildren(SQLColumn.class)) {
                                
col.getUserDefinedSQLType().removeSPListener(this);
                                if 
(col.getUserDefinedSQLType().isMagicEnabled()) {
-                                   
cleanupSnapshot(col.getUserDefinedSQLType().getUpstreamType());
+ UserDefinedSQLType snapshotType = col.getUserDefinedSQLType().getUpstreamType();
+                                   Integer cleanupCount = 
typesToCleanup.get(snapshotType);
+                                   if (cleanupCount == null) {
+                                       cleanupCount = 0;
+                                   }
+                                   typesToCleanup.put(snapshotType, 
cleanupCount + 1);
                                }
                        }
                } else if (e.getChild() instanceof SQLColumn) {
UserDefinedSQLType colType = ((SQLColumn) e.getChild()).getUserDefinedSQLType();
                        colType.removeSPListener(this);
                        if (colType.isMagicEnabled()) {
-                           cleanupSnapshot(colType.getUpstreamType());
+ UserDefinedSQLType snapshotType = colType.getUpstreamType();
+                Integer cleanupCount = typesToCleanup.get(snapshotType);
+                if (cleanupCount == null) {
+                    cleanupCount = 0;
+                }
+                typesToCleanup.put(snapshotType, cleanupCount + 1);
                        }
                }
        }
@@ -385,19 +408,16 @@
             logger.debug("Ignoring begin");
             return;
         }
-        if (e.getSource() instanceof UserDefinedSQLType) {
-            logger.debug("Processing begin (\"" + e.getMessage() + "\")");
-            UserDefinedSQLType udt = (UserDefinedSQLType) e.getSource();
-            transactionCount++;
- logger.debug("Incremented transaction counter to " + transactionCount);
-            if (transactionCount == 1) {
-                logger.debug("Firing snapshot begin");
-                try {
-                    settingSnapshot = true;
-                    udt.begin("setting upstream type (snapshot)");
-                } finally {
-                    settingSnapshot = false;
-                }
+        logger.debug("Processing begin (\"" + e.getMessage() + "\")");
+        transactionCount++;
+ logger.debug("Incremented transaction counter to " + transactionCount);
+        if (transactionCount == 1) {
+            logger.debug("Firing snapshot begin");
+            try {
+                settingSnapshot = true;
+ ((SPObject) e.getSource()).begin("setting upstream type (snapshot)");
+            } finally {
+                settingSnapshot = false;
             }
         }
     }
@@ -408,37 +428,40 @@
             logger.debug("Ignoring commit");
             return;
         }
-        if (e.getSource() instanceof UserDefinedSQLType) {
-            logger.debug("Processing commit (\"" + e.getMessage() + "\")");
-            UserDefinedSQLType udt = (UserDefinedSQLType) e.getSource();
-
-            transactionCount--;
- logger.debug("Decremented transaction counter to " + transactionCount);
-            if (transactionCount == 0) {
-                try {
-                    settingSnapshot = true;
- for (Entry<UserDefinedSQLType, PropertyChangeEvent> entry : upstreamTypeChangeEventMap.entrySet()) { - UserDefinedSQLType newValue = (UserDefinedSQLType) entry.getValue().getNewValue(); - UserDefinedSQLType source = (UserDefinedSQLType) entry.getKey(); - UserDefinedSQLType oldValue = (UserDefinedSQLType) entry.getValue().getOldValue();
-
- logger.debug("Replacing upstreamType with snapshot!");
-                        createSPObjectSnapshot(source, newValue);
-
-                        if (oldValue != null && source.isMagicEnabled()) {
-                            cleanupSnapshot(oldValue);
-                        }
-
-                        UserDefinedSQLType columnProxyType = source;
- addUpdateListener(columnProxyType.getUpstreamType());
-                    }
-                    upstreamTypeChangeEventMap.clear();
-                    udt.commit("snapshot commit");
-                    logger.debug("Firing snapshot commit");
-                } finally {
-                    settingSnapshot = false;
-                }
-            }
+        logger.debug("Processing commit (\"" + e.getMessage() + "\")");
+
+        transactionCount--;
+ logger.debug("Decremented transaction counter to " + transactionCount);
+        if (transactionCount == 0) {
+            try {
+                settingSnapshot = true;
+ for (Entry<UserDefinedSQLType, PropertyChangeEvent> entry : upstreamTypeChangeEventMap.entrySet()) { + UserDefinedSQLType newValue = (UserDefinedSQLType) entry.getValue().getNewValue(); + UserDefinedSQLType source = (UserDefinedSQLType) entry.getKey(); + UserDefinedSQLType oldValue = (UserDefinedSQLType) entry.getValue().getOldValue();
+
+                    logger.debug("Replacing upstreamType with snapshot!");
+                    createSPObjectSnapshot(source, newValue);
+
+                    if (oldValue != null && source.isMagicEnabled()) {
+                        cleanupSnapshot(oldValue);
+                    }
+
+                    UserDefinedSQLType columnProxyType = source;
+                    addUpdateListener(columnProxyType.getUpstreamType());
+                }
+                upstreamTypeChangeEventMap.clear();
+                ((SPObject) e.getSource()).commit("snapshot commit");
+                logger.debug("Firing snapshot commit");
+            } finally {
+                settingSnapshot = false;
+            }
+ for (Map.Entry<UserDefinedSQLType, Integer> entry : typesToCleanup.entrySet()) {
+                for (int i = 0; i < entry.getValue(); i++) {
+                    cleanupSnapshot(entry.getKey());
+                }
+            }
+            typesToCleanup.clear();
         }
     }
 }

Reply via email to