Merge Kepler changes
diff --git a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/ModelHandler.java b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/ModelHandler.java
index 39c2f37..531e996 100644
--- a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/ModelHandler.java
+++ b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/ModelHandler.java
@@ -59,16 +59,16 @@
 import org.eclipse.bpmn2.modeler.core.model.Bpmn2ModelerFactory;
 import org.eclipse.bpmn2.modeler.core.preferences.Bpmn2Preferences;
 import org.eclipse.bpmn2.modeler.core.utils.BusinessObjectUtil;
+import org.eclipse.bpmn2.modeler.core.utils.FixDuplicateIdsDialog;
 import org.eclipse.bpmn2.modeler.core.utils.GraphicsUtil;
 import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
 import org.eclipse.bpmn2.modeler.core.utils.ModelUtil.Bpmn2DiagramType;
+import org.eclipse.bpmn2.modeler.core.utils.Tuple;
 import org.eclipse.bpmn2.util.Bpmn2ResourceImpl;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.dd.dc.Bounds;
 import org.eclipse.dd.dc.DcFactory;
 import org.eclipse.dd.dc.Point;
-import org.eclipse.dd.di.DiagramElement;
-import org.eclipse.emf.common.util.ECollections;
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.common.util.TreeIterator;
 import org.eclipse.emf.ecore.EClass;
@@ -752,45 +752,15 @@
 		return (Definitions) resource.getContents().get(0).eContents().get(0);
 	}
 
-//	public void save() {
-//		TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(resource);
-//		if (domain != null) {
-//			domain.getCommandStack().execute(new RecordingCommand(domain) {
-//				@Override
-//				protected void doExecute() {
-//					saveResource();
-//				}
-//			});
-//		} else {
-//			saveResource();
-//		}
-//	}
-
-//	private void saveResource() {
-//		fixZOrder();
-//		try {
-//			resource.save(null);
-//		} catch (IOException e) {
-//			Activator.logError(e);
-//		}
-//	}
-//
-//	private void fixZOrder() {
-//		final List<BPMNDiagram> diagrams = getAll(BPMNDiagram.class);
-//		for (BPMNDiagram bpmnDiagram : diagrams) {
-//			fixZOrder(bpmnDiagram);
-//		}
-//
-//	}
-//
-//	private void fixZOrder(BPMNDiagram bpmnDiagram) {
-//		EList<DiagramElement> elements = (EList<DiagramElement>) bpmnDiagram.getPlane().getPlaneElement();
-//		ECollections.sort(elements, new DIZorderComparator());
-//	}
-
+	// TODO: Move all of this model handler crap into BPMN2PersistencyBehavior where it belongs
 	void loadResource() {
 		try {
 			resource.load(null);
+			List<Tuple<EObject,EObject>> dups = ModelUtil.findDuplicateIds(resource);
+			if (dups.size()>0) {
+				FixDuplicateIdsDialog dlg = new FixDuplicateIdsDialog(dups);
+				dlg.open();
+			}
 		} catch (IOException e) {
 			if (!resource.getErrors().isEmpty()) {
 				ImportDiagnostics diagnostics = new ImportDiagnostics(resource);
diff --git a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/ImportDiagnostics.java b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/ImportDiagnostics.java
index 124b6ca..4373b93 100644
--- a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/ImportDiagnostics.java
+++ b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/di/ImportDiagnostics.java
@@ -3,17 +3,13 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.eclipse.bpmn2.BaseElement;
 import org.eclipse.bpmn2.modeler.core.Activator;
 import org.eclipse.bpmn2.modeler.core.runtime.CustomTaskDescriptor;
 import org.eclipse.bpmn2.modeler.core.runtime.TargetRuntime;
-import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
 import org.eclipse.core.runtime.Status;
-import org.eclipse.dd.di.DiagramElement;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EStructuralFeature;
 import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.graphiti.ui.editor.DiagramEditor;
 import org.eclipse.jface.viewers.ILabelProvider;
 import org.eclipse.jface.viewers.ILabelProviderListener;
 import org.eclipse.jface.viewers.IStructuredContentProvider;
@@ -121,11 +117,10 @@
 		ImportDiagnostic d = (ImportDiagnostic)element;
 		String text = "";
 		String id = "";
-		String name = "";
 		if (d.element!=null)
 			text = getText(d.element);
 		else
-			text = "Unknown Type";
+			return d.message;
 		
 		text += ": " + d.message;
 		return text;
diff --git a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/model/Bpmn2ModelerResourceImpl.java b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/model/Bpmn2ModelerResourceImpl.java
index b0741eb..9aec416 100644
--- a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/model/Bpmn2ModelerResourceImpl.java
+++ b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/model/Bpmn2ModelerResourceImpl.java
@@ -50,6 +50,7 @@
 import org.eclipse.bpmn2.modeler.core.utils.ImportUtil;
 import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
 import org.eclipse.bpmn2.modeler.core.utils.NamespaceUtil;
+import org.eclipse.bpmn2.modeler.core.utils.Tuple;
 import org.eclipse.bpmn2.util.Bpmn2ResourceImpl;
 import org.eclipse.bpmn2.util.ImportHelper;
 import org.eclipse.bpmn2.util.OnlyContainmentTypeInfo;
@@ -81,6 +82,8 @@
 import org.eclipse.emf.ecore.resource.ResourceSet;
 import org.eclipse.emf.ecore.util.EObjectWithInverseEList;
 import org.eclipse.emf.ecore.util.ExtendedMetaData;
+import org.eclipse.emf.ecore.xmi.IllegalValueException;
+import org.eclipse.emf.ecore.xmi.XMIException;
 import org.eclipse.emf.ecore.xmi.XMLHelper;
 import org.eclipse.emf.ecore.xmi.XMLLoad;
 import org.eclipse.emf.ecore.xmi.XMLResource;
@@ -235,49 +238,9 @@
 	}
 	
 	public void save(Map<?, ?> options) throws IOException {
-		
-		// Ensure that there are no duplicate IDs. This could corrupt the BPMN2 file.
-		// If this happens, do NOT save the file until the problem has been fixed.
-		Definitions definitions = ImportHelper.getDefinitions(this);
-		String message = null;
-		TreeIterator<EObject> iter1 = definitions.eAllContents();
-		HashSet<EObject> map = new HashSet<EObject>();
-		while (iter1.hasNext()) {
-			EObject o1 = iter1.next();
-			EStructuralFeature id1Feature = o1.eClass().getEIDAttribute();
-			if (id1Feature!=null && !map.contains(o1)) {
-				TreeIterator<EObject> iter2 = definitions.eAllContents();
-				map.add(o1);
-				String id1 = (String)o1.eGet(id1Feature);
-				
-				while (iter2.hasNext()) {
-					EObject o2 = iter2.next();
-					EStructuralFeature id2Feature = o2.eClass().getEIDAttribute();
-					if (id2Feature!=null && o1!=o2 && !map.contains(o2)) {
-						String id2 = (String)o2.eGet(id2Feature);
-						if (id1!=null && !id1.isEmpty() && id2!=null && !id2.isEmpty()) {
-							if (id1.equals(id2)) {
-								String msg =
-										ModelUtil.getLabel(o1) + " \"" + ModelUtil.getDisplayName(o1) + "\" and " +
-										ModelUtil.getLabel(o2) + " \"" + ModelUtil.getDisplayName(o2) + "\" have the same ID";
-								if (message==null)
-									message = msg;
-								else
-									message += "\n" + msg;
-							}
-						}
-					}
-				}
-			}
-		}
-		if (message != null) {
-			throw new IllegalArgumentException("Duplicate IDs:\n" + message);
-		}
-		
 		super.save(options);
 	}
 
-
     @Override
     protected XMLHelper createXMLHelper() {
     	if (xmlHelper!=null)
diff --git a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/FixDuplicateIdsDialog.java b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/FixDuplicateIdsDialog.java
new file mode 100644
index 0000000..7948651
--- /dev/null
+++ b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/FixDuplicateIdsDialog.java
@@ -0,0 +1,165 @@
+package org.eclipse.bpmn2.modeler.core.utils;
+
+import java.util.List;
+
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.transaction.RecordingCommand;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.emf.transaction.util.TransactionUtil;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.dialogs.ListSelectionDialog;
+
+public class FixDuplicateIdsDialog extends ListSelectionDialog {
+
+	static private MyContentProvider contentProvider = new MyContentProvider();
+	static private MyLabelProvider labelProvider = new MyLabelProvider();
+	List<Tuple<EObject,EObject>> duplicates;
+	
+	public FixDuplicateIdsDialog(List<Tuple<EObject,EObject>> duplicates) {
+		super(Display.getDefault().getActiveShell(), duplicates, contentProvider, labelProvider,
+				"This file is corrupt because multiple elements have the same ID!\n"+
+				"You can repair this file by reassigning new IDs for the duplicate elements.\n" +
+				"Simply select the elements for which you wish to reassign new IDs.\n" +
+				"Note that if you do not \"Select All\", the file will still be corrupt.");
+		this.duplicates = duplicates;
+	}
+	
+	@SuppressWarnings("unchecked")
+	@Override
+	public int open() {
+		final int status[] = new int[1];
+		Display.getDefault().asyncExec( new Runnable() {
+
+			@Override
+			public void run() {
+				status[0] = FixDuplicateIdsDialog.super.open();
+				if (status[0]==Window.OK) {
+					final Object[] results = getResult();
+					if (results.length>0) {
+						Tuple<EObject,EObject> tuple = (Tuple<EObject,EObject>)results[0];
+						TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(tuple.getFirst().eResource());
+						domain.getCommandStack().execute(new RecordingCommand(domain) {
+							@Override
+							protected void doExecute() {
+						
+								for (Object entry : results) {
+									Tuple<EObject,EObject> tuple = (Tuple<EObject,EObject>)entry;
+									EObject object = tuple.getSecond();
+					
+									EStructuralFeature idFeature = object.eClass().getEIDAttribute();
+									Object id = object.eGet(idFeature);
+									Object uniqueId = makeUniqueId(object,id);
+									object.eSet(idFeature, uniqueId);
+								}
+							}
+						});
+					}
+				}
+			}
+			
+		});
+		return status[0];
+	}
+
+	private Object makeUniqueId(EObject object, Object id) {
+		int i = 1;
+		Object uniqueId = id;
+		EObject dup = null;
+		do {
+			dup = findDuplicateId(object,uniqueId);
+			if (dup!=null) {
+				uniqueId = id + "_" + i++;
+			}
+		}
+		while (dup!=null);
+		return uniqueId;
+	}
+
+	private EObject findDuplicateId(EObject object, Object id) {
+		if (object!=null && id!=null) {
+			Resource resource = object.eResource();
+			
+			TreeIterator<EObject> iter = resource.getAllContents();
+			while (iter.hasNext()) {
+				EObject o = iter.next();
+				if (o!=object) {
+					EStructuralFeature f = o.eClass().getEStructuralFeature("id");
+					if (f!=null) {
+						Object existingId = o.eGet(f);
+						if (id.equals(existingId))
+							return o;
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+	private static class MyContentProvider implements IStructuredContentProvider {
+
+		public MyContentProvider() {
+			super();
+		}
+		
+		@Override
+		public void dispose() {
+		}
+
+		@Override
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		}
+
+		@Override
+		public Object[] getElements(Object inputElement) {
+			List<Tuple<EObject,EObject>> duplicates = (List<Tuple<EObject,EObject>>) inputElement;
+			return duplicates.toArray();
+		}
+		
+	}
+
+	private static class MyLabelProvider implements ILabelProvider {
+
+		@Override
+		public void addListener(ILabelProviderListener listener) {
+		}
+
+		@Override
+		public void dispose() {
+		}
+
+		@Override
+		public boolean isLabelProperty(Object element, String property) {
+			return false;
+		}
+
+		@Override
+		public void removeListener(ILabelProviderListener listener) {
+		}
+
+		@Override
+		public Image getImage(Object element) {
+			return null;
+		}
+
+		@Override
+		public String getText(Object element) {
+			Tuple<EObject,EObject> tuple = (Tuple<EObject,EObject>)element;
+			EObject o1 = tuple.getFirst();
+			EObject o2 = tuple.getSecond();
+			String message =
+				ModelUtil.getLongDisplayName(o1) + " and " +
+				ModelUtil.getLongDisplayName(o2) + " have the same ID";
+			return message;
+		}
+		
+	}
+}
diff --git a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/ModelUtil.java b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/ModelUtil.java
index 627f495..74c63a7 100644
--- a/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/ModelUtil.java
+++ b/org.eclipse.bpmn2.modeler.core/src/org/eclipse/bpmn2/modeler/core/utils/ModelUtil.java
@@ -14,6 +14,7 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
@@ -1486,8 +1487,12 @@
 		}
 		feature = object.eClass().getEStructuralFeature("id");
 		if (feature!=null) {
-			if (object.eGet(feature)!=null)
-				objName = (String)object.eGet(feature);
+			String id = (String)object.eGet(feature);
+			if (id==null || id.isEmpty())
+				id = "Unknown " + objName;
+			else
+				id = objName + " \"" + id + "\"";
+			return id;
 		}
 		feature = object.eClass().getEStructuralFeature("qName");
 		if (feature!=null) {
@@ -1606,4 +1611,36 @@
         }
         return body;
     }
+
+	public static List<Tuple<EObject,EObject>> findDuplicateIds(Resource resource) {
+		List<Tuple<EObject,EObject>> list = new ArrayList<Tuple<EObject,EObject>>();
+		Definitions definitions = ModelUtil.getDefinitions(resource);
+		TreeIterator<EObject> iter1 = definitions.eAllContents();
+		HashSet<EObject> map = new HashSet<EObject>();
+		while (iter1.hasNext()) {
+			EObject o1 = iter1.next();
+			EStructuralFeature id1Feature = o1.eClass().getEIDAttribute();
+			if (id1Feature!=null && !map.contains(o1)) {
+				TreeIterator<EObject> iter2 = definitions.eAllContents();
+				map.add(o1);
+				String id1 = (String)o1.eGet(id1Feature);
+				
+				while (iter2.hasNext()) {
+					EObject o2 = iter2.next();
+					EStructuralFeature id2Feature = o2.eClass().getEIDAttribute();
+					if (id2Feature!=null && o1!=o2 && !map.contains(o2)) {
+						String id2 = (String)o2.eGet(id2Feature);
+						if (id1!=null && !id1.isEmpty() && id2!=null && !id2.isEmpty()) {
+							if (id1.equals(id2)) {
+								list.add( new Tuple<EObject,EObject>(o1,o2) );
+							}
+						}
+					}
+				}
+			}
+		}
+		
+		return list;
+	}
+	
 }
diff --git a/org.eclipse.bpmn2.modeler.ui/META-INF/MANIFEST.MF b/org.eclipse.bpmn2.modeler.ui/META-INF/MANIFEST.MF
index 950553c..74f86e1 100644
--- a/org.eclipse.bpmn2.modeler.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.bpmn2.modeler.ui/META-INF/MANIFEST.MF
@@ -31,7 +31,9 @@
  org.eclipse.jface.text,
  org.eclipse.jdt,
  org.eclipse.jdt.core,
- org.eclipse.emf.workspace
+ org.eclipse.emf.workspace,
+ org.eclipse.bpmn2,
+ org.eclipse.emf.common
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 Bundle-ActivationPolicy: lazy
 Export-Package: org.eclipse.bpmn2.modeler.ui,
diff --git a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/BPMN2Editor.java b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/BPMN2Editor.java
index 7272790..82820ad 100644
--- a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/BPMN2Editor.java
+++ b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/BPMN2Editor.java
@@ -326,7 +326,7 @@
 	private Bpmn2Preferences preferences;
 	private TargetRuntime targetRuntime;
 	private String modelEnablementProfile;
-//	private Hashtable<BPMNDiagram, GraphicalViewer> mapDiagramToViewer = new Hashtable<BPMNDiagram, GraphicalViewer>();
+	private boolean importInProgress;
 	private BPMN2EditorSelectionSynchronizer synchronizer;
 
 	protected DiagramEditorAdapter editorAdapter;
@@ -366,52 +366,155 @@
 
 	@Override
 	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
-		try {
-			Bpmn2DiagramType diagramType = Bpmn2DiagramType.NONE;
-			String targetNamespace = null;
-			bpmnDiagram = null;
-
-			if (input instanceof IStorageEditorInput) {
-				input = createNewDiagramEditorInput(site, input, diagramType, targetNamespace);
-			}
-			else if (input instanceof DiagramEditorInput) {
-				if (input instanceof Bpmn2DiagramEditorInput) {
-					diagramType = ((Bpmn2DiagramEditorInput)input).getInitialDiagramType();
-					targetNamespace = ((Bpmn2DiagramEditorInput)input).getTargetNamespace();
-					bpmnDiagram = ((Bpmn2DiagramEditorInput)input).getBpmnDiagram();
-				}
-				if (bpmnDiagram==null) {
-					// This was incorrectly constructed input, we ditch the old one and make a new and clean one instead
-					// This code path comes in from the New File Wizard
-					input = createNewDiagramEditorInput(site, input, diagramType, targetNamespace);
-				}
-				else {
-					BPMNDiagram d = bpmnDiagram;
-					bpmnDiagram = null;
-					setBpmnDiagram(d);
-					return;
-				}
-			}
-			else {
-				throw new PartInitException("Invalid Editor Input: "
-						+input.getClass().getSimpleName()+" "
-						+input.getName());
-			}
-		} catch (Exception e) {
-			Activator.showErrorWithLogging(e);
-			throw new PartInitException(e.getMessage());
-		}
-		
-		// add a listener so we get notified if the workbench is shutting down.
-		// in this case we don't want to delete the temp file!
-		addWorkbenchListener();
-		getTargetRuntime(input);
+			
 		setActiveEditor(this);
 		
-		super.init(site, input);
+		if (this.getDiagramTypeProvider()==null) {
+			super.init(site, input);
+			// add a listener so we get notified if the workbench is shutting down.
+			// in this case we don't want to delete the temp file!
+			addWorkbenchListener();
+			addSelectionListener();
+			addMarkerChangeListener();
+		}
+		else {
+			if (input instanceof Bpmn2DiagramEditorInput) {
+				bpmnDiagram = ((Bpmn2DiagramEditorInput)input).getBpmnDiagram();
+				if (bpmnDiagram!=null) {
+					setBpmnDiagram(bpmnDiagram);
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Beware, creates a new input and changes this editor!
+	 */
+	private Bpmn2DiagramEditorInput createNewDiagramEditorInput(IEditorInput input, Bpmn2DiagramType diagramType, String targetNamespace)
+			throws PartInitException {
 		
-		addSelectionListener();
-		addMarkerChangeListener();
+		modelUri = FileService.getInputUri(input);
+		if (modelUri==null)
+			throw new PartInitException("Can't create BPMN2Editor Input");
+		input = BPMN2DiagramCreator.createDiagram(input, modelUri, diagramType,targetNamespace,this);
+		diagramUri = ((Bpmn2DiagramEditorInput)input).getUri();
+
+		return (Bpmn2DiagramEditorInput)input;
+	}
+
+	/**
+	 * Bypasses Graphiti's Persistency Behavior code and save only the BPMN2 model resource. 
+	 * This is only used after a successful Import if the BPMN2 model was changed in any way,
+	 * e.g. missing DI elements were added.
+	 */
+	private void saveModelFile() {
+		try {
+			bpmnResource.save(null);
+			((BasicCommandStack) getEditingDomain().getCommandStack()).saveIsDone();
+			updateDirtyState();
+		}
+		catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	protected void setInput(IEditorInput input) {
+		try {
+			if (input instanceof Bpmn2DiagramEditorInput) {
+				Bpmn2DiagramType diagramType = Bpmn2DiagramType.NONE;
+				String targetNamespace = null;
+				diagramType = ((Bpmn2DiagramEditorInput)input).getInitialDiagramType();
+				targetNamespace = ((Bpmn2DiagramEditorInput)input).getTargetNamespace();
+				input = createNewDiagramEditorInput(input, diagramType, targetNamespace);
+			}
+		}
+		catch (Exception e) {
+			Activator.logError(e);
+		}
+		
+		// Determine which Target Runtime to use for this input and initialize the ResourceSet
+		TargetRuntime targetRuntime = getTargetRuntime(input);
+		ResourceSet resourceSet = getEditingDomain().getResourceSet();
+		resourceSet.setURIConverter(new ProxyURIConverterImplExtension(modelUri));
+		resourceSet.eAdapters().add(editorAdapter = new DiagramEditorAdapter(this));
+
+		// Tell the TargetRuntime about the ResourceSet. This allows the TargetRuntime to provide its
+		// own ResourceFactory if needed.
+		targetRuntime.setResourceSet(resourceSet);
+		
+		// Now create the BPMN2 model resource.
+		bpmnResource = (Bpmn2ResourceImpl) resourceSet.createResource(modelUri, Bpmn2ModelerResourceImpl.BPMN2_CONTENT_TYPE_ID);
+		
+		// Set this input in Graphiti DiagramEditor
+		super.setInput(input);
+		
+		// Hook a transaction exception handler so we can get diagnostics about EMF validation errors.
+		getEditingDomainListener();
+		
+		// This does the actual loading of the resource.
+		// TODO: move the loading code to BPMN2PersistencyBehavior where it belongs,
+		// and get rid of ModelHandler and ModelHandlerLocator
+		modelHandler = ModelHandlerLocator.createModelHandler(modelUri, bpmnResource);
+		ModelHandlerLocator.put(diagramUri, modelHandler);
+
+		// Allow the runtime extension to construct custom tasks and whatever else it needs
+		// custom tasks should be added to the current target runtime's custom tasks list
+		// where they will be picked up by the toolpalette refresh.
+		getTargetRuntime().getRuntimeExtension().initialize(this);
+
+		// Import the BPMNDI model that creates the Graphiti shapes, connections, etc.
+		BasicCommandStack commandStack = (BasicCommandStack) getEditingDomain().getCommandStack();
+		commandStack.execute(new RecordingCommand(getEditingDomain()) {
+			@Override
+			protected void doExecute() {
+				importDiagram();
+				getTargetRuntime().setResource(bpmnResource);
+			}
+		});
+
+		// Reset the save point and initialize the undo stack
+		commandStack.saveIsDone();
+		commandStack.flush();
+		
+		// Load error markers
+		loadMarkers();
+	}
+	
+	protected DiagramEditorInput convertToDiagramEditorInput(IEditorInput input) throws PartInitException {
+		IEditorInput newInput = createNewDiagramEditorInput(input, Bpmn2DiagramType.NONE, "");
+		if (newInput==null)
+			newInput = super.convertToDiagramEditorInput(input);
+		return (DiagramEditorInput) newInput;
+	}
+	
+	private void importDiagram() {
+		try {
+			importInProgress = true;
+			// make sure this guy is active, otherwise it's not selectable
+			Diagram diagram = getDiagramTypeProvider().getDiagram();
+			IFeatureProvider featureProvider = getDiagramTypeProvider().getFeatureProvider();
+			diagram.setActive(true);
+			Bpmn2DiagramEditorInput input = (Bpmn2DiagramEditorInput) getEditorInput();
+			Bpmn2DiagramType diagramType = input.getInitialDiagramType();
+			String targetNamespace = input.getTargetNamespace();
+	
+			if (diagramType != Bpmn2DiagramType.NONE) {
+				bpmnDiagram = modelHandler.createDiagramType(diagramType, targetNamespace);
+				featureProvider.link(diagram, bpmnDiagram);
+				// If the bpmn file was missing DI elements, they would have been added by the importer
+				// so save the file now in case it was changed.
+				saveModelFile();
+			}
+			
+			DIImport di = new DIImport(this);
+			di.setModelHandler(modelHandler);
+	
+			di.generateFromDI();
+		}
+		finally {
+			importInProgress = false;
+		}
 	}
 	
 	public void setEditable(boolean editable) {
@@ -518,108 +621,6 @@
 		return targetRuntime;
 	}
 	
-	/**
-	 * Beware, creates a new input and changes this editor!
-	 */
-	private Bpmn2DiagramEditorInput createNewDiagramEditorInput(IEditorSite site, IEditorInput input, Bpmn2DiagramType diagramType, String targetNamespace)
-			throws CoreException {
-		
-		modelUri = FileService.getInputUri(input);
-		if (modelUri==null)
-			throw new PartInitException("Can't create BPMN2Editor Input");
-		input = BPMN2DiagramCreator.createDiagram(modelUri, diagramType,targetNamespace,this);
-		diagramUri = ((Bpmn2DiagramEditorInput)input).getUri();
-
-		return (Bpmn2DiagramEditorInput)input;
-	}
-
-	private void saveModelFile() {
-		try {
-			bpmnResource.save(null);
-			((BasicCommandStack) getEditingDomain().getCommandStack()).saveIsDone();
-			updateDirtyState();
-		}
-		catch (IOException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
-	}
-
-	@Override
-	protected void setInput(IEditorInput input) {
-		super.setInput(input);
-		
-		// Hook a transaction exception handler so we can get diagnostics about EMF validation errors.
-		getEditingDomainListener();
-		
-		BasicCommandStack basicCommandStack = (BasicCommandStack) getEditingDomain().getCommandStack();
-
-		if (input instanceof DiagramEditorInput) {
-			ResourceSet resourceSet = getEditingDomain().getResourceSet();
-			getTargetRuntime().setResourceSet(resourceSet);
-			
-			bpmnResource = (Bpmn2ResourceImpl) resourceSet.createResource(modelUri,
-					Bpmn2ModelerResourceImpl.BPMN2_CONTENT_TYPE_ID);
-
-			resourceSet.setURIConverter(new ProxyURIConverterImplExtension(modelUri));
-			resourceSet.eAdapters().add(editorAdapter = new DiagramEditorAdapter(this));
-
-			modelHandler = ModelHandlerLocator.createModelHandler(modelUri, bpmnResource);
-			ModelHandlerLocator.put(diagramUri, modelHandler);
-
-			getTargetRuntime(input);
-			setActiveEditor(this);
-
-			// allow the runtime extension to construct custom tasks and whatever else it needs
-			// custom tasks should be added to the current target runtime's custom tasks list
-			// where they will be picked up by the toolpalette refresh.
-			getTargetRuntime().getRuntimeExtension().initialize(this);
-
-			try {
-				if (getModelFile()==null || getModelFile().exists()) {
-					bpmnResource.load(null);
-				} else {
-					saveModelFile();
-				}
-			} catch (IOException e) {
-				Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);
-				ErrorUtils.showErrorWithLogging(status);
-			}
-			basicCommandStack.execute(new RecordingCommand(getEditingDomain()) {
-
-				@Override
-				protected void doExecute() {
-					importDiagram();
-					getTargetRuntime().setResource(bpmnResource);
-				}
-			});
-		}
-		basicCommandStack.saveIsDone();
-		basicCommandStack.flush();
-		loadMarkers();
-	}
-	
-	private void importDiagram() {
-		// make sure this guy is active, otherwise it's not selectable
-		Diagram diagram = getDiagramTypeProvider().getDiagram();
-		IFeatureProvider featureProvider = getDiagramTypeProvider().getFeatureProvider();
-		diagram.setActive(true);
-		Bpmn2DiagramEditorInput input = (Bpmn2DiagramEditorInput) getEditorInput();
-		Bpmn2DiagramType diagramType = input.getInitialDiagramType();
-		String targetNamespace = input.getTargetNamespace();
-
-		if (diagramType != Bpmn2DiagramType.NONE) {
-			bpmnDiagram = modelHandler.createDiagramType(diagramType, targetNamespace);
-			featureProvider.link(diagram, bpmnDiagram);
-			saveModelFile();
-		}
-		
-		DIImport di = new DIImport(this);
-		di.setModelHandler(modelHandler);
-
-		di.generateFromDI();
-	}
-
 	public void updatePalette() {
 		GFPaletteRoot pr = (GFPaletteRoot)getPaletteRoot();
 		if (pr!=null) {
@@ -924,6 +925,19 @@
 		return modelHandler;
 	}
 	
+	public Resource getResource() {
+		return bpmnResource;
+	}
+	
+	public ResourceSet getResourceSet() {
+		return getEditingDomain().getResourceSet();
+	}
+	
+	public void refresh() {
+		if (!importInProgress)
+			getRefreshBehavior().refresh();
+	}
+	
 	public void createPartControl(Composite parent) {
 		if (getGraphicalViewer()==null) {
 			super.createPartControl(parent);
diff --git a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/BPMN2PersistencyBehavior.java b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/BPMN2PersistencyBehavior.java
index 901d14b..e098315 100644
--- a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/BPMN2PersistencyBehavior.java
+++ b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/editor/BPMN2PersistencyBehavior.java
@@ -10,12 +10,18 @@
  *******************************************************************************/
 package org.eclipse.bpmn2.modeler.ui.editor;
 
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.eclipse.bpmn2.modeler.core.utils.FixDuplicateIdsDialog;
+import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
+import org.eclipse.bpmn2.modeler.core.utils.Tuple;
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.common.util.WrappedException;
+import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.resource.Resource;
 import org.eclipse.graphiti.mm.pictograms.Diagram;
 import org.eclipse.graphiti.ui.editor.DefaultPersistencyBehavior;
@@ -32,13 +38,31 @@
 		super(diagramEditor);
 		editor = (BPMN2Editor)diagramEditor;
 	}
+	
     @Override
-    public Diagram loadDiagram(URI modelUri) {
-    	Diagram diagram = super.loadDiagram(modelUri);
-
+    public Diagram loadDiagram(URI diagramUri) {
+    	Diagram diagram = super.loadDiagram(diagramUri);
+//    	Resource resource = editor.getResource();
+//		List<Tuple<EObject,EObject>> dups = ModelUtil.findDuplicateIds(resource);
+//		if (dups.size()>0) {
+//			FixDuplicateIdsDialog dlg = new FixDuplicateIdsDialog(dups);
+//			dlg.open();
+//		}
     	return diagram;
     }
     
+    @Override
+	public void saveDiagram(IProgressMonitor monitor) {
+    	Resource resource = editor.getResource();
+		List<Tuple<EObject,EObject>> dups = ModelUtil.findDuplicateIds(resource);
+		if (dups.size()>0) {
+			FixDuplicateIdsDialog dlg = new FixDuplicateIdsDialog(dups);
+			dlg.open();
+		}
+
+    	super.saveDiagram(monitor);
+    }
+    
 	protected IRunnableWithProgress createOperation(final Set<Resource> savedResources,
 			final Map<Resource, Map<?, ?>> saveOptions) {
 		// Do the work within an operation because this is a long running
diff --git a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/wizards/BPMN2DiagramCreator.java b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/wizards/BPMN2DiagramCreator.java
index 2fe9110..5daebe4 100644
--- a/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/wizards/BPMN2DiagramCreator.java
+++ b/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/wizards/BPMN2DiagramCreator.java
@@ -21,11 +21,11 @@
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.transaction.TransactionalEditingDomain;
 import org.eclipse.graphiti.mm.pictograms.Diagram;
 import org.eclipse.graphiti.services.Graphiti;
 import org.eclipse.graphiti.ui.editor.DiagramEditorInput;
 import org.eclipse.graphiti.ui.services.GraphitiUi;
+import org.eclipse.ui.IEditorInput;
 import org.eclipse.ui.IEditorPart;
 import org.eclipse.ui.IWorkbenchPage;
 import org.eclipse.ui.PartInitException;
@@ -33,34 +33,39 @@
 
 public class BPMN2DiagramCreator {
 
-	private final static String TEMPFILE_EXTENSION = "bpmn2d"; 
-//	private IFolder diagramFolder;
-//	private IFile diagramFile;
-//	private URI uri;
-
 	public static Bpmn2DiagramEditorInput createDiagram(URI uri, Bpmn2DiagramType diagramType, String targetNamespace) throws CoreException {
-		return createDiagram(uri, diagramType, targetNamespace, null);
+		return createDiagram(null, uri, diagramType, targetNamespace, null);
 	}
 
-	public static Bpmn2DiagramEditorInput createDiagram(URI modelUri, Bpmn2DiagramType diagramType, String targetNamespace, BPMN2Editor diagramEditor) {
+	public static Bpmn2DiagramEditorInput createDiagram(IEditorInput oldInput, URI modelUri, Bpmn2DiagramType diagramType, String targetNamespace, BPMN2Editor diagramEditor) {
 
 		String modelName = modelUri.trimFragment().trimFileExtension().lastSegment();
 		final Diagram diagram = Graphiti.getPeCreateService().createDiagram("BPMN2", modelName, true);
 
 		String diagramName = FileService.createTempName(modelName);
 		URI diagramUri = URI.createFileURI(diagramName);
-		TransactionalEditingDomain domain = FileService.createEmfFileForDiagram(diagramUri, diagram, diagramEditor);
+		FileService.createEmfFileForDiagram(diagramUri, diagram, diagramEditor);
 
 		String providerId = GraphitiUi.getExtensionManager().getDiagramTypeProviderId(diagram.getDiagramTypeId());
-		final Bpmn2DiagramEditorInput editorInput = new Bpmn2DiagramEditorInput(modelUri, diagramUri, providerId);
-		editorInput.setInitialDiagramType(diagramType);
-		editorInput.setTargetNamespace(targetNamespace);
+		
+		// No need to create a new one if old input is already a Bpmn2DiagramEditorInput,
+		// just update it
+		Bpmn2DiagramEditorInput newInput;
+		if (oldInput instanceof Bpmn2DiagramEditorInput) {
+			newInput = (Bpmn2DiagramEditorInput)oldInput;
+			newInput.updateUri(diagramUri);
+		}
+		else
+			newInput = new Bpmn2DiagramEditorInput(modelUri, diagramUri, providerId);
+		
+		newInput.setInitialDiagramType(diagramType);
+		newInput.setTargetNamespace(targetNamespace);
 
 		if (diagramEditor==null) {
-			openEditor(editorInput);
+			openEditor(newInput);
 		}
 
-		return editorInput;
+		return newInput;
 	}
 
 	public static IEditorPart openEditor(final DiagramEditorInput editorInput) {