/*
* Copyright (c) 2005, 2010 Borland Software 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: Radek Dvorak (Borland) - initial API and implementation
*/
package org.eclipse.gmf.tests.rt;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.codegen.ecore.genmodel.GenClass;
import org.eclipse.emf.codegen.ecore.genmodel.GenFeature;
import org.eclipse.emf.common.util.Enumerator;
import org.eclipse.emf.ecore.EAttribute;
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.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.gmf.codegen.gmfgen.GenCommonBase;
import org.eclipse.gmf.codegen.gmfgen.GenExpressionProviderBase;
import org.eclipse.gmf.codegen.gmfgen.GenExpressionProviderContainer;
import org.eclipse.gmf.codegen.gmfgen.GenFeatureInitializer;
import org.eclipse.gmf.codegen.gmfgen.GenFeatureSeqInitializer;
import org.eclipse.gmf.codegen.gmfgen.GenFeatureValueSpec;
import org.eclipse.gmf.codegen.gmfgen.GenJavaExpressionProvider;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.tests.setup.RuntimeBasedGeneratorConfiguration;
import org.eclipse.gmf.tests.setup.ViewerConfiguration;
/**
* Tests domain meta-model element initialization
*/
public class ElementInitializerTest extends GeneratedCanvasTest {
private EObject nodeAElement;
private EObject nodeBElement;
protected String myElementInitializersClassName;
private Node myNodeB;
private Node myNodeA;
public ElementInitializerTest(String name) {
this(name, new RuntimeBasedGeneratorConfiguration());
}
protected ElementInitializerTest(String name, ViewerConfiguration.Factory viewerConfigFactory) {
super(name, viewerConfigFactory);
}
protected void setUp() throws Exception {
super.setUp();
myNodeA = createNode(getGenModel().getNodeA(), getDiagram());
this.nodeAElement = myNodeA.getElement();
myNodeB = createNode(getGenModel().getNodeB(), getDiagram());
this.nodeBElement = myNodeB.getElement();
assertNotNull("Tested node A element not available", nodeAElement); //$NON-NLS-1$
assertNotNull("Tested node B element not available", nodeBElement); //$NON-NLS-1$
myElementInitializersClassName = getGenModel().getGenDiagram().getProvidersPackageName() + ".ElementInitializers"; //$NON-NLS-1$
}
public void testNewElementInitializer() throws Exception {
EStructuralFeature feature = nodeAElement.eClass().getEStructuralFeature("refNewElement"); //$NON-NLS-1$
assertNotNull("feature not found in the intializer class", feature); //$NON-NLS-1$
Object val = nodeAElement.eGet(feature);
assertTrue(val instanceof EClass);
EClass newEClass = (EClass)val;
assertEquals("Only one attribute expected", 1, newEClass.getEAllAttributes().size()); //$NON-NLS-1$
EAttribute attribute = newEClass.getEAllAttributes().iterator().next();
assertEquals("attribute should be named by its EClass name", attribute.eClass().getName(), attribute.getName()); //$NON-NLS-1$
assertEquals("attribute must be of String type", EcorePackage.eINSTANCE.getEString(), attribute.getEType()); //$NON-NLS-1$
assertEquals("Only one operation expected", 1, newEClass.getEOperations().size()); //$NON-NLS-1$
EOperation operation = newEClass.getEOperations().iterator().next();
assertEquals("operation should be named by its metaclass", operation.eClass().getName(), operation.getName()); //$NON-NLS-1$
EClassifier expectedType = nodeAElement.eClass();
assertEquals("operation should return type of its containing class", expectedType, operation.getEType()); //$NON-NLS-1$
}
public void testSeveralNewElementInitializers() {
EStructuralFeature feature = nodeAElement.eClass().getEStructuralFeature("nestedNodes1"); //$NON-NLS-1$
assertNotNull("feature not found in the intializer class", feature); //$NON-NLS-1$
Object val = nodeAElement.eGet(feature);
assertTrue(val instanceof Collection<?>);
Collection<?> children = (Collection<?>) val;
assertEquals("2 child nodes expected", 2, children.size());
int index = 0;
for (Iterator<?> it = children.iterator(); it.hasNext(); index++) {
Object nextChild = it.next();
assertTrue("Incorrect child present", nextChild instanceof EObject);
EObject nextEObject = (EObject) nextChild;
EStructuralFeature nameFeature = nextEObject.eClass().getEStructuralFeature("name");
assertNotNull("feature 'name' was not found in child node", nameFeature);
Object name = nextEObject.eGet(nameFeature);
assertTrue("Incorrect name value returned", name instanceof String);
assertEquals("Name feature was not correctly initialized", nextEObject.eClass().getName() + "_" + index, (String) name);
}
}
/*
* [227127] Literal element initializers
*/
public void testLiteralElementInitializers() {
Edge a2b = createLink(getGenModel().getLinkC(), myNodeA, myNodeB);
assertNotNull("There were no link kind restrictions, should be no problem to create a link", a2b);
EObject linkObject = a2b.getElement();
assertNotNull(linkObject);
EStructuralFeature boolAttr = linkObject.eClass().getEStructuralFeature("boolToInit");
assertNotNull(boolAttr);
EStructuralFeature stringAttr = linkObject.eClass().getEStructuralFeature("stringToInit");
assertNotNull(stringAttr);
assertEquals("Value of boolean attribute after element creation should match one set in LinkSessionSetup", Boolean.TRUE, linkObject.eGet(boolAttr));
assertEquals("Value of string attribute after element creation should match one set in LinkSessionSetup", "init-string", linkObject.eGet(stringAttr));
}
public void testDeepNewElementInitializers() {
// Node_0
EObject child = getFirstChildNode1(nodeAElement);
// Node_0_0
child = getFirstChildNode1(child);
// Node_0_0_0
child = getFirstChildNode1(child);
// Node_0_0_0_0
child = getFirstChildNode1(child);
// Node_0_0_0_0_0
child = getFirstChildNode1(child);
}
private EObject getFirstChildNode1(EObject parent) {
EStructuralFeature feature = parent.eClass().getEStructuralFeature("nestedNodes1"); //$NON-NLS-1$
assertNotNull("feature not found in the intializer class", feature); //$NON-NLS-1$
Object val = parent.eGet(feature);
assertTrue(val instanceof Collection<?>);
Collection<?> children = (Collection<?>) val;
assertTrue("At least one child node expected", children.size() > 0);
Object child = children.iterator().next();
assertTrue("Child element dhould be EObject", child instanceof EObject);
return (EObject) child;
}
public void testJavaInitializers() throws Exception {
Class<?> javaContainerClass = getSetup().loadGeneratedClass(myElementInitializersClassName);
assertNotNull("Could not find generated java initializer class", javaContainerClass); //$NON-NLS-1$
GenJavaExpressionProvider javaProvider = null;
GenExpressionProviderContainer container = getGenModel().getGenDiagram().getEditorGen().getExpressionProviders();
for (GenExpressionProviderBase nextProvider : container.getProviders()) {
if(nextProvider instanceof GenJavaExpressionProvider) {
javaProvider = (GenJavaExpressionProvider)nextProvider;
}
}
assertNotNull(javaProvider);
boolean primitiveTypeAttrTested = false;
boolean objValTypeAttrTested = false;
boolean refTested = false;
boolean multiValPrimitiveTypeAttrTested = false;
boolean multiObjValTypeAttrTested = false;
boolean multiRefTested = false;
Iterator<EObject> it = getGenModel().getGenDiagram().eAllContents();
while (it.hasNext()) {
Object element = it.next();
if(element instanceof GenFeatureSeqInitializer) {
GenFeatureSeqInitializer fsInitializer = (GenFeatureSeqInitializer) element;
for (GenFeatureInitializer featureInitializer : fsInitializer.getInitializers()) {
if(!(featureInitializer instanceof GenFeatureValueSpec)) continue;
GenFeatureValueSpec nextFtValSpec = (GenFeatureValueSpec)featureInitializer;
if (nextFtValSpec.getValue().getProvider() != javaProvider) continue;
GenCommonBase diagramElement = null;
if (fsInitializer.getTypeModelFacet().eContainer() instanceof GenCommonBase) {
// hack to get required element to construct java operation name -
// assume model facets are contained in GenNode/GenLink
diagramElement = (GenCommonBase ) fsInitializer.getTypeModelFacet().eContainer();
}
if (diagramElement == null) {
continue; // just in case
}
// ElementInitializers.ext#javaMethodName
StringBuilder operationName = new StringBuilder(nextFtValSpec.getFeature().getEcoreFeature().getName());
operationName.append('_');
if (nextFtValSpec.getFeatureSeqInitializer().getCreatingInitializer() != null) {
operationName.append(nextFtValSpec.getFeatureSeqInitializer().getCreatingInitializer().getFeature().getEcoreFeature().getName());
operationName.append('_');
}
operationName.append(diagramElement.getUniqueIdentifier());
Method method = findMethod(javaContainerClass, operationName.toString(), fsInitializer.getElementClass());
assertNotNull("Can't find Java method:" + operationName.toString(), method);
GenFeature genFeature = nextFtValSpec.getFeature();
if(genFeature.isPrimitiveType() && !genFeature.isListType()) {
assertTrue("Use wrapper class for primitive return type", //$NON-NLS-1$
!method.getReturnType().isPrimitive() && genFeature.isPrimitiveType());
assertEquals(method.getReturnType(), EcoreUtil.wrapperClassFor(genFeature.getEcoreFeature().getEType().getInstanceClass()));
primitiveTypeAttrTested = true;
}
else if(!genFeature.isReferenceType() && genFeature.getEcoreFeature().isMany() && genFeature.getEcoreFeature().getEType().getInstanceClass().isPrimitive()) {
assertEquals(List.class.getName(), method.getReturnType().getName());
multiValPrimitiveTypeAttrTested = true;
}
else if(!genFeature.isReferenceType() && !genFeature.isPrimitiveType() && !genFeature.isListType()) {
assertEquals(genFeature.getType(genFeature.getGenClass()), method.getReturnType().getName());
objValTypeAttrTested = true;
}
else if(!genFeature.isReferenceType() && !genFeature.isPrimitiveType() && genFeature.isListType()) {
assertEquals(List.class.getName(), method.getReturnType().getName());
multiObjValTypeAttrTested = true;
}
else if(genFeature.isReferenceType() && !genFeature.isListType()) {
assertEquals(genFeature.getTypeGenClass().getQualifiedInterfaceName(), method.getReturnType().getName());
refTested = true;
}
else if(genFeature.isReferenceType() && genFeature.isListType()) {
assertEquals(List.class.getName(), method.getReturnType().getName());
multiRefTested = true;
}
}
}
}
assertTrue(primitiveTypeAttrTested);
assertTrue(objValTypeAttrTested);
assertTrue(refTested);
assertTrue(multiValPrimitiveTypeAttrTested);
assertTrue(multiObjValTypeAttrTested);
assertTrue(multiRefTested);
}
public void testAttrMany() throws Exception {
EStructuralFeature attrManyFeature = nodeBElement.eClass().getEStructuralFeature("integers_Init"); //$NON-NLS-1$
assertNotNull("field not found in tested class", attrManyFeature); //$NON-NLS-1$
Object value = nodeBElement.eGet(attrManyFeature);
assertEquals(value, Arrays.asList(new Object[] { new Integer(10), new Integer(20) }));
}
public void testReferenceToMany() throws Exception {
EStructuralFeature refToManyFeature = nodeAElement.eClass().getEStructuralFeature("reference_Init"); //$NON-NLS-1$
assertNotNull("field not found in tested class", refToManyFeature); //$NON-NLS-1$
Object value = nodeAElement.eGet(refToManyFeature);
assertEquals(value, Arrays.asList(new Object[] { nodeAElement }));
}
// #115521 - test of enum literal assignment to a structural feature
public void testEnumLiteralAttr() throws Exception {
EStructuralFeature enumField = nodeAElement.eClass().getEStructuralFeature("enumAttr_Init"); //$NON-NLS-1$
assertNotNull("enum field not found in tested class", enumField); //$NON-NLS-1$
assertTrue(enumField.getEType() instanceof EEnum);
EEnum testEnum = (EEnum) enumField.getEType();
EEnumLiteral literal = testEnum.getEEnumLiteral("LIT1"); //$NON-NLS-1$
Object literalValue = nodeAElement.eGet(enumField);
assertNotNull(literalValue);
assertFalse("Should be set to different from default", literalValue.equals(enumField.getDefaultValue())); //$NON-NLS-1$
assertSame("Expected literal set by initializer", literal.getInstance(), literalValue); //$NON-NLS-1$
}
public void testManyEnumLiteralAttr() throws Exception {
EStructuralFeature enumField = nodeAElement.eClass().getEStructuralFeature("manyEnumAttr_Init"); //$NON-NLS-1$
assertNotNull("enum field not found in tested class", enumField); //$NON-NLS-1$
assertTrue(enumField.getEType() instanceof EEnum);
EEnum testEnum = (EEnum) enumField.getEType();
Collection<Enumerator> expectedValues = new ArrayList<Enumerator>();
expectedValues.add(getEnumLiteralInstance(testEnum, "LIT0")); //$NON-NLS-1$
expectedValues.add(getEnumLiteralInstance(testEnum, "LIT1")); //$NON-NLS-1$
Object literalValues = nodeAElement.eGet(enumField);
assertTrue(literalValues instanceof Collection<?>);
Collection<?> retrivedValues = (Collection<?>) literalValues;
assertEquals(expectedValues, retrivedValues);
}
public void testManyRealAttr() throws Exception {
EStructuralFeature realField = nodeAElement.eClass().getEStructuralFeature("manyRealAttr_Init"); //$NON-NLS-1$
assertNotNull("Float type attribute not found in tested class", realField); //$NON-NLS-1$
Object realValues = nodeAElement.eGet(realField);
assertTrue(realValues instanceof Collection<?>);
Collection<?> retrivedValues = (Collection<?>) realValues;
// @see LinkSessionSetup
Collection<Float> expectedValues = new ArrayList<Float>();
expectedValues.add(new Float(1.0));
expectedValues.add(new Float(1.5));
// 1->1.0 should involve known numeric type default conversion in Element Initializer
assertEquals(expectedValues, retrivedValues);
}
private Enumerator getEnumLiteralInstance(EEnum eEnum, String literalName) {
EEnumLiteral literal = eEnum.getEEnumLiteral(literalName);
assertNotNull("Enum literal not found", literal); //$NON-NLS-1$
assertNotNull("Enum literal has no instance", literal.getInstance()); //$NON-NLS-1$
return literal.getInstance();
}
private Method findMethod(Class<?> clazz, String methodName, GenClass contextClass) throws Exception {
try {
Class<?>[] params = new Class[] { getSetup().loadGeneratedClass(contextClass.getQualifiedInterfaceName()) };
for (int i = 0; i < clazz.getDeclaredMethods().length; i++) {
Method method = clazz.getDeclaredMethods()[i];
if(method.getName().equals(methodName)) {
if(Arrays.equals(params, method.getParameterTypes())) {
return method;
}
}
}
} catch (ClassNotFoundException e) {
fail("Expected class not generated. " + e.toString()); //$NON-NLS-1$
}
return null;
}
}