Add tests for references per QName

Test our QName (de)resolution in intra- and cross-file situations.
diff --git a/org.eclipse.bpmn2.tests/src/org/eclipse/bpmn2/tests/QNameReferenceTest.java b/org.eclipse.bpmn2.tests/src/org/eclipse/bpmn2/tests/QNameReferenceTest.java
new file mode 100644
index 0000000..55921be
--- /dev/null
+++ b/org.eclipse.bpmn2.tests/src/org/eclipse/bpmn2/tests/QNameReferenceTest.java
@@ -0,0 +1,208 @@
+/**
+ * Copyright (c) 2010 Henning Heitkoetter.
+ * 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:
+ *    Henning Heitkoetter - initial API and implementation
+ */
+package org.eclipse.bpmn2.tests;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.eclipse.bpmn2.Bpmn2Factory;
+import org.eclipse.bpmn2.Collaboration;
+import org.eclipse.bpmn2.Definitions;
+import org.eclipse.bpmn2.EventDefinition;
+import org.eclipse.bpmn2.Import;
+import org.eclipse.bpmn2.LinkEventDefinition;
+import org.eclipse.bpmn2.Process;
+import org.eclipse.bpmn2.StartEvent;
+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.emf.ecore.xmi.ClassNotFoundException;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests our QName (de)resolution mechanism both for intra- and inter-model references.
+ * 
+ * This test uses XML serialization (no QNames in XMI).
+ * @author Henning Heitkoetter
+ *
+ */
+public class QNameReferenceTest extends Bpmn2SerializationTest {
+    protected Definitions A_model, B_model;
+    protected Collaboration A_collab, B_collab;
+    protected Process A_process, B_process;
+    protected Resource A_resource, B_resource;
+
+    @Before
+    public void setUpModels() {
+        A_model = TestHelper.initBasicModel("urn:modelA");
+        B_model = TestHelper.initBasicModel("urn:modelB");
+        A_collab = Bpmn2Factory.eINSTANCE.createCollaboration();
+        A_model.getRootElements().add(A_collab);
+        A_process = Bpmn2Factory.eINSTANCE.createProcess();
+        A_model.getRootElements().add(A_process);
+        B_collab = Bpmn2Factory.eINSTANCE.createCollaboration();
+        B_model.getRootElements().add(B_collab);
+        B_process = Bpmn2Factory.eINSTANCE.createProcess();
+        B_model.getRootElements().add(B_process);
+    }
+
+    @Override
+    protected String getFileExtension() {
+        return EXTENSION_BPMN2_XML;
+    }
+
+    /**
+     * Saves both models (A and B). Creates a import element in A pointing to B.
+     * Loads the created resources into {@link #A_resource} and {@link #B_resource}, respectively.
+     *  
+     * @param name Part of the file name that is used to identify different tests.
+     * @throws IOException
+     */
+    protected void saveAndLoadModels(String name) throws IOException {
+        Map<URI, EObject> uriToContentMap = new LinkedHashMap<URI, EObject>();
+        URI A_fileUri = URI.createFileURI("tmp/qname_" + name + "_A." + getFileExtension());
+        URI B_fileUri = URI.createFileURI("tmp/qname_" + name + "_B." + getFileExtension());
+        uriToContentMap.put(A_fileUri, A_model);
+        uriToContentMap.put(B_fileUri, B_model);
+
+        Import importBintoA = Bpmn2Factory.eINSTANCE.createImport();
+        importBintoA.setImportType("http://www.omg.org/spec/BPMN/20100524/MODEL");
+        importBintoA.setLocation(B_fileUri.toString());
+        importBintoA.setNamespace("urn:modelB");
+        A_model.getImports().add(importBintoA);
+
+        TestHelper.createResourcesWithContent(uriToContentMap);
+        createdFiles.add(A_fileUri);
+        createdFiles.add(B_fileUri);
+
+        A_resource = TestHelper.getResource(A_fileUri);
+        B_resource = TestHelper.getResource(B_fileUri);
+    }
+
+    /**
+     * Test proxy-resolving references (i.e. potentially cross-file references) when
+     * they point to objects within the same file.
+     * @throws IOException
+     */
+    @Test
+    public void testIntraModelReferences() throws IOException {
+        // single @ XML attribute
+        A_process.setDefinitionalCollaborationRef(A_collab);
+
+        // many @ XML attribute - no cross-file reference available
+
+        // single @ XML element
+        LinkEventDefinition A_led1, A_led2;
+        A_led1 = Bpmn2Factory.eINSTANCE.createLinkEventDefinition();
+        A_model.getRootElements().add(A_led1);
+        A_led2 = Bpmn2Factory.eINSTANCE.createLinkEventDefinition();
+        A_model.getRootElements().add(A_led2);
+        A_led1.setTarget(A_led2);
+
+        // many @ XML element
+        Process A_process2 = Bpmn2Factory.eINSTANCE.createProcess();
+        A_model.getRootElements().add(A_process2);
+        A_process.getSupports().add(A_process2);
+
+        Resource res = saveAndLoadModel("qname_intra", A_model);
+
+        Process A_processNew = (Process) res.getEObject(A_process.getId());
+        LinkEventDefinition A_led1New = (LinkEventDefinition) res.getEObject(A_led1.getId());
+
+        assertFalse("Proxy could not be resolved (single attr)", A_processNew
+                .getDefinitionalCollaborationRef().eIsProxy());
+        assertEquals(A_collab.getId(), A_processNew.getDefinitionalCollaborationRef().getId());
+
+        assertFalse("Proxy could not be resolved (single elem)", A_led1New.getTarget().eIsProxy());
+        assertEquals(A_led2.getId(), A_led1New.getTarget().getId());
+
+        assertFalse("Proxy could not be resolved (many elem)", A_processNew.getSupports().get(0)
+                .eIsProxy());
+        assertEquals(A_process2.getId(), A_processNew.getSupports().get(0).getId());
+    }
+
+    /**
+     * Test a proxy-resolving intra-file reference with an abstract type.
+     * @throws Exception
+     */
+    @Test
+    public void testReferenceToAbstractType() throws Exception {
+        EventDefinition A_eventDef = Bpmn2Factory.eINSTANCE.createSignalEventDefinition();
+        A_model.getRootElements().add(A_eventDef);
+
+        StartEvent A_event = Bpmn2Factory.eINSTANCE.createStartEvent();
+        A_event.getEventDefinitionRefs().add(A_eventDef);
+        A_process.getFlowElements().add(A_event);
+
+        try {
+            Resource res = saveAndLoadModel("qname_toAbstract", A_model);
+            StartEvent A_eventNew = (StartEvent) res.getEObject(A_event.getId());
+            assertFalse("Proxy could not be resolved (abstract)", A_eventNew
+                    .getEventDefinitionRefs().get(0).eIsProxy());
+            assertEquals(A_eventDef.getId(), A_eventNew.getEventDefinitionRefs().get(0).getId());
+        } catch (WrappedException e) {
+            if (e.exception() instanceof ClassNotFoundException)
+                fail("Class EventDefinition was recognized as abstract.");
+            else
+                throw e;
+        } catch (IllegalArgumentException e) {
+            // different error in Eclipse 3.4
+            if (e.getMessage().endsWith("not a valid classifier"))
+                fail("Class EventDefinition was recognized as abstract.");
+            else
+                throw e;
+        }
+    }
+
+    /**
+     * Test cross-file references.
+     * @throws IOException
+     */
+    @Test
+    public void testInterModelReferences() throws IOException {
+        // single @ XML attribute
+        A_process.setDefinitionalCollaborationRef(B_collab);
+
+        // many @ XML attribute - no cross-file reference available
+
+        // single @ XML element
+        LinkEventDefinition A_led, B_led;
+        A_led = Bpmn2Factory.eINSTANCE.createLinkEventDefinition();
+        A_model.getRootElements().add(A_led);
+        B_led = Bpmn2Factory.eINSTANCE.createLinkEventDefinition();
+        B_model.getRootElements().add(B_led);
+        A_led.setTarget(B_led);
+
+        // many @ XML element
+        A_process.getSupports().add(B_process);
+
+        saveAndLoadModels("inter");
+
+        Process A_processNew = (Process) A_resource.getEObject(A_process.getId());
+        LinkEventDefinition A_ledNew = (LinkEventDefinition) A_resource.getEObject(A_led.getId());
+
+        assertFalse("Proxy could not be resolved (single attr)", A_processNew
+                .getDefinitionalCollaborationRef().eIsProxy());
+        assertEquals(B_collab.getId(), A_processNew.getDefinitionalCollaborationRef().getId());
+
+        assertFalse("Proxy could not be resolved (single elem)", A_ledNew.getTarget().eIsProxy());
+        assertEquals(B_led.getId(), A_ledNew.getTarget().getId());
+
+        assertFalse("Proxy could not be resolved (many elem)", A_processNew.getSupports().get(0)
+                .eIsProxy());
+        assertEquals(B_process.getId(), A_processNew.getSupports().get(0).getId());
+    }
+}
diff --git a/org.eclipse.bpmn2.tests/src/org/eclipse/bpmn2/tests/TestHelper.java b/org.eclipse.bpmn2.tests/src/org/eclipse/bpmn2/tests/TestHelper.java
index bd7a149..46f0222 100644
--- a/org.eclipse.bpmn2.tests/src/org/eclipse/bpmn2/tests/TestHelper.java
+++ b/org.eclipse.bpmn2.tests/src/org/eclipse/bpmn2/tests/TestHelper.java
@@ -18,6 +18,8 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 import org.eclipse.bpmn2.Bpmn2Factory;
 import org.eclipse.bpmn2.Definitions;
@@ -26,6 +28,7 @@
 import org.eclipse.emf.common.util.WrappedException;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
 import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
 import org.eclipse.emf.ecore.xmi.PackageNotFoundException;
 
@@ -126,6 +129,28 @@
     }
 
     /**
+     * Creates a resource for each URI-content combination in the map, sets its respective content
+     * and saves it.
+     * 
+     * @param uriToContentMap A list of pairs of URI and EObject to save under that URI.
+     * @throws IOException
+     */
+    protected static void createResourcesWithContent(Map<URI, EObject> uriToContentMap)
+            throws IOException {
+        ResourceSet resSet = new ResourceSetImpl();
+        Resource curRes;
+
+        for (Entry<URI, EObject> curEntry : uriToContentMap.entrySet()) {
+            curRes = resSet.createResource(curEntry.getKey());
+            assertNotNull("No resource factory registered for " + curEntry.getKey(), curRes);
+            curRes.getContents().add(curEntry.getValue());
+        }
+
+        for (Resource cur : resSet.getResources())
+            cur.save(null);
+    }
+
+    /**
      * Retrieves the root definition element from a resource.
      * @param res A BPMN2 resource.
      * @return The root definition element representing the model contained in the resource.