Revision: 3832
Author: [email protected]
Date: Wed Aug 4 07:32:07 2010
Log: Added a use count to a snapshot similar to the reference count in
SQLColumn to track how many columns are using a snapshot. When a snapshot
is no longer being used it will be removed from the project automatically.
http://code.google.com/p/power-architect/source/detail?r=3832
Modified:
/trunk/src/main/java/ca/sqlpower/architect/SPObjectSnapshotHierarchyListener.java
=======================================
---
/trunk/src/main/java/ca/sqlpower/architect/SPObjectSnapshotHierarchyListener.java
Tue Aug 3 13:38:41 2010
+++
/trunk/src/main/java/ca/sqlpower/architect/SPObjectSnapshotHierarchyListener.java
Wed Aug 4 07:32:07 2010
@@ -20,6 +20,8 @@
package ca.sqlpower.architect;
import java.beans.PropertyChangeEvent;
+import java.util.HashMap;
+import java.util.Map;
import ca.sqlpower.architect.enterprise.ArchitectClientSideSession;
import ca.sqlpower.architect.enterprise.DomainCategory;
@@ -47,6 +49,15 @@
*/
private final ArchitectClientSideSession session;
+ /**
+ * 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.
+ * This lets us remove these listeners when the type or domain is being
+ * removed from the system.
+ */
+ private final Map<SPObjectSnapshot<?>, SPObjectSnapshotUpdateListener>
listenerMap =
+ new HashMap<SPObjectSnapshot<?>, SPObjectSnapshotUpdateListener>();
+
public SPObjectSnapshotHierarchyListener(ArchitectClientSideSession
session) {
this.session = session;
}
@@ -71,11 +82,16 @@
e.getChild().removeSPListener(this);
for (SQLColumn col :
e.getChild().getChildren(SQLColumn.class)) {
col.getUserDefinedSQLType().removeSPListener(this);
- cleanupSnapshot();
+ if
(col.getUserDefinedSQLType().isMagicEnabled()) {
+
cleanupSnapshot(col.getUserDefinedSQLType().getUpstreamType());
+ }
}
} else if (e.getChild() instanceof SQLColumn) {
- ((SQLColumn)
e.getChild()).getUserDefinedSQLType().removeSPListener(this);
- cleanupSnapshot();
+ UserDefinedSQLType colType = ((SQLColumn)
e.getChild()).getUserDefinedSQLType();
+ colType.removeSPListener(this);
+ if (colType.isMagicEnabled()) {
+ cleanupSnapshot(colType.getUpstreamType());
+ }
}
}
@@ -88,7 +104,9 @@
createSPObjectSnapshot((UserDefinedSQLType) e.getSource(),
(UserDefinedSQLType) e.getNewValue());
}
- cleanupSnapshot();
+ if (e.getOldValue() != null && ((UserDefinedSQLType)
e.getSource()).isMagicEnabled()) {
+ cleanupSnapshot((UserDefinedSQLType) e.getOldValue());
+ }
UserDefinedSQLType columnProxyType =
(UserDefinedSQLType) e.getSource();
addUpdateListener(columnProxyType);
@@ -97,13 +115,62 @@
/**
* This method will remove the snapshot and the listener on the
system's
- * type if the snapshot is no longer in use.
+ * type if the snapshot is no longer in use. Only call this method if
magic
+ * is enabled.
+ *
+ * @param typeRemoved
+ * The snapshot type that is a child of the workspace that
is/was
+ * referenced by the column's type proxy that is being
removed.
+ * Either the column is being removed or the type is
changing.
*/
- private void cleanupSnapshot() {
- //find if the snapshot is being referenced by any of the columns in
the workspace.
- //if it is not referenced remove it from the project
+ private void cleanupSnapshot(UserDefinedSQLType typeRemoved) {
+ //The first type set will be from the system workspace and will not
+ //have a snapshot, then the snapshot will replace the one set from
the system.
+ if (typeRemoved.getParent() == session.getSystemWorkspace() ||
+ (typeRemoved.getParent() instanceof DomainCategory &&
+ typeRemoved.getParent().getParent() ==
session.getSystemWorkspace())) return;
+
+ UserDefinedSQLTypeSnapshot udtSnapshot = null;
+ for (SPObjectSnapshot<?> snapshot :
session.getWorkspace().getSPObjectSnapshots()) {
+ if (snapshot.getSPObject().equals(typeRemoved)) {
+ udtSnapshot = (UserDefinedSQLTypeSnapshot) snapshot;
+
udtSnapshot.setSnapshotUseCount(udtSnapshot.getSnapshotUseCount() - 1);
+ if (udtSnapshot.getSnapshotUseCount() > 0) return;
+ break;
+ }
+ }
+ if (udtSnapshot == null) throw new NullPointerException("The type " +
typeRemoved +
+ " is a snapshot type but does not have a snapshot object in
the project.");
+
+ //If we are here the snapshot is no longer in use.
+ session.getWorkspace().removeSPObjectSnapshot(udtSnapshot);
+ try {
+ if (udtSnapshot.isDomainSnapshot()) {
+ DomainCategory cat = (DomainCategory)
udtSnapshot.getSPObject().getParent();
+ cat.removeChild(udtSnapshot.getSPObject());
+ //TODO decrement upstream type of the domain, remove if 0
+
+ if (cat.getChildren().size() == 0) {
+ for (SPObjectSnapshot<?> snapshot :
session.getWorkspace().getSPObjectSnapshots()) {
+ if (snapshot.getSPObject().equals(cat)) {
+ session.getWorkspace().removeChild(snapshot);
+ session.getWorkspace().removeChild(cat);
+ break;
+ }
+ }
+ }
+ } else {
+
session.getWorkspace().removeChild(udtSnapshot.getSPObject());
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
//find its upstream type and remove its listener.
- //XXX Need to remove the old listener
+ UserDefinedSQLType systemType =
session.findSystemTypeFromSnapshot(udtSnapshot);
+ SQLPowerUtils.unlistenToHierarchy(systemType,
listenerMap.get(udtSnapshot));
+
+ //handle domain categories and domain's upstream type as well.
}
/**
@@ -129,12 +196,16 @@
}
UserDefinedSQLType systemType =
session.findSystemTypeFromSnapshot(snapshot);
- SQLPowerUtils.listenToHierarchy(systemType, new
SPObjectSnapshotUpdateListener(snapshot));
+ SPObjectSnapshotUpdateListener udtSnapshotListener = new
SPObjectSnapshotUpdateListener(snapshot);
+ SQLPowerUtils.listenToHierarchy(systemType, udtSnapshotListener);
+ listenerMap.put(snapshot, udtSnapshotListener);
if (systemType.getParent() instanceof DomainCategory) {
DomainCategory category = (DomainCategory)
systemType.getParent();
for (SPObjectSnapshot<?> categorySnapshot :
session.getWorkspace().getSPObjectSnapshots()) {
if
(categorySnapshot.getOriginalUUID().equals(category.getUUID())) {
- category.addSPListener(new
SPObjectSnapshotUpdateListener(categorySnapshot));
+ SPObjectSnapshotUpdateListener
categorySnapshotListener = new
SPObjectSnapshotUpdateListener(categorySnapshot);
+ category.addSPListener(categorySnapshotListener);
+ listenerMap.put(categorySnapshot,
categorySnapshotListener);
break;
}
}
@@ -159,6 +230,7 @@
session.getWorkspace().addChild(upstreamSnapshot, 0);
session.getWorkspace().addChild(upstreamSnapshot.getSPObject(), 0);
snapshot = new UserDefinedSQLTypeSnapshot(upstreamType,
systemRevision, isDomainSnapshot, upstreamSnapshot);
+ //TODO increment upstream type use count and check if one
exists already instead of always creating a new one.
} else {
snapshot = new UserDefinedSQLTypeSnapshot(upstreamType,
systemRevision, isDomainSnapshot);
}
@@ -174,6 +246,18 @@
session.getWorkspace().addChild(snapshot.getSPObject(), 0);
}
typeProxy.setUpstreamType(snapshot.getSPObject());
+ snapshot.setSnapshotUseCount(1);
+ } else if (upstreamTypeParent != null &&
+ (upstreamTypeParent.equals(session.getWorkspace()) ||
+ (upstreamTypeParent instanceof DomainCategory &&
+
upstreamTypeParent.getParent().equals(session.getWorkspace())))) {
+ for (SPObjectSnapshot<?> snapshot :
session.getWorkspace().getSPObjectSnapshots()) {
+ if (snapshot.getSPObject().equals(upstreamType)) {
+ UserDefinedSQLTypeSnapshot udtSnapshot =
(UserDefinedSQLTypeSnapshot) snapshot;
+
udtSnapshot.setSnapshotUseCount(udtSnapshot.getSnapshotUseCount() + 1);
+ return;
+ }
+ }
}
}
}