/** * Copyright (c) 2007 IBM Corporation and others. * 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: * IBM - Initial API and implementation */ package org.eclipse.emf.test.core.ecore; import java.util.List; import java.util.Set; import java.util.HashSet; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.eclipse.emf.common.util.Diagnostic; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.ETypedElement; import org.eclipse.emf.ecore.EcoreFactory; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.resource.impl.ResourceImpl; import org.eclipse.emf.ecore.util.Diagnostician; import org.eclipse.emf.ecore.util.EcoreUtil; public class ResourceAttachmentTest extends TestCase { private EPackage compositePackage; private EClass compositeClass; private EAttribute compositeName; private EReference compositeChildren; static class AttachmentTrackingResourceImpl extends ResourceImpl { public Set<EObject> attachedEObjects = new HashSet<EObject>(); @Override protected boolean isAttachedDetachedHelperRequired() { return true; } @Override public void attachedHelper(EObject eObject) { super.attachedHelper(eObject); // Ensure that an object is only attached once. // boolean result = attachedEObjects.add(eObject); assertTrue(result); } @Override public void detachedHelper(EObject eObject) { super.detachedHelper(eObject); // Ensure that an object is only detached once. // boolean result = attachedEObjects.remove(eObject); assertTrue(result); } } public ResourceAttachmentTest(String name) { super(name); } public static Test suite() { TestSuite ts = new TestSuite(ResourceAttachmentTest.class.getSimpleName()); ts.addTest(new ResourceAttachmentTest("testPackage")); ts.addTest(new ResourceAttachmentTest("testSimpleAttachAndDetach")); ts.addTest(new ResourceAttachmentTest("testSimpleCrossResourceAttachAndDetach")); ts.addTest(new ResourceAttachmentTest("testIndirectAttachAndDetach")); ts.addTest(new ResourceAttachmentTest("testIndirectCrossResourceAttachAndDetach")); return ts; } /** * @see junit.framework.TestCase#setUp() */ @Override protected void setUp() throws Exception { EcoreFactory ecoreFactory = EcoreFactory.eINSTANCE; EcorePackage ecorePackage = EcorePackage.eINSTANCE; compositeClass = ecoreFactory.createEClass(); compositeClass.setName("Composite"); compositeName = ecoreFactory.createEAttribute(); compositeName.setName("name"); compositeName.setEType(ecorePackage.getEString()); compositeClass.getEStructuralFeatures().add(compositeName); compositeChildren = ecoreFactory.createEReference(); compositeChildren.setName("children"); compositeChildren.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY); compositeChildren.setEType(compositeClass); compositeChildren.setContainment(true); compositeClass.getEStructuralFeatures().add(compositeChildren); compositePackage = ecoreFactory.createEPackage(); compositePackage.setName("composite"); compositePackage.setNsPrefix("composite"); compositePackage.setNsURI("http:///com.example.composite.ecore"); compositePackage.getEClassifiers().add(compositeClass); EPackage.Registry.INSTANCE.put(compositePackage.getNsURI(), compositePackage); } /** * @see junit.framework.TestCase#tearDown() */ @Override protected void tearDown() throws Exception { EPackage.Registry.INSTANCE.remove(compositePackage.getNsURI()); compositeClass = null; compositeName = null; compositeChildren = null; compositePackage = null; } public void testPackage() { assertEquals(Diagnostician.INSTANCE.validate(compositePackage).getSeverity(), Diagnostic.OK); } public void testSimpleAttachAndDetach() { AttachmentTrackingResourceImpl resource1 = new AttachmentTrackingResourceImpl(); EObject composite1 = EcoreUtil.create(compositeClass); // Directly adding the object to the resource will attach it. // resource1.getContents().add(composite1); assertTrue(resource1.attachedEObjects.contains(composite1)); // Directly adding the object from the resource will detach it. // resource1.getContents().remove(composite1); assertFalse(resource1.attachedEObjects.contains(composite1)); } public void testIndirectAttachAndDetach() { AttachmentTrackingResourceImpl resource1 = new AttachmentTrackingResourceImpl(); EObject composite1 = EcoreUtil.create(compositeClass); @SuppressWarnings("unchecked") List<EObject> children = (List<EObject>)composite1.eGet(compositeChildren); EObject composite2 = EcoreUtil.create(compositeClass); // Adding an object to the resource and a contained child to that object will attach them both. // resource1.getContents().add(composite1); children.add(composite2); assertTrue(resource1.attachedEObjects.contains(composite1)); assertTrue(resource1.attachedEObjects.contains(composite2)); // Removing a child from a parent and removing the parent from the resource will detach them both. // children.remove(composite2); assertFalse(resource1.attachedEObjects.contains(composite2)); resource1.getContents().remove(composite1); assertFalse(resource1.attachedEObjects.contains(composite1)); // Adding an object with an existing contained child will attach them both. // children.add(composite2); resource1.getContents().add(composite1); assertTrue(resource1.attachedEObjects.contains(composite1)); assertTrue(resource1.attachedEObjects.contains(composite2)); // Removing an object with an existing contained child will detach them both. // resource1.getContents().remove(composite1); assertFalse(resource1.attachedEObjects.contains(composite1)); assertFalse(resource1.attachedEObjects.contains(composite2)); } public void testSimpleCrossResourceAttachAndDetach() { AttachmentTrackingResourceImpl resource1 = new AttachmentTrackingResourceImpl(); AttachmentTrackingResourceImpl resource2 = new AttachmentTrackingResourceImpl(); EObject composite1 = EcoreUtil.create(compositeClass); // Directly adding the object to the resource will attach it. // resource1.getContents().add(composite1); assertTrue(resource1.attachedEObjects.contains(composite1)); // Directly adding the object a different resource will detach it from the old one and attach it to the new one. // resource2.getContents().add(composite1); assertFalse(resource1.attachedEObjects.contains(composite1)); assertTrue(resource2.attachedEObjects.contains(composite1)); } public void testIndirectCrossResourceAttachAndDetach() { AttachmentTrackingResourceImpl resource1 = new AttachmentTrackingResourceImpl(); resource1.setURI(URI.createURI("resource1")); AttachmentTrackingResourceImpl resource2 = new AttachmentTrackingResourceImpl(); resource2.setURI(URI.createURI("resource2")); EObject composite1 = EcoreUtil.create(compositeClass); @SuppressWarnings("unchecked") List<EObject> children = (List<EObject>)composite1.eGet(compositeChildren); EObject composite2 = EcoreUtil.create(compositeClass); // Adding an object to the resource and a contained child to that object will attach them both. // resource1.getContents().add(composite1); children.add(composite2); assertTrue(resource1.attachedEObjects.contains(composite1)); assertTrue(resource1.attachedEObjects.contains(composite2)); // Directly adding an object with a contained child to a different resource will detach both from the old one and attach both to the new one. // resource2.getContents().add(composite1); assertFalse(resource1.attachedEObjects.contains(composite1)); assertFalse(resource1.attachedEObjects.contains(composite2)); assertTrue(resource2.attachedEObjects.contains(composite1)); assertTrue(resource2.attachedEObjects.contains(composite2)); // Moving it back does the expected thing too. // resource1.getContents().add(composite1); assertTrue(resource1.attachedEObjects.contains(composite1)); assertTrue(resource1.attachedEObjects.contains(composite2)); assertFalse(resource2.attachedEObjects.contains(composite1)); assertFalse(resource2.attachedEObjects.contains(composite2)); // Adding a proxy resolving contained child to a different resource will detach it from the old one and attach it to the new one. // resource2.getContents().add(composite2); assertFalse(resource1.attachedEObjects.contains(composite2)); assertTrue(resource2.attachedEObjects.contains(composite2)); // Removing a proxy resolving contained child from a different resource will detach it from the old one and attach it to the one for the container. // resource2.getContents().remove(composite2); assertFalse(resource2.attachedEObjects.contains(composite2)); assertTrue(resource1.attachedEObjects.contains(composite2)); // Add it back in again. // resource2.getContents().add(composite2); assertFalse(resource1.attachedEObjects.contains(composite2)); assertTrue(resource2.attachedEObjects.contains(composite2)); // Remove it by unloading. // resource2.unload(); assertFalse(resource2.attachedEObjects.contains(composite2)); assertTrue(resource1.attachedEObjects.contains(composite2)); } }