Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2014-04-17 16:51:25 +0000
committerEd Merks2014-05-05 13:08:04 +0000
commitbeac8a81689e9a2b745078425914501ab764d39c (patch)
treebe22d94bbb694127dd11f29910d7ad9f9c279aa8
parent5101bb8dbce61f37339e2a44afa2640f441d7e71 (diff)
downloadorg.eclipse.emf-beac8a81689e9a2b745078425914501ab764d39c.tar.gz
org.eclipse.emf-beac8a81689e9a2b745078425914501ab764d39c.tar.xz
org.eclipse.emf-beac8a81689e9a2b745078425914501ab764d39c.zip
[433027] ECrossReferenceAdapter leaks cross-references on ETypedElement::eGenericType
https://bugs.eclipse.org/bugs/show_bug.cgi?id=433027 Fix memory leaks in ECrossReferenceAdapters that index the cross-references between ETypedElements and their types via contained EGenericTypes. Includes comprehensive JUnit tests for the intrinsic and extrinsic cross-reference iterator filtering and for the original memory-leak scenario. Signed-off-by: Christian W. Damus <give.a.damus@gmail.com> Change-Id: Ie6c5f0b6d5c32d8451b6dd96acad6a431be0c027
-rw-r--r--plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/util/EContentsEList.java60
-rw-r--r--plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/util/ECrossReferenceAdapter.java91
-rw-r--r--tests/org.eclipse.emf.test.core/META-INF/MANIFEST.MF7
-rw-r--r--tests/org.eclipse.emf.test.core/data/xrefs0.xmi19
-rw-r--r--tests/org.eclipse.emf.test.core/data/xrefs1.xmi21
-rw-r--r--tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/AllSuites.java3
-rw-r--r--tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/ecore/ECrossReferenceAdapterTest.java376
-rw-r--r--tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/A.java113
-rw-r--r--tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/XRefsModelFactory.java52
-rw-r--r--tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/XRefsModelPackage.java256
-rw-r--r--tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/impl/AImpl.java282
-rw-r--r--tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/impl/XRefsModelFactoryImpl.java115
-rw-r--r--tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/impl/XRefsModelPackageImpl.java230
-rw-r--r--tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/util/XRefsModelAdapterFactory.java141
-rw-r--r--tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/util/XRefsModelSwitch.java128
-rw-r--r--tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/util/XRefsModelUtil.java296
-rw-r--r--tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/xrefsmodel.ecore14
-rw-r--r--tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/xrefsmodel.genmodel18
18 files changed, 2201 insertions, 21 deletions
diff --git a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/util/EContentsEList.java b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/util/EContentsEList.java
index b4637f965..107568a0b 100644
--- a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/util/EContentsEList.java
+++ b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/util/EContentsEList.java
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2002-2007 IBM Corporation and others.
+ * Copyright (c) 2002-2014 IBM Corporation, itemis AG, CEA, 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
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM - Initial API and implementation
+ * Ed Merks (itemis AG) - bug 433027
+ * Christian W. Damus (CEA) - bug 433027
*/
package org.eclipse.emf.ecore.util;
@@ -311,7 +313,23 @@ public class EContentsEList<E> extends AbstractSequentialInternalEList<E> implem
// No new methods.
}
- public static class FeatureIteratorImpl<E> implements FeatureListIterator<E>
+ /**
+ * @since 2.10
+ */
+ public interface FeatureFilter
+ {
+ boolean isIncluded(EStructuralFeature eStructuralFeature);
+ }
+
+ /**
+ * @since 2.10
+ */
+ public interface Filterable
+ {
+ void filter(FeatureFilter featureFilter);
+ }
+
+ public static class FeatureIteratorImpl<E> implements FeatureListIterator<E>, Filterable
{
protected final EObject eObject;
protected final EStructuralFeature [] eStructuralFeatures;
@@ -328,6 +346,11 @@ public class EContentsEList<E> extends AbstractSequentialInternalEList<E> implem
protected int valueListSize;
protected int valueListIndex;
+ /**
+ * @since 2.10
+ */
+ protected FeatureFilter featureFilter;
+
public FeatureIteratorImpl(EObject eObject, List<? extends EStructuralFeature> eStructuralFeatures)
{
this.eObject = eObject;
@@ -361,6 +384,19 @@ public class EContentsEList<E> extends AbstractSequentialInternalEList<E> implem
return eStructuralFeature instanceof EReference && ((EReference)eStructuralFeature).isContainment();
}
+ /**
+ * @since 2.10
+ */
+ public void filter(FeatureFilter featureFilter)
+ {
+ if (prepared != 0 || this.featureFilter != null)
+ {
+ throw new IllegalStateException("Iterator already in use or already filtered"); //$NON-NLS-1$
+ }
+
+ this.featureFilter = featureFilter;
+ }
+
public EStructuralFeature feature()
{
return feature;
@@ -398,7 +434,7 @@ public class EContentsEList<E> extends AbstractSequentialInternalEList<E> implem
while (featureCursor < eStructuralFeatures.length)
{
EStructuralFeature feature = eStructuralFeatures[featureCursor++];
- if (isIncluded(feature) && (!useIsSet() || eObject.eIsSet(feature)))
+ if (isIncluded(feature) && (featureFilter == null || featureFilter.isIncluded(feature)) && (!useIsSet() || eObject.eIsSet(feature)))
{
Object value = eObject.eGet(feature, resolve());
isHandlingFeatureMap = FeatureMapUtil.isFeatureMap(feature);
@@ -505,7 +541,7 @@ public class EContentsEList<E> extends AbstractSequentialInternalEList<E> implem
{
FeatureMap.Entry entry = (FeatureMap.Entry)values.next();
EStructuralFeature entryFeature = entry.getEStructuralFeature();
- if (isIncludedEntry(entryFeature) && entry.getValue() != null)
+ if (isIncludedEntry(entryFeature) && (featureFilter == null || featureFilter.isIncluded(entryFeature)) && entry.getValue() != null)
{
values.previous();
return true;
@@ -531,7 +567,7 @@ public class EContentsEList<E> extends AbstractSequentialInternalEList<E> implem
valueList.get(valueListIndex) :
valueInternalEList.basicGet(valueListIndex));
EStructuralFeature entryFeature = entry.getEStructuralFeature();
- if (isIncludedEntry(entryFeature) && entry.getValue() != null)
+ if (isIncludedEntry(entryFeature) && (featureFilter == null || featureFilter.isIncluded(entryFeature)) && entry.getValue() != null)
{
return true;
}
@@ -602,7 +638,7 @@ public class EContentsEList<E> extends AbstractSequentialInternalEList<E> implem
while (featureCursor > 0)
{
EStructuralFeature feature = eStructuralFeatures[--featureCursor];
- if (isIncluded(feature) && (!useIsSet() || eObject.eIsSet(feature)))
+ if (isIncluded(feature) && (featureFilter == null || featureFilter.isIncluded(feature)) && (!useIsSet() || eObject.eIsSet(feature)))
{
Object value = eObject.eGet(feature, resolve());
isHandlingFeatureMap = FeatureMapUtil.isFeatureMap(feature);
@@ -707,7 +743,7 @@ public class EContentsEList<E> extends AbstractSequentialInternalEList<E> implem
{
FeatureMap.Entry entry = (FeatureMap.Entry)values.previous();
EStructuralFeature entryFeature = entry.getEStructuralFeature();
- if (isIncludedEntry(entryFeature) && entry.getValue() != null)
+ if (isIncludedEntry(entryFeature) && (featureFilter == null || featureFilter.isIncluded(entryFeature)) && entry.getValue() != null)
{
values.next();
return true;
@@ -729,7 +765,7 @@ public class EContentsEList<E> extends AbstractSequentialInternalEList<E> implem
{
FeatureMap.Entry entry = (FeatureMap.Entry)valueList.get(valueListIndex - 1);
EStructuralFeature entryFeature = entry.getEStructuralFeature();
- if (isIncludedEntry(entryFeature) && entry.getValue() != null)
+ if (isIncludedEntry(entryFeature) && (featureFilter == null || featureFilter.isIncluded(entryFeature)) && entry.getValue() != null)
{
return true;
}
@@ -787,6 +823,12 @@ public class EContentsEList<E> extends AbstractSequentialInternalEList<E> implem
new FeatureIteratorImpl<Object>(null, (EStructuralFeature [] )null)
{
@Override
+ public void filter(EContentsEList.FeatureFilter featureFilter)
+ {
+ // I'm empty, so there's nothing to filter
+ }
+
+ @Override
public boolean hasNext()
{
return false;
@@ -824,4 +866,4 @@ public class EContentsEList<E> extends AbstractSequentialInternalEList<E> implem
return true;
}
}
-}
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/util/ECrossReferenceAdapter.java b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/util/ECrossReferenceAdapter.java
index b242b2f13..af97bc352 100644
--- a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/util/ECrossReferenceAdapter.java
+++ b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/util/ECrossReferenceAdapter.java
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2005-2012 IBM Corporation and others.
+ * Copyright (c) 2005-2014 IBM Corporation, CEA, 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
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM - Initial API and implementation
+ * Christian W. Damus (CEA) - bug 433027
*/
package org.eclipse.emf.ecore.util;
@@ -19,6 +20,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.Set;
import org.eclipse.emf.common.notify.Adapter;
@@ -32,6 +34,7 @@ import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.util.EContentsEList.FeatureIterator;
/**
@@ -70,27 +73,97 @@ public class ECrossReferenceAdapter implements Adapter.Internal
protected Map<URI, List<EObject>> proxyMap;
+ /**
+ * @since 2.10
+ */
+ protected EContentsEList.FeatureFilter crossReferenceFilter;
+
protected InverseCrossReferencer()
{
super((Collection<Notifier>)null);
+
+ crossReferenceFilter = createCrossReferenceFilter();
+ }
+
+ /**
+ * @since 2.10
+ */
+ protected EContentsEList.FeatureFilter createCrossReferenceFilter()
+ {
+ return new EContentsEList.FeatureFilter()
+ {
+ public boolean isIncluded(EStructuralFeature eStructuralFeature)
+ {
+ return FeatureMapUtil.isFeatureMap(eStructuralFeature) || ECrossReferenceAdapter.this.isIncluded((EReference)eStructuralFeature);
+ }
+ };
}
@Override
protected EContentsEList.FeatureIterator<EObject> getCrossReferences(EObject eObject)
{
- return
- new ECrossReferenceEList.FeatureIteratorImpl<EObject>(eObject)
+ InternalEList<EObject> eCrossReferences = (InternalEList<EObject>)eObject.eCrossReferences();
+
+ final EContentsEList.FeatureIterator<EObject> underlyingIterator = (FeatureIterator<EObject>)(resolve() ? eCrossReferences.iterator() : eCrossReferences.basicIterator());
+
+ if (underlyingIterator instanceof EContentsEList.Filterable)
+ {
+ // Simply filter the model-provided iterator to skip the references that we don't need to index
+ ((EContentsEList.Filterable)underlyingIterator).filter(crossReferenceFilter);
+ return underlyingIterator;
+ }
+
+ // Otherwise, we'll post-filter the iterator, ourselves, but this does mean that we may compute derived features unnecessarily
+ return new EContentsEList.FeatureIterator<EObject>()
{
- @Override
- protected boolean isIncluded(EStructuralFeature eStructuralFeature)
+ private boolean prepared;
+
+ private EObject preparedNext;
+
+ private EStructuralFeature preparedFeature;
+
+ private EStructuralFeature feature;
+
+ public boolean hasNext()
{
- return FeatureMapUtil.isFeatureMap(eStructuralFeature) || ECrossReferenceAdapter.this.isIncluded((EReference)eStructuralFeature);
+ if (!prepared)
+ {
+ while (underlyingIterator.hasNext())
+ {
+ preparedNext = underlyingIterator.next();
+ preparedFeature = underlyingIterator.feature();
+ if (crossReferenceFilter.isIncluded(preparedFeature))
+ {
+ prepared = true;
+ break;
+ }
+ }
+ }
+
+ return prepared;
}
- @Override
- protected boolean resolve()
+ public EObject next()
+ {
+ if (!prepared && !hasNext())
+ {
+ throw new NoSuchElementException();
+ }
+
+ feature = preparedFeature;
+ prepared = false;
+ return preparedNext;
+ }
+
+ public void remove()
+ {
+ // Must not attempt to remove cross-references in indexing them
+ throw new UnsupportedOperationException();
+ }
+
+ public EStructuralFeature feature()
{
- return InverseCrossReferencer.this.resolve();
+ return feature;
}
};
}
diff --git a/tests/org.eclipse.emf.test.core/META-INF/MANIFEST.MF b/tests/org.eclipse.emf.test.core/META-INF/MANIFEST.MF
index 195b8670a..3e27c759d 100644
--- a/tests/org.eclipse.emf.test.core/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.emf.test.core/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
-Bundle-SymbolicName: org.eclipse.emf.test.core; singleton:=true
+Bundle-SymbolicName: org.eclipse.emf.test.core;singleton:=true
Bundle-Version: 2.10.0.qualifier
Bundle-ClassPath: test.core.jar
Bundle-Vendor: %providerName
@@ -19,7 +19,10 @@ Export-Package: org.eclipse.emf.test.core,
org.eclipse.emf.test.core.featuremap,
org.eclipse.emf.test.core.featuremap.supplier,
org.eclipse.emf.test.core.featuremap.supplier.impl,
- org.eclipse.emf.test.core.featuremap.supplier.util
+ org.eclipse.emf.test.core.featuremap.supplier.util,
+ org.eclipse.emf.test.core.xrefsmodel,
+ org.eclipse.emf.test.core.xrefsmodel.impl,
+ org.eclipse.emf.test.core.xrefsmodel.util
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.core.resources,
org.eclipse.emf.ecore,
diff --git a/tests/org.eclipse.emf.test.core/data/xrefs0.xmi b/tests/org.eclipse.emf.test.core/data/xrefs0.xmi
new file mode 100644
index 000000000..522ed4514
--- /dev/null
+++ b/tests/org.eclipse.emf.test.core/data/xrefs0.xmi
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ASCII"?>
+<xmi:XMI xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xrefs="http://www.eclipse.org/EMF/2014/test/xrefsmodel">
+ <xrefs:A
+ name="a0">
+ <others href="xrefs1.xmi#/0"/>
+ <others href="xrefs1.xmi#/1"/>
+ <nonOthers href="xrefs1.xmi#/2"/>
+ </xrefs:A>
+ <xrefs:A
+ name="a5">
+ </xrefs:A>
+ <xrefs:A
+ name="a6">
+ <others href="xrefs1.xmi#/0"/>
+ </xrefs:A>
+</xmi:XMI>
diff --git a/tests/org.eclipse.emf.test.core/data/xrefs1.xmi b/tests/org.eclipse.emf.test.core/data/xrefs1.xmi
new file mode 100644
index 000000000..1a557027d
--- /dev/null
+++ b/tests/org.eclipse.emf.test.core/data/xrefs1.xmi
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="ASCII"?>
+<xmi:XMI xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xrefs="http://www.eclipse.org/EMF/2014/test/xrefsmodel">
+ <xrefs:A
+ name="a1"
+ others="/2 /3">
+ </xrefs:A>
+ <xrefs:A
+ name="a2">
+ <others href="xrefs0.xmi#/1"/>
+ <others href="xrefs0.xmi#/2"/>
+ </xrefs:A>
+ <xrefs:A
+ name="a3">
+ </xrefs:A>
+ <xrefs:A
+ name="a4">
+ </xrefs:A>
+</xmi:XMI>
diff --git a/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/AllSuites.java b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/AllSuites.java
index 93b3cc9d2..65c285675 100644
--- a/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/AllSuites.java
+++ b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/AllSuites.java
@@ -7,7 +7,7 @@
*
* Contributors:
* IBM - Initial API and implementation
- * Christian W. Damus (CEA) - 433108
+ * Christian W. Damus (CEA) - 433108, 433027
*/
package org.eclipse.emf.test.core;
@@ -52,6 +52,7 @@ public class AllSuites extends TestSuite
org.eclipse.emf.test.core.ecore.SwitchTest.suite(),
org.eclipse.emf.test.core.ecore.ResourceSetMappedResourceLocatorTest.suite(),
org.eclipse.emf.test.core.ecore.ReificationTest.suite(),
+ org.eclipse.emf.test.core.ecore.ECrossReferenceAdapterTest.suite(),
org.eclipse.emf.test.core.common.util.WeakInterningHashSetTest.suite(),
org.eclipse.emf.test.core.common.util.PoolTest.suite(),
org.eclipse.emf.test.core.common.util.StringPoolTest.suite(),
diff --git a/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/ecore/ECrossReferenceAdapterTest.java b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/ecore/ECrossReferenceAdapterTest.java
new file mode 100644
index 000000000..969b9843e
--- /dev/null
+++ b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/ecore/ECrossReferenceAdapterTest.java
@@ -0,0 +1,376 @@
+/**
+ * Copyright (c) 2014 CEA 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:
+ * CEA - Initial API and implementation
+ */
+package org.eclipse.emf.test.core.ecore;
+
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EGenericType;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.ETypedElement;
+import org.eclipse.emf.ecore.EcoreFactory;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceImpl;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.EContentsEList;
+import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
+import org.eclipse.emf.test.common.TestUtil;
+import org.eclipse.emf.test.core.AllSuites;
+import org.eclipse.emf.test.core.xrefsmodel.A;
+import org.eclipse.emf.test.core.xrefsmodel.XRefsModelPackage;
+import org.eclipse.emf.test.core.xrefsmodel.util.XRefsModelUtil;
+
+
+public class ECrossReferenceAdapterTest extends TestCase
+{
+ private EPackage testPackage;
+
+ private EAttribute mapAttribute;
+
+ private ECrossReferenceAdapterFixture fixture;
+
+ public ECrossReferenceAdapterTest(String name)
+ {
+ super(name);
+ }
+
+ public static Test suite()
+ {
+ TestSuite ts = new TestSuite("ECrossReferenceAdapterTest");
+ ts.addTest(new ECrossReferenceAdapterTest("testCrossReferenceIterator_resolving"));
+ ts.addTest(new ECrossReferenceAdapterTest("testCrossReferenceIterator_nonResolving"));
+ ts.addTest(new ECrossReferenceAdapterTest("testCrossReferenceIterator_resolving_wrapper"));
+ ts.addTest(new ECrossReferenceAdapterTest("testCrossReferenceIterator_nonResolving_wrapper"));
+ ts.addTest(new ECrossReferenceAdapterTest("testSimpleTypeTypeReferencesDoNotLeak"));
+ ts.addTest(new ECrossReferenceAdapterTest("testGenericTypeTypeReferencesDoNotLeak"));
+ return ts;
+ }
+
+ /**
+ * Tests the filtered intrinsic cross-reference iterator for a resolving cross-referencer.
+ */
+ public void testCrossReferenceIterator_resolving()
+ {
+ A a0 = loadXRefsInstance();
+
+ List<EStructuralFeature> expectedEntries = new ArrayList<EStructuralFeature>(Arrays.asList(
+ XRefsModelPackage.Literals.A__OTHERS,
+ XRefsModelPackage.Literals.A__OTHERS,
+ XRefsModelPackage.Literals.A__NON_OTHERS));
+ List<String> expectedNames = new ArrayList<String>(Arrays.asList("a1", "a2", "a3"));
+ for (EContentsEList.FeatureIterator<EObject> iter = fixture.getCrossReferences(a0); iter.hasNext();)
+ {
+ A next = (A)iter.next();
+ EStructuralFeature feature = iter.feature();
+
+ // Assert that we don't get an unexpected entry
+ assertTrue(expectedEntries.remove(feature));
+
+ // Assert that we get the expected object
+ assertFalse(next.eIsProxy());
+ assertEquals(expectedNames.remove(0), next.getName());
+ }
+
+ // Assert that all of the expected entries were found
+ assertTrue(expectedEntries.isEmpty());
+ }
+
+ /**
+ * Tests the filtered intrinsic cross-reference iterator for a non-resolving cross-referencer.
+ */
+ public void testCrossReferenceIterator_nonResolving()
+ {
+ // Don't resolve cross-references
+ fixture.setResolve(false);
+
+ A a0 = loadXRefsInstance();
+
+ List<EStructuralFeature> expectedEntries = new ArrayList<EStructuralFeature>(Arrays.asList(
+ XRefsModelPackage.Literals.A__OTHERS,
+ XRefsModelPackage.Literals.A__OTHERS,
+ XRefsModelPackage.Literals.A__NON_OTHERS));
+ List<String> expectedURIs = new ArrayList<String>(Arrays.asList("xrefs1.xmi#/0", "xrefs1.xmi#/1", "xrefs1.xmi#/2"));
+ for (EContentsEList.FeatureIterator<EObject> iter = fixture.getCrossReferences(a0); iter.hasNext();)
+ {
+ A next = (A)iter.next();
+ EStructuralFeature feature = iter.feature();
+
+ // Assert that we don't get an unexpected entry
+ assertTrue(expectedEntries.remove(feature));
+
+ // Assert that we get the expected object
+ assertTrue(next.eIsProxy());
+ assertEquals(expectedURIs.remove(0), EcoreUtil.getURI(next).deresolve(a0.eResource().getURI()).toString());
+ }
+
+ // Assert that all of the expected entries were found
+ assertTrue(expectedEntries.isEmpty());
+ }
+
+ /**
+ * Tests the wrapped intrinsic cross-reference iterator for a resolving cross-referencer. This also tests that
+ * its implementation of {@link EContentsEList.FeatureIterator#feature()} is consistent.
+ */
+ public void testCrossReferenceIterator_resolving_wrapper()
+ {
+ XRefsModelUtil.setWrapCrossReferenceIterators(true);
+
+ A a0 = loadXRefsInstance();
+
+ List<EStructuralFeature> expectedEntries = new ArrayList<EStructuralFeature>(Arrays.asList(
+ XRefsModelPackage.Literals.A__OTHERS,
+ XRefsModelPackage.Literals.A__OTHERS,
+ XRefsModelPackage.Literals.A__NON_OTHERS));
+ List<String> expectedNames = new ArrayList<String>(Arrays.asList("a1", "a2", "a3"));
+ for (EContentsEList.FeatureIterator<EObject> iter = fixture.getCrossReferences(a0); iter.hasNext();)
+ {
+ A next = (A)iter.next();
+ EStructuralFeature feature = iter.feature();
+
+ // Assert that we don't get an unexpected entry
+ assertTrue(expectedEntries.remove(feature));
+
+ // Assert that we get the expected object
+ assertFalse(next.eIsProxy());
+ assertEquals(expectedNames.remove(0), next.getName());
+ }
+
+ // Assert that all of the expected entries were found
+ assertTrue(expectedEntries.isEmpty());
+
+ // And that we couldn't avoid calling the derived A::getAllOthers() exactly twice:
+ // once for eIsSet() and once for eGet()
+ assertEquals(2, XRefsModelUtil.getAllOthersCallCount());
+ }
+
+ /**
+ * Tests the wrapped intrinsic cross-reference iterator for a non-resolving cross-referencer. This also tests that
+ * its implementation of {@link EContentsEList.FeatureIterator#feature()} is consistent.
+ */
+ public void testCrossReferenceIterator_nonResolving_wrapper()
+ {
+ XRefsModelUtil.setWrapCrossReferenceIterators(true);
+
+ // Don't resolve cross-references
+ fixture.setResolve(false);
+
+ A a0 = loadXRefsInstance();
+
+ List<EStructuralFeature> expectedEntries = new ArrayList<EStructuralFeature>(Arrays.asList(
+ XRefsModelPackage.Literals.A__OTHERS,
+ XRefsModelPackage.Literals.A__OTHERS,
+ XRefsModelPackage.Literals.A__NON_OTHERS));
+ List<String> expectedURIs = new ArrayList<String>(Arrays.asList("xrefs1.xmi#/0", "xrefs1.xmi#/1", "xrefs1.xmi#/2"));
+ for (EContentsEList.FeatureIterator<EObject> iter = fixture.getCrossReferences(a0); iter.hasNext();)
+ {
+ A next = (A)iter.next();
+ EStructuralFeature feature = iter.feature();
+
+ // Assert that we don't get an unexpected entry
+ assertTrue(expectedEntries.remove(feature));
+
+ // Assert that we get the expected object
+ assertTrue(next.eIsProxy());
+ assertEquals(expectedURIs.remove(0), EcoreUtil.getURI(next).deresolve(a0.eResource().getURI()).toString());
+ }
+
+ // Assert that all of the expected entries were found
+ assertTrue(expectedEntries.isEmpty());
+
+ // And that we couldn't avoid calling the derived A::getAllOthers() exactly twice:
+ // once for eIsSet() and once for eGet()
+ assertEquals(2, XRefsModelUtil.getAllOthersCallCount());
+ }
+
+ /**
+ * Control test case: ETypedElements referencing types simply by eType.
+ */
+ public void testSimpleTypeTypeReferencesDoNotLeak()
+ {
+ Resource resource = new ResourceImpl(URI.createURI("http:///bogus/testpackage.ecore"));
+ resource.getContents().add(testPackage);
+ resource.eAdapters().add(fixture);
+ EcoreUtil.resolveAll(resource);
+
+ // sanity check
+ assertSame(EcorePackage.Literals.ESTRING, mapAttribute.getEType());
+
+ fixture.assertCrossReferenceMapNotEmpty();
+ fixture.assertCrossReferenced(mapAttribute, EcorePackage.Literals.ESTRING);
+
+ resource.unload();
+
+ fixture.assertCrossReferenceMapEmpty();
+ }
+
+ /**
+ * Memory leak scenario: ETypedElements referencing types via eGenericType
+ *
+ * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=433027
+ */
+ public void testGenericTypeTypeReferencesDoNotLeak()
+ {
+ // change the map attribute to a generic type
+ mapAttribute.setEType(null);
+ EGenericType genType = EcoreFactory.eINSTANCE.createEGenericType();
+ mapAttribute.setEGenericType(genType);
+ genType.setEClassifier(EcorePackage.Literals.EMAP);
+ EGenericType k = EcoreFactory.eINSTANCE.createEGenericType();
+ genType.getETypeArguments().add(k);
+ k.setEClassifier(EcorePackage.Literals.EJAVA_OBJECT);
+ EGenericType t = EcoreFactory.eINSTANCE.createEGenericType();
+ genType.getETypeArguments().add(t);
+ t.setEClassifier(EcorePackage.Literals.EJAVA_OBJECT);
+
+ Resource resource = new ResourceImpl(URI.createURI("http:///bogus/testpackage.ecore"));
+ resource.getContents().add(testPackage);
+ resource.eAdapters().add(fixture);
+ EcoreUtil.resolveAll(resource);
+
+ // sanity check
+ assertSame(EcorePackage.Literals.EMAP, mapAttribute.getEType());
+
+ fixture.assertCrossReferenceMapNotEmpty();
+ fixture.assertCrossReferenced(mapAttribute, EcorePackage.Literals.EMAP);
+
+ resource.unload();
+
+ fixture.assertCrossReferenceMapEmpty();
+ }
+
+ //
+ // Test framework
+ //
+
+ @Override
+ protected void setUp()
+ {
+ // We must never call the A::getAllOthers() derived reference accessor when cross-referencing
+ XRefsModelUtil.assertNoAllOthersCalls(true);
+
+ fixture = new ECrossReferenceAdapterFixture();
+
+ testPackage = EcoreFactory.eINSTANCE.createEPackage();
+ testPackage.setName("test");
+ testPackage.setNsPrefix("test");
+ testPackage.setNsURI("http://testpackage");
+
+ EClass foo = EcoreFactory.eINSTANCE.createEClass();
+ testPackage.getEClassifiers().add(foo);
+ foo.setName("Foo");
+
+ mapAttribute = EcoreFactory.eINSTANCE.createEAttribute();
+ foo.getEStructuralFeatures().add(mapAttribute);
+ mapAttribute.setName("map");
+ mapAttribute.setEType(EcorePackage.Literals.ESTRING);
+ }
+
+ @Override
+ protected void tearDown()
+ {
+ XRefsModelUtil.assertNoAllOthersCalls(false);
+
+ // In case it was set by a test case
+ XRefsModelUtil.setWrapCrossReferenceIterators(false);
+
+ testPackage = null;
+ mapAttribute = null;
+ fixture = null;
+ }
+
+ A loadXRefsInstance()
+ {
+ ResourceSet rset = new ResourceSetImpl();
+ rset.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xmi", new XMIResourceFactoryImpl());
+ rset.getPackageRegistry().put(XRefsModelPackage.eNS_URI, XRefsModelPackage.eINSTANCE);
+ Resource resource = rset.getResource(URI.createFileURI(TestUtil.getPluginDirectory(AllSuites.PLUGIN_ID) + "/data/xrefs0.xmi"), true);
+ return (A)resource.getContents().get(0);
+ }
+
+ static class ECrossReferenceAdapterFixture extends ECrossReferenceAdapter
+ {
+ private boolean resolve = true;
+
+ class InverseCrossReferencerFixture extends InverseCrossReferencer
+ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected EContentsEList.FeatureIterator<EObject> getCrossReferences(EObject eObject)
+ {
+ return super.getCrossReferences(eObject);
+ }
+ }
+
+ @Override
+ protected InverseCrossReferencer createInverseCrossReferencer()
+ {
+ return new InverseCrossReferencerFixture();
+ }
+
+ EContentsEList.FeatureIterator<EObject> getCrossReferences(EObject eObject)
+ {
+ return ((InverseCrossReferencerFixture)inverseCrossReferencer).getCrossReferences(eObject);
+ }
+
+ void setResolve(boolean resolve)
+ {
+ this.resolve = resolve;
+ }
+
+ @Override
+ protected boolean resolve()
+ {
+ return resolve;
+ }
+
+ void assertCrossReferenced(ETypedElement typedElement, EClassifier type)
+ {
+ Collection<EStructuralFeature.Setting> settings = getInverseReferences(type);
+ for (EStructuralFeature.Setting next : settings)
+ {
+ if ((next.getEObject() == typedElement) && (next.getEStructuralFeature() == EcorePackage.Literals.ETYPED_ELEMENT__ETYPE))
+ {
+ return;
+ }
+ }
+
+ fail("Cross-reference not found for ETypedElement::eType");
+ }
+
+ void assertCrossReferenceMapNotEmpty()
+ {
+ assertFalse("Cross-reference map is empty", inverseCrossReferencer.isEmpty());
+ }
+
+ void assertCrossReferenceMapEmpty()
+ {
+ assertTrue("Cross-reference map is not empty", inverseCrossReferencer.isEmpty());
+ }
+ }
+}
diff --git a/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/A.java b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/A.java
new file mode 100644
index 000000000..c69f28a7a
--- /dev/null
+++ b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/A.java
@@ -0,0 +1,113 @@
+/**
+ * Copyright (c) 2014 CEA 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:
+ * CEA - Initial API and implementation
+ *
+ */
+package org.eclipse.emf.test.core.xrefsmodel;
+
+import org.eclipse.emf.common.util.EList;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * <!-- begin-user-doc -->
+ * A representation of the model object '<em><b>A</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ * <p>
+ * The following features are supported:
+ * <ul>
+ * <li>{@link org.eclipse.emf.test.core.xrefsmodel.A#getName <em>Name</em>}</li>
+ * <li>{@link org.eclipse.emf.test.core.xrefsmodel.A#getOthers <em>Others</em>}</li>
+ * <li>{@link org.eclipse.emf.test.core.xrefsmodel.A#getAllOthers <em>All Others</em>}</li>
+ * <li>{@link org.eclipse.emf.test.core.xrefsmodel.A#getNonOthers <em>Non Others</em>}</li>
+ * </ul>
+ * </p>
+ *
+ * @see org.eclipse.emf.test.core.xrefsmodel.XRefsModelPackage#getA()
+ * @model
+ * @generated
+ */
+public interface A extends EObject
+{
+ /**
+ * Returns the value of the '<em><b>Name</b></em>' attribute.
+ * <!-- begin-user-doc -->
+ * <p>
+ * If the meaning of the '<em>Name</em>' attribute isn't clear,
+ * there really should be more of a description here...
+ * </p>
+ * <!-- end-user-doc -->
+ * @return the value of the '<em>Name</em>' attribute.
+ * @see #setName(String)
+ * @see org.eclipse.emf.test.core.xrefsmodel.XRefsModelPackage#getA_Name()
+ * @model required="true"
+ * @generated
+ */
+ String getName();
+
+ /**
+ * Sets the value of the '{@link org.eclipse.emf.test.core.xrefsmodel.A#getName <em>Name</em>}' attribute.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @param value the new value of the '<em>Name</em>' attribute.
+ * @see #getName()
+ * @generated
+ */
+ void setName(String value);
+
+ /**
+ * Returns the value of the '<em><b>Others</b></em>' reference list.
+ * The list contents are of type {@link org.eclipse.emf.test.core.xrefsmodel.A}.
+ * <!-- begin-user-doc -->
+ * <p>
+ * If the meaning of the '<em>Others</em>' reference list isn't clear,
+ * there really should be more of a description here...
+ * </p>
+ * <!-- end-user-doc -->
+ * @return the value of the '<em>Others</em>' reference list.
+ * @see org.eclipse.emf.test.core.xrefsmodel.XRefsModelPackage#getA_Others()
+ * @model
+ * @generated
+ */
+ EList<A> getOthers();
+
+ /**
+ * Returns the value of the '<em><b>All Others</b></em>' reference list.
+ * The list contents are of type {@link org.eclipse.emf.test.core.xrefsmodel.A}.
+ * <!-- begin-user-doc -->
+ * <p>
+ * If the meaning of the '<em>All Others</em>' reference list isn't clear,
+ * there really should be more of a description here...
+ * </p>
+ * <!-- end-user-doc -->
+ * @return the value of the '<em>All Others</em>' reference list.
+ * @see org.eclipse.emf.test.core.xrefsmodel.XRefsModelPackage#getA_AllOthers()
+ * @model transient="true" changeable="false" volatile="true" derived="true"
+ * @generated
+ */
+ EList<A> getAllOthers();
+
+ /**
+ * Returns the value of the '<em><b>Non Others</b></em>' reference list.
+ * The list contents are of type {@link org.eclipse.emf.test.core.xrefsmodel.A}.
+ * <!-- begin-user-doc -->
+ * <p>
+ * If the meaning of the '<em>Non Others</em>' reference list isn't clear,
+ * there really should be more of a description here...
+ * </p>
+ * <!-- end-user-doc -->
+ * @return the value of the '<em>Non Others</em>' reference list.
+ * @see org.eclipse.emf.test.core.xrefsmodel.XRefsModelPackage#getA_NonOthers()
+ * @model
+ * @generated
+ */
+ EList<A> getNonOthers();
+
+} // A
diff --git a/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/XRefsModelFactory.java b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/XRefsModelFactory.java
new file mode 100644
index 000000000..d51e63a46
--- /dev/null
+++ b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/XRefsModelFactory.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2014 CEA 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:
+ * CEA - Initial API and implementation
+ *
+ */
+package org.eclipse.emf.test.core.xrefsmodel;
+
+import org.eclipse.emf.ecore.EFactory;
+
+/**
+ * <!-- begin-user-doc -->
+ * The <b>Factory</b> for the model.
+ * It provides a create method for each non-abstract class of the model.
+ * <!-- end-user-doc -->
+ * @see org.eclipse.emf.test.core.xrefsmodel.XRefsModelPackage
+ * @generated
+ */
+public interface XRefsModelFactory extends EFactory
+{
+ /**
+ * The singleton instance of the factory.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ XRefsModelFactory eINSTANCE = org.eclipse.emf.test.core.xrefsmodel.impl.XRefsModelFactoryImpl.init();
+
+ /**
+ * Returns a new object of class '<em>A</em>'.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @return a new object of class '<em>A</em>'.
+ * @generated
+ */
+ A createA();
+
+ /**
+ * Returns the package supported by this factory.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @return the package supported by this factory.
+ * @generated
+ */
+ XRefsModelPackage getXRefsModelPackage();
+
+} //XRefsModelFactory
diff --git a/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/XRefsModelPackage.java b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/XRefsModelPackage.java
new file mode 100644
index 000000000..b11b62ee2
--- /dev/null
+++ b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/XRefsModelPackage.java
@@ -0,0 +1,256 @@
+/**
+ * Copyright (c) 2014 CEA 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:
+ * CEA - Initial API and implementation
+ *
+ */
+package org.eclipse.emf.test.core.xrefsmodel;
+
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+
+/**
+ * <!-- begin-user-doc -->
+ * The <b>Package</b> for the model.
+ * It contains accessors for the meta objects to represent
+ * <ul>
+ * <li>each class,</li>
+ * <li>each feature of each class,</li>
+ * <li>each operation of each class,</li>
+ * <li>each enum,</li>
+ * <li>and each data type</li>
+ * </ul>
+ * <!-- end-user-doc -->
+ * @see org.eclipse.emf.test.core.xrefsmodel.XRefsModelFactory
+ * @model kind="package"
+ * @generated
+ */
+public interface XRefsModelPackage extends EPackage
+{
+ /**
+ * The package name.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ String eNAME = "xrefsmodel";
+
+ /**
+ * The package namespace URI.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ String eNS_URI = "http://www.eclipse.org/EMF/2014/test/xrefsmodel";
+
+ /**
+ * The package namespace name.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ String eNS_PREFIX = "xrefs";
+
+ /**
+ * The singleton instance of the package.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ XRefsModelPackage eINSTANCE = org.eclipse.emf.test.core.xrefsmodel.impl.XRefsModelPackageImpl.init();
+
+ /**
+ * The meta object id for the '{@link org.eclipse.emf.test.core.xrefsmodel.impl.AImpl <em>A</em>}' class.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @see org.eclipse.emf.test.core.xrefsmodel.impl.AImpl
+ * @see org.eclipse.emf.test.core.xrefsmodel.impl.XRefsModelPackageImpl#getA()
+ * @generated
+ */
+ int A = 0;
+
+ /**
+ * The feature id for the '<em><b>Name</b></em>' attribute.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ * @ordered
+ */
+ int A__NAME = 0;
+
+ /**
+ * The feature id for the '<em><b>Others</b></em>' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ * @ordered
+ */
+ int A__OTHERS = 1;
+
+ /**
+ * The feature id for the '<em><b>All Others</b></em>' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ * @ordered
+ */
+ int A__ALL_OTHERS = 2;
+
+ /**
+ * The feature id for the '<em><b>Non Others</b></em>' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ * @ordered
+ */
+ int A__NON_OTHERS = 3;
+
+ /**
+ * The number of structural features of the '<em>A</em>' class.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ * @ordered
+ */
+ int A_FEATURE_COUNT = 4;
+
+ /**
+ * The number of operations of the '<em>A</em>' class.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ * @ordered
+ */
+ int A_OPERATION_COUNT = 0;
+
+
+ /**
+ * Returns the meta object for class '{@link org.eclipse.emf.test.core.xrefsmodel.A <em>A</em>}'.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @return the meta object for class '<em>A</em>'.
+ * @see org.eclipse.emf.test.core.xrefsmodel.A
+ * @generated
+ */
+ EClass getA();
+
+ /**
+ * Returns the meta object for the attribute '{@link org.eclipse.emf.test.core.xrefsmodel.A#getName <em>Name</em>}'.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @return the meta object for the attribute '<em>Name</em>'.
+ * @see org.eclipse.emf.test.core.xrefsmodel.A#getName()
+ * @see #getA()
+ * @generated
+ */
+ EAttribute getA_Name();
+
+ /**
+ * Returns the meta object for the reference list '{@link org.eclipse.emf.test.core.xrefsmodel.A#getOthers <em>Others</em>}'.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @return the meta object for the reference list '<em>Others</em>'.
+ * @see org.eclipse.emf.test.core.xrefsmodel.A#getOthers()
+ * @see #getA()
+ * @generated
+ */
+ EReference getA_Others();
+
+ /**
+ * Returns the meta object for the reference list '{@link org.eclipse.emf.test.core.xrefsmodel.A#getAllOthers <em>All Others</em>}'.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @return the meta object for the reference list '<em>All Others</em>'.
+ * @see org.eclipse.emf.test.core.xrefsmodel.A#getAllOthers()
+ * @see #getA()
+ * @generated
+ */
+ EReference getA_AllOthers();
+
+ /**
+ * Returns the meta object for the reference list '{@link org.eclipse.emf.test.core.xrefsmodel.A#getNonOthers <em>Non Others</em>}'.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @return the meta object for the reference list '<em>Non Others</em>'.
+ * @see org.eclipse.emf.test.core.xrefsmodel.A#getNonOthers()
+ * @see #getA()
+ * @generated
+ */
+ EReference getA_NonOthers();
+
+ /**
+ * Returns the factory that creates the instances of the model.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @return the factory that creates the instances of the model.
+ * @generated
+ */
+ XRefsModelFactory getXRefsModelFactory();
+
+ /**
+ * <!-- begin-user-doc -->
+ * Defines literals for the meta objects that represent
+ * <ul>
+ * <li>each class,</li>
+ * <li>each feature of each class,</li>
+ * <li>each operation of each class,</li>
+ * <li>each enum,</li>
+ * <li>and each data type</li>
+ * </ul>
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ interface Literals
+ {
+ /**
+ * The meta object literal for the '{@link org.eclipse.emf.test.core.xrefsmodel.impl.AImpl <em>A</em>}' class.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @see org.eclipse.emf.test.core.xrefsmodel.impl.AImpl
+ * @see org.eclipse.emf.test.core.xrefsmodel.impl.XRefsModelPackageImpl#getA()
+ * @generated
+ */
+ EClass A = eINSTANCE.getA();
+
+ /**
+ * The meta object literal for the '<em><b>Name</b></em>' attribute feature.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ EAttribute A__NAME = eINSTANCE.getA_Name();
+
+ /**
+ * The meta object literal for the '<em><b>Others</b></em>' reference list feature.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ EReference A__OTHERS = eINSTANCE.getA_Others();
+
+ /**
+ * The meta object literal for the '<em><b>All Others</b></em>' reference list feature.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ EReference A__ALL_OTHERS = eINSTANCE.getA_AllOthers();
+
+ /**
+ * The meta object literal for the '<em><b>Non Others</b></em>' reference list feature.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ EReference A__NON_OTHERS = eINSTANCE.getA_NonOthers();
+
+ }
+
+} //XRefsModelPackage
diff --git a/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/impl/AImpl.java b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/impl/AImpl.java
new file mode 100644
index 000000000..d0afa3646
--- /dev/null
+++ b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/impl/AImpl.java
@@ -0,0 +1,282 @@
+/**
+ * Copyright (c) 2014 CEA 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:
+ * CEA - Initial API and implementation
+ *
+ */
+package org.eclipse.emf.test.core.xrefsmodel.impl;
+
+import java.util.Collection;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.impl.ENotificationImpl;
+import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
+import org.eclipse.emf.ecore.util.EObjectResolvingEList;
+import org.eclipse.emf.test.core.xrefsmodel.A;
+import org.eclipse.emf.test.core.xrefsmodel.XRefsModelPackage;
+import org.eclipse.emf.test.core.xrefsmodel.util.XRefsModelUtil;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>A</b></em>'.
+ * <!-- end-user-doc -->
+ * <p>
+ * The following features are implemented:
+ * <ul>
+ * <li>{@link org.eclipse.emf.test.core.xrefsmodel.impl.AImpl#getName <em>Name</em>}</li>
+ * <li>{@link org.eclipse.emf.test.core.xrefsmodel.impl.AImpl#getOthers <em>Others</em>}</li>
+ * <li>{@link org.eclipse.emf.test.core.xrefsmodel.impl.AImpl#getAllOthers <em>All Others</em>}</li>
+ * <li>{@link org.eclipse.emf.test.core.xrefsmodel.impl.AImpl#getNonOthers <em>Non Others</em>}</li>
+ * </ul>
+ * </p>
+ *
+ * @generated
+ */
+public class AImpl extends MinimalEObjectImpl.Container implements A
+{
+ /**
+ * The default value of the '{@link #getName() <em>Name</em>}' attribute.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @see #getName()
+ * @generated
+ * @ordered
+ */
+ protected static final String NAME_EDEFAULT = null;
+
+ /**
+ * The cached value of the '{@link #getName() <em>Name</em>}' attribute.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @see #getName()
+ * @generated
+ * @ordered
+ */
+ protected String name = NAME_EDEFAULT;
+
+ /**
+ * The cached value of the '{@link #getOthers() <em>Others</em>}' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @see #getOthers()
+ * @generated
+ * @ordered
+ */
+ protected EList<A> others;
+
+ /**
+ * The cached value of the '{@link #getNonOthers() <em>Non Others</em>}' reference list.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @see #getNonOthers()
+ * @generated
+ * @ordered
+ */
+ protected EList<A> nonOthers;
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ protected AImpl()
+ {
+ super();
+ }
+
+ @Override
+ public EList<EObject> eCrossReferences()
+ {
+ return XRefsModelUtil.getCrossReferences(super.eCrossReferences());
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ @Override
+ protected EClass eStaticClass()
+ {
+ return XRefsModelPackage.Literals.A;
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public void setName(String newName)
+ {
+ String oldName = name;
+ name = newName;
+ if (eNotificationRequired())
+ eNotify(new ENotificationImpl(this, Notification.SET, XRefsModelPackage.A__NAME, oldName, name));
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public EList<A> getOthers()
+ {
+ if (others == null)
+ {
+ others = new EObjectResolvingEList<A>(A.class, this, XRefsModelPackage.A__OTHERS);
+ }
+ return others;
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated NOT
+ */
+ public EList<A> getAllOthers()
+ {
+ return XRefsModelUtil.getAllOthers(this);
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public EList<A> getNonOthers()
+ {
+ if (nonOthers == null)
+ {
+ nonOthers = new EObjectResolvingEList<A>(A.class, this, XRefsModelPackage.A__NON_OTHERS);
+ }
+ return nonOthers;
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ @Override
+ public Object eGet(int featureID, boolean resolve, boolean coreType)
+ {
+ switch (featureID)
+ {
+ case XRefsModelPackage.A__NAME:
+ return getName();
+ case XRefsModelPackage.A__OTHERS:
+ return getOthers();
+ case XRefsModelPackage.A__ALL_OTHERS:
+ return getAllOthers();
+ case XRefsModelPackage.A__NON_OTHERS:
+ return getNonOthers();
+ }
+ return super.eGet(featureID, resolve, coreType);
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void eSet(int featureID, Object newValue)
+ {
+ switch (featureID)
+ {
+ case XRefsModelPackage.A__NAME:
+ setName((String)newValue);
+ return;
+ case XRefsModelPackage.A__OTHERS:
+ getOthers().clear();
+ getOthers().addAll((Collection<? extends A>)newValue);
+ return;
+ case XRefsModelPackage.A__NON_OTHERS:
+ getNonOthers().clear();
+ getNonOthers().addAll((Collection<? extends A>)newValue);
+ return;
+ }
+ super.eSet(featureID, newValue);
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ @Override
+ public void eUnset(int featureID)
+ {
+ switch (featureID)
+ {
+ case XRefsModelPackage.A__NAME:
+ setName(NAME_EDEFAULT);
+ return;
+ case XRefsModelPackage.A__OTHERS:
+ getOthers().clear();
+ return;
+ case XRefsModelPackage.A__NON_OTHERS:
+ getNonOthers().clear();
+ return;
+ }
+ super.eUnset(featureID);
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ @Override
+ public boolean eIsSet(int featureID)
+ {
+ switch (featureID)
+ {
+ case XRefsModelPackage.A__NAME:
+ return NAME_EDEFAULT == null ? name != null : !NAME_EDEFAULT.equals(name);
+ case XRefsModelPackage.A__OTHERS:
+ return others != null && !others.isEmpty();
+ case XRefsModelPackage.A__ALL_OTHERS:
+ return !getAllOthers().isEmpty();
+ case XRefsModelPackage.A__NON_OTHERS:
+ return nonOthers != null && !nonOthers.isEmpty();
+ }
+ return super.eIsSet(featureID);
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ @Override
+ public String toString()
+ {
+ if (eIsProxy()) return super.toString();
+
+ StringBuffer result = new StringBuffer(super.toString());
+ result.append(" (name: ");
+ result.append(name);
+ result.append(')');
+ return result.toString();
+ }
+
+} //AImpl
diff --git a/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/impl/XRefsModelFactoryImpl.java b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/impl/XRefsModelFactoryImpl.java
new file mode 100644
index 000000000..8fdda4883
--- /dev/null
+++ b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/impl/XRefsModelFactoryImpl.java
@@ -0,0 +1,115 @@
+/**
+ * Copyright (c) 2014 CEA 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:
+ * CEA - Initial API and implementation
+ *
+ */
+package org.eclipse.emf.test.core.xrefsmodel.impl;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+
+import org.eclipse.emf.ecore.impl.EFactoryImpl;
+
+import org.eclipse.emf.ecore.plugin.EcorePlugin;
+
+import org.eclipse.emf.test.core.xrefsmodel.*;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model <b>Factory</b>.
+ * <!-- end-user-doc -->
+ * @generated
+ */
+public class XRefsModelFactoryImpl extends EFactoryImpl implements XRefsModelFactory
+{
+ /**
+ * Creates the default factory implementation.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public static XRefsModelFactory init()
+ {
+ try
+ {
+ XRefsModelFactory theXRefsModelFactory = (XRefsModelFactory)EPackage.Registry.INSTANCE.getEFactory(XRefsModelPackage.eNS_URI);
+ if (theXRefsModelFactory != null)
+ {
+ return theXRefsModelFactory;
+ }
+ }
+ catch (Exception exception)
+ {
+ EcorePlugin.INSTANCE.log(exception);
+ }
+ return new XRefsModelFactoryImpl();
+ }
+
+ /**
+ * Creates an instance of the factory.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public XRefsModelFactoryImpl()
+ {
+ super();
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ @Override
+ public EObject create(EClass eClass)
+ {
+ switch (eClass.getClassifierID())
+ {
+ case XRefsModelPackage.A: return createA();
+ default:
+ throw new IllegalArgumentException("The class '" + eClass.getName() + "' is not a valid classifier");
+ }
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public A createA()
+ {
+ AImpl a = new AImpl();
+ return a;
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public XRefsModelPackage getXRefsModelPackage()
+ {
+ return (XRefsModelPackage)getEPackage();
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @deprecated
+ * @generated
+ */
+ @Deprecated
+ public static XRefsModelPackage getPackage()
+ {
+ return XRefsModelPackage.eINSTANCE;
+ }
+
+} //XRefsModelFactoryImpl
diff --git a/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/impl/XRefsModelPackageImpl.java b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/impl/XRefsModelPackageImpl.java
new file mode 100644
index 000000000..3918b01bd
--- /dev/null
+++ b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/impl/XRefsModelPackageImpl.java
@@ -0,0 +1,230 @@
+/**
+ * Copyright (c) 2014 CEA 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:
+ * CEA - Initial API and implementation
+ *
+ */
+package org.eclipse.emf.test.core.xrefsmodel.impl;
+
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+
+import org.eclipse.emf.ecore.impl.EPackageImpl;
+
+import org.eclipse.emf.test.core.xrefsmodel.XRefsModelFactory;
+import org.eclipse.emf.test.core.xrefsmodel.XRefsModelPackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model <b>Package</b>.
+ * <!-- end-user-doc -->
+ * @generated
+ */
+public class XRefsModelPackageImpl extends EPackageImpl implements XRefsModelPackage
+{
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ private EClass aEClass = null;
+
+ /**
+ * Creates an instance of the model <b>Package</b>, registered with
+ * {@link org.eclipse.emf.ecore.EPackage.Registry EPackage.Registry} by the package
+ * package URI value.
+ * <p>Note: the correct way to create the package is via the static
+ * factory method {@link #init init()}, which also performs
+ * initialization of the package, or returns the registered package,
+ * if one already exists.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @see org.eclipse.emf.ecore.EPackage.Registry
+ * @see org.eclipse.emf.test.core.xrefsmodel.XRefsModelPackage#eNS_URI
+ * @see #init()
+ * @generated
+ */
+ private XRefsModelPackageImpl()
+ {
+ super(eNS_URI, XRefsModelFactory.eINSTANCE);
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ private static boolean isInited = false;
+
+ /**
+ * Creates, registers, and initializes the <b>Package</b> for this model, and for any others upon which it depends.
+ *
+ * <p>This method is used to initialize {@link XRefsModelPackage#eINSTANCE} when that field is accessed.
+ * Clients should not invoke it directly. Instead, they should simply access that field to obtain the package.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @see #eNS_URI
+ * @see #createPackageContents()
+ * @see #initializePackageContents()
+ * @generated
+ */
+ public static XRefsModelPackage init()
+ {
+ if (isInited) return (XRefsModelPackage)EPackage.Registry.INSTANCE.getEPackage(XRefsModelPackage.eNS_URI);
+
+ // Obtain or create and register package
+ XRefsModelPackageImpl theXRefsModelPackage = (XRefsModelPackageImpl)(EPackage.Registry.INSTANCE.get(eNS_URI) instanceof XRefsModelPackageImpl ? EPackage.Registry.INSTANCE.get(eNS_URI) : new XRefsModelPackageImpl());
+
+ isInited = true;
+
+ // Create package meta-data objects
+ theXRefsModelPackage.createPackageContents();
+
+ // Initialize created meta-data
+ theXRefsModelPackage.initializePackageContents();
+
+ // Mark meta-data to indicate it can't be changed
+ theXRefsModelPackage.freeze();
+
+
+ // Update the registry and return the package
+ EPackage.Registry.INSTANCE.put(XRefsModelPackage.eNS_URI, theXRefsModelPackage);
+ return theXRefsModelPackage;
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public EClass getA()
+ {
+ return aEClass;
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public EAttribute getA_Name()
+ {
+ return (EAttribute)aEClass.getEStructuralFeatures().get(0);
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public EReference getA_Others()
+ {
+ return (EReference)aEClass.getEStructuralFeatures().get(1);
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public EReference getA_AllOthers()
+ {
+ return (EReference)aEClass.getEStructuralFeatures().get(2);
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public EReference getA_NonOthers()
+ {
+ return (EReference)aEClass.getEStructuralFeatures().get(3);
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public XRefsModelFactory getXRefsModelFactory()
+ {
+ return (XRefsModelFactory)getEFactoryInstance();
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ private boolean isCreated = false;
+
+ /**
+ * Creates the meta-model objects for the package. This method is
+ * guarded to have no affect on any invocation but its first.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public void createPackageContents()
+ {
+ if (isCreated) return;
+ isCreated = true;
+
+ // Create classes and their features
+ aEClass = createEClass(A);
+ createEAttribute(aEClass, A__NAME);
+ createEReference(aEClass, A__OTHERS);
+ createEReference(aEClass, A__ALL_OTHERS);
+ createEReference(aEClass, A__NON_OTHERS);
+ }
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ private boolean isInitialized = false;
+
+ /**
+ * Complete the initialization of the package and its meta-model. This
+ * method is guarded to have no affect on any invocation but its first.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public void initializePackageContents()
+ {
+ if (isInitialized) return;
+ isInitialized = true;
+
+ // Initialize package
+ setName(eNAME);
+ setNsPrefix(eNS_PREFIX);
+ setNsURI(eNS_URI);
+
+ // Create type parameters
+
+ // Set bounds for type parameters
+
+ // Add supertypes to classes
+
+ // Initialize classes, features, and operations; add parameters
+ initEClass(aEClass, org.eclipse.emf.test.core.xrefsmodel.A.class, "A", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
+ initEAttribute(getA_Name(), ecorePackage.getEString(), "name", null, 1, 1, org.eclipse.emf.test.core.xrefsmodel.A.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+ initEReference(getA_Others(), this.getA(), null, "others", null, 0, -1, org.eclipse.emf.test.core.xrefsmodel.A.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+ initEReference(getA_AllOthers(), this.getA(), null, "allOthers", null, 0, -1, org.eclipse.emf.test.core.xrefsmodel.A.class, IS_TRANSIENT, IS_VOLATILE, !IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, IS_DERIVED, IS_ORDERED);
+ initEReference(getA_NonOthers(), this.getA(), null, "nonOthers", null, 0, -1, org.eclipse.emf.test.core.xrefsmodel.A.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+
+ // Create resource
+ createResource(eNS_URI);
+ }
+
+} //XRefsModelPackageImpl
diff --git a/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/util/XRefsModelAdapterFactory.java b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/util/XRefsModelAdapterFactory.java
new file mode 100644
index 000000000..b444b77aa
--- /dev/null
+++ b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/util/XRefsModelAdapterFactory.java
@@ -0,0 +1,141 @@
+/**
+ * Copyright (c) 2014 CEA 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:
+ * CEA - Initial API and implementation
+ *
+ */
+package org.eclipse.emf.test.core.xrefsmodel.util;
+
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.notify.Notifier;
+
+import org.eclipse.emf.common.notify.impl.AdapterFactoryImpl;
+
+import org.eclipse.emf.ecore.EObject;
+
+import org.eclipse.emf.test.core.xrefsmodel.*;
+
+/**
+ * <!-- begin-user-doc -->
+ * The <b>Adapter Factory</b> for the model.
+ * It provides an adapter <code>createXXX</code> method for each class of the model.
+ * <!-- end-user-doc -->
+ * @see org.eclipse.emf.test.core.xrefsmodel.XRefsModelPackage
+ * @generated
+ */
+public class XRefsModelAdapterFactory extends AdapterFactoryImpl
+{
+ /**
+ * The cached model package.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ protected static XRefsModelPackage modelPackage;
+
+ /**
+ * Creates an instance of the adapter factory.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public XRefsModelAdapterFactory()
+ {
+ if (modelPackage == null)
+ {
+ modelPackage = XRefsModelPackage.eINSTANCE;
+ }
+ }
+
+ /**
+ * Returns whether this factory is applicable for the type of the object.
+ * <!-- begin-user-doc -->
+ * This implementation returns <code>true</code> if the object is either the model's package or is an instance object of the model.
+ * <!-- end-user-doc -->
+ * @return whether this factory is applicable for the type of the object.
+ * @generated
+ */
+ @Override
+ public boolean isFactoryForType(Object object)
+ {
+ if (object == modelPackage)
+ {
+ return true;
+ }
+ if (object instanceof EObject)
+ {
+ return ((EObject)object).eClass().getEPackage() == modelPackage;
+ }
+ return false;
+ }
+
+ /**
+ * The switch that delegates to the <code>createXXX</code> methods.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ protected XRefsModelSwitch<Adapter> modelSwitch =
+ new XRefsModelSwitch<Adapter>()
+ {
+ @Override
+ public Adapter caseA(A object)
+ {
+ return createAAdapter();
+ }
+ @Override
+ public Adapter defaultCase(EObject object)
+ {
+ return createEObjectAdapter();
+ }
+ };
+
+ /**
+ * Creates an adapter for the <code>target</code>.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @param target the object to adapt.
+ * @return the adapter for the <code>target</code>.
+ * @generated
+ */
+ @Override
+ public Adapter createAdapter(Notifier target)
+ {
+ return modelSwitch.doSwitch((EObject)target);
+ }
+
+
+ /**
+ * Creates a new adapter for an object of class '{@link org.eclipse.emf.test.core.xrefsmodel.A <em>A</em>}'.
+ * <!-- begin-user-doc -->
+ * This default implementation returns null so that we can easily ignore cases;
+ * it's useful to ignore a case when inheritance will catch all the cases anyway.
+ * <!-- end-user-doc -->
+ * @return the new adapter.
+ * @see org.eclipse.emf.test.core.xrefsmodel.A
+ * @generated
+ */
+ public Adapter createAAdapter()
+ {
+ return null;
+ }
+
+ /**
+ * Creates a new adapter for the default case.
+ * <!-- begin-user-doc -->
+ * This default implementation returns null.
+ * <!-- end-user-doc -->
+ * @return the new adapter.
+ * @generated
+ */
+ public Adapter createEObjectAdapter()
+ {
+ return null;
+ }
+
+} //XRefsModelAdapterFactory
diff --git a/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/util/XRefsModelSwitch.java b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/util/XRefsModelSwitch.java
new file mode 100644
index 000000000..ea91bfdde
--- /dev/null
+++ b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/util/XRefsModelSwitch.java
@@ -0,0 +1,128 @@
+/**
+ * Copyright (c) 2014 CEA 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:
+ * CEA - Initial API and implementation
+ *
+ */
+package org.eclipse.emf.test.core.xrefsmodel.util;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+
+import org.eclipse.emf.ecore.util.Switch;
+
+import org.eclipse.emf.test.core.xrefsmodel.*;
+
+/**
+ * <!-- begin-user-doc -->
+ * The <b>Switch</b> for the model's inheritance hierarchy.
+ * It supports the call {@link #doSwitch(EObject) doSwitch(object)}
+ * to invoke the <code>caseXXX</code> method for each class of the model,
+ * starting with the actual class of the object
+ * and proceeding up the inheritance hierarchy
+ * until a non-null result is returned,
+ * which is the result of the switch.
+ * <!-- end-user-doc -->
+ * @see org.eclipse.emf.test.core.xrefsmodel.XRefsModelPackage
+ * @generated
+ */
+public class XRefsModelSwitch<T> extends Switch<T>
+{
+ /**
+ * The cached model package
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ protected static XRefsModelPackage modelPackage;
+
+ /**
+ * Creates an instance of the switch.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+ public XRefsModelSwitch()
+ {
+ if (modelPackage == null)
+ {
+ modelPackage = XRefsModelPackage.eINSTANCE;
+ }
+ }
+
+ /**
+ * Checks whether this is a switch for the given package.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @parameter ePackage the package in question.
+ * @return whether this is a switch for the given package.
+ * @generated
+ */
+ @Override
+ protected boolean isSwitchFor(EPackage ePackage)
+ {
+ return ePackage == modelPackage;
+ }
+
+ /**
+ * Calls <code>caseXXX</code> for each class of the model until one returns a non null result; it yields that result.
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @return the first non-null result returned by a <code>caseXXX</code> call.
+ * @generated
+ */
+ @Override
+ protected T doSwitch(int classifierID, EObject theEObject)
+ {
+ switch (classifierID)
+ {
+ case XRefsModelPackage.A:
+ {
+ A a = (A)theEObject;
+ T result = caseA(a);
+ if (result == null) result = defaultCase(theEObject);
+ return result;
+ }
+ default: return defaultCase(theEObject);
+ }
+ }
+
+ /**
+ * Returns the result of interpreting the object as an instance of '<em>A</em>'.
+ * <!-- begin-user-doc -->
+ * This implementation returns null;
+ * returning a non-null result will terminate the switch.
+ * <!-- end-user-doc -->
+ * @param object the target of the switch.
+ * @return the result of interpreting the object as an instance of '<em>A</em>'.
+ * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
+ * @generated
+ */
+ public T caseA(A object)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the result of interpreting the object as an instance of '<em>EObject</em>'.
+ * <!-- begin-user-doc -->
+ * This implementation returns null;
+ * returning a non-null result will terminate the switch, but this is the last case anyway.
+ * <!-- end-user-doc -->
+ * @param object the target of the switch.
+ * @return the result of interpreting the object as an instance of '<em>EObject</em>'.
+ * @see #doSwitch(org.eclipse.emf.ecore.EObject)
+ * @generated
+ */
+ @Override
+ public T defaultCase(EObject object)
+ {
+ return null;
+ }
+
+} //XRefsModelSwitch
diff --git a/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/util/XRefsModelUtil.java b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/util/XRefsModelUtil.java
new file mode 100644
index 000000000..34bfaeece
--- /dev/null
+++ b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/util/XRefsModelUtil.java
@@ -0,0 +1,296 @@
+/**
+ * Copyright (c) 2014 CEA 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:
+ * CEA - Initial API and implementation
+ *
+ */
+package org.eclipse.emf.test.core.xrefsmodel.util;
+
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Queue;
+import java.util.Set;
+
+import junit.framework.Assert;
+
+import org.eclipse.emf.common.notify.NotificationChain;
+import org.eclipse.emf.common.util.DelegatingEList;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.util.EContentsEList;
+import org.eclipse.emf.ecore.util.EcoreEList;
+import org.eclipse.emf.ecore.util.InternalEList;
+import org.eclipse.emf.test.core.xrefsmodel.A;
+import org.eclipse.emf.test.core.xrefsmodel.XRefsModelPackage;
+
+
+public class XRefsModelUtil
+{
+ private static boolean wrapCrossReferenceIterators;
+
+ private static boolean assertNoAllOthersCalls;
+
+ private static int allOthersCallCount;
+
+ public static EList<A> getAllOthers(A self)
+ {
+ Assert.assertFalse("A::allOthers() was called", assertNoAllOthersCalls);
+ allOthersCallCount++;
+
+ Set<A> result = new LinkedHashSet<A>();
+ Queue<A> queue = new LinkedList<A>();
+ queue.add(self);
+
+ for (A next = queue.poll(); next != null; next = queue.poll())
+ {
+ for (A other : next.getOthers())
+ {
+ if (result.add(other))
+ {
+ queue.offer(other);
+ }
+ }
+ }
+
+ return new EcoreEList.UnmodifiableEList.FastCompare<A>((InternalEObject)self, XRefsModelPackage.Literals.A__ALL_OTHERS, result.size(), result.toArray());
+ }
+
+ public static void assertNoAllOthersCalls(boolean assertNoAllOthersCalls)
+ {
+ XRefsModelUtil.assertNoAllOthersCalls = assertNoAllOthersCalls;
+ XRefsModelUtil.allOthersCallCount = 0;
+ }
+
+ public static int getAllOthersCallCount()
+ {
+ return allOthersCallCount;
+ }
+
+ /**
+ * Sets whether {@link EObject#eCrossReferences()} iterators will be wrapped so that they do not implement the
+ * {@link EContentsEList.Filterable} interface.
+ */
+ public static void setWrapCrossReferenceIterators(boolean wrap)
+ {
+ wrapCrossReferenceIterators = wrap;
+
+ if (wrap)
+ {
+ // The wrapper will cause A::getAllOthers() to be called
+ assertNoAllOthersCalls(false);
+ }
+ }
+
+ public static boolean isWrapCrossReferenceIterators()
+ {
+ return wrapCrossReferenceIterators;
+ }
+
+ /**
+ * Obtains a list for {@link EObject#eCrossReferences()} which may provide iterators that do not implement
+ * the {@link EContentsEList.Filterable} interface.
+ *
+ * @see #setWrapCrossReferenceIterators(boolean)
+ */
+ public static EList<EObject> getCrossReferences(EList<EObject> crossReferences)
+ {
+ return isWrapCrossReferenceIterators() ? wrapCrossReferences(crossReferences) : crossReferences;
+ }
+
+ private static EList<EObject> wrapCrossReferences(final EList<EObject> crossReferences)
+ {
+ class Wrapper extends DelegatingEList.UnmodifiableEList<EObject> implements InternalEList<EObject>
+ {
+
+ private static final long serialVersionUID = 1L;
+
+ Wrapper(EList<EObject> delegate)
+ {
+ super(delegate);
+ }
+
+ @Override
+ protected InternalEList<EObject> delegateBasicList()
+ {
+ return (InternalEList<EObject>)super.delegateBasicList();
+ }
+
+ protected EContentsEList.FeatureIterator<EObject> wrap(Iterator<EObject> iterator)
+ {
+ final EContentsEList.FeatureIterator<EObject> delegate = (EContentsEList.FeatureIterator<EObject>)iterator;
+ return new EContentsEList.FeatureIterator<EObject>()
+ {
+ public boolean hasNext()
+ {
+ return delegate.hasNext();
+ }
+
+ public EObject next()
+ {
+ return delegate.next();
+ }
+
+ public void remove()
+ {
+ delegate.remove();
+ }
+
+ public EStructuralFeature feature()
+ {
+ return delegate.feature();
+ }
+
+ };
+ }
+
+ protected EContentsEList.FeatureListIterator<EObject> wrap(ListIterator<EObject> iterator)
+ {
+ final EContentsEList.FeatureListIterator<EObject> delegate = (EContentsEList.FeatureListIterator<EObject>)iterator;
+ return new EContentsEList.FeatureListIterator<EObject>()
+ {
+
+ public EStructuralFeature feature()
+ {
+ return delegate.feature();
+ }
+
+ public boolean hasNext()
+ {
+ return delegate.hasNext();
+ }
+
+ public EObject next()
+ {
+ return delegate.next();
+ }
+
+ public void remove()
+ {
+ delegate.remove();
+ }
+
+ public void add(EObject e)
+ {
+ delegate.add(e);
+ }
+
+ public boolean hasPrevious()
+ {
+ return delegate.hasPrevious();
+ }
+
+ public int nextIndex()
+ {
+ return delegate.nextIndex();
+ }
+
+ public EObject previous()
+ {
+ return delegate.previous();
+ }
+
+ public int previousIndex()
+ {
+ return delegate.previousIndex();
+ }
+
+ public void set(EObject e)
+ {
+ delegate.set(e);
+ }
+
+ };
+ }
+
+ @Override
+ public Iterator<EObject> iterator()
+ {
+ return wrap(delegateList().iterator());
+ }
+
+ @Override
+ public Iterator<EObject> basicIterator()
+ {
+ return wrap(delegateBasicList().basicIterator());
+ }
+
+ @Override
+ public ListIterator<EObject> basicListIterator(final int index)
+ {
+ return wrap(delegateBasicList().basicListIterator(index));
+ }
+
+ @Override
+ public ListIterator<EObject> basicListIterator()
+ {
+ return basicListIterator(0);
+ }
+
+ @Override
+ public List<EObject> basicList()
+ {
+ return super.basicList();
+ }
+
+ @Override
+ public EObject basicGet(int index)
+ {
+ return super.basicGet(index);
+ }
+
+ public Object[] basicToArray()
+ {
+ return delegateBasicList().basicToArray();
+ }
+
+ public <T> T[] basicToArray(T[] array)
+ {
+ return delegateBasicList().basicToArray(array);
+ }
+
+ public int basicIndexOf(Object object)
+ {
+ return delegateBasicList().basicIndexOf(object);
+ }
+
+ public int basicLastIndexOf(Object object)
+ {
+ return delegateBasicList().basicLastIndexOf(object);
+ }
+
+ public boolean basicContains(Object object)
+ {
+ return delegateBasicList().basicContains(object);
+ }
+
+ public boolean basicContainsAll(Collection<?> collection)
+ {
+ return delegateBasicList().basicContainsAll(collection);
+ }
+
+ public NotificationChain basicRemove(Object object, NotificationChain notifications)
+ {
+ return delegateBasicList().basicRemove(object, notifications);
+ }
+
+ public NotificationChain basicAdd(EObject object, NotificationChain notifications)
+ {
+ return delegateBasicList().basicAdd(object, notifications);
+ }
+ };
+
+ return new Wrapper(crossReferences);
+ }
+}
diff --git a/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/xrefsmodel.ecore b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/xrefsmodel.ecore
new file mode 100644
index 000000000..5871fbe24
--- /dev/null
+++ b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/xrefsmodel.ecore
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="xrefsmodel" nsURI="http://www.eclipse.org/EMF/2014/test/xrefsmodel"
+ nsPrefix="xrefs">
+ <eClassifiers xsi:type="ecore:EClass" name="A">
+ <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="others" upperBound="-1"
+ eType="#//A"/>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="allOthers" upperBound="-1"
+ eType="#//A" changeable="false" volatile="true" transient="true" derived="true"/>
+ <eStructuralFeatures xsi:type="ecore:EReference" name="nonOthers" upperBound="-1"
+ eType="#//A"/>
+ </eClassifiers>
+</ecore:EPackage>
diff --git a/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/xrefsmodel.genmodel b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/xrefsmodel.genmodel
new file mode 100644
index 000000000..2c5db420d
--- /dev/null
+++ b/tests/org.eclipse.emf.test.core/src/org/eclipse/emf/test/core/xrefsmodel/xrefsmodel.genmodel
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<genmodel:GenModel xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
+ xmlns:genmodel="http://www.eclipse.org/emf/2002/GenModel" copyrightText="Copyright (c) 2014 CEA and others.&#xA;All rights reserved. This program and the accompanying materials&#xA;are made available under the terms of the Eclipse Public License v1.0&#xA;which accompanies this distribution, and is available at&#xA;http://www.eclipse.org/legal/epl-v10.html&#xA;&#xA;Contributors:&#xA; CEA - Initial API and implementation&#xA;"
+ modelDirectory="/org.eclipse.emf.test.core/src" modelPluginID="org.eclipse.emf.test.core"
+ modelName="Xrefsmodel" rootExtendsClass="org.eclipse.emf.ecore.impl.MinimalEObjectImpl$Container"
+ importerID="org.eclipse.emf.importer.ecore" complianceLevel="5.0" copyrightFields="false"
+ language="" operationReflection="true" importOrganizing="true">
+ <foreignModel>xrefsmodel.ecore</foreignModel>
+ <genPackages prefix="XRefsModel" basePackage="org.eclipse.emf.test.core" disposableProviderFactory="true"
+ ecorePackage="xrefsmodel.ecore#/">
+ <genClasses ecoreClass="xrefsmodel.ecore#//A">
+ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute xrefsmodel.ecore#//A/name"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference xrefsmodel.ecore#//A/others"/>
+ <genFeatures property="Readonly" notify="false" createChild="false" ecoreFeature="ecore:EReference xrefsmodel.ecore#//A/allOthers"/>
+ <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference xrefsmodel.ecore#//A/nonOthers"/>
+ </genClasses>
+ </genPackages>
+</genmodel:GenModel>

Back to the top