blob: 2f5963950da34dc0eb994204444cbee13358d71d [file] [log] [blame]
/*
* Copyright (c) 2013, 2018 CEA and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Christian W. Damus (CEA) - initial API and implementation
* Kenn Hussey (CEA) - 399544
* Kenn Hussey - 535301
*/
package org.eclipse.uml2.uml.bug.tests;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
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.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
import org.eclipse.uml2.common.util.UML2Util;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Enumeration;
import org.eclipse.uml2.uml.EnumerationLiteral;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.UMLFactory;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.resource.UMLResource;
import org.eclipse.uml2.uml.tests.util.StandaloneSupport;
import org.eclipse.uml2.uml.util.UMLUtil;
/**
* Test suite for the changes introduced for Bug 392833.
*
* @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=392833
*/
public class Bug392833Test
extends TestCase {
private final UMLUtilAccess util = new UMLUtilAccess();
private ResourceSet rset;
private Profile profile;
/**
* Initializes me with my name.
*
* @param name
* my name
*/
public Bug392833Test(String name) {
super(name);
}
public static Test suite() {
return new TestSuite(Bug392833Test.class, "Bug 392833 tests"); //$NON-NLS-1$
}
/**
* Test that Ecore definitions correctly resolve to their UML counterparts
* when the Ecore definition resides separately in a package registry as it
* does in the CDO context.
*/
public void test_emulatingCDOPackageRegistry()
throws IOException {
Stereotype bean = profile.getOwnedStereotype("Bean"); //$NON-NLS-1$
EPackage definition = profile.define();
EPackage copy = makeUMLReferencesUnresolvable(EcoreUtil
.copy(definition));
Resource res = new EcoreResourceFactoryImpl().createResource(URI
.createURI(definition.getNsURI()));
res.getContents().add(copy);
profile.eResource().getResourceSet().getPackageRegistry()
.put(copy.getNsURI(), copy);
Model model = createModel();
model.applyProfile(profile);
profile.define(); // define it again to try to confuse the profile look-up
Class myEJB = model.createOwnedClass("MyEJB", false); //$NON-NLS-1$
myEJB.applyStereotype(bean);
assertTrue("Stereotype not properly applied.", //$NON-NLS-1$
myEJB.isStereotypeApplied(bean));
// note that this API requires the Ecore name
myEJB.setValue(bean, "type", "session"); //$NON-NLS-1$ //$NON-NLS-2$
// reload from fake storage in which the xsi:schemaLocation is *not*
// used (the schema implicitly resolves from the package registry).
// This emulates the CDO package registry structure
String text = serialize(model.eResource());
text = text.replaceFirst("\\s*xsi:schemaLocation=\"[^\"]+\"", ""); //$NON-NLS-1$ //$NON-NLS-2$
model = reload(model.eResource(), text, UMLPackage.Literals.MODEL);
// stereotype is still applied
myEJB = (Class) model.getOwnedType("MyEJB"); //$NON-NLS-1$
assertTrue("Stereotype not properly applied.", //$NON-NLS-1$
myEJB.isStereotypeApplied(bean));
// note that this API requires the Ecore name
assertEquals("session", String.valueOf(myEJB.getValue(bean, "type"))); //$NON-NLS-1$ //$NON-NLS-2$
}
public void test_profileDefinitionsAccess() {
EPackage discombobulatedPackage = makeUMLReferencesUnresolvable(EcoreUtil
.copy(profile.define()));
Model model = createModel();
model.applyProfile(profile);
assertEEquals(discombobulatedPackage, profile.getDefinition());
assertSame(profile,
util.access_getNamedElement(discombobulatedPackage, model));
EClass ejb = (EClass) discombobulatedPackage.getEClassifier("EJB"); //$NON-NLS-1$
assertNotNull(ejb);
Stereotype bean = profile.getOwnedStereotype("Bean"); //$NON-NLS-1$
assertEEquals(ejb, profile.getDefinition(bean));
assertSame(bean, util.access_getNamedElement(ejb, model));
EStructuralFeature type = ejb.getEStructuralFeature("type"); //$NON-NLS-1$
assertNotNull(type);
Property kind = bean.getOwnedAttribute("kind", null); //$NON-NLS-1$
assertEEquals(type, profile.getDefinition(kind));
assertSame(kind, util.access_getNamedElement(type, model));
EEnum ejbKind = (EEnum) discombobulatedPackage
.getEClassifier("EJBKind"); //$NON-NLS-1$
assertNotNull(ejbKind);
Enumeration beanKind = (Enumeration) profile.getOwnedType("BeanKind"); //$NON-NLS-1$
assertEEquals(ejbKind, profile.getDefinition(beanKind));
assertSame(beanKind, util.access_getNamedElement(ejbKind, model));
EEnumLiteral eLiteral = ejbKind.getEEnumLiteral("messagedriven"); //$NON-NLS-1$
assertNotNull(eLiteral);
EnumerationLiteral literal = beanKind.getOwnedLiteral("messagedriven"); //$NON-NLS-1$
assertEEquals(eLiteral, profile.getDefinition(literal));
assertSame(literal, util.access_getNamedElement(eLiteral, model));
}
//
// Test framework
//
@Override
protected void setUp()
throws Exception {
rset = new ResourceSetImpl();
if (StandaloneSupport.isStandalone()) {
StandaloneSupport.init(rset);
}
profile = getTestProfile();
}
@Override
protected void tearDown()
throws Exception {
profile = null;
for (Resource next : rset.getResources()) {
next.unload();
}
rset.getResources().clear();
rset.eAdapters().clear();
rset = null;
}
protected void assertEEquals(EObject obj1, EObject obj2) {
new EcoreUtil.EqualityHelper() {
private static final long serialVersionUID = 1L;
protected boolean haveEqualReference(EObject eObject1,
EObject eObject2, EReference reference) {
// don't look at annotation references because we made the
// unresolvable in the copy
return (reference == EcorePackage.Literals.EANNOTATION__REFERENCES)
|| super.haveEqualReference(eObject1, eObject2, reference);
}
}.equals(obj1, obj2);
}
Profile getTestProfile() {
URL url = getClass().getResource("Bug392833.profile.uml"); //$NON-NLS-1$
return (Profile) UML2Util.load(rset,
URI.createURI(url.toExternalForm()), UMLPackage.Literals.PROFILE);
}
EPackage makeUMLReferencesUnresolvable(EPackage ecoreDefinition) {
for (EClassifier next : ecoreDefinition.getEClassifiers()) {
EAnnotation annotation = next
.getEAnnotation(UMLUtil.UML2_UML_PACKAGE_2_0_NS_URI);
assertNotNull("Missing annotation", annotation); //$NON-NLS-1$
assertEquals("Expected exactly one UML reference", 1, annotation //$NON-NLS-1$
.getReferences().size());
// replace the UML classifier reference with an unresolvable proxy
EObject proxy = EcoreFactory.eINSTANCE.createEObject();
((InternalEObject) proxy).eSetProxyURI(URI
.createURI("test://bogus/" + next.getName())); //$NON-NLS-1$
annotation.getReferences().set(0, proxy);
}
return ecoreDefinition;
}
Model createModel() {
Resource res = UMLResource.Factory.INSTANCE.createResource(URI
.createURI("temp://model.uml")); //$NON-NLS-1$
rset.getResources().add(res);
// "temp" URI scheme is fake, so force-create resource
Model result = UMLFactory.eINSTANCE.createModel();
res.getContents().add(result);
return result;
}
String serialize(Resource res)
throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
try {
res.save(out, null);
return new String(out.toByteArray(), "UTF-8"); //$NON-NLS-1$
} finally {
out.close();
}
}
<T> T reload(Resource resource, String text, EClass rootClass)
throws IOException {
ByteArrayInputStream in = new ByteArrayInputStream(
text.getBytes("UTF-8")); //$NON-NLS-1$
resource.unload();
try {
resource.load(in, null);
return UMLUtil.load(rset, resource.getURI(), rootClass);
} finally {
in.close();
}
}
private static class UMLUtilAccess
extends UMLUtil {
NamedElement access_getNamedElement(ENamedElement definition,
EObject context) {
return getNamedElement(definition, context);
}
}
}