Revision: 3887
Author: [email protected]
Date: Mon Aug 16 11:37:28 2010
Log: NEW - bug 2914: Reverse engineering can bring user out of sync with
server
http://trillian.sqlpower.ca/bugzilla/show_bug.cgi?id=2914
I believe this should fix the issue with reverse engineering. The
NetworkConflictResolver, on flush(), will decode the JSON and notify all of
the UpdateListeners that an update is going through. This call needs to
occur on a foreground thread because if a component is being dragged in the
PlayPen, it needs to be interrupted and rolled back correctly before
applying the change from the server.
The UpdateListener for PlayPenComponent now rolls back the drag transaction
on a preUpdatePerformed call instead of an updatePerformed call, and
removes the FloatingContainerPaneListeners from the PlayPen.
http://code.google.com/p/power-architect/source/detail?r=3887
Modified:
/trunk/src/main/java/ca/sqlpower/architect/enterprise/NetworkConflictResolver.java
/trunk/src/main/java/ca/sqlpower/architect/swingui/PlayPen.java
/trunk/src/main/java/ca/sqlpower/architect/swingui/PlayPenComponent.java
=======================================
---
/trunk/src/main/java/ca/sqlpower/architect/enterprise/NetworkConflictResolver.java
Thu Aug 12 11:32:38 2010
+++
/trunk/src/main/java/ca/sqlpower/architect/enterprise/NetworkConflictResolver.java
Mon Aug 16 11:37:28 2010
@@ -264,8 +264,8 @@
throw new
FriendlyRuntimeSPPersistenceException(response.getBody());
}
- String json;
- int newRev;
+ final String json;
+ final int newRev;
try {
JSONObject jsonObject = new
JSONObject(response.getBody());
json = jsonObject.getString("data");
@@ -276,34 +276,41 @@
// Try to create inboundPersistedLists for comparison with
the outbound. These will be used
// for special case collision detection.
fillInboundPersistedLists(json);
- // Try to apply update
- decodeMessage(json, newRev);
- // We need an additional step here for checking for
special case conflicts
- List<ConflictMessage> conflicts = detectConflicts();
- if (conflicts.size() == 0) {
- // Try to return the persisted objects to their state
pre-update.
- try {
-
SPSessionPersister.redoForSession(session.getWorkspace(),
- new
LinkedList<PersistedSPObject>(outboundObjectsToAdd.values()),
- outboundPropertiesToChange,
- new
LinkedList<RemovedObjectEntry>(outboundObjectsToRemove.values()),
converter);
- // We want to re-send our changes, but only if we
were able to restore them
- flush(true);
- } catch (Exception ex) {
- throw new RuntimeException("Reflush failed on
rollforward", ex);
- }
- } else {
- String message = "";
- message += "Your changes have been discarded due to a
conflict between you and another user: \n";
- for (int i = 0; i < MAX_CONFLICTS_TO_DISPLAY && i <
conflicts.size(); i++) {
- message += conflicts.get(i).getMessage() + "\n";
- }
- session.createUserPrompter(message,
- UserPromptType.MESSAGE,
- UserPromptOptions.OK,
- UserPromptResponse.OK,
- "OK", "OK").promptUser("");
- }
+
+ session.runInForeground(new Runnable() {
+
+ @Override
+ public void run() {
+ // Try to apply update
+ decodeMessage(json, newRev);
+ // We need an additional step here for checking
for special case conflicts
+ List<ConflictMessage> conflicts =
detectConflicts();
+ if (conflicts.size() == 0) {
+ // Try to return the persisted objects to
their state pre-update.
+ try {
+
SPSessionPersister.redoForSession(session.getWorkspace(),
+ new
LinkedList<PersistedSPObject>(outboundObjectsToAdd.values()),
+ outboundPropertiesToChange,
+ new
LinkedList<RemovedObjectEntry>(outboundObjectsToRemove.values()),
converter);
+ // We want to re-send our changes, but
only if we were able to restore them
+ flush(true);
+ } catch (Exception ex) {
+ throw new RuntimeException("Reflush failed
on rollforward", ex);
+ }
+ } else {
+ String message = "";
+ message += "Your changes have been discarded
due to a conflict between you and another user: \n";
+ for (int i = 0; i < MAX_CONFLICTS_TO_DISPLAY
&& i < conflicts.size(); i++) {
+ message += conflicts.get(i).getMessage()
+ "\n";
+ }
+ session.createUserPrompter(message,
+ UserPromptType.MESSAGE,
+ UserPromptOptions.OK,
+ UserPromptResponse.OK,
+ "OK", "OK").promptUser("");
+ }
+ }
+ });
}
} finally {
if (monitor != null) {
=======================================
--- /trunk/src/main/java/ca/sqlpower/architect/swingui/PlayPen.java Wed Aug
11 11:27:52 2010
+++ /trunk/src/main/java/ca/sqlpower/architect/swingui/PlayPen.java Mon Aug
16 11:37:28 2010
@@ -2637,8 +2637,6 @@
pp.addMouseListener(this); // the click that ends this
operation
pp.cursorManager.tableDragStarted();
- pp.startCompoundEdit("Move " + ppc.getName());
//$NON-NLS-1$
- pp.getContentPane().begin("Move " + ppc.getName());
}
public void mouseMoved(MouseEvent e) {
@@ -2685,23 +2683,17 @@
*/
public void mouseReleased(MouseEvent e) {
cleanup();
+ // normalize changes to table panes are part
+ // of this compound edit, refer to bug 1592.
+ pp.normalize();
+ pp.revalidate();
}
protected void cleanup() {
- try {
- pp.cursorManager.placeModeFinished();
- pp.cursorManager.tableDragFinished();
- pp.removeMouseMotionListener(this);
- pp.removeMouseListener(this);
-
- // normalize changes to table panes are part
- // of this compound edit, refer to bug 1592.
- pp.normalize();
- pp.revalidate();
- } finally {
- pp.endCompoundEdit("Ending move for table "+ppc.getName());
//$NON-NLS-1$
- pp.getContentPane().commit("Ending move for table
"+ppc.getName());
- }
+ pp.cursorManager.placeModeFinished();
+ pp.cursorManager.tableDragFinished();
+ pp.removeMouseMotionListener(this);
+ pp.removeMouseListener(this);
}
}
=======================================
---
/trunk/src/main/java/ca/sqlpower/architect/swingui/PlayPenComponent.java
Tue Aug 10 14:52:03 2010
+++
/trunk/src/main/java/ca/sqlpower/architect/swingui/PlayPenComponent.java
Mon Aug 16 11:37:28 2010
@@ -102,9 +102,6 @@
*/
private final UpdateListener updateWhileMovingListener = new
UpdateListener() {
public boolean updatePerformed(NetworkConflictResolver resolver) {
- if (isBeingDragged) {
- doneDragging(false);
- }
return true;
}
@@ -113,7 +110,9 @@
}
public void preUpdatePerformed(NetworkConflictResolver resolver) {
- //do nothing
+ if (isBeingDragged) {
+ doneDragging(false);
+ }
}
public void workspaceDeleted() {
@@ -650,7 +649,8 @@
if (getPlayPen().getSession().isEnterpriseSession()) {
getPlayPen().getSession().getEnterpriseSession().getUpdater().addListener(updateWhileMovingListener);
}
- begin("Dragging " + this);
+ getParent().begin("Dragging " + this);
+ getPlayPen().startCompoundEdit("Dragging " + this);
} else {
throw new IllegalStateException("Component is already in the
middle of a drag");
}
@@ -669,16 +669,18 @@
if (isBeingDragged) {
isBeingDragged = false;
if (ok) {
- commit();
+ getPlayPen().endCompoundEdit("Done dragging " + this);
+ getParent().commit("Done dragging " + this);
} else {
- rollback("Update received while dragging");
-
- // We need to emulate a mouse released event on all the
- // FloatingContainerPaneListeners since the following
message
- // dialog prompt interrupts the drag.
+ getPlayPen().endCompoundEdit("Update received while
dragging.");
+ getParent().rollback("Update received while dragging");
+
+ // We need to cleanup all of the
FloatingContainerPaneListeners
+ // on the PlayPen because we no longer want to keep track
+ // of dragging.
for (MouseMotionListener l :
getPlayPen().getMouseMotionListeners()) {
if (l instanceof FloatingContainerPaneListener) {
- ((FloatingContainerPaneListener)
l).mouseReleased(null);
+ ((FloatingContainerPaneListener) l).cleanup();
}
}