Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2013-09-06 11:37:34 -0400
committerChristian W. Damus2013-09-16 16:02:46 -0400
commit2a36cf4f54847aa650eed9eb00d552e8fa3fc1c4 (patch)
tree5093302e04d03f355d2666f1ccbbe01b689966d2
parent78b304cdae37ac7195af173414ad2661a7a8ac6a (diff)
downloadorg.eclipse.papyrus-2a36cf4f54847aa650eed9eb00d552e8fa3fc1c4.tar.gz
org.eclipse.papyrus-2a36cf4f54847aa650eed9eb00d552e8fa3fc1c4.tar.xz
org.eclipse.papyrus-2a36cf4f54847aa650eed9eb00d552e8fa3fc1c4.zip
415369: [CDO] Support controlled resources and lazy loading
https://bugs.eclipse.org/bugs/show_bug.cgi?id=415369 Ensure on save that new/changed cross-unit references use the proper lazy-loading proxies.
-rw-r--r--extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOAwareModelSet.java77
-rw-r--r--extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/CDOUtils.java145
-rw-r--r--extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/controlmode/CDOControlModeParticipant.java26
-rw-r--r--tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/resources/xmi/A.ecore8
-rw-r--r--tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/resources/xmi/B.ecore6
-rw-r--r--tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/tests/AllTests.java4
-rw-r--r--tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/internal/core/tests/AllInternalCoreTests.java30
-rw-r--r--tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/internal/core/tests/CDOUtilsTest.java139
8 files changed, 423 insertions, 12 deletions
diff --git a/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOAwareModelSet.java b/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOAwareModelSet.java
index c3fb05d993c..4725713ad04 100644
--- a/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOAwareModelSet.java
+++ b/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/core/resource/CDOAwareModelSet.java
@@ -12,10 +12,14 @@
package org.eclipse.papyrus.cdo.core.resource;
import java.io.IOException;
+import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.CDOState;
import org.eclipse.emf.cdo.dawn.gmf.util.DawnDiagramUpdater;
import org.eclipse.emf.cdo.eresource.CDOResource;
@@ -29,6 +33,7 @@ import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gmf.runtime.notation.Diagram;
@@ -37,12 +42,14 @@ import org.eclipse.net4j.util.event.IListener;
import org.eclipse.papyrus.cdo.core.IPapyrusRepository;
import org.eclipse.papyrus.cdo.core.IPapyrusRepositoryManager;
import org.eclipse.papyrus.cdo.internal.core.CDOUtils;
+import org.eclipse.papyrus.cdo.internal.core.controlmode.CDOControlModeParticipant;
import org.eclipse.papyrus.cdo.internal.core.controlmode.CDOProxyManager;
import org.eclipse.papyrus.infra.core.Activator;
import org.eclipse.papyrus.infra.core.resource.ModelMultiException;
import org.eclipse.papyrus.infra.services.resourceloading.OnDemandLoadingModelSet;
import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
/**
@@ -177,21 +184,21 @@ public class CDOAwareModelSet extends OnDemandLoadingModelSet {
try {
super.unload();
} finally {
- if((repository != null) && (getCDOView() != null)) {
- CDOView view = getCDOView();
- if(view != null) {
- view.removeListener(getInvalidationListener());
- }
- invalidationListener = null;
+ if((repository != null) && (getCDOView() != null)) {
+ CDOView view = getCDOView();
+ if(view != null) {
+ view.removeListener(getInvalidationListener());
+ }
+ invalidationListener = null;
- // dispose the transaction
- repository.close(this);
+ // dispose the transaction
+ repository.close(this);
// now, we can remove the CDOViewSet adapter
eAdapters().clear();
- }
+ }
- repository = null;
+ repository = null;
}
}
@@ -330,6 +337,56 @@ public class CDOAwareModelSet extends OnDemandLoadingModelSet {
return result;
}
+ @Override
+ public void save(IProgressMonitor monitor) throws IOException {
+ CDOView view = getCDOView();
+ CDOTransaction transaction = null;
+
+ Collection<CDOObject> updates;
+ if((view instanceof CDOTransaction) && view.isDirty()) {
+ // collect updated objects to post-process for cross-unit references
+ transaction = (CDOTransaction)view;
+ updates = ImmutableList.<CDOObject> builder() //
+ .addAll(transaction.getNewObjects().values()) //
+ .addAll(transaction.getDirtyObjects().values()) //
+ .build();
+ } else {
+ updates = Collections.emptyList();
+ }
+
+ SubMonitor sub = SubMonitor.convert(monitor, updates.isEmpty() ? 1 : 2);
+
+ super.save(sub.newChild(1));
+
+ if(!updates.isEmpty()) {
+ CDOControlModeParticipant control = new CDOControlModeParticipant();
+ CDOControlModeParticipant.IUpdate run = CDOControlModeParticipant.IUpdate.EMPTY;
+
+ for(CDOObject next : updates) {
+ EObject object = CDOUtil.getEObject(next);
+ if(object != null) {
+ for(EReference xref : object.eClass().getEAllReferences()) {
+ if(!xref.isContainment() && xref.isChangeable() && !xref.isDerived() && !xref.isTransient()) {
+ run = run.chain(control.getProxyCrossReferencesUpdate(object, xref));
+ }
+ }
+ }
+ }
+
+ if(!run.isEmpty()) {
+ run.apply();
+
+ try {
+ transaction.commit(sub.newChild(1));
+ } catch (CommitException e) {
+ Activator.log.error("Follow-up commit after save failed.", e);
+ }
+ } else {
+ sub.done();
+ }
+ }
+ }
+
//
// Nested types
//
diff --git a/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/CDOUtils.java b/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/CDOUtils.java
index 02b97de7bc0..0c021b6f628 100644
--- a/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/CDOUtils.java
+++ b/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/CDOUtils.java
@@ -14,6 +14,8 @@ package org.eclipse.papyrus.cdo.internal.core;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getFirst;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.Executor;
@@ -32,11 +34,14 @@ import org.eclipse.emf.cdo.view.CDOViewSet;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.util.EContentsEList.FeatureListIterator;
import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.transaction.ResourceSetChangeEvent;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
@@ -45,6 +50,7 @@ import org.eclipse.papyrus.cdo.core.util.CDOFunctions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
+import com.google.common.collect.UnmodifiableListIterator;
/**
* This is the CDOUtils type. Enjoy.
@@ -225,6 +231,145 @@ public class CDOUtils {
}
/**
+ * Obtains an unmodifiable iterator over the values in the specified {@code feature} of an {@code object}. The resulting iterator supplies zero
+ * or one element for scalar features, according to whether the feature's value is {@code null} or not. In the case of a scalar feature,
+ * the index of the element as reported by {@link ListIterator#nextIndex()} and {@link ListIterator#previousIndex()} is {@code -1}.
+ *
+ * @param object
+ * an object
+ * @param feature
+ * a feature of the {@code object}
+ * @param resolve
+ * whether to resolve proxies (in the case of an {@link EReference}
+ *
+ * @return the unmodifiable feature list iterator
+ */
+ public static <E> FeatureListIterator<E> iterator(EObject object, final EStructuralFeature feature, boolean resolve) {
+ FeatureListIterator<E> result;
+
+ Object value = object.eGet(feature, resolve);
+ if(value instanceof InternalEList<?>) {
+ @SuppressWarnings("unchecked")
+ InternalEList<E> list = (InternalEList<E>)value;
+ final ListIterator<E> delegate = (resolve) ? list.listIterator() : list.basicListIterator();
+
+ class NonEmpty extends UnmodifiableListIterator<E> implements FeatureListIterator<E> {
+
+ public EStructuralFeature feature() {
+ return feature;
+ }
+
+ public boolean hasNext() {
+ return delegate.hasNext();
+ }
+
+ public E next() {
+ return delegate.next();
+ }
+
+ public int nextIndex() {
+ return delegate.nextIndex();
+ }
+
+ public boolean hasPrevious() {
+ return delegate.hasPrevious();
+ }
+
+ public E previous() {
+ return delegate.previous();
+ }
+
+ public int previousIndex() {
+ return delegate.previousIndex();
+ }
+ };
+
+ result = new NonEmpty();
+ } else if(value == null) {
+ class Empty extends UnmodifiableListIterator<E> implements FeatureListIterator<E> {
+
+ public EStructuralFeature feature() {
+ return feature;
+ }
+
+ public boolean hasNext() {
+ return false;
+ }
+
+ public E next() {
+ throw new NoSuchElementException();
+ }
+
+ public int nextIndex() {
+ return -1;
+ }
+
+ public boolean hasPrevious() {
+ return false;
+ }
+
+ public E previous() {
+ throw new NoSuchElementException();
+ }
+
+ public int previousIndex() {
+ return -2;
+ }
+ };
+
+ result = new Empty();
+ } else {
+ @SuppressWarnings("unchecked")
+ final E onlyValue = (E)value;
+
+ class Singleton extends UnmodifiableListIterator<E> implements FeatureListIterator<E> {
+
+ private int index = -1;
+
+ public EStructuralFeature feature() {
+ return feature;
+ }
+
+ public boolean hasNext() {
+ return index < 0;
+ }
+
+ public E next() {
+ if(!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ index++;
+ return onlyValue;
+ }
+
+ public int nextIndex() {
+ return index;
+ }
+
+ public boolean hasPrevious() {
+ return index == 0;
+ }
+
+ public E previous() {
+ if(!hasPrevious()) {
+ throw new NoSuchElementException();
+ }
+ index--;
+ return onlyValue;
+ }
+
+ public int previousIndex() {
+ return index - 1;
+ }
+ };
+
+ result = new Singleton();
+ }
+
+ return result;
+ }
+
+ /**
* <p>
* Runs a code block that broadcasts notification of {@link ResourceSetChangeEvent}s, {@link CDOViewInvalidationEvent}s, etc. to listeners using
* the most appropriate {@linkplain #setBroadcastExecutor() executor} available. This allows a UI-safe execution to be injected if necessary.
diff --git a/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/controlmode/CDOControlModeParticipant.java b/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/controlmode/CDOControlModeParticipant.java
index 47d73b54142..ee6563e87ae 100644
--- a/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/controlmode/CDOControlModeParticipant.java
+++ b/extraplugins/cdo/org.eclipse.papyrus.cdo.core/src/org/eclipse/papyrus/cdo/internal/core/controlmode/CDOControlModeParticipant.java
@@ -14,6 +14,7 @@ package org.eclipse.papyrus.cdo.internal.core.controlmode;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
+import static org.eclipse.papyrus.cdo.internal.core.controlmode.CDOProxyManager.createPapyrusCDOURI;
import java.util.Collections;
import java.util.EnumSet;
@@ -139,6 +140,31 @@ public class CDOControlModeParticipant implements IControlCommandParticipant, IU
}
}
+ public IUpdate getProxyCrossReferencesUpdate(final EObject owner, final EReference crossReference) {
+ IUpdate result = IUpdate.EMPTY;
+ final CDOStore[] store = { null };
+
+ for(ListIterator<? extends EObject> xrefs = CDOUtils.iterator(owner, crossReference, false); xrefs.hasNext();) {
+ final int index = xrefs.nextIndex();
+ final EObject referent = xrefs.next();
+
+ if(!referent.eIsProxy() && !inSameUnit(owner, referent)) {
+ if(store[0] == null) {
+ store[0] = ((InternalCDOView)CDOUtils.getCDOObject(owner).cdoView()).getStore();
+ }
+
+ result = result.chain(new OneWayUpdate() {
+
+ public void apply() {
+ store[0].set((InternalEObject)owner, crossReference, index, CDOIDUtil.createExternal(createPapyrusCDOURI(referent)));
+ }
+ });
+ }
+ }
+
+ return result;
+ }
+
public ICommand getPreUncontrolCommand(ControlModeRequest request) {
return new AbstractCDOControlCommand(request) {
diff --git a/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/resources/xmi/A.ecore b/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/resources/xmi/A.ecore
new file mode 100644
index 00000000000..b5ef8ae8408
--- /dev/null
+++ b/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/resources/xmi/A.ecore
@@ -0,0 +1,8 @@
+<?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="a" nsURI="http://www.eclipse.org/papyrus/test/2013/a" nsPrefix="a">
+ <eClassifiers xsi:type="ecore:EClass" name="A1" eSuperTypes="B.ecore#//B1 B.ecore#//B2"/>
+ <eClassifiers xsi:type="ecore:EClass" name="A2">
+ <eStructuralFeatures xsi:type="ecore:EReference" name="a1" upperBound="-1" eType="#//A1"/>
+ </eClassifiers>
+</ecore:EPackage>
diff --git a/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/resources/xmi/B.ecore b/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/resources/xmi/B.ecore
new file mode 100644
index 00000000000..0cf9cc7e559
--- /dev/null
+++ b/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/resources/xmi/B.ecore
@@ -0,0 +1,6 @@
+<?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="b" nsURI="http://www.eclipse.org/papyrus/test/2013/b" nsPrefix="b">
+ <eClassifiers xsi:type="ecore:EClass" name="B1"/>
+ <eClassifiers xsi:type="ecore:EClass" name="B2"/>
+</ecore:EPackage>
diff --git a/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/tests/AllTests.java b/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/tests/AllTests.java
index 6d5865486f3..43633eba7dd 100644
--- a/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/tests/AllTests.java
+++ b/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/core/tests/AllTests.java
@@ -16,7 +16,7 @@ import org.eclipse.papyrus.cdo.core.util.tests.AllUtilTests;
import org.eclipse.papyrus.cdo.internal.core.exporter.tests.AllModelExportTests;
import org.eclipse.papyrus.cdo.internal.core.expressions.tests.AllExpressionsTests;
import org.eclipse.papyrus.cdo.internal.core.importer.tests.AllModelImportTests;
-import org.eclipse.papyrus.cdo.internal.core.tests.PapyrusRepositoryManagerTest;
+import org.eclipse.papyrus.cdo.internal.core.tests.AllInternalCoreTests;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@@ -26,7 +26,7 @@ import org.junit.runners.Suite.SuiteClasses;
*/
@RunWith(Suite.class)
@SuiteClasses({ AllUtilTests.class, AllExpressionsTests.class, //
-PapyrusRepositoryManagerTest.class, CDOAwareModelSetTest.class, //
+AllInternalCoreTests.class, CDOAwareModelSetTest.class, //
AllModelImportTests.class, AllModelExportTests.class })
public class AllTests {
diff --git a/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/internal/core/tests/AllInternalCoreTests.java b/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/internal/core/tests/AllInternalCoreTests.java
new file mode 100644
index 00000000000..ff7c4a89a3c
--- /dev/null
+++ b/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/internal/core/tests/AllInternalCoreTests.java
@@ -0,0 +1,30 @@
+/*****************************************************************************
+ * Copyright (c) 2013 CEA LIST.
+ *
+ * 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 LIST - Initial API and implementation
+ *****************************************************************************/
+package org.eclipse.papyrus.cdo.internal.core.tests;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+
+/**
+ * This is the AllInternalCoreTests type. Enjoy.
+ */
+@RunWith(Suite.class)
+@SuiteClasses({ CDOUtilsTest.class, PapyrusRepositoryManagerTest.class })
+public class AllInternalCoreTests {
+
+ public AllInternalCoreTests() {
+ super();
+ }
+
+}
diff --git a/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/internal/core/tests/CDOUtilsTest.java b/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/internal/core/tests/CDOUtilsTest.java
new file mode 100644
index 00000000000..ab9b621a79b
--- /dev/null
+++ b/tests/junit/extraplugins/cdo/org.eclipse.papyrus.cdo.core.tests/src/org/eclipse/papyrus/cdo/internal/core/tests/CDOUtilsTest.java
@@ -0,0 +1,139 @@
+/*****************************************************************************
+ * Copyright (c) 2013 CEA LIST.
+ *
+ * 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 LIST - Initial API and implementation
+ *****************************************************************************/
+package org.eclipse.papyrus.cdo.internal.core.tests;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.net.URL;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+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.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.EContentsEList.FeatureListIterator;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.papyrus.cdo.internal.core.CDOUtils;
+import org.junit.Test;
+
+
+/**
+ * Selected unit tests for the {@link CDOUtils} class.
+ */
+public class CDOUtilsTest {
+
+ public CDOUtilsTest() {
+ super();
+ }
+
+ @Test
+ public void testIteratorScalarAttribute() throws Exception {
+ FeatureListIterator<String> sIter = CDOUtils.iterator(EcorePackage.Literals.ECLASS, EcorePackage.Literals.ENAMED_ELEMENT__NAME, false);
+
+ assertThat(sIter.hasNext(), is(true));
+ assertThat(sIter.nextIndex(), is(-1));
+ assertThat(sIter.next(), is(EcorePackage.Literals.ECLASS.getName()));
+
+ assertThat(sIter.hasPrevious(), is(true));
+ assertThat(sIter.previousIndex(), is(-1));
+ assertThat(sIter.previous(), is(EcorePackage.Literals.ECLASS.getName()));
+ }
+
+ @Test
+ public void testIteratorEmptyReference() throws Exception {
+ FeatureListIterator<String> sIter = CDOUtils.iterator(EcorePackage.eINSTANCE, EcorePackage.Literals.EPACKAGE__ESUPER_PACKAGE, false);
+
+ assertThat(sIter.hasNext(), is(false));
+ assertThat(sIter.nextIndex(), is(-1));
+ assertThat(sIter.hasPrevious(), is(false));
+ }
+
+ @Test
+ public void testIteratorReferenceResolving() throws Exception {
+ ResourceSet rset = new ResourceSetImpl();
+ Resource a = rset.getResource(getTestResourceURI("A.ecore"), true);
+
+ EClass a1 = (EClass)((EPackage)a.getContents().get(0)).getEClassifier("A1");
+ FeatureListIterator<EClass> sIter = CDOUtils.iterator(a1, EcorePackage.Literals.ECLASS__ESUPER_TYPES, true);
+
+ assertThat(sIter.hasNext(), is(true));
+ assertThat(sIter.nextIndex(), is(0));
+ assertThat(sIter.next().getName(), is("B1"));
+
+ assertThat(sIter.hasNext(), is(true));
+ assertThat(sIter.nextIndex(), is(1));
+ assertThat(sIter.next().getName(), is("B2"));
+
+ assertThat(sIter.hasNext(), is(false));
+ assertThat(sIter.nextIndex(), is(2));
+
+ assertThat(sIter.hasPrevious(), is(true));
+ assertThat(sIter.previousIndex(), is(1));
+ assertThat(sIter.previous().getName(), is("B2"));
+
+ assertThat(sIter.hasPrevious(), is(true));
+ assertThat(sIter.previousIndex(), is(0));
+ assertThat(sIter.previous().getName(), is("B1"));
+
+ assertThat(sIter.hasPrevious(), is(false));
+ }
+
+ @Test
+ public void testIteratorReferenceNonesolving() throws Exception {
+ ResourceSet rset = new ResourceSetImpl();
+ Resource a = rset.getResource(getTestResourceURI("A.ecore"), true);
+
+ EClass a1 = (EClass)((EPackage)a.getContents().get(0)).getEClassifier("A1");
+ FeatureListIterator<EClass> sIter = CDOUtils.iterator(a1, EcorePackage.Literals.ECLASS__ESUPER_TYPES, false);
+
+ assertThat(sIter.hasNext(), is(true));
+ assertThat(sIter.nextIndex(), is(0));
+ EClass next = sIter.next();
+ assertThat(next.eIsProxy(), is(true));
+ assertThat(EcoreUtil.getURI(next).fragment(), containsString("B1"));
+
+ assertThat(sIter.hasNext(), is(true));
+ next = sIter.next();
+ assertThat(next.eIsProxy(), is(true));
+ assertThat(EcoreUtil.getURI(next).fragment(), containsString("B2"));
+
+ assertThat(sIter.hasNext(), is(false));
+ assertThat(sIter.nextIndex(), is(2));
+
+ assertThat(sIter.hasPrevious(), is(true));
+ assertThat(sIter.previousIndex(), is(1));
+ EClass previous = sIter.previous();
+ assertThat(previous.eIsProxy(), is(true));
+ assertThat(EcoreUtil.getURI(previous).fragment(), containsString("B2"));
+
+ assertThat(sIter.hasPrevious(), is(true));
+ assertThat(sIter.previousIndex(), is(0));
+ previous = sIter.previous();
+ assertThat(previous.eIsProxy(), is(true));
+ assertThat(EcoreUtil.getURI(previous).fragment(), containsString("B1"));
+
+ assertThat(sIter.hasPrevious(), is(false));
+ }
+
+ //
+ // Test framework
+ //
+
+ URI getTestResourceURI(String name) {
+ URL result = getClass().getClassLoader().getResource("resources/xmi/" + name);
+ return URI.createURI(result.toExternalForm(), true);
+ }
+}

Back to the top