/**
* Copyright (c) 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
*/
package org.eclipse.emf.test.core.ecore;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.ETypedElement;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.ExtendedMetaData;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.eclipse.emf.ecore.util.FeatureMapUtil;
import org.junit.Test;
public class FeatureMapTest
{
@Test
public void testAttributesAsFeatures() throws Exception
{
EcorePackage ecorePackage = EcorePackage.eINSTANCE;
EcoreFactory ecoreFactory = EcoreFactory.eINSTANCE;
EPackage myPack = ecoreFactory.createEPackage();
myPack.setName("mypack");
EClass employeeClass = ecoreFactory.createEClass();
myPack.getEClassifiers().add(employeeClass);
employeeClass.setName("Employee");
// Sequence
EAttribute ordersAttr = ecoreFactory.createEAttribute();
employeeClass.getEStructuralFeatures().add(ordersAttr);
ordersAttr.setName("orders");
// set the multiplicity
ordersAttr.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);
// use the EFeatureMapEntry type
ordersAttr.setEType(ecorePackage.getEFeatureMapEntry());
// use the default ExtendedMetadata instance to set the feature to the desired kind
ExtendedMetaData.INSTANCE.setFeatureKind(ordersAttr, ExtendedMetaData.GROUP_FEATURE);
// the first derived reference
EAttribute preferredAtt = ecoreFactory.createEAttribute();
employeeClass.getEStructuralFeatures().add(preferredAtt);
preferredAtt.setName("preferredOrders");
preferredAtt.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);
preferredAtt.setEType(ecorePackage.getEString());
preferredAtt.setVolatile(true);
preferredAtt.setTransient(true);
preferredAtt.setDerived(true);
ExtendedMetaData.INSTANCE.setGroup(preferredAtt, ordersAttr);
// the second derived reference
EAttribute standardAtt = ecoreFactory.createEAttribute();
employeeClass.getEStructuralFeatures().add(standardAtt);
standardAtt.setName("standardOrders");
standardAtt.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);
standardAtt.setEType(ecorePackage.getEString());
standardAtt.setVolatile(true);
standardAtt.setTransient(true);
standardAtt.setDerived(true);
ExtendedMetaData.INSTANCE.setGroup(standardAtt, ordersAttr);
assertTrue(FeatureMapUtil.isFeatureMap(ordersAttr));
assertFalse(FeatureMapUtil.isFeatureMap(preferredAtt));
assertFalse(FeatureMapUtil.isFeatureMap(standardAtt));
EObject eObject = myPack.getEFactoryInstance().create(employeeClass);
@SuppressWarnings("unchecked")
List<String> preferredList = (List<String>)eObject.eGet(preferredAtt);
@SuppressWarnings("unchecked")
List<String> standardList = (List<String>)eObject.eGet(standardAtt);
preferredList.add("String1");
preferredList.add("String2");
standardList.add("String3");
standardList.add("String4");
assertEquals("String1", preferredList.get(0));
assertEquals("String2", preferredList.get(1));
assertEquals("String3", standardList.get(0));
assertEquals("String4", standardList.get(1));
FeatureMap ordersFeatureMap = (FeatureMap)eObject.eGet(ordersAttr);
assertEquals(preferredList, ordersFeatureMap.get(preferredAtt, false));
assertEquals(standardList, ordersFeatureMap.get(standardAtt, false));
ordersFeatureMap.add(preferredAtt, "String5");
ordersFeatureMap.add(standardAtt, "String6");
assertEquals("String5", preferredList.get(2));
assertEquals("String6", standardList.get(2));
}
@Test
public void testReferencesAsFeatures() throws Exception
{
EcorePackage ecorePackage = EcorePackage.eINSTANCE;
EcoreFactory ecoreFactory = EcoreFactory.eINSTANCE;
EPackage myPack = ecoreFactory.createEPackage();
myPack.setName("mypack");
EClass employeeClass = ecoreFactory.createEClass();
myPack.getEClassifiers().add(employeeClass);
employeeClass.setName("Employee");
EClass orderClass = ecoreFactory.createEClass();
myPack.getEClassifiers().add(orderClass);
orderClass.setName("Order");
// Sequence
EAttribute ordersAttr = ecoreFactory.createEAttribute();
employeeClass.getEStructuralFeatures().add(ordersAttr);
ordersAttr.setName("orders");
ordersAttr.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);
ordersAttr.setEType(ecorePackage.getEFeatureMapEntry());
ExtendedMetaData.INSTANCE.setFeatureKind(ordersAttr, ExtendedMetaData.GROUP_FEATURE);
// the first derived reference
EReference preferredRef = ecoreFactory.createEReference();
employeeClass.getEStructuralFeatures().add(preferredRef);
preferredRef.setName("preferredOrders");
preferredRef.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);
preferredRef.setContainment(true);
preferredRef.setEType(orderClass);
preferredRef.setVolatile(true);
preferredRef.setTransient(true);
preferredRef.setDerived(true);
ExtendedMetaData.INSTANCE.setGroup(preferredRef, ordersAttr);
// the second derived reference
EReference standardRef = ecoreFactory.createEReference();
employeeClass.getEStructuralFeatures().add(standardRef);
standardRef.setName("standardOrders");
standardRef.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);
standardRef.setEType(orderClass);
standardRef.setContainment(true);
standardRef.setVolatile(true);
standardRef.setTransient(true);
standardRef.setDerived(true);
ExtendedMetaData.INSTANCE.setGroup(standardRef, ordersAttr);
EObject eObject = myPack.getEFactoryInstance().create(employeeClass);
@SuppressWarnings("unchecked")
List<EObject> preferredList = (List<EObject>)eObject.eGet(preferredRef);
@SuppressWarnings("unchecked")
List<EObject> standardList = (List<EObject>)eObject.eGet(standardRef);
EObject order1 = myPack.getEFactoryInstance().create(orderClass);
EObject order2 = myPack.getEFactoryInstance().create(orderClass);
EObject order3 = myPack.getEFactoryInstance().create(orderClass);
EObject order4 = myPack.getEFactoryInstance().create(orderClass);
preferredList.add(order1);
preferredList.add(order2);
standardList.add(order3);
standardList.add(order4);
assertEquals(order1, preferredList.get(0));
assertEquals(order2, preferredList.get(1));
assertEquals(order3, standardList.get(0));
assertEquals(order4, standardList.get(1));
FeatureMap ordersFeatureMap = (FeatureMap)eObject.eGet(ordersAttr);
assertEquals(preferredList, ordersFeatureMap.get(preferredRef, false));
assertEquals(standardList, ordersFeatureMap.get(standardRef, false));
EObject order5 = myPack.getEFactoryInstance().create(orderClass);
EObject order6 = myPack.getEFactoryInstance().create(orderClass);
ordersFeatureMap.add(preferredRef, order5);
ordersFeatureMap.add(standardRef, order6);
assertEquals(order5, preferredList.get(2));
assertEquals(order6, standardList.get(2));
assertEquals(3, preferredList.size());
assertEquals(3, standardList.size());
ordersFeatureMap.add(preferredRef, order3);
assertEquals(4, preferredList.size());
assertEquals(order3, preferredList.get(3));
assertEquals(2, standardList.size());
assertFalse(standardList.contains(order3));
}
/*
* Bugzilla 127109
*/
@Test
public void testMoveElements() throws Exception
{
moveElementsTest(false);
}
/*
* Bugzilla 127109
*/
@Test
public void testMoveElements_WithNotification() throws Exception
{
moveElementsTest(true);
}
public void moveElementsTest(boolean withNotification) throws Exception
{
EPackage pack = EcoreFactory.eINSTANCE.createEPackage();
pack.setName("pack");
pack.setNsURI("featureMap.test.pack");
EClass house = EcoreFactory.eINSTANCE.createEClass();
pack.getEClassifiers().add(house);
house.setName("Order");
EClass car = EcoreFactory.eINSTANCE.createEClass();
pack.getEClassifiers().add(car);
car.setName("Car");
EClass person = EcoreFactory.eINSTANCE.createEClass();
pack.getEClassifiers().add(person);
person.setName("Person");
EAttribute things = EcoreFactory.eINSTANCE.createEAttribute();
person.getEStructuralFeatures().add(things);
things.setName("things");
things.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);
things.setEType(EcorePackage.Literals.EFEATURE_MAP_ENTRY);
ExtendedMetaData.INSTANCE.setFeatureKind(things, ExtendedMetaData.GROUP_FEATURE);
EReference houses = EcoreFactory.eINSTANCE.createEReference();
person.getEStructuralFeatures().add(houses);
houses.setName("houses");
houses.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);
houses.setContainment(true);
houses.setEType(house);
houses.setVolatile(true);
houses.setTransient(true);
houses.setDerived(true);
ExtendedMetaData.INSTANCE.setGroup(houses, things);
EReference cars = EcoreFactory.eINSTANCE.createEReference();
person.getEStructuralFeatures().add(cars);
cars.setName("cars");
cars.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);
cars.setContainment(true);
cars.setEType(car);
cars.setVolatile(true);
cars.setTransient(true);
cars.setDerived(true);
ExtendedMetaData.INSTANCE.setGroup(cars, things);
EObject john = EcoreUtil.create(person);
EObject house1 = EcoreUtil.create(house);
EObject car1 = EcoreUtil.create(car);
FeatureMap thingsFeatureMap = (FeatureMap)john.eGet(things);
final List<Adapter> referenceNotificationCount = new ArrayList<Adapter>();
final List<Adapter> attributeNotificationCount = new ArrayList<Adapter>();
final Map<EObject, EReference> referenceByValueMap = new LinkedHashMap<EObject, EReference>();
if (withNotification)
{
final FeatureMap theFeatureMap = thingsFeatureMap;
Adapter adapter = new AdapterImpl()
{
@Override
public void notifyChanged(Notification msg)
{
assertEquals(referenceByValueMap.size(), theFeatureMap.size());
int valueCount = 0;
int index=0;
for (Map.Entry<?, ?> entry : referenceByValueMap.entrySet())
{
assertEquals(entry.getValue(), theFeatureMap.getEStructuralFeature(index));
assertEquals(entry.getKey(), theFeatureMap.getValue(index));
++index;
if (entry.getValue() == msg.getFeature())
{
valueCount++;
}
}
if (msg.getFeature() instanceof EReference)
{
referenceNotificationCount.add(this);
if (msg.getEventType() == Notification.MOVE)
{
assertTrue("pos: " + msg.getPosition(), msg.getPosition() >= 0);
assertTrue("pos: " + msg.getPosition() + " vc:" + valueCount, msg.getPosition() < valueCount);
}
}
else if (msg.getFeature() instanceof EAttribute)
{
attributeNotificationCount.add(this);
}
}
};
john.eAdapters().add(adapter);
}
if (withNotification) referenceByValueMap.put(house1, houses);
@SuppressWarnings("unchecked")
List<EObject> johnHouses = ((List<EObject>)john.eGet(houses));
johnHouses.add(house1);
if (withNotification) assertEquals(1, referenceNotificationCount.size());
if (withNotification) assertEquals(1, attributeNotificationCount.size());
if (withNotification) referenceByValueMap.put(car1, cars);
@SuppressWarnings("unchecked")
List<EObject> johnCars = ((List<EObject>)john.eGet(cars));
johnCars.add(car1);
if (withNotification) assertEquals(2, referenceNotificationCount.size());
if (withNotification) assertEquals(2, attributeNotificationCount.size());
assertEquals(2, thingsFeatureMap.size());
assertEquals(houses, thingsFeatureMap.getEStructuralFeature(0));
assertEquals(cars, thingsFeatureMap.getEStructuralFeature(1));
assertEquals(house1, thingsFeatureMap.getValue(0));
assertEquals(car1, thingsFeatureMap.getValue(1));
// Target > Source && Different References
if (withNotification) referenceByValueMap.clear();
if (withNotification) referenceByValueMap.put(car1, cars);
if (withNotification) referenceByValueMap.put(house1, houses);
thingsFeatureMap.move(1, 0);
if (withNotification) assertEquals(2, referenceNotificationCount.size());
if (withNotification) assertEquals(3, attributeNotificationCount.size());
assertEquals(2, thingsFeatureMap.size());
assertEquals(cars, thingsFeatureMap.getEStructuralFeature(0));
assertEquals(houses, thingsFeatureMap.getEStructuralFeature(1));
assertEquals(car1, thingsFeatureMap.getValue(0));
assertEquals(house1, thingsFeatureMap.getValue(1));
EObject car2 = EcoreUtil.create(car);
if (withNotification) referenceByValueMap.clear();
if (withNotification) referenceByValueMap.put(car1, cars);
if (withNotification) referenceByValueMap.put(car2, cars);
if (withNotification) referenceByValueMap.put(house1, houses);
thingsFeatureMap.add(1, cars, car2);
if (withNotification) assertEquals(3, referenceNotificationCount.size());
if (withNotification) assertEquals(4, attributeNotificationCount.size());
assertEquals(3, thingsFeatureMap.size());
assertEquals(cars, thingsFeatureMap.getEStructuralFeature(0));
assertEquals(cars, thingsFeatureMap.getEStructuralFeature(1));
assertEquals(houses, thingsFeatureMap.getEStructuralFeature(2));
assertEquals(car1, thingsFeatureMap.getValue(0));
assertEquals(car2, thingsFeatureMap.getValue(1));
assertEquals(house1, thingsFeatureMap.getValue(2));
// Target < Source && Different References
if (withNotification) referenceByValueMap.clear();
if (withNotification) referenceByValueMap.put(house1, houses);
if (withNotification) referenceByValueMap.put(car1, cars);
if (withNotification) referenceByValueMap.put(car2, cars);
thingsFeatureMap.move(0, 2);
if (withNotification) assertEquals(3, referenceNotificationCount.size());
if (withNotification) assertEquals(5, attributeNotificationCount.size());
assertEquals(3, thingsFeatureMap.size());
assertEquals(houses, thingsFeatureMap.getEStructuralFeature(0));
assertEquals(cars, thingsFeatureMap.getEStructuralFeature(1));
assertEquals(cars, thingsFeatureMap.getEStructuralFeature(2));
assertEquals(house1, thingsFeatureMap.getValue(0));
assertEquals(car1, thingsFeatureMap.getValue(1));
assertEquals(car2, thingsFeatureMap.getValue(2));
// Target < Source && Same Reference
if (withNotification) referenceByValueMap.clear();
if (withNotification) referenceByValueMap.put(house1, houses);
if (withNotification) referenceByValueMap.put(car2, cars);
if (withNotification) referenceByValueMap.put(car1, cars);
thingsFeatureMap.move(1, 2);
if (withNotification) assertEquals(4, referenceNotificationCount.size());
if (withNotification) assertEquals(6, attributeNotificationCount.size());
assertEquals(3, thingsFeatureMap.size());
assertEquals(houses, thingsFeatureMap.getEStructuralFeature(0));
assertEquals(cars, thingsFeatureMap.getEStructuralFeature(1));
assertEquals(cars, thingsFeatureMap.getEStructuralFeature(2));
assertEquals(house1, thingsFeatureMap.getValue(0));
assertEquals(car2, thingsFeatureMap.getValue(1));
assertEquals(car1, thingsFeatureMap.getValue(2));
// Target > Source && Same Reference
if (withNotification) referenceByValueMap.clear();
if (withNotification) referenceByValueMap.put(house1, houses);
if (withNotification) referenceByValueMap.put(car1, cars);
if (withNotification) referenceByValueMap.put(car2, cars);
thingsFeatureMap.move(2, 1);
if (withNotification) assertEquals(5, referenceNotificationCount.size());
if (withNotification) assertEquals(7, attributeNotificationCount.size());
assertEquals(3, thingsFeatureMap.size());
assertEquals(houses, thingsFeatureMap.getEStructuralFeature(0));
assertEquals(cars, thingsFeatureMap.getEStructuralFeature(1));
assertEquals(cars, thingsFeatureMap.getEStructuralFeature(2));
assertEquals(house1, thingsFeatureMap.getValue(0));
assertEquals(car1, thingsFeatureMap.getValue(1));
assertEquals(car2, thingsFeatureMap.getValue(2));
// Target == Source
thingsFeatureMap.move(2, 2);
if (withNotification) assertEquals(5, referenceNotificationCount.size());
if (withNotification) assertEquals(8, attributeNotificationCount.size());
assertEquals(3, thingsFeatureMap.size());
assertEquals(houses, thingsFeatureMap.getEStructuralFeature(0));
assertEquals(cars, thingsFeatureMap.getEStructuralFeature(1));
assertEquals(cars, thingsFeatureMap.getEStructuralFeature(2));
assertEquals(house1, thingsFeatureMap.getValue(0));
assertEquals(car1, thingsFeatureMap.getValue(1));
assertEquals(car2, thingsFeatureMap.getValue(2));
// Target < Source && Different References && Source Reference changes
if (withNotification) referenceByValueMap.clear();
if (withNotification) referenceByValueMap.put(car2, cars);
if (withNotification) referenceByValueMap.put(house1, houses);
if (withNotification) referenceByValueMap.put(car1, cars);
thingsFeatureMap.move(0, 2);
if (withNotification) assertEquals(6, referenceNotificationCount.size());
if (withNotification) assertEquals(9, attributeNotificationCount.size());
assertEquals(3, thingsFeatureMap.size());
assertEquals(cars, thingsFeatureMap.getEStructuralFeature(0));
assertEquals(houses, thingsFeatureMap.getEStructuralFeature(1));
assertEquals(cars, thingsFeatureMap.getEStructuralFeature(2));
assertEquals(car2, thingsFeatureMap.getValue(0));
assertEquals(house1, thingsFeatureMap.getValue(1));
assertEquals(car1, thingsFeatureMap.getValue(2));
if (withNotification)
{
assertFalse(referenceByValueMap.isEmpty());
assertFalse(referenceNotificationCount.isEmpty());
assertFalse(attributeNotificationCount.isEmpty());
}
else
{
assertTrue(referenceByValueMap.isEmpty());
assertTrue(referenceNotificationCount.isEmpty());
assertTrue(attributeNotificationCount.isEmpty());
}
}
}