From 7726e19ca0834ab1117003e08d35deea2c7ff020 Mon Sep 17 00:00:00 2001
From: Eike Stepper
Date: Wed, 7 Nov 2007 15:09:13 +0000
Subject: [209036] Offer RollbackTransactionDialog on save conflict
https://bugs.eclipse.org/bugs/show_bug.cgi?id=209036
---
plugins/org.eclipse.emf.cdo.ui/CDOClient1.launch | 72 ++++-----
.../ui/actions/RollbackTransactionAction.java | 74 ++-------
.../ui/dialogs/RollbackTransactionDialog.java | 178 +++++++++++++++++++++
.../emf/cdo/internal/ui/editor/CDOEditor.java | 16 +-
.../src/org/eclipse/emf/cdo/CDOObject.java | 2 +
.../src/org/eclipse/emf/cdo/CDOTransaction.java | 8 +-
.../eclipse/emf/internal/cdo/CDOAdapterImpl.java | 1 +
.../eclipse/emf/internal/cdo/CDOLegacyImpl.java | 10 ++
.../org/eclipse/emf/internal/cdo/CDOMetaImpl.java | 5 +
.../eclipse/emf/internal/cdo/CDOObjectImpl.java | 11 +-
.../eclipse/emf/internal/cdo/CDOStateMachine.java | 77 +++++++--
.../emf/internal/cdo/CDOTransactionImpl.java | 4 +-
12 files changed, 334 insertions(+), 124 deletions(-)
create mode 100644 plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/dialogs/RollbackTransactionDialog.java
diff --git a/plugins/org.eclipse.emf.cdo.ui/CDOClient1.launch b/plugins/org.eclipse.emf.cdo.ui/CDOClient1.launch
index 14101303f4..8f627f5aa8 100644
--- a/plugins/org.eclipse.emf.cdo.ui/CDOClient1.launch
+++ b/plugins/org.eclipse.emf.cdo.ui/CDOClient1.launch
@@ -14,8 +14,8 @@
-
+
@@ -24,7 +24,7 @@
-
+
@@ -39,8 +39,8 @@
-
+
@@ -53,8 +53,8 @@
-
+
@@ -64,11 +64,11 @@
-
+
-
+
@@ -78,15 +78,15 @@
-
+
-
+
@@ -98,8 +98,8 @@
-
+
@@ -113,11 +113,11 @@
-
+
-
+
@@ -126,17 +126,17 @@
-
-
+
+
-
-
+
+
@@ -147,26 +147,26 @@
-
+
-
+
-
+
-
+
-
+
@@ -177,11 +177,11 @@
-
+
-
+
@@ -207,8 +207,8 @@
-
+
@@ -220,12 +220,12 @@
-
+
-
+
@@ -246,11 +246,11 @@
-
+
-
+
@@ -266,16 +266,16 @@
-
+
-
+
-
+
@@ -293,16 +293,16 @@
-
+
-
+
-
+
@@ -313,10 +313,10 @@
-
-
+
+
@@ -334,8 +334,8 @@
-
+
diff --git a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/actions/RollbackTransactionAction.java b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/actions/RollbackTransactionAction.java
index 948367a88d..5fc3ca5b57 100644
--- a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/actions/RollbackTransactionAction.java
+++ b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/actions/RollbackTransactionAction.java
@@ -2,8 +2,9 @@ package org.eclipse.emf.cdo.internal.ui.actions;
import org.eclipse.emf.cdo.CDOTransaction;
import org.eclipse.emf.cdo.CDOView;
+import org.eclipse.emf.cdo.internal.ui.dialogs.RollbackTransactionDialog;
-import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.ui.IWorkbenchPage;
/**
@@ -15,6 +16,8 @@ public final class RollbackTransactionAction extends ViewAction
private static final String TOOL_TIP = "Rollback this transaction";
+ private boolean remote;
+
public RollbackTransactionAction(IWorkbenchPage page, CDOView view)
{
super(page, TITLE + INTERACTIVE, TOOL_TIP, null, view);
@@ -25,70 +28,25 @@ public final class RollbackTransactionAction extends ViewAction
protected void preRun() throws Exception
{
CDOTransaction transaction = (CDOTransaction)getView();
- int newResources = transaction.getNewResources().size();
- int newObjects = transaction.getNewObjects().size();
- int dirtyObjects = transaction.getDirtyObjects().size();
- int count = (newResources > 0 ? 1 : 0) + (newObjects > 0 ? 1 : 0) + (dirtyObjects > 0 ? 1 : 0);
-
- StringBuilder builder = new StringBuilder();
- builder.append("This transaction contains ");
- if (newResources > 0)
- {
- builder.append(newResources);
- builder.append(" new resource");
- if (newResources > 1)
- {
- builder.append("s");
- }
- }
-
- if (newObjects > 0)
- {
- if (newResources > 0)
- {
- if (count > 2)
- {
- builder.append(", ");
- }
- else
- {
- builder.append(" and ");
- }
- }
-
- builder.append(newObjects);
- builder.append(" new object");
- if (newObjects > 1)
- {
- builder.append("s");
- }
- }
-
- if (dirtyObjects > 0)
- {
- if (count > 1)
- {
- builder.append(" and ");
- }
-
- builder.append(dirtyObjects);
- builder.append(" dirty object");
- if (dirtyObjects > 1)
- {
- builder.append("s");
- }
- }
-
- builder.append(".\nAre you sure to rollback this transaction?");
- if (!MessageDialog.openQuestion(getShell(), TITLE, builder.toString()))
+ Dialog dialog = new RollbackTransactionDialog(getPage(), TITLE, "Choose how to rollback this transaction.",
+ transaction);
+ switch (dialog.open())
{
+ case RollbackTransactionDialog.REMOTE:
+ remote = true;
+ break;
+ case RollbackTransactionDialog.LOCAL:
+ remote = false;
+ break;
+ default:
cancel();
+ break;
}
}
@Override
protected void doRun() throws Exception
{
- getTransaction().rollback();
+ getTransaction().rollback(remote);
}
}
\ No newline at end of file
diff --git a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/dialogs/RollbackTransactionDialog.java b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/dialogs/RollbackTransactionDialog.java
new file mode 100644
index 0000000000..b626b0ab40
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/dialogs/RollbackTransactionDialog.java
@@ -0,0 +1,178 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2007 Eike Stepper, Germany.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ **************************************************************************/
+package org.eclipse.emf.cdo.internal.ui.dialogs;
+
+import org.eclipse.emf.cdo.CDOTransaction;
+
+import org.eclipse.net4j.util.ui.UIUtil;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchPage;
+
+/**
+ * @author Eike Stepper
+ */
+public class RollbackTransactionDialog extends TitleAreaDialog
+{
+ // public static final String TITLE = "Rollback Transaction";
+
+ public static final int REMOTE = CANCEL + 1;
+
+ public static final int LOCAL = CANCEL + 2;
+
+ private static final int REMOTE_ID = IDialogConstants.CLIENT_ID + REMOTE;
+
+ private static final int LOCAL_ID = IDialogConstants.CLIENT_ID + LOCAL;
+
+ private IWorkbenchPage page;
+
+ private String title;
+
+ private String description;
+
+ private CDOTransaction transaction;
+
+ public RollbackTransactionDialog(IWorkbenchPage page, String title, String description, CDOTransaction transaction)
+ {
+ super(new Shell(page.getWorkbenchWindow().getShell()));
+ this.page = page;
+ this.title = title;
+ this.description = description;
+ this.transaction = transaction;
+ setShellStyle(getShellStyle() | SWT.APPLICATION_MODAL | SWT.MAX | SWT.TITLE | SWT.RESIZE);
+ }
+
+ public IWorkbenchPage getPage()
+ {
+ return page;
+ }
+
+ @Override
+ protected void configureShell(Shell newShell)
+ {
+ super.configureShell(newShell);
+ newShell.setText(title);
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent)
+ {
+ Composite composite = new Composite((Composite)super.createDialogArea(parent), SWT.NONE);
+ composite.setLayoutData(UIUtil.createGridData());
+ composite.setLayout(new GridLayout(1, false));
+
+ setTitle(description);
+ setTitleImage(getShell().getDisplay().getSystemImage(SWT.ICON_QUESTION));
+
+ Label label = new Label(composite, SWT.NONE);
+ label.setText(formatMessage());
+ label.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
+
+ return composite;
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent)
+ {
+ createButton(parent, REMOTE_ID, "Remote Rollback", true);
+ createButton(parent, LOCAL_ID, "Local Rollback", false);
+ createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+ }
+
+ @Override
+ protected void buttonPressed(int buttonId)
+ {
+ if (buttonId == REMOTE_ID)
+ {
+ setReturnCode(REMOTE);
+ close();
+ }
+ else if (buttonId == LOCAL_ID)
+ {
+ setReturnCode(LOCAL);
+ close();
+ }
+ else
+ {
+ super.buttonPressed(buttonId);
+ }
+ }
+
+ protected String formatMessage()
+ {
+ int newResources = transaction.getNewResources().size();
+ int newObjects = transaction.getNewObjects().size();
+ int dirtyObjects = transaction.getDirtyObjects().size();
+ int count = (newResources > 0 ? 1 : 0) + (newObjects > 0 ? 1 : 0) + (dirtyObjects > 0 ? 1 : 0);
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("This transaction contains ");
+ if (newResources > 0)
+ {
+ builder.append(newResources);
+ builder.append(" new resource");
+ if (newResources > 1)
+ {
+ builder.append("s");
+ }
+ }
+
+ if (newObjects > 0)
+ {
+ if (newResources > 0)
+ {
+ if (count > 2)
+ {
+ builder.append(", ");
+ }
+ else
+ {
+ builder.append(" and ");
+ }
+ }
+
+ builder.append(newObjects);
+ builder.append(" new object");
+ if (newObjects > 1)
+ {
+ builder.append("s");
+ }
+ }
+
+ if (dirtyObjects > 0)
+ {
+ if (count > 1)
+ {
+ builder.append(" and ");
+ }
+
+ builder.append(dirtyObjects);
+ builder.append(" dirty object");
+ if (dirtyObjects > 1)
+ {
+ builder.append("s");
+ }
+ }
+
+ builder.append(".\nBe careful, rolling back to local state can result\n"
+ + "in visible state that is different from the remote state!");
+ builder.append("\n\nAre you sure to rollback this transaction?");
+ return builder.toString();
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOEditor.java b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOEditor.java
index 0129734d6f..30c8ecc133 100644
--- a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOEditor.java
+++ b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOEditor.java
@@ -12,6 +12,7 @@ import org.eclipse.emf.cdo.CDOView;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.internal.ui.SharedIcons;
import org.eclipse.emf.cdo.internal.ui.bundle.OM;
+import org.eclipse.emf.cdo.internal.ui.dialogs.RollbackTransactionDialog;
import org.eclipse.emf.cdo.internal.ui.views.CDOEventHandler;
import org.eclipse.emf.cdo.protocol.model.CDOClass;
import org.eclipse.emf.cdo.protocol.model.CDOPackage;
@@ -82,6 +83,7 @@ import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.viewers.ISelection;
@@ -1586,13 +1588,23 @@ public class CDOEditor extends MultiPageEditorPart implements IEditingDomainProv
}
catch (final TransactionException exception)
{
- OM.LOG.error(exception);
final Shell shell = getSite().getShell();
shell.getDisplay().syncExec(new Runnable()
{
public void run()
{
- MessageDialog.openError(shell, "Transaction Error", exception.getMessage());
+ CDOTransaction transaction = (CDOTransaction)view;
+ Dialog dialog = new RollbackTransactionDialog(getEditorSite().getPage(), "Transaction Error",
+ exception.getMessage(), transaction);
+ switch (dialog.open())
+ {
+ case RollbackTransactionDialog.REMOTE:
+ transaction.rollback(true);
+ break;
+ case RollbackTransactionDialog.LOCAL:
+ transaction.rollback(false);
+ break;
+ }
}
});
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOObject.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOObject.java
index 567b0dc153..f38fbe42a2 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOObject.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOObject.java
@@ -33,4 +33,6 @@ public interface CDOObject extends EObject
public CDOResource cdoResource();
public CDORevision cdoRevision();
+
+ public boolean cdoRefresh(boolean force);
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java
index d869e63fc6..ee4a56bdae 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java
@@ -38,15 +38,9 @@ public interface CDOTransaction extends CDOView
public CDOObject newInstance(CDOClass cdoClass);
- /**
- * @see CDOTransaction#commit()
- */
public void commit() throws TransactionException;
- /**
- * @see CDOTransaction#rollback()
- */
- public void rollback();
+ public void rollback(boolean remote);
public void addHandler(CDOTransactionHandler handler);
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOAdapterImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOAdapterImpl.java
index 0de8c82b2d..703cc18cb3 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOAdapterImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOAdapterImpl.java
@@ -22,6 +22,7 @@ public class CDOAdapterImpl extends CDOLegacyImpl
{
}
+ @Override
public boolean isAdapterForType(Object type)
{
return type == CDOAdapterImpl.class;
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOLegacyImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOLegacyImpl.java
index fcf62e68d8..0a79ec6950 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOLegacyImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOLegacyImpl.java
@@ -101,6 +101,16 @@ public abstract class CDOLegacyImpl extends CDOWrapperImpl implements Adapter.In
return view;
}
+ public boolean cdoRefresh(boolean force)
+ {
+ return CDOStateMachine.INSTANCE.refresh(this, force);
+ }
+
+ public boolean isAdapterForType(Object type)
+ {
+ return false;
+ }
+
public CDOState cdoInternalSetState(CDOState state)
{
if (this.state != state)
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOMetaImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOMetaImpl.java
index 2efa0676a2..4aa4a5de4e 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOMetaImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOMetaImpl.java
@@ -50,6 +50,11 @@ public class CDOMetaImpl extends CDOWrapperImpl
throw new UnsupportedOperationException();
}
+ public boolean cdoRefresh(boolean force)
+ {
+ throw new UnsupportedOperationException();
+ }
+
public boolean cdoTransient()
{
return false;
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java
index c3ea214032..c5f47a9a70 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java
@@ -20,9 +20,6 @@ import org.eclipse.emf.cdo.internal.protocol.revision.CDORevisionImpl;
import org.eclipse.emf.cdo.protocol.CDOID;
import org.eclipse.emf.cdo.protocol.revision.CDORevision;
-import org.eclipse.net4j.internal.util.om.trace.ContextTracer;
-import org.eclipse.net4j.util.ImplementationError;
-
import org.eclipse.emf.common.util.BasicEMap;
import org.eclipse.emf.common.util.ECollections;
import org.eclipse.emf.common.util.EList;
@@ -43,6 +40,9 @@ import org.eclipse.emf.internal.cdo.bundle.OM;
import org.eclipse.emf.internal.cdo.util.FSMUtil;
import org.eclipse.emf.internal.cdo.util.ModelUtil;
+import org.eclipse.net4j.internal.util.om.trace.ContextTracer;
+import org.eclipse.net4j.util.ImplementationError;
+
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@@ -104,6 +104,11 @@ public class CDOObjectImpl extends EStoreEObjectImpl implements InternalCDOObjec
return resource;
}
+ public boolean cdoRefresh(boolean force)
+ {
+ return CDOStateMachine.INSTANCE.refresh(this, force);
+ }
+
public void cdoInternalSetID(CDOID id)
{
if (id == null)
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java
index 74889bd408..f5a50793aa 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java
@@ -48,63 +48,70 @@ public final class CDOStateMachine extends FiniteStateMachine
+ private final class RollbackTransition implements ITransition
{
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object NULL)
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Boolean remote)
{
CDOViewImpl view = (CDOViewImpl)object.cdoView();
@@ -323,7 +338,7 @@ public final class CDOStateMachine extends FiniteStateMachine
+ private final class RefreshTransition implements ITransition
+ {
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, boolean[] forceAndResult)
+ {
+ if (forceAndResult[0])
+ {
+ }
+
+ changeState(object, CDOState.CLEAN);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private class InvalidateTransition implements ITransition
{
public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Long timeStamp)
{
- ((CDORevisionImpl)object.cdoRevision()).setRevised(timeStamp - 1);
+ reviseObject(object, timeStamp);
changeState(object, CDOState.PROXY);
}
+
+ protected void reviseObject(InternalCDOObject object, Long timeStamp)
+ {
+ CDORevisionImpl revision = (CDORevisionImpl)object.cdoRevision();
+ revision.setRevised(timeStamp - 1);
+
+ if (revision.isTransactional())
+ {
+ CDOViewImpl view = (CDOViewImpl)object.cdoView();
+ revision = view.getRevision(object.cdoID());
+ revision.setRevised(timeStamp - 1);
+ }
+ }
}
/**
* @author Eike Stepper
*/
- private final class ConflictTransition implements ITransition
+ private final class ConflictTransition extends InvalidateTransition
{
+ @Override
public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Long timeStamp)
{
+ reviseObject(object, timeStamp);
CDOViewImpl view = (CDOViewImpl)object.cdoView();
CDOTransactionImpl transaction = view.toTransaction();
transaction.setConflict(object);
@@ -452,5 +497,5 @@ public final class CDOStateMachine extends FiniteStateMachine