diff options
author | Mark Brörkens | 2013-08-16 10:56:26 +0000 |
---|---|---|
committer | Mark Brörkens | 2013-08-16 10:56:26 +0000 |
commit | bd0bed78246b36e1a603a213cbd8c1a596ff5cd5 (patch) | |
tree | 16113a104bc969682f92301b06ade70857fc7086 | |
parent | ca39ccfcc4abcf072d514c79827cf75bf3fba4c5 (diff) | |
download | org.eclipse.rmf-bd0bed78246b36e1a603a213cbd8c1a596ff5cd5.tar.gz org.eclipse.rmf-bd0bed78246b36e1a603a213cbd8c1a596ff5cd5.tar.xz org.eclipse.rmf-bd0bed78246b36e1a603a213cbd8c1a596ff5cd5.zip |
RESOLVED - bug 400951: Analyze potential side effects of
setIntrinsicIDToEObjectMap
https://bugs.eclipse.org/bugs/show_bug.cgi?id=400951
added adapter that creates missing IDs as soon as an EObject that has an
IDAttribute is added to the containment tree of the resource.
Lookup caches for IDs and EObjects in a resource are implemented and are
updated whenever in id is changed or EObjects with ID are removed or
added.
4 files changed, 567 insertions, 4 deletions
diff --git a/org.eclipse.rmf.serialization2/src/org/eclipse/rmf/serialization/XMLPersistenceMappingResourceImpl.java b/org.eclipse.rmf.serialization2/src/org/eclipse/rmf/serialization/XMLPersistenceMappingResourceImpl.java index 6528cfaf..b8048a8d 100644 --- a/org.eclipse.rmf.serialization2/src/org/eclipse/rmf/serialization/XMLPersistenceMappingResourceImpl.java +++ b/org.eclipse.rmf.serialization2/src/org/eclipse/rmf/serialization/XMLPersistenceMappingResourceImpl.java @@ -11,14 +11,25 @@ package org.eclipse.rmf.serialization; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import javax.xml.XMLConstants; import org.apache.xerces.impl.Constants; +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.util.EContentAdapter; +import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.xmi.XMLHelper; import org.eclipse.emf.ecore.xmi.XMLLoad; import org.eclipse.emf.ecore.xmi.XMLOptions; @@ -35,6 +46,205 @@ public class XMLPersistenceMappingResourceImpl extends XMLResourceImpl implement // This is a temporal HACK public boolean enableSchemaValidation = false; + class IdAdapter extends EContentAdapter { + public IdAdapter() { + super(); + } + + @Override + public boolean isAdapterForType(Object type) { + // TODO Auto-generated method stub + return super.isAdapterForType(type); + } + + @Override + public void notifyChanged(Notification n) { + assert null != n.getNotifier(); + super.notifyChanged(n); // the superclass handles adding/removing this Adapter to new Books + + Object notifier_ = n.getNotifier(); + if (!n.isTouch()) { + if (notifier_ instanceof EObject) { + Object feature = n.getFeature(); + if (feature instanceof EAttribute) { + // handle changed id + EAttribute attribute = (EAttribute) feature; + if (attribute.isID()) { + String newId = n.getNewStringValue(); + String oldId = n.getOldStringValue(); + EObject objectWithId = (EObject) n.getNotifier(); + switch (n.getEventType()) { + case Notification.SET: + if (null == newId) { + eObjectToIDMap.remove(objectWithId); + } else { + eObjectToIDMap.put(objectWithId, newId); + idToEObjectMap.put(newId, objectWithId); + } + + if (null != oldId) { + idToEObjectMap.remove(oldId); + } + break; + case Notification.UNSET: + eObjectToIDMap.remove(objectWithId); + idToEObjectMap.remove(oldId); + break; + } + } + } else { + // handle removed or added objects + EReference reference = (EReference) feature; + if (reference.isContainment()) { + + switch (n.getEventType()) { + case Notification.SET: + case Notification.ADD: + handleNewObjectAndSubObjects((EObject) n.getNewValue()); + break; + case Notification.ADD_MANY: + EList<EObject> newObjects = (EList<EObject>) n.getNewValue(); + int size = newObjects.size(); + for (int i = 0; i < size; i++) { + handleNewObjectAndSubObjects(newObjects.get(i)); + } + break; + case Notification.UNSET: + case Notification.REMOVE: + handleRemoveObjectAndSubObjects((EObject) n.getOldValue()); + break; + case Notification.REMOVE_MANY: + EList<EObject> removeObjects = (EList<EObject>) n.getOldValue(); + size = removeObjects.size(); + for (int i = 0; i < size; i++) { + handleRemoveObjectAndSubObjects(removeObjects.get(i)); + } + break; + } + + } + } + + } else if (notifier_ instanceof Resource) { + // feature is null + int featureID = n.getFeatureID(Resource.class); + if (Resource.RESOURCE__CONTENTS == featureID) { + switch (n.getEventType()) { + case Notification.SET: + case Notification.ADD: + handleNewObjectAndSubObjects((EObject) n.getNewValue()); + break; + case Notification.ADD_MANY: + EList<EObject> newObjects = (EList<EObject>) n.getNewValue(); + int size = newObjects.size(); + for (int i = 0; i < size; i++) { + handleNewObjectAndSubObjects(newObjects.get(i)); + } + break; + case Notification.UNSET: + case Notification.REMOVE: + handleRemoveObjectAndSubObjects((EObject) n.getOldValue()); + break; + case Notification.REMOVE_MANY: + EList<EObject> removeObjects = (EList<EObject>) n.getOldValue(); + size = removeObjects.size(); + for (int i = 0; i < size; i++) { + handleRemoveObjectAndSubObjects(removeObjects.get(i)); + } + break; + } + } + } else if (notifier_ instanceof ResourceSet) { + // NOP + } else { + // NOP + } + + } // end if isTouch + + }// end notifyChanged + + void handleNewObjectAndSubObjects(EObject objectWithId) { + if (null != objectWithId) { + handleNewObject(objectWithId); + } + TreeIterator<EObject> iterator = objectWithId.eAllContents(); + while (iterator.hasNext()) { + handleNewObject(iterator.next()); + } + } + + void handleNewObject(EObject objectWithId) { + assert null != objectWithId; + EAttribute idAttribute = objectWithId.eClass().getEIDAttribute(); + if (null != idAttribute) { + String id = (String) objectWithId.eGet(idAttribute); + if (id == null || 0 == id.length()) { + id = EcoreUtil.generateUUID(); + objectWithId.eSet(idAttribute, id); + // id map gets updated by notification on setId + } else { + eObjectToIDMap.put(objectWithId, id); + idToEObjectMap.put(id, objectWithId); + } + } + } + + void handleRemoveObjectAndSubObjects(EObject objectWithId) { + if (null != objectWithId) { + handleRemoveObject(objectWithId); + } + TreeIterator<EObject> iterator = objectWithId.eAllContents(); + while (iterator.hasNext()) { + handleRemoveObject(iterator.next()); + } + } + + void handleRemoveObject(EObject objectWithId) { + assert null != objectWithId; + String id = eObjectToIDMap.remove(objectWithId); + if (null != id) { + idToEObjectMap.remove(id); + } + } + + } + + class ResourceHandlerImpl implements ResourceHandler { + + ResourceHandlerImpl(Resource resource) { + super(); + } + + public void preLoad(XMLResource resource, InputStream inputStream, Map<?, ?> options) { + // NOP + } + + public void postLoad(XMLResource resource, InputStream inputStream, Map<?, ?> options) { + // register ContentAdapter for setting IDs and updating the intrinsic Id to EObject map + System.out.println("postLoadActions"); + /* + * EList<EObject> contents = resource.getContents(); int size = contents.size(); for (int i = 0; i < size; + * i++) { contents.get(i).eAdapters().add(idAdapter); } // set the id maps TreeIterator<EObject> iterator = + * resource.getAllContents(); Map<String, EObject> id2eObjectMap = getIDToEObjectMap(); Map<EObject, String> + * eObject2IdMap = getEObjectToIDMap(); while (iterator.hasNext()) { EObject eObject = iterator.next(); + * String id = EcoreUtil.getID(eObject); if (null != id && 0 < id.length()) { id2eObjectMap.put(id, + * eObject); eObject2IdMap.put(eObject, id); } } + */ + } + + public void preSave(XMLResource resource, OutputStream outputStream, Map<?, ?> options) { + // NOP + + } + + public void postSave(XMLResource resource, OutputStream outputStream, Map<?, ?> options) { + // NOP + + } + + } + public XMLPersistenceMappingResourceImpl() { super(); initDefaultOptions(); @@ -74,7 +284,22 @@ public class XMLPersistenceMappingResourceImpl extends XMLResourceImpl implement return object; } + /** + * Initializes the resource. Is called by the constructors of XMLResourceImpl + */ + @Override + protected void init() { + encoding = "UTF-8"; + xmlVersion = "1.0"; + // enable id creation and maintenance + idToEObjectMap = new HashMap<String, EObject>(); + eObjectToIDMap = new HashMap<EObject, String>(); + eAdapters().add(new IdAdapter()); + + } + public void initDefaultOptions() { + ResourceHandler resourceHandler = new ResourceHandlerImpl(this); // ========= default save options =================== Map<Object, Object> saveOptions = getDefaultSaveOptions(); // set encoding to UTF-8 @@ -89,6 +314,8 @@ public class XMLPersistenceMappingResourceImpl extends XMLResourceImpl implement saveOptions.put(XMLResource.OPTION_USE_ENCODED_ATTRIBUTE_STYLE, Boolean.FALSE); + saveOptions.put(XMLResource.OPTION_RESOURCE_HANDLER, resourceHandler); + // ========= default load options =================== Map<Object, Object> loadOptions = getDefaultLoadOptions(); // get XML names and attribute/value information from extended metadata @@ -108,6 +335,13 @@ public class XMLPersistenceMappingResourceImpl extends XMLResourceImpl implement // Performance enhancement loadOptions.put(XMLResource.OPTION_DEFER_IDREF_RESOLUTION, Boolean.TRUE); + loadOptions.put(XMLResource.OPTION_RESOURCE_HANDLER, resourceHandler); + + // defer attachment of object tree created during load to end of load process. + // this creating notifications by EContentAdapters that might be registered for the resource or resource set + // during load + loadOptions.put(XMLResource.OPTION_DEFER_ATTACHMENT, Boolean.TRUE); + // Retrieve application-defined XMLReader features (see http://xerces.apache.org/xerces2-j/features.html for // available features and their details) Map<String, Boolean> parserFeatures = new HashMap<String, Boolean>(); @@ -141,10 +375,6 @@ public class XMLPersistenceMappingResourceImpl extends XMLResourceImpl implement loadOptions.put(XMLResource.OPTION_XML_OPTIONS, xmlOptions); - // Sets the map used to cache the EObject identified by the value of its ID feature. - // TODO: This is related to https://git.eclipse.org/r/#/c/8251/ and should be reviewed by Mark. - setIntrinsicIDToEObjectMap(new HashMap<String, EObject>()); - } } diff --git a/org.eclipse.rmf.tests.serialization/resources/input/org.eclipse.rmf.tests.serialization.adapter/minimal.xml b/org.eclipse.rmf.tests.serialization/resources/input/org.eclipse.rmf.tests.serialization.adapter/minimal.xml new file mode 100644 index 00000000..36df2871 --- /dev/null +++ b/org.eclipse.rmf.tests.serialization/resources/input/org.eclipse.rmf.tests.serialization.adapter/minimal.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?> +<nodes:NODE xmlns:nodes="http://www.eclipse.org/rmf/serialization/model/nodes.ecore"> +</nodes:NODE> diff --git a/org.eclipse.rmf.tests.serialization/resources/input/org.eclipse.rmf.tests.serialization.adapter/minimalWithId.xml b/org.eclipse.rmf.tests.serialization/resources/input/org.eclipse.rmf.tests.serialization.adapter/minimalWithId.xml new file mode 100644 index 00000000..6b37aadc --- /dev/null +++ b/org.eclipse.rmf.tests.serialization/resources/input/org.eclipse.rmf.tests.serialization.adapter/minimalWithId.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?> +<nodes:NODE xmlns:nodes="http://www.eclipse.org/rmf/serialization/model/nodes.ecore" name="root"> +</nodes:NODE> diff --git a/org.eclipse.rmf.tests.serialization/src/org/eclipse/rmf/tests/serialization/adapter/IDAdapterTests.java b/org.eclipse.rmf.tests.serialization/src/org/eclipse/rmf/tests/serialization/adapter/IDAdapterTests.java new file mode 100644 index 00000000..de3c7321 --- /dev/null +++ b/org.eclipse.rmf.tests.serialization/src/org/eclipse/rmf/tests/serialization/adapter/IDAdapterTests.java @@ -0,0 +1,327 @@ +/** + * Copyright (c) 2013 itemis AG. + * 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: + * itemis AG - initial API and implementation + */ +package org.eclipse.rmf.tests.serialization.adapter; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.xmi.XMLResource; +import org.eclipse.rmf.serialization.XMLPersistenceMappingResourceFactoryImpl; +import org.eclipse.rmf.serialization.XMLPersistenceMappingResourceImpl; +import org.eclipse.rmf.tests.serialization.model.nodes.Node; +import org.eclipse.rmf.tests.serialization.model.nodes.NodesFactory; +import org.eclipse.rmf.tests.serialization.model.nodes.NodesPackage; +import org.eclipse.rmf.tests.serialization.util.AbstractTestCase; +import org.junit.Before; +import org.junit.Test; + +// Junit 3.8 test +@SuppressWarnings("nls") +public class IDAdapterTests extends AbstractTestCase { + + static final String INPUT_PATH = "org.eclipse.rmf.tests.serialization.adapter/"; + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + EPackage.Registry.INSTANCE.put(NodesPackage.eNS_URI, NodesPackage.eINSTANCE); + } + + @Test + public void testIdOnLoad() { + String inputFileName = INPUT_PATH + "minimal.xml"; + try { + EObject modelRoot = loadInputFile(inputFileName, new XMLPersistenceMappingResourceFactoryImpl(), null); + assertTrue(modelRoot instanceof Node); + Node rootNode = (Node) modelRoot; + assertTrue(rootNode.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + + } catch (Exception ex) { + ex.printStackTrace(); + assertTrue(ex.getMessage(), false); + } + } + + @Test + public void testIdOnLoadNotModified() { + String inputFileName = INPUT_PATH + "minimalWithId.xml"; + try { + EObject modelRoot = loadInputFile(inputFileName, new XMLPersistenceMappingResourceFactoryImpl(), null); + assertTrue(modelRoot instanceof Node); + Node rootNode = (Node) modelRoot; + assertEquals("root", rootNode.getName()); + + } catch (Exception ex) { + ex.printStackTrace(); + assertTrue(ex.getMessage(), false); + } + } + + @Test + public void testIdForNewObjectsAfterLoad1() { + String inputFileName = INPUT_PATH + "minimal.xml"; + try { + EObject modelRoot = loadInputFile(inputFileName, new XMLPersistenceMappingResourceFactoryImpl(), null); + assertTrue(modelRoot instanceof Node); + Node rootNode = (Node) modelRoot; + assertTrue(rootNode.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + assertSame(1, ((XMLResource) modelRoot.eResource()).getEObjectToIDMap().size()); + + // test set + Node subNode = NodesFactory.eINSTANCE.createNode(); + rootNode.setEReference_Contained0100Single(subNode); + assertTrue(subNode.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + assertSame(2, ((XMLResource) modelRoot.eResource()).getEObjectToIDMap().size()); + + // test add single + rootNode.getEReference_Contained1100Many().add(NodesFactory.eINSTANCE.createNode()); + assertTrue(5 < rootNode.getEReference_Contained1100Many().get(0).getName().length()); + assertSame(3, ((XMLResource) modelRoot.eResource()).getEObjectToIDMap().size()); + + // test add many + List<Node> newNodes = new ArrayList<Node>(); + for (int i = 0; i < 5; i++) { + newNodes.add(NodesFactory.eINSTANCE.createNode()); + } + rootNode.getEReference_Contained0100Many().addAll(newNodes); + for (int i = 0; i < 5; i++) { + assertTrue(5 < rootNode.getEReference_Contained0100Many().get(i).getName().length()); + } + assertSame(8, ((XMLResource) modelRoot.eResource()).getEObjectToIDMap().size()); + + } catch (Exception ex) { + assertTrue(ex.getMessage(), false); + } + } + + @Test + public void testIdForNewObjectsAfterLoad2() { + String inputFileName = INPUT_PATH + "minimal.xml"; + try { + EObject modelRoot = loadInputFile(inputFileName, new XMLPersistenceMappingResourceFactoryImpl(), null); + assertTrue(modelRoot instanceof Node); + Node rootNode = (Node) modelRoot; + assertTrue(rootNode.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + assertSame(1, ((XMLResource) modelRoot.eResource()).getEObjectToIDMap().size()); + + // test set + Node sub1Node = NodesFactory.eINSTANCE.createNode(); + Node sub2Node = NodesFactory.eINSTANCE.createNode(); + Node sub3Node = NodesFactory.eINSTANCE.createNode(); + Node sub4Node = NodesFactory.eINSTANCE.createNode(); + sub4Node.setName("sub4Node"); + + sub1Node.setEReference_Contained0101Single(sub2Node); + sub2Node.setEReference_Contained0101Single(sub3Node); + sub3Node.setEReference_Contained0101Single(sub4Node); + + assertFalse(sub1Node.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + assertFalse(sub2Node.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + assertFalse(sub3Node.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + assertTrue(sub4Node.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + assertEquals("sub4Node", sub4Node.getName()); + assertSame(1, ((XMLResource) modelRoot.eResource()).getEObjectToIDMap().size()); + + // set + rootNode.setEReference_Contained0100Single(sub1Node); + + assertTrue(sub1Node.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + assertTrue(sub2Node.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + assertTrue(sub3Node.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + assertTrue(sub4Node.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + assertEquals("sub4Node", sub4Node.getName()); + assertSame(5, ((XMLResource) modelRoot.eResource()).getEObjectToIDMap().size()); + + } catch (Exception ex) { + assertTrue(ex.getMessage(), false); + } + } + + @Test + public void testAddNewElementToEmptyResource() { + Resource resource = new XMLPersistenceMappingResourceImpl(); + Node node = NodesFactory.eINSTANCE.createNode(); + Node subNode = NodesFactory.eINSTANCE.createNode(); + node.getEReference_Contained0100Many().add(subNode); + assertFalse(node.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + assertFalse(subNode.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + + resource.getContents().add(node); + assertTrue(node.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + assertTrue(subNode.eIsSet(NodesPackage.eINSTANCE.getNode_Name())); + } + + @Test + public void testIdMapSet() { + XMLResource resource = new XMLPersistenceMappingResourceImpl(); + String nodeName = "root"; + String subNodeName = "subNode"; + Node node = NodesFactory.eINSTANCE.createNode(); + node.setName(nodeName); + Node subNode = NodesFactory.eINSTANCE.createNode(); + subNode.setName(subNodeName); + node.setEReference_Contained0100Single(subNode); + + assertNull(resource.getEObject(nodeName)); + assertNull(resource.getID(node)); + assertNull(resource.getEObject(subNodeName)); + assertNull(resource.getID(subNode)); + + resource.getContents().add(node); + assertSame(node, resource.getEObject(nodeName)); + assertSame(nodeName, resource.getID(node)); + + assertSame(subNode, resource.getEObject(subNodeName)); + assertSame(subNodeName, resource.getID(subNode)); + } + + @Test + public void testIdMapAdd() { + XMLResource resource = new XMLPersistenceMappingResourceImpl(); + String nodeName = "root"; + String subNodeName = "subNode"; + Node node = NodesFactory.eINSTANCE.createNode(); + node.setName(nodeName); + Node subNode = NodesFactory.eINSTANCE.createNode(); + subNode.setName(subNodeName); + node.getEReference_Contained0100Many().add(subNode); + + assertNull(resource.getEObject(nodeName)); + assertNull(resource.getID(node)); + assertNull(resource.getEObject(subNodeName)); + assertNull(resource.getID(subNode)); + + resource.getContents().add(node); + assertSame(node, resource.getEObject(nodeName)); + assertSame(nodeName, resource.getID(node)); + + assertSame(subNode, resource.getEObject(subNodeName)); + assertSame(subNodeName, resource.getID(subNode)); + } + + @Test + public void testIdMapAddMany() { + XMLResource resource = new XMLPersistenceMappingResourceImpl(); + String node1Name = "node1"; + String node2Name = "node2"; + Node node1 = NodesFactory.eINSTANCE.createNode(); + node1.setName(node1Name); + Node node2 = NodesFactory.eINSTANCE.createNode(); + node2.setName(node2Name); + List<Node> nodes = new ArrayList<Node>(2); + nodes.add(node1); + nodes.add(node2); + + assertNull(resource.getEObject(node1Name)); + assertNull(resource.getID(node1)); + assertNull(resource.getEObject(node2Name)); + assertNull(resource.getID(node2)); + + resource.getContents().addAll(nodes); + + assertSame(node1, resource.getEObject(node1Name)); + assertSame(node1Name, resource.getID(node1)); + + assertSame(node2, resource.getEObject(node2Name)); + assertSame(node2Name, resource.getID(node2)); + } + + @Test + public void testIdMapMove() { + XMLResource resource = new XMLPersistenceMappingResourceImpl(); + String nodeName = "root"; + String subNodeName = "subNode"; + Node node = NodesFactory.eINSTANCE.createNode(); + node.setName(nodeName); + Node subNode = NodesFactory.eINSTANCE.createNode(); + subNode.setName(subNodeName); + node.getEReference_Contained0100Many().add(subNode); + + assertNull(resource.getEObject(nodeName)); + assertNull(resource.getID(node)); + assertNull(resource.getEObject(subNodeName)); + assertNull(resource.getID(subNode)); + + resource.getContents().add(node); + assertSame(node, resource.getEObject(nodeName)); + assertSame(nodeName, resource.getID(node)); + assertSame(subNode, resource.getEObject(subNodeName)); + assertSame(subNodeName, resource.getID(subNode)); + + node.setEReference_Contained0100Single(subNode); + assertSame(node, resource.getEObject(nodeName)); + assertSame(nodeName, resource.getID(node)); + assertSame(subNode, resource.getEObject(subNodeName)); + assertSame(subNodeName, resource.getID(subNode)); + } + + @Test + public void testIdMapRemove() { + XMLResource resource = new XMLPersistenceMappingResourceImpl(); + String nodeName = "root"; + String subNodeName = "subNode"; + Node node = NodesFactory.eINSTANCE.createNode(); + node.setName(nodeName); + Node subNode = NodesFactory.eINSTANCE.createNode(); + subNode.setName(subNodeName); + node.getEReference_Contained0100Many().add(subNode); + + assertNull(resource.getEObject(nodeName)); + assertNull(resource.getID(node)); + assertNull(resource.getEObject(subNodeName)); + assertNull(resource.getID(subNode)); + + resource.getContents().add(node); + assertSame(node, resource.getEObject(nodeName)); + assertSame(nodeName, resource.getID(node)); + assertSame(subNode, resource.getEObject(subNodeName)); + assertSame(subNodeName, resource.getID(subNode)); + + node.getEReference_Contained0100Many().remove(subNode); + assertSame(node, resource.getEObject(nodeName)); + assertSame(nodeName, resource.getID(node)); + assertNull(resource.getEObject(subNodeName)); + assertNull(resource.getID(subNode)); + + resource.getContents().remove(node); + assertNull(resource.getEObject(nodeName)); + assertNull(resource.getID(node)); + assertNull(resource.getEObject(subNodeName)); + assertNull(resource.getID(subNode)); + } + + @Test + public void testIdMapRename() { + XMLResource resource = new XMLPersistenceMappingResourceImpl(); + String nodeName = "root"; + String newNodeName = "new_root"; + Node node = NodesFactory.eINSTANCE.createNode(); + node.setName(nodeName); + + assertNull(resource.getEObject(nodeName)); + assertNull(resource.getID(node)); + + resource.getContents().add(node); + assertNull(resource.getEObject(newNodeName)); + assertSame(node, resource.getEObject(nodeName)); + assertSame(nodeName, resource.getID(node)); + + node.setName(newNodeName); + assertNull(resource.getEObject(nodeName)); + assertSame(node, resource.getEObject(newNodeName)); + assertSame(newNodeName, resource.getID(node)); + } + +} |