[398218] fix problems with asynchronous events on UI thread; leave
Structure page tree icons to be disposed by the Structure view; copy
only a *specified* join table when converting orm.xml mappings; prevent
"updates" from executing while modifying orm.xml from Structure view;
add Structure view listener to workbench window's JPA selection model to
"activate" it when there is no Details view
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/AbstractItemExtendedLabelProvider.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/AbstractItemExtendedLabelProvider.java
index 42b0c33..33fc572 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/AbstractItemExtendedLabelProvider.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/AbstractItemExtendedLabelProvider.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2012 Oracle. All rights reserved.
+ * Copyright (c) 2008, 2013 Oracle. 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.
@@ -120,10 +120,8 @@
 
 	protected void disposeImageDescriptorModel() {
 		if (this.imageDescriptorModel != null) {
-			ImageDescriptor descriptor = this.imageDescriptorModel.getValue();
-			if (descriptor != null) {
-				this.manager.getResourceManager().destroyImage(descriptor);
-			}
+			// for now, leave the image in the resource manager cache
+			// to be disposed when the view is disposed
 			this.disengageImageDescriptorModel();
 			this.imageDescriptorModel = null;
 		}
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTCollectionChangeListenerWrapper.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTCollectionChangeListenerWrapper.java
index 3f5ce0e..c0589d1 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTCollectionChangeListenerWrapper.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTCollectionChangeListenerWrapper.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2012 Oracle. All rights reserved.
+ * Copyright (c) 2007, 2013 Oracle. 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.
@@ -9,11 +9,14 @@
  ******************************************************************************/
 package org.eclipse.jpt.common.ui.internal.listeners;
 
+import org.eclipse.jpt.common.ui.internal.plugin.JptCommonUiPlugin;
 import org.eclipse.jpt.common.ui.internal.swt.widgets.DisplayTools;
 import org.eclipse.jpt.common.utility.internal.RunnableAdapter;
+import org.eclipse.jpt.common.utility.internal.collection.SynchronizedQueue;
 import org.eclipse.jpt.common.utility.model.event.CollectionAddEvent;
 import org.eclipse.jpt.common.utility.model.event.CollectionChangeEvent;
 import org.eclipse.jpt.common.utility.model.event.CollectionClearEvent;
+import org.eclipse.jpt.common.utility.model.event.CollectionEvent;
 import org.eclipse.jpt.common.utility.model.event.CollectionRemoveEvent;
 import org.eclipse.jpt.common.utility.model.listener.CollectionChangeListener;
 
@@ -27,6 +30,8 @@
 	implements CollectionChangeListener
 {
 	private final CollectionChangeListener listener;
+	private final SynchronizedQueue<CollectionEvent> events = new SynchronizedQueue<CollectionEvent>();
+
 
 	public SWTCollectionChangeListenerWrapper(CollectionChangeListener listener) {
 		super();
@@ -37,91 +42,57 @@
 	}
 
 	public void itemsAdded(CollectionAddEvent event) {
-		this.execute(new ItemsAddedRunnable(event));
-	}
-
-	/* CU private */ class ItemsAddedRunnable
-		extends RunnableAdapter
-	{
-		private final CollectionAddEvent event;
-		ItemsAddedRunnable(CollectionAddEvent event) {
-			super();
-			this.event = event;
-		}
-		@Override
-		public void run() {
-			SWTCollectionChangeListenerWrapper.this.itemsAdded_(this.event);
-		}
-	}
-
-	void itemsAdded_(CollectionAddEvent event) {
-		this.listener.itemsAdded(event);
+		this.events.enqueue(event);
+		this.execute(new ForwardEventsRunnable());
 	}
 
 	public void itemsRemoved(CollectionRemoveEvent event) {
-		this.execute(new ItemsRemovedRunnable(event));
-	}
-
-	/* CU private */ class ItemsRemovedRunnable
-		extends RunnableAdapter
-	{
-		private final CollectionRemoveEvent event;
-		ItemsRemovedRunnable(CollectionRemoveEvent event) {
-			super();
-			this.event = event;
-		}
-		@Override
-		public void run() {
-			SWTCollectionChangeListenerWrapper.this.itemsRemoved_(this.event);
-		}
-	}
-
-	void itemsRemoved_(CollectionRemoveEvent event) {
-		this.listener.itemsRemoved(event);
+		this.events.enqueue(event);
+		this.execute(new ForwardEventsRunnable());
 	}
 
 	public void collectionCleared(CollectionClearEvent event) {
-		this.execute(new CollectionClearedRunnable(event));
-	}
-
-	/* CU private */ class CollectionClearedRunnable
-		extends RunnableAdapter
-	{
-		private final CollectionClearEvent event;
-		CollectionClearedRunnable(CollectionClearEvent event) {
-			super();
-			this.event = event;
-		}
-		@Override
-		public void run() {
-			SWTCollectionChangeListenerWrapper.this.collectionCleared_(this.event);
-		}
-	}
-
-	void collectionCleared_(CollectionClearEvent event) {
-		this.listener.collectionCleared(event);
+		this.events.enqueue(event);
+		this.execute(new ForwardEventsRunnable());
 	}
 
 	public void collectionChanged(CollectionChangeEvent event) {
-		this.execute(new CollectionChangedRunnable(event));
+		this.events.enqueue(event);
+		this.execute(new ForwardEventsRunnable());
 	}
 
-	/* CU private */ class CollectionChangedRunnable
+	/* CU private */ class ForwardEventsRunnable
 		extends RunnableAdapter
 	{
-		private final CollectionChangeEvent event;
-		CollectionChangedRunnable(CollectionChangeEvent event) {
-			super();
-			this.event = event;
-		}
 		@Override
 		public void run() {
-			SWTCollectionChangeListenerWrapper.this.collectionChanged_(this.event);
+			SWTCollectionChangeListenerWrapper.this.forwardEvents();
 		}
 	}
 
-	void collectionChanged_(CollectionChangeEvent event) {
-		this.listener.collectionChanged(event);
+	void forwardEvents() {
+		for (CollectionEvent event : this.events.drain()) {
+			try {
+				this.forwardEvent(event);
+			} catch (RuntimeException ex) {
+				JptCommonUiPlugin.instance().logError(ex);
+			}
+		}
+	}
+
+	private void forwardEvent(CollectionEvent event) {
+		if (event instanceof CollectionAddEvent) {
+			this.listener.itemsAdded((CollectionAddEvent) event);
+		}
+		else if (event instanceof CollectionRemoveEvent) {
+			this.listener.itemsRemoved((CollectionRemoveEvent) event);
+		}
+		else if (event instanceof CollectionClearEvent) {
+			this.listener.collectionCleared((CollectionClearEvent) event);
+		}
+		else if (event instanceof CollectionChangeEvent) {
+			this.listener.collectionChanged((CollectionChangeEvent) event);
+		}
 	}
 
 	/**
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTListChangeListenerWrapper.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTListChangeListenerWrapper.java
index 5135ee8..16f9ee6 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTListChangeListenerWrapper.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTListChangeListenerWrapper.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2012 Oracle. All rights reserved.
+ * Copyright (c) 2007, 2013 Oracle. 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.
@@ -9,11 +9,14 @@
  ******************************************************************************/
 package org.eclipse.jpt.common.ui.internal.listeners;
 
+import org.eclipse.jpt.common.ui.internal.plugin.JptCommonUiPlugin;
 import org.eclipse.jpt.common.ui.internal.swt.widgets.DisplayTools;
 import org.eclipse.jpt.common.utility.internal.RunnableAdapter;
+import org.eclipse.jpt.common.utility.internal.collection.SynchronizedQueue;
 import org.eclipse.jpt.common.utility.model.event.ListAddEvent;
 import org.eclipse.jpt.common.utility.model.event.ListChangeEvent;
 import org.eclipse.jpt.common.utility.model.event.ListClearEvent;
+import org.eclipse.jpt.common.utility.model.event.ListEvent;
 import org.eclipse.jpt.common.utility.model.event.ListMoveEvent;
 import org.eclipse.jpt.common.utility.model.event.ListRemoveEvent;
 import org.eclipse.jpt.common.utility.model.event.ListReplaceEvent;
@@ -29,6 +32,8 @@
 	implements ListChangeListener
 {
 	private final ListChangeListener listener;
+	private final SynchronizedQueue<ListEvent> events = new SynchronizedQueue<ListEvent>();
+
 
 	public SWTListChangeListenerWrapper(ListChangeListener listener) {
 		super();
@@ -39,135 +44,73 @@
 	}
 
 	public void itemsAdded(ListAddEvent event) {
-		this.execute(new ItemsAddedRunnable(event));
-	}
-
-	/* CU private */ class ItemsAddedRunnable
-		extends RunnableAdapter
-	{
-		private final ListAddEvent event;
-		ItemsAddedRunnable(ListAddEvent event) {
-			super();
-			this.event = event;
-		}
-		@Override
-		public void run() {
-			SWTListChangeListenerWrapper.this.itemsAdded_(this.event);
-		}
-	}
-
-	void itemsAdded_(ListAddEvent event) {
-		this.listener.itemsAdded(event);
+		this.events.enqueue(event);
+		this.execute(new ForwardEventsRunnable());
 	}
 
 	public void itemsRemoved(ListRemoveEvent event) {
-		this.execute(new ItemsRemovedRunnable(event));
-	}
-
-	/* CU private */ class ItemsRemovedRunnable
-		extends RunnableAdapter
-	{
-		private final ListRemoveEvent event;
-		ItemsRemovedRunnable(ListRemoveEvent event) {
-			super();
-			this.event = event;
-		}
-		@Override
-		public void run() {
-			SWTListChangeListenerWrapper.this.itemsRemoved_(this.event);
-		}
-	}
-
-	void itemsRemoved_(ListRemoveEvent event) {
-		this.listener.itemsRemoved(event);
+		this.events.enqueue(event);
+		this.execute(new ForwardEventsRunnable());
 	}
 
 	public void itemsMoved(ListMoveEvent event) {
-		this.execute(new ItemsMovedRunnable(event));
-	}
-
-	/* CU private */ class ItemsMovedRunnable
-		extends RunnableAdapter
-	{
-		private final ListMoveEvent event;
-		ItemsMovedRunnable(ListMoveEvent event) {
-			super();
-			this.event = event;
-		}
-		@Override
-		public void run() {
-			SWTListChangeListenerWrapper.this.itemsMoved_(this.event);
-		}
-	}
-
-	void itemsMoved_(ListMoveEvent event) {
-		this.listener.itemsMoved(event);
+		this.events.enqueue(event);
+		this.execute(new ForwardEventsRunnable());
 	}
 
 	public void itemsReplaced(ListReplaceEvent event) {
-		this.execute(new ItemsReplacedRunnable(event));
-	}
-
-	/* CU private */ class ItemsReplacedRunnable
-		extends RunnableAdapter
-	{
-		private final ListReplaceEvent event;
-		ItemsReplacedRunnable(ListReplaceEvent event) {
-			super();
-			this.event = event;
-		}
-		@Override
-		public void run() {
-			SWTListChangeListenerWrapper.this.itemsReplaced_(this.event);
-		}
+		this.events.enqueue(event);
+		this.execute(new ForwardEventsRunnable());
 	}
 
 	public void listCleared(ListClearEvent event) {
-		this.execute(new ListClearedRunnable(event));
-	}
-
-	void itemsReplaced_(ListReplaceEvent event) {
-		this.listener.itemsReplaced(event);
-	}
-
-	/* CU private */ class ListClearedRunnable
-		extends RunnableAdapter
-	{
-		private final ListClearEvent event;
-		ListClearedRunnable(ListClearEvent event) {
-			super();
-			this.event = event;
-		}
-		@Override
-		public void run() {
-			SWTListChangeListenerWrapper.this.listCleared_(this.event);
-		}
-	}
-
-	void listCleared_(ListClearEvent event) {
-		this.listener.listCleared(event);
+		this.events.enqueue(event);
+		this.execute(new ForwardEventsRunnable());
 	}
 
 	public void listChanged(ListChangeEvent event) {
-		this.execute(new ListChangedRunnable(event));
+		this.events.enqueue(event);
+		this.execute(new ForwardEventsRunnable());
 	}
 
-	/* CU private */ class ListChangedRunnable
+	/* CU private */ class ForwardEventsRunnable
 		extends RunnableAdapter
 	{
-		private final ListChangeEvent event;
-		ListChangedRunnable(ListChangeEvent event) {
-			super();
-			this.event = event;
-		}
 		@Override
 		public void run() {
-			SWTListChangeListenerWrapper.this.listChanged_(this.event);
+			SWTListChangeListenerWrapper.this.forwardEvents();
 		}
 	}
 
-	void listChanged_(ListChangeEvent event) {
-		this.listener.listChanged(event);
+	void forwardEvents() {
+		for (ListEvent event : this.events.drain()) {
+			try {
+				this.forwardEvent(event);
+			} catch (RuntimeException ex) {
+				JptCommonUiPlugin.instance().logError(ex);
+			}
+		}
+	}
+
+	private void forwardEvent(ListEvent event) {
+		if (event instanceof ListAddEvent) {
+			this.listener.itemsAdded((ListAddEvent) event);
+		}
+		else if (event instanceof ListRemoveEvent) {
+			this.listener.itemsRemoved((ListRemoveEvent) event);
+		}
+		else if (event instanceof ListMoveEvent) {
+			this.listener.itemsMoved((ListMoveEvent) event);
+		}
+		else if (event instanceof ListReplaceEvent) {
+			this.listener.itemsReplaced((ListReplaceEvent) event);
+		}
+		else if (event instanceof ListClearEvent) {
+			this.listener.listCleared((ListClearEvent) event);
+		}
+		else if (event instanceof ListChangeEvent) {
+			this.listener.listChanged((ListChangeEvent) event);
+		}
 	}
 
 	/**
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTPropertyChangeListenerWrapper.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTPropertyChangeListenerWrapper.java
index 9462188..7c0bf5e 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTPropertyChangeListenerWrapper.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTPropertyChangeListenerWrapper.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2012 Oracle. All rights reserved.
+ * Copyright (c) 2007, 2013 Oracle. 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.
@@ -9,6 +9,7 @@
  ******************************************************************************/
 package org.eclipse.jpt.common.ui.internal.listeners;
 
+import org.eclipse.jpt.common.ui.internal.plugin.JptCommonUiPlugin;
 import org.eclipse.jpt.common.ui.internal.swt.widgets.DisplayTools;
 import org.eclipse.jpt.common.utility.internal.RunnableAdapter;
 import org.eclipse.jpt.common.utility.internal.collection.SynchronizedQueue;
@@ -59,7 +60,11 @@
 
 	void forwardEvents() {
 		for (PropertyChangeEvent event : this.events.drain()) {
-			this.listener.propertyChanged(event);
+			try {
+				this.listener.propertyChanged(event);
+			} catch (RuntimeException ex) {
+				JptCommonUiPlugin.instance().logError(ex);
+			}
 		}
 	}
 
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTStateChangeListenerWrapper.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTStateChangeListenerWrapper.java
index f7b4ab3..fbfb57a 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTStateChangeListenerWrapper.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTStateChangeListenerWrapper.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2012 Oracle. All rights reserved.
+ * Copyright (c) 2007, 2013 Oracle. 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.
@@ -9,6 +9,7 @@
  ******************************************************************************/
 package org.eclipse.jpt.common.ui.internal.listeners;
 
+import org.eclipse.jpt.common.ui.internal.plugin.JptCommonUiPlugin;
 import org.eclipse.jpt.common.ui.internal.swt.widgets.DisplayTools;
 import org.eclipse.jpt.common.utility.internal.RunnableAdapter;
 import org.eclipse.jpt.common.utility.internal.collection.SynchronizedQueue;
@@ -54,7 +55,11 @@
 
 	void forwardEvents() {
 		for (StateChangeEvent event : this.events.drain()) {
-			this.listener.stateChanged(event);
+			try {
+				this.listener.stateChanged(event);
+			} catch (RuntimeException ex) {
+				JptCommonUiPlugin.instance().logError(ex);
+			}
 		}
 	}
 
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoubleModifiablePropertyValueModel.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoubleModifiablePropertyValueModel.java
index 9d4e1d7..e104c73 100644
--- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoubleModifiablePropertyValueModel.java
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoubleModifiablePropertyValueModel.java
@@ -31,11 +31,11 @@
 	}
 
 	public void setValue(V value) {
-		ModifiablePropertyValueModel<V> vmv = this.getValueModelValueModel();
-		if (vmv == null) {
+		ModifiablePropertyValueModel<V> vmvm = this.getValueModelValueModel();
+		if (vmvm == null) {
 			this.setValue_(value);
 		} else {
-			vmv.setValue(value);
+			vmvm.setValue(value);
 		}
 	}
 
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractOrmJoinTableRelationshipStrategy.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractOrmJoinTableRelationshipStrategy.java
index b52c659..305f860 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractOrmJoinTableRelationshipStrategy.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractOrmJoinTableRelationshipStrategy.java
@@ -152,7 +152,8 @@
 
 	public void initializeFrom(JoinTableRelationshipStrategy oldStrategy) {
 		JoinTable oldJoinTable = oldStrategy.getJoinTable();
-		if (oldJoinTable != null) {
+		// the old join table should always be an orm specified join table...
+		if ((oldJoinTable instanceof OrmSpecifiedJoinTable) && ((OrmSpecifiedJoinTable) oldJoinTable).isSpecifiedInResource()) {
 			this.addStrategy();
 			this.joinTable.initializeFrom(oldJoinTable);
 		}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/MapAsComposite.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/MapAsComposite.java
index b5d889b..cc29b04 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/MapAsComposite.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/MapAsComposite.java
@@ -10,25 +10,29 @@
 package org.eclipse.jpt.jpa.ui.internal.details;
 
 import java.util.Comparator;
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.dialogs.IDialogSettings;
 import org.eclipse.jface.resource.JFaceColors;
 import org.eclipse.jface.resource.ResourceManager;
 import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jpt.common.ui.internal.WorkbenchTools;
 import org.eclipse.jpt.common.ui.internal.jface.ResourceManagerLabelProvider;
 import org.eclipse.jpt.common.ui.internal.widgets.Pane;
 import org.eclipse.jpt.common.utility.internal.StringTools;
 import org.eclipse.jpt.common.utility.model.value.PropertyValueModel;
-import org.eclipse.jpt.jpa.core.JpaModel;
+import org.eclipse.jpt.jpa.core.JpaStructureNode;
 import org.eclipse.jpt.jpa.ui.JpaPlatformUi;
 import org.eclipse.jpt.jpa.ui.details.DefaultMappingUiDefinition;
 import org.eclipse.jpt.jpa.ui.details.JptJpaUiDetailsMessages;
 import org.eclipse.jpt.jpa.ui.details.MappingUiDefinition;
 import org.eclipse.jpt.jpa.ui.internal.plugin.JptJpaUiPlugin;
+import org.eclipse.jpt.jpa.ui.selection.JpaSelectionManager;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.StyleRange;
@@ -61,7 +65,7 @@
  * -----------------------------------------------------------------------------</pre>
  */
 @SuppressWarnings("nls")
-public abstract class MapAsComposite<T extends JpaModel>
+public abstract class MapAsComposite<T extends JpaStructureNode>
 	extends Pane<T>
 {
 	protected boolean dragEvent;
@@ -433,6 +437,43 @@
 	}
 
 	/**
+	 * Lock the project while morphing the mapping to postpone any "updates"
+	 * until we are finished; then set the JPA selection.
+	 */
+	public abstract class AbstractMappingChangeHandler
+		implements MappingChangeHandler
+	{
+		/**
+		 * @see org.eclipse.jpt.jpa.ui.internal.handlers.JpaStructureViewHandler#execute(org.eclipse.core.commands.ExecutionEvent)
+		 */
+		public final void morphMapping(MappingUiDefinition definition) {
+			IProject project = MapAsComposite.this.getSubject().getJpaProject().getProject();
+			try {
+				Job.getJobManager().beginRule(project, null);
+				this.morphMapping_(definition);
+				this.setJpaSelection(MapAsComposite.this.getSubject());
+			} finally {
+				Job.getJobManager().endRule(project);
+			}
+		}
+
+		protected abstract void morphMapping_(MappingUiDefinition definition);
+
+		/**
+		 * @see org.eclipse.jpt.jpa.ui.internal.handlers.JpaStructureViewHandler#setJpaSelection(org.eclipse.ui.IWorkbenchWindow, JpaStructureNode)
+		 */
+		private void setJpaSelection(JpaStructureNode jpaSelection) {
+			JpaSelectionManager mgr = this.getJpaSelectionManager();
+			mgr.setSelection(null);
+			mgr.setSelection(jpaSelection);
+		}
+
+		private JpaSelectionManager getJpaSelectionManager() {
+			return WorkbenchTools.getAdapter(JpaSelectionManager.class);
+		}
+	}
+
+	/**
 	 * This dialog shows the list of possible mapping types and lets the user
 	 * the option to filter them using a search field.
 	 */
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentAttributeMapAsComposite.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentAttributeMapAsComposite.java
index d4ed003..0d3fdb2 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentAttributeMapAsComposite.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentAttributeMapAsComposite.java
@@ -15,8 +15,8 @@
 import org.eclipse.jpt.common.utility.model.value.PropertyValueModel;
 import org.eclipse.jpt.jpa.core.MappingKeys;
 import org.eclipse.jpt.jpa.core.context.AttributeMapping;
-import org.eclipse.jpt.jpa.core.context.SpecifiedPersistentAttribute;
 import org.eclipse.jpt.jpa.core.context.PersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.SpecifiedPersistentAttribute;
 import org.eclipse.jpt.jpa.ui.JpaPlatformUi;
 import org.eclipse.jpt.jpa.ui.details.DefaultMappingUiDefinition;
 import org.eclipse.jpt.jpa.ui.details.JptJpaUiDetailsMessages;
@@ -49,7 +49,7 @@
 	}
 
 	protected class AttributeMappingChangeHandler
-		implements MappingChangeHandler
+		extends AbstractMappingChangeHandler
 	{
 		public String getLabelText() {
 			String mappingKey = getMappingKey();
@@ -72,11 +72,12 @@
                           getDefaultDefinition(mappingKey).getLinkLabel() : 
                           getMappingUiDefinition().getLinkLabel();
 		}
-		
-		public void morphMapping(MappingUiDefinition definition) {
+
+		@Override
+		protected void morphMapping_(MappingUiDefinition definition) {
 			((SpecifiedPersistentAttribute) getSubject()).setMappingKey(definition.getKey());
 		}
-		
+
 		public String getName() {
 			return getSubject().getName();
 		}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentTypeMapAsComposite.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentTypeMapAsComposite.java
index a410c66..6bcfe6d 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentTypeMapAsComposite.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/PersistentTypeMapAsComposite.java
@@ -40,8 +40,8 @@
 		return new TypeMappingChangeHandler();
 	}
 
-	protected class TypeMappingChangeHandler
-		implements MappingChangeHandler
+	public class TypeMappingChangeHandler
+		extends AbstractMappingChangeHandler
 	{
 		public String getLabelText() {
 			String mappingKey = getMappingKey();
@@ -54,7 +54,8 @@
 			return getMappingUiDefinition().getLinkLabel();
 		}
 
-		public void morphMapping(MappingUiDefinition definition) {
+		@Override
+		protected void morphMapping_(MappingUiDefinition definition) {
 			getSubject().setMappingKey(definition.getKey());
 		}
 
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/AddPersistentAttributeToXmlAndMapHandler.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/AddPersistentAttributeToXmlAndMapHandler.java
index ad1c6f2..6b243e9 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/AddPersistentAttributeToXmlAndMapHandler.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/AddPersistentAttributeToXmlAndMapHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2012 Oracle. All rights reserved.
+ * Copyright (c) 2007, 2013 Oracle. 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.
@@ -9,18 +9,11 @@
  ******************************************************************************/
 package org.eclipse.jpt.jpa.ui.internal.handlers;
 
-import java.util.ArrayList;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jpt.common.core.internal.utility.PlatformTools;
-import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentType;
+import java.util.Map;
 import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentType;
 import org.eclipse.jpt.jpa.ui.internal.dialogs.AddPersistentAttributeToXmlAndMapDialog;
-import org.eclipse.jpt.jpa.ui.selection.JpaSelectionManager;
 import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.handlers.HandlerUtil;
 
 /**
  * Convert a list of <code>orm.xml</code> <em>virtual</em> attributes to
@@ -31,29 +24,18 @@
  * See <code>org.eclipse.jpt.jpa.ui/plugin.xml</code>.
  */
 public class AddPersistentAttributeToXmlAndMapHandler
-	extends AbstractHandler
+	extends JpaStructureViewHandler
 {
-	public Object execute(ExecutionEvent event) throws ExecutionException {
-		this.execute_(event);
-		return null;
-	}
-
-	private void execute_(ExecutionEvent event) throws ExecutionException {
-		IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
-		ArrayList<OrmPersistentAttribute> newAttributes = new ArrayList<OrmPersistentAttribute>();
-		IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelectionChecked(event);
-		for (Object each : selection.toList()) {
-			OrmPersistentAttribute attribute = (OrmPersistentAttribute) each;
+	@Override
+	protected void execute_(Object[] items, Map<String, String> parameters, IWorkbenchWindow window) {
+		for (int i = 0; i < items.length; i++) {
+			OrmPersistentAttribute attribute = (OrmPersistentAttribute) items[i];
 			OrmPersistentAttribute newAttribute = this.addAndMap(attribute, window);
 			if (newAttribute != null) {
-				newAttributes.add(newAttribute);
+				// a little hacky... :-)
+				items[i] = newAttribute;
 			}
 		}
-		
-		if (newAttributes.size() == 1) {
-			JpaSelectionManager selectionManager = PlatformTools.getAdapter(window, JpaSelectionManager.class);
-			selectionManager.setSelection(newAttributes.get(0));
-		}
 	}
 
 	private OrmPersistentAttribute addAndMap(OrmPersistentAttribute attribute, IWorkbenchWindow window) {
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/AddPersistentAttributeToXmlHandler.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/AddPersistentAttributeToXmlHandler.java
index ca1edad..1e0a986 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/AddPersistentAttributeToXmlHandler.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/AddPersistentAttributeToXmlHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2012 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2013 Oracle. 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.
@@ -9,16 +9,9 @@
  ******************************************************************************/
 package org.eclipse.jpt.jpa.ui.internal.handlers;
 
-import java.util.ArrayList;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jpt.common.core.internal.utility.PlatformTools;
+import java.util.Map;
 import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute;
-import org.eclipse.jpt.jpa.ui.selection.JpaSelectionManager;
 import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.handlers.HandlerUtil;
 
 /**
  * Convert a list of <code>orm.xml</code> <em>virtual</em> attributes to
@@ -30,25 +23,14 @@
  * See <code>org.eclipse.jpt.jpa.ui/plugin.xml</code>.
  */
 public class AddPersistentAttributeToXmlHandler
-	extends AbstractHandler
-{	
-	public Object execute(ExecutionEvent event) throws ExecutionException {
-		this.execute_(event);
-		return null;
-	}
-
-	private void execute_(ExecutionEvent event) throws ExecutionException {
-		ArrayList<OrmPersistentAttribute> specifiedAttributes = new ArrayList<OrmPersistentAttribute>();
-		IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelectionChecked(event);
-		for (Object each : selection.toList()) {
-			OrmPersistentAttribute attribute = (OrmPersistentAttribute) each;
-			specifiedAttributes.add(attribute.addToXml());
-		}
-
-		if (specifiedAttributes.size() == 1) {
-			IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
-			JpaSelectionManager selectionManager = PlatformTools.getAdapter(window, JpaSelectionManager.class);
-			selectionManager.setSelection(specifiedAttributes.get(0));
+	extends JpaStructureViewHandler
+{
+	@Override
+	protected void execute_(Object[] items, Map<String, String> parameters, IWorkbenchWindow window) {
+		for (int i = 0; i < items.length; i++) {
+			OrmPersistentAttribute attribute = (OrmPersistentAttribute) items[i];
+			// a little hacky... :-)
+			items[i] = attribute.addToXml();
 		}
 	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/AddPersistentClassHandler.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/AddPersistentClassHandler.java
index aff176c..2c5426b 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/AddPersistentClassHandler.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/AddPersistentClassHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2012 Oracle. All rights reserved.
+ * Copyright (c) 2008, 2013 Oracle. 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.
@@ -9,17 +9,11 @@
  ******************************************************************************/
 package org.eclipse.jpt.jpa.ui.internal.handlers;
 
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jpt.common.core.internal.utility.PlatformTools;
+import java.util.Map;
 import org.eclipse.jpt.jpa.core.context.orm.EntityMappings;
 import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentType;
 import org.eclipse.jpt.jpa.ui.internal.dialogs.AddPersistentClassDialog;
-import org.eclipse.jpt.jpa.ui.selection.JpaSelectionManager;
 import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.handlers.HandlerUtil;
 
 /**
  * Add an <code>orm.xml</code> type to the selected entity mappings.
@@ -28,26 +22,18 @@
  * See <code>org.eclipse.jpt.jpa.ui/plugin.xml</code>.
  */
 public class AddPersistentClassHandler
-	extends AbstractHandler
+	extends JpaStructureViewHandler
 {
-	public Object execute(ExecutionEvent event) throws ExecutionException {
-		this.execute_(event);
-		return null;
-	}
-
-	private void execute_(ExecutionEvent event) throws ExecutionException {
-		IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
-		IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelectionChecked(event);
-		EntityMappings entityMappings = (EntityMappings) selection.getFirstElement();
-
+	@Override
+	protected void execute_(Object[] items, Map<String, String> parameters, IWorkbenchWindow window) {
+		EntityMappings entityMappings = (EntityMappings) items[0];
 		AddPersistentClassDialog dialog = new AddPersistentClassDialog(window.getShell(), entityMappings);
 		dialog.create();
 		dialog.setBlockOnOpen(true);
 		OrmPersistentType type = dialog.openAndReturnType();
-
 		if (type != null) {
-			JpaSelectionManager selectionManager = PlatformTools.getAdapter(window, JpaSelectionManager.class);
-			selectionManager.setSelection(type);
+			// a little hacky... :-)
+			items[0] = type;
 		}
 	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/JpaStructureViewHandler.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/JpaStructureViewHandler.java
new file mode 100644
index 0000000..ee63337
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/JpaStructureViewHandler.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2013 Oracle. 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:
+ *     Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.ui.internal.handlers;
+
+import java.util.Map;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jpt.common.core.internal.utility.PlatformTools;
+import org.eclipse.jpt.jpa.core.JpaStructureNode;
+import org.eclipse.jpt.jpa.core.context.SpecifiedPersistentAttribute;
+import org.eclipse.jpt.jpa.ui.selection.JpaSelectionManager;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Lock the project to postpone any "updates" and set the JPA selection
+ * afterwards.
+ */
+public abstract class JpaStructureViewHandler
+	extends AbstractHandler
+{
+	/**
+	 * Lock the project while executing to postpone any "updates"
+	 * until we are finished; then set the JPA selection.
+	 */
+	public final Object execute(ExecutionEvent event) throws ExecutionException {
+		IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelectionChecked(event);
+		Object[] items = selection.toArray();
+		if (items.length == 0) {
+			return null;  // not sure this can happen...
+		}
+
+		IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
+		IProject project = ((JpaStructureNode) items[0]).getJpaProject().getProject();
+		@SuppressWarnings("unchecked")
+		Map<String, String> parameters = event.getParameters();
+		try {
+			Job.getJobManager().beginRule(project, null);
+			this.execute_(items, parameters, window);
+		} finally {
+			Job.getJobManager().endRule(project);
+		}
+		// re-get the first item as it might have been replaced by execute_(...)
+		this.setJpaSelection(window, (JpaStructureNode) items[0]);
+		return null;
+	}
+
+	protected abstract void execute_(Object[] items, Map<String, String> parameters, IWorkbenchWindow window);
+
+	/**
+	 * When we are changing an attribute mapping in the <code>orm.xml</code>
+	 * file (by calling {@link SpecifiedPersistentAttribute#setMappingKey(String)},
+	 * the following happens synchronously during the call:<ul>
+	 * <li>The mapping (persistent attribute) is removed from the XML file.
+	 * <li>The cursor moves to the empty position where the mapping used to be,
+	 *     between the remaining, surrounding mappings, effectively changing the
+	 *     JPA selection to the persistent type that contained the selected
+	 *     persistent attribute.
+	 * <li>The new mapping (persistent attribute) is added to the XML file in
+	 *     the appropriate position, usually not at the same location as the old
+	 *     mapping.
+	 * </ul>
+	 * At this point, the JPA selection is still the selected persistent
+	 * attribute; but a text editor event has been fired (with a half-second
+	 * delay - see
+	 * {@link org.eclipse.jface.text.TextViewer#queuePostSelectionChanged(boolean)})
+	 * that will change the JPA selection to the persistent type that contains
+	 * the selected persistent attribute (as calculated from the current cursor
+	 * position). We short-circuit this event by setting the JPA selection to
+	 * <code>null</code> and back to the selected persistent attribute. We set
+	 * the JPA selection to <code>null</code> and back because we
+	 * must <em>change</em> the JPA selection (as opposed to simply re-setting
+	 * it to the same persistent attribute) or no change event will be fired
+	 * (since nothing changed). This double change should be invisible to the
+	 * user....
+	 */
+	private void setJpaSelection(IWorkbenchWindow window, JpaStructureNode jpaSelection) {
+		JpaSelectionManager mgr = PlatformTools.getAdapter(window, JpaSelectionManager.class);
+		mgr.setSelection(null);
+		mgr.setSelection(jpaSelection);
+	}
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/PersistentAttributeMapAsHandler.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/PersistentAttributeMapAsHandler.java
index f1cee63..0b82166 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/PersistentAttributeMapAsHandler.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/PersistentAttributeMapAsHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2012 Oracle. All rights reserved.
+ * Copyright (c) 2008, 2013 Oracle. 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.
@@ -10,17 +10,12 @@
 package org.eclipse.jpt.jpa.ui.internal.handlers;
 
 import java.util.Map;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
 import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jpt.common.ui.internal.WorkbenchTools;
 import org.eclipse.jpt.jpa.core.context.SpecifiedPersistentAttribute;
-import org.eclipse.jpt.jpa.ui.selection.JpaSelectionManager;
 import org.eclipse.ui.ISources;
 import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.commands.IElementUpdater;
-import org.eclipse.ui.handlers.HandlerUtil;
 import org.eclipse.ui.menus.UIElement;
 import org.eclipse.ui.services.IEvaluationService;
 
@@ -34,11 +29,9 @@
  * 
  * @see org.eclipse.jpt.jpa.ui.internal.menus.PersistentAttributeMapAsContribution
  * @see SpecifiedPersistentAttribute
- * @version 2.0
- * @since 2.0
  */
 public class PersistentAttributeMapAsHandler
-	extends AbstractHandler
+	extends JpaStructureViewHandler
 	implements IElementUpdater
 {
 	/**
@@ -67,55 +60,13 @@
 		super();
 	}
 
-	public Object execute(ExecutionEvent event) throws ExecutionException {
-		IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelectionChecked(event);
-		String mappingKey = event.getParameter(SPECIFIED_MAPPING_COMMAND_PARAMETER_ID);
-		Object[] items = selection.toArray();
+	@Override
+	protected void execute_(Object[] items, Map<String, String> parameters, IWorkbenchWindow window) {
+		String mappingKey = parameters.get(SPECIFIED_MAPPING_COMMAND_PARAMETER_ID);
 		for (Object item : items) {
 			SpecifiedPersistentAttribute attribute = (SpecifiedPersistentAttribute) item;
 			attribute.setMappingKey(mappingKey);
 		}
-		this.setJpaSelection(items);
-		return null;
-	}
-
-	/**
-	 * When we are changing an attribute mapping in the <code>orm.xml</code>
-	 * file (by calling {@link SpecifiedPersistentAttribute#setMappingKey(String)},
-	 * the following happens synchronously during the call:<ul>
-	 * <li>The mapping (persistent attribute) is removed from the XML file.
-	 * <li>The cursor moves to the empty position where the mapping used to be,
-	 *     between the remaining, surrounding mappings, effectively changing the
-	 *     JPA selection to the persistent type that contained the selected
-	 *     persistent attribute.
-	 * <li>The new mapping (persistent attribute) is added to the XML file in
-	 *     the appropriate position, usually not at the same location as the old
-	 *     mapping.
-	 * </ul>
-	 * At this point, the JPA selection is still the selected persistent
-	 * attribute; but a text editor event has been fired (with a half-second
-	 * delay - see
-	 * {@link org.eclipse.jface.text.TextViewer#queuePostSelectionChanged(boolean)})
-	 * that will change the JPA selection to the persistent type that contains
-	 * the selected persistent attribute (as calculated from the current cursor
-	 * position). We short-circuit this event by setting the JPA selection to
-	 * <code>null</code> and back to the selected persistent attribute. We set
-	 * the JPA selection to <code>null</code> and back because we
-	 * must <em>change</em> the JPA selection (as opposed to simply re-setting
-	 * it to the same persistent attribute) or no change event will be fired
-	 * (since nothing changed). This double change should be invisible to the
-	 * user....
-	 */
-	private void setJpaSelection(Object[] items) {
-		if (items.length == 1) {
-			JpaSelectionManager mgr = this.getJpaSelectionManager();
-			mgr.setSelection(null);
-			mgr.setSelection((SpecifiedPersistentAttribute) items[0]);
-		}
-	}
-
-	private JpaSelectionManager getJpaSelectionManager() {
-		return WorkbenchTools.getAdapter(JpaSelectionManager.class);
 	}
 
 	public void updateElement(UIElement element, @SuppressWarnings("rawtypes") Map parameters) {
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/PersistentTypeMapAsHandler.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/PersistentTypeMapAsHandler.java
index 0d17d89..3685ec7 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/PersistentTypeMapAsHandler.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/PersistentTypeMapAsHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2012 Oracle. All rights reserved.
+ * Copyright (c) 2008, 2013 Oracle. 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.
@@ -10,17 +10,12 @@
 package org.eclipse.jpt.jpa.ui.internal.handlers;
 
 import java.util.Map;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
 import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jpt.common.ui.internal.WorkbenchTools;
 import org.eclipse.jpt.jpa.core.context.PersistentType;
-import org.eclipse.jpt.jpa.ui.selection.JpaSelectionManager;
 import org.eclipse.ui.ISources;
 import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.commands.IElementUpdater;
-import org.eclipse.ui.handlers.HandlerUtil;
 import org.eclipse.ui.menus.UIElement;
 import org.eclipse.ui.services.IEvaluationService;
 
@@ -34,11 +29,9 @@
  * 
  * @see org.eclipse.jpt.jpa.ui.internal.menus.PersistentTypeMapAsContribution
  * @see PersistentType
- * @version 2.0
- * @since 2.0
  */
 public class PersistentTypeMapAsHandler
-	extends AbstractHandler
+	extends JpaStructureViewHandler
 	implements IElementUpdater
 {
 	/**
@@ -65,31 +58,13 @@
 		super();
 	}
 
-	public Object execute(ExecutionEvent event) throws ExecutionException {
-		IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelectionChecked(event);
-		String mappingKey = event.getParameter(COMMAND_PARAMETER_ID);
-		Object[] items = selection.toArray();
+	@Override
+	protected void execute_(Object[] items, Map<String, String> parameters, IWorkbenchWindow window) {
+		String mappingKey = parameters.get(COMMAND_PARAMETER_ID);
 		for (Object item : items) {
 			PersistentType type = (PersistentType) item;
 			type.setMappingKey(mappingKey);
 		}
-		this.setJpaSelection(items);
-		return null;
-	}
-
-	/**
-	 * @see PersistentAttributeMapAsHandler#setJpaSelection(Object[])
-	 */
-	private void setJpaSelection(Object[] items) {
-		if (items.length == 1) {
-			JpaSelectionManager mgr = this.getJpaSelectionManager();
-			mgr.setSelection(null);
-			mgr.setSelection((PersistentType) items[0]);
-		}
-	}
-
-	private JpaSelectionManager getJpaSelectionManager() {
-		return WorkbenchTools.getAdapter(JpaSelectionManager.class);
 	}
 
 	public void updateElement(UIElement element, @SuppressWarnings("rawtypes") Map parameters) {
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/RemovePersistentAttributeFromXmlHandler.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/RemovePersistentAttributeFromXmlHandler.java
index 4171185..91b5ceb 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/RemovePersistentAttributeFromXmlHandler.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/handlers/RemovePersistentAttributeFromXmlHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2012 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2013 Oracle. 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.
@@ -9,17 +9,10 @@
  ******************************************************************************/
 package org.eclipse.jpt.jpa.ui.internal.handlers;
 
-import java.util.ArrayList;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jpt.common.core.internal.utility.PlatformTools;
-import org.eclipse.jpt.jpa.core.context.orm.OrmSpecifiedPersistentAttribute;
+import java.util.Map;
 import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute;
-import org.eclipse.jpt.jpa.ui.selection.JpaSelectionManager;
+import org.eclipse.jpt.jpa.core.context.orm.OrmSpecifiedPersistentAttribute;
 import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.handlers.HandlerUtil;
 
 /**
  * Convert a list of <code>orm.xml</code> <em>specified</em> attributes to
@@ -30,28 +23,17 @@
  * See <code>org.eclipse.jpt.jpa.ui/plugin.xml</code>.
  */
 public class RemovePersistentAttributeFromXmlHandler
-	extends AbstractHandler
+	extends JpaStructureViewHandler
 {
-	public Object execute(ExecutionEvent event) throws ExecutionException {
-		this.execute_(event);
-		return null;
-	}
-
-	private void execute_(ExecutionEvent event) throws ExecutionException {
-		ArrayList<OrmPersistentAttribute> virtualAttributes = new ArrayList<OrmPersistentAttribute>();
-		IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelectionChecked(event);
-		for (Object each : selection.toList()) {
-			OrmSpecifiedPersistentAttribute attribute = (OrmSpecifiedPersistentAttribute) each;
+	@Override
+	protected void execute_(Object[] items, Map<String, String> parameters, IWorkbenchWindow window) {
+		for (int i = 0; i < items.length; i++) {
+			OrmSpecifiedPersistentAttribute attribute = (OrmSpecifiedPersistentAttribute) items[i];
 			OrmPersistentAttribute newAttribute = attribute.removeFromXml();
 			if (newAttribute != null) {
-				virtualAttributes.add(newAttribute);
+				// a little hacky... :-)
+				items[i] = newAttribute;
 			}
 		}
-
-		if (virtualAttributes.size() == 1) {
-			IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
-			JpaSelectionManager selectionManager = PlatformTools.getAdapter(window, JpaSelectionManager.class);
-			selectionManager.setSelection(virtualAttributes.get(0));
-		}
 	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/selection/JpaWorkbenchSelectionManager.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/selection/JpaWorkbenchSelectionManager.java
index d0e50d1..b96039e 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/selection/JpaWorkbenchSelectionManager.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/selection/JpaWorkbenchSelectionManager.java
@@ -67,7 +67,8 @@
 	 * <br>
 	 * <strong>NB:</strong> {@link IWorkbench#getActiveWorkbenchWindow()}
 	 * (and, thus, this method) must
-	 * be called from the UI thread or it will return <code>null</code>.
+	 * be called from the UI thread or it will return <code>null</code>
+	 * (and this method will do nothing).
 	 * @see SetJpaSelectionJob.SetJpaSelectionRunnable#run()
 	 */
 	public void setSelection_(JpaStructureNode selection) {
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/selection/SetJpaSelectionJob.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/selection/SetJpaSelectionJob.java
index 93e981e..1001f10 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/selection/SetJpaSelectionJob.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/selection/SetJpaSelectionJob.java
@@ -14,7 +14,7 @@
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jpt.common.ui.internal.swt.widgets.DisplayTools;
-import org.eclipse.jpt.common.utility.internal.RunnableAdapter;
+import org.eclipse.jpt.common.utility.internal.ObjectTools;
 import org.eclipse.jpt.jpa.core.JpaStructureNode;
 import org.eclipse.jpt.jpa.ui.JptJpaUiMessages;
 
@@ -76,7 +76,7 @@
 	 * @see SetJpaSelectionJob#run(IProgressMonitor)
 	 */
 	private static class SetJpaSelectionRunnable
-		extends RunnableAdapter
+		implements Runnable
 	{
 		private final Manager jpaSelectionManager;
 		private final JpaStructureNode selection;
@@ -87,10 +87,14 @@
 			this.selection = selection;
 		}
 
-		@Override
 		public void run() {
 			this.jpaSelectionManager.setSelection_(this.selection);
 		}
+
+		@Override
+		public String toString() {
+			return ObjectTools.toString(this, this.selection);
+		}
 	}
 
 	/**
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/views/JpaStructureView.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/views/JpaStructureView.java
index 3625270..b7618f9 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/views/JpaStructureView.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/views/JpaStructureView.java
@@ -14,6 +14,11 @@
 import org.eclipse.jface.resource.ResourceManager;
 import org.eclipse.jpt.common.core.internal.utility.PlatformTools;
 import org.eclipse.jpt.common.utility.internal.ObjectTools;
+import org.eclipse.jpt.common.utility.model.listener.PropertyChangeAdapter;
+import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener;
+import org.eclipse.jpt.common.utility.model.value.ModifiablePropertyValueModel;
+import org.eclipse.jpt.common.utility.model.value.PropertyValueModel;
+import org.eclipse.jpt.jpa.core.JpaStructureNode;
 import org.eclipse.jpt.jpa.ui.JpaWorkbench;
 import org.eclipse.jpt.jpa.ui.JptJpaUiMessages;
 import org.eclipse.jpt.jpa.ui.selection.JpaEditorManager;
@@ -58,6 +63,21 @@
 	private volatile Manager manager;
 
 	/**
+	 * <strong>NB:</strong> We add a <strong>NOP</strong> listener to the
+	 * {@link org.eclipse.jpt.jpa.ui.selection.JpaViewManager.PageManager
+	 * <em>workbench window</em> page manager's}
+	 * JPA selection model to force it to be active so it will notify the
+	 * structure view's {@link JpaStructurePage <em>structure</em> pages} when
+	 * the JPA selection is changed from elsewhere (e.g. a menu command
+	 * handler).
+	 * Otherwise, the <em>workbench window</em> page manager's JPA selection
+	 * model, since it has no direct listeners, will ignore any changes and not
+	 * forward them to the {@link JpaEditorManager JPA editor manager} of the
+	 * current editor, which is what the <em>structure</em> page listens to.
+	 */
+	private final PropertyChangeListener jpaSelectionListener = new PropertyChangeAdapter();
+
+	/**
 	 * The resource manager is created when the view's control is
 	 * {@link #createPartControl(Composite) created}
 	 * and disposed, if necessary, when the view is
@@ -73,6 +93,9 @@
 	@Override
 	public void createPartControl(Composite parent) {
 		this.manager = this.buildManager();
+		if (this.manager != null) {
+			this.manager.getJpaSelectionModel().addPropertyChangeListener(PropertyValueModel.VALUE, this.jpaSelectionListener);
+		}
 		this.resourceManager = this.buildResourceManager();
 		super.createPartControl(parent);
 	}
@@ -175,6 +198,7 @@
 	public void dispose() {
 		super.dispose();
 		if (this.manager != null) {
+			this.manager.getJpaSelectionModel().removePropertyChangeListener(PropertyValueModel.VALUE, this.jpaSelectionListener);
 			this.manager.dispose();
 		}
 		if (this.resourceManager != null) {
@@ -219,6 +243,10 @@
 			return this.pageManager.getEditorManager(editor);
 		}
 
+		ModifiablePropertyValueModel<JpaStructureNode> getJpaSelectionModel() {
+			return this.pageManager.getJpaSelectionModel();
+		}
+
 		void dispose() {
 			this.pageManager.removeViewManager(this);
 		}