/* * Copyright (c) 2014-2016 Eike Stepper (Berlin, Germany) 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: * Laurent Fasani - initial API and implementation */ package org.eclipse.emf.cdo.tests.bugzilla; import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.tests.AbstractCDOTest; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.cdo.util.CDOUtil; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; 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.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.util.EContentAdapter; import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; /** * Bug 429659 - check notifications when unsetting EStructuralFeature. * test TransientStore/CDOStoreImpl.unset() with * single-valued/multi-valued/settable/unsettable feature in CDO * and XMI mode. * * @author <a href="mailto:laurent.fasani@obeo.fr">Laurent Fasani</a> */ public class Bugzilla_429659_Test extends AbstractCDOTest { public void testUnsetOnUnsettableMultiValuedFeatureXMIResource() throws Exception { List<EObject> objectsToAdd = new ArrayList<EObject>(); objectsToAdd.add(getModel3SubpackageFactory().createClass2()); objectsToAdd.add(getModel3SubpackageFactory().createClass2()); performUnsetOnMultiValuedFeature(getXMIResource(), getModel3Factory().createClass1(), getModel3Package().getClass1_Class2(), true, objectsToAdd); } public void testUnsetOnUnsettableMultiValuedFeatureCDOResource() throws Exception { List<EObject> objectsToAdd = new ArrayList<EObject>(); objectsToAdd.add(getModel3SubpackageFactory().createClass2()); objectsToAdd.add(getModel3SubpackageFactory().createClass2()); performUnsetOnMultiValuedFeature(getCDOResource(), getModel3Factory().createClass1(), getModel3Package().getClass1_Class2(), true, objectsToAdd); } public void testUnsetOnNonUnsettableMultiValuedFeatureXMIResource() throws Exception { List<EObject> objectsToAdd = new ArrayList<EObject>(); objectsToAdd.add(getModel6Factory().createBaseObject()); objectsToAdd.add(getModel6Factory().createBaseObject()); performUnsetOnMultiValuedFeature(getXMIResource(), getModel6Factory().createReferenceObject(), getModel6Package().getReferenceObject_ReferenceList(), false, objectsToAdd); } public void testUnsetOnNonUnsettableMultiValuedFeatureCDOResource() throws Exception { List<EObject> objectsToAdd = new ArrayList<EObject>(); objectsToAdd.add(getModel6Factory().createBaseObject()); objectsToAdd.add(getModel6Factory().createBaseObject()); performUnsetOnMultiValuedFeature(getCDOResource(), getModel6Factory().createReferenceObject(), getModel6Package().getReferenceObject_ReferenceList(), false, objectsToAdd); } public void testUnsetOnUnsettableSingleValuedAttributeCDOResource() throws Exception { performUnsetOnSingleValuedFeature(getCDOResource(), getModel6Factory().createEmptyStringDefaultUnsettable(), getModel6Package().getEmptyStringDefaultUnsettable_Attribute(), true, "test"); } public void testUnsetOnUnsettableSingleValuedAttributeXMIResource() throws Exception { performUnsetOnSingleValuedFeature(getXMIResource(), getModel6Factory().createEmptyStringDefaultUnsettable(), getModel6Package().getEmptyStringDefaultUnsettable_Attribute(), true, "test"); } public void testUnsetOnNonUnsettableSingleValuedAttributeCDOResource() throws Exception { performUnsetOnSingleValuedFeature(getCDOResource(), getModel6Factory().createEmptyStringDefault(), getModel6Package().getEmptyStringDefault_Attribute(), false, "test"); } public void testUnsetOnNonUnsettableSingleValuedAttributeXMIResource() throws Exception { performUnsetOnSingleValuedFeature(getXMIResource(), getModel6Factory().createEmptyStringDefault(), getModel6Package().getEmptyStringDefault_Attribute(), false, "test"); } private Resource getCDOResource() { CDOSession openSession = openSession(); CDOTransaction transaction = openSession.openTransaction(); Resource resourceCDO = transaction.createResource(getResourcePath("resource")); return resourceCDO; } private Resource getXMIResource() throws Exception { Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("*", new XMIResourceFactoryImpl()); ResourceSet resourceSet = new ResourceSetImpl(); URI localURI = URI.createFileURI(createTempFile().getCanonicalPath()); Resource localResource = resourceSet.createResource(localURI); return localResource; } private void performUnsetOnSingleValuedFeature(Resource resource, EObject root, EStructuralFeature feature, boolean unsettable, Object addedObject) throws Exception { // To have CDOLegacyAdapter even in local CDOUtil.getCDOObject(root); // check that Feature is unsettable or not assertEquals(unsettable, feature.isUnsettable()); resource.getContents().add(root); resource.save(Collections.emptyMap()); // allow notifications checking NotificationAsserter notificationAsserter = new NotificationAsserter(); resource.eAdapters().add(notificationAsserter); List<Notification> notifications = notificationAsserter.getNotifications(); root.eSet(feature, addedObject); // unset notifications.clear(); root.eUnset(feature); // check assertEquals("Incorrect number of expected notifications: ", 1, notifications.size()); assertEquals("Incorrect notification: ", unsettable ? Notification.UNSET : Notification.SET, notifications.get(0).getEventType()); } @SuppressWarnings("unchecked") private void performUnsetOnMultiValuedFeature(Resource resource, EObject root, EStructuralFeature feature, boolean unsettable, List<EObject> objectstoAdd) throws Exception { // To have CDOLegacyAdapter even in local CDOUtil.getCDOObject(root); for (EObject objectToAdd : objectstoAdd) { CDOUtil.getCDOObject(objectToAdd); } // check that feature is unsettable or not assertEquals(unsettable, feature.isUnsettable()); resource.getContents().add(root); resource.save(Collections.emptyMap()); // allow notifications checking NotificationAsserter notificationAsserter = new NotificationAsserter(); root.eAdapters().add(notificationAsserter); List<Notification> notifications = notificationAsserter.getNotifications(); // ----------------------------- // Step 1: unset many elements ((Collection<EObject>)root.eGet(feature)).addAll(objectstoAdd); // unset notifications.clear(); root.eUnset(feature); // check assertEquals("Incorrect number of expected notifications: ", unsettable ? 2 : 1, notifications.size()); assertEquals("Incorrect notification: ", Notification.REMOVE_MANY, notifications.get(0).getEventType()); if (unsettable) { assertEquals("Incorrect notification: ", Notification.UNSET, notifications.get(1).getEventType()); } // ------------------------------------- // Step 2: unset single element ((Collection<EObject>)root.eGet(feature)).add(objectstoAdd.get(0)); // unset notifications.clear(); root.eUnset(feature); // check assertEquals("Incorrect number of expected notifications: ", unsettable ? 2 : 1, notifications.size()); assertEquals("Incorrect notification: ", Notification.REMOVE, notifications.get(0).getEventType()); if (unsettable) { assertEquals("Incorrect notification: ", Notification.UNSET, notifications.get(1).getEventType()); } notifications.clear(); root.eUnset(feature); assertEquals("Incorrect number of expected notifications: ", unsettable ? 2 : 1, notifications.size()); } private static class NotificationAsserter extends EContentAdapter { private List<Notification> notifications = new ArrayList<Notification>(); @Override public void notifyChanged(Notification notification) { super.notifyChanged(notification); notifications.add(notification); } public List<Notification> getNotifications() { return notifications; } } }