/*******************************************************************************
* Copyright (c) 2008, 2015 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:
* Borland Software Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.m2m.tests.qvt.oml.ocl2qvt;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.m2m.internal.qvt.oml.blackbox.BlackboxUnitDescriptor;
import org.eclipse.m2m.internal.qvt.oml.blackbox.BlackboxRegistry;
import org.eclipse.m2m.internal.qvt.oml.blackbox.BlackboxUnit;
import org.eclipse.m2m.internal.qvt.oml.blackbox.LoadContext;
import org.eclipse.m2m.internal.qvt.oml.blackbox.ResolutionContext;
import org.eclipse.m2m.internal.qvt.oml.blackbox.ResolutionContextImpl;
import org.eclipse.m2m.internal.qvt.oml.compiler.CompiledUnit;
import org.eclipse.m2m.internal.qvt.oml.expressions.Module;
import org.eclipse.m2m.internal.qvt.oml.runtime.util.OCLEnvironmentWithQVTAccessFactory;
import org.eclipse.m2m.tests.qvt.oml.util.TestUtil;
import org.eclipse.ocl.ParserException;
import org.eclipse.ocl.ecore.Constraint;
import org.eclipse.ocl.ecore.EcoreEvaluationEnvironment;
import org.eclipse.ocl.ecore.OCL;
import org.eclipse.ocl.ecore.OCL.Query;
import org.eclipse.ocl.ecore.Variable;
import org.eclipse.ocl.helper.OCLHelper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import junit.framework.TestCase;
public class OCLEnvironmentWithQVTAccessTest extends TestCase {
private static final String SRC_CONTAINER = "parserTestData/externlib"; //$NON-NLS-1$
protected OCL fOCL;
protected OCLEnvironmentWithQVTAccessFactory fEnvFactory;
public OCLEnvironmentWithQVTAccessTest() {
super();
}
protected LinkedHashSet<Module> getImportedModules() {
return new LinkedHashSet<Module>(fEnvFactory.getQVTModules());
}
protected EcoreEvaluationEnvironment getEvaluationEnv(Query query) {
return (EcoreEvaluationEnvironment)query.getEvaluationEnvironment();
}
protected final Object evaluate(Query query) {
return evaluate(getEvaluationEnv(query), query);
}
protected Object evaluate(EcoreEvaluationEnvironment evalEnv, Query query) {
return query.evaluate();
}
protected Object evaluate(EcoreEvaluationEnvironment evalEnv, Query query, Object self) {
return query.evaluate(self);
}
@Override
@Before
protected void setUp() {
fEnvFactory = createOCLEnvFactory();
assertTrue(fEnvFactory.getDiagnostic().getSeverity() == Diagnostic.OK);
fOCL = OCL.newInstance(fEnvFactory);
}
protected OCLEnvironmentWithQVTAccessFactory createOCLEnvFactory() {
return new OCLEnvironmentWithQVTAccessFactory(createImportedModules(), EPackage.Registry.INSTANCE);
}
private LinkedHashSet<Module> createImportedModules() {
final Set<CompiledUnit> compileModules = TestUtil.compileModules(SRC_CONTAINER, new String[] {
"org.q1", "org.q2" //$NON-NLS-1$ //$NON-NLS-2$
});
LinkedHashSet<Module> modules = new LinkedHashSet<Module>();
for (CompiledUnit compiledUnits : compileModules) {
modules.addAll(compiledUnits.getModules());
}
try {
ResolutionContext resolutionContext = new ResolutionContextImpl(compileModules.iterator().next().getURI());
// import "Strings" black-box library
BlackboxUnitDescriptor abstractCompilationUnitDescriptor = BlackboxRegistry.INSTANCE.getCompilationUnitDescriptor("Strings", resolutionContext);
assertNotNull("descriptor must be found", abstractCompilationUnitDescriptor); //$NON-NLS-1$
LoadContext loadContext = new LoadContext(EPackage.Registry.INSTANCE);
BlackboxUnit loadCompilationUnit = abstractCompilationUnitDescriptor.load(loadContext); //BlackboxRegistry.INSTANCE.loadCompilationUnit(abstractCompilationUnitDescriptor, loadContext);
modules.add(loadCompilationUnit.getElements().get(0).getModuleContextType());
} catch (Exception e) {
throw new RuntimeException("Failed to setup test", e);
}
return modules;
}
@Override
@After
protected void tearDown() throws Exception {
this.fEnvFactory = null;
this.fOCL = null;
}
@SuppressWarnings("unchecked")
@Test
public void testUserDefinedVariables() throws Exception {
OCLHelper<EClassifier, EOperation, EStructuralFeature, Constraint> helper = fOCL.createOCLHelper();
helper.setContext(EcorePackage.eINSTANCE.getENamedElement());
try {
helper.setValidating(true);
Variable var = org.eclipse.ocl.ecore.EcoreFactory.eINSTANCE.createVariable();
// name it 'this' intentionally, as it also tests, that non-QVT execution context
// has now predefined this variable and it brings now collision with QVT
var.setName("this");
var.setEType(helper.getEnvironment().getOCLStandardLibrary().getString());
var.setType(var.getEType());
helper.getEnvironment().addElement(var.getName(), (org.eclipse.ocl.expressions.Variable)var, true);
org.eclipse.ocl.expressions.OCLExpression<EClassifier> q = helper.createQuery("this.concat(getModulePropertyValue())");
assertNull(helper.getProblems());
Query query = fOCL.createQuery(q);
EcoreEvaluationEnvironment evalEnv = getEvaluationEnv(query);
evalEnv.add(var.getName(), "userVarValue");
Object result = evaluate(evalEnv, query);
assertEquals("userVarValuemoduleProperty_suffix_suffix", result);
} catch (ParserException e) {
e.printStackTrace();
fail("Additional operation should come from super type"); //$NON-NLS-1$
}
}
@Test
public void testImportedOperationAccessingModuleProperty() throws Exception {
OCLHelper<EClassifier, EOperation, EStructuralFeature, Constraint> helper = fOCL.createOCLHelper();
helper.setContext(EcorePackage.eINSTANCE.getENamedElement());
try {
helper.setValidating(true);
org.eclipse.ocl.expressions.OCLExpression<EClassifier> q = helper.createQuery("getModulePropertyValue()");
assertNull(helper.getProblems());
Object result = evaluate(fOCL.createQuery(q));
assertEquals("moduleProperty_suffix_suffix", result);
} catch (ParserException e) {
e.printStackTrace();
fail("Additional operation should come from super type"); //$NON-NLS-1$
}
}
@Test
public void testStdlibOperationAccess() throws ParserException {
OCLHelper<EClassifier, EOperation, EStructuralFeature, Constraint> helper = fOCL.createOCLHelper();
helper.setContext(EcorePackage.eINSTANCE.getENamedElement());
try {
helper.setValidating(true);
org.eclipse.ocl.expressions.OCLExpression<EClassifier> q =
helper.createQuery("createTestedInvalid().oclIsUndefined()");
assertNull(helper.getProblems());
Query query = fOCL.createQuery(q);
Object result = evaluate(getEvaluationEnv(query),
query, EcoreFactory.eINSTANCE.createEClass());
assertEquals(Boolean.TRUE, result);
} catch (ParserException e) {
e.printStackTrace();
fail("Additional operation should come from super type"); //$NON-NLS-1$
}
}
@Test
public void testQVTStdlibOperationAccess() throws ParserException {
OCLHelper<EClassifier, EOperation, EStructuralFeature, Constraint> helper = fOCL.createOCLHelper();
helper.setContext(EcorePackage.eINSTANCE.getENamedElement());
try {
helper.setValidating(true);
org.eclipse.ocl.expressions.OCLExpression<EClassifier> q =
helper.createQuery("let e : Stdlib::Element = self in e.subobjects()"); //$NON-NLS-1$
assertNull(helper.getProblems());
Query query = fOCL.createQuery(q);
Object result = evaluate(getEvaluationEnv(query),
query, EcorePackage.eINSTANCE);
assertEquals(new HashSet<EClassifier>(EcorePackage.eINSTANCE.getEClassifiers()), result);
} catch (ParserException e) {
e.printStackTrace();
fail(e.getMessage());
}
}
@Test
public void testImportedModulePropertyAccess() throws ParserException {
OCLHelper<EClassifier, EOperation, EStructuralFeature, Constraint> helper = fOCL.createOCLHelper();
helper.setContext(EcorePackage.eINSTANCE.getENamedElement());
try {
helper.setValidating(true);
org.eclipse.ocl.expressions.OCLExpression<EClassifier> q =
helper.createQuery("moduleProperty");
assertNull(helper.getProblems());
Object result = fOCL.createQuery(q).evaluate();
assertEquals("moduleProperty_suffix", result);
} catch (ParserException e) {
e.printStackTrace();
fail("Additional operation should come from super type"); //$NON-NLS-1$
}
}
@Test
public void testImportedOperations() throws ParserException {
OCLHelper<EClassifier, EOperation, EStructuralFeature, Constraint> helper = fOCL.createOCLHelper();
helper.setContext(EcorePackage.eINSTANCE.getENamedElement());
try {
helper.setValidating(true);
org.eclipse.ocl.expressions.OCLExpression<EClassifier> q = helper.createQuery(
"let c : Sequence(String) = Sequence {} in " +
"q1(c).concat(q2(Bag{'aString'})).concat('ab'.firstToUpper()).concat('xx'.lastIndexOf('x').repr())");
assertNull(helper.getProblems());
Object result = evaluate(fOCL.createQuery(q));
assertEquals("name = xxxAb2", result);
} catch (ParserException e) {
e.printStackTrace();
fail(e.getLocalizedMessage());
}
}
@Test
public void testComplextTypeInSignatures() throws Exception {
OCLHelper<EClassifier, EOperation, EStructuralFeature, Constraint> helper = fOCL.createOCLHelper();
helper.setContext(EcorePackage.eINSTANCE.getENamedElement());
try {
helper.setValidating(true);
org.eclipse.ocl.expressions.OCLExpression<EClassifier> q = helper.createQuery(
"let t : Tuple(name : String, size : Integer) = Tuple { name = 'bob', size = 10} " +
"in let result : Tuple(name1 : String, name2 : String) = callOnTupleType(t) " +
"in result.name1.concat(result.name2) = 'bob10'");
assertNull(helper.getProblems());
Object result = evaluate(fOCL.createQuery(q));
assertEquals(Boolean.TRUE, result);
} catch (ParserException e) {
e.printStackTrace();
fail(e.getLocalizedMessage());
}
}
@Test
public void testImportedContextualOperation() throws ParserException {
OCLHelper<EClassifier, EOperation, EStructuralFeature, Constraint> helper = fOCL.createOCLHelper();
helper.setContext(EcorePackage.eINSTANCE.getENamedElement());
try {
helper.setValidating(true);
org.eclipse.ocl.expressions.OCLExpression<EClassifier> q = helper.createQuery(
"self.getUpperName()");
assertNull(helper.getProblems());
EClass eClass = EcoreFactory.eINSTANCE.createEClass();
eClass.setName("foo");
Object result = fOCL.createQuery(q).evaluate(eClass);
assertEquals("EClass-FOO", result);
EParameter eParam = EcoreFactory.eINSTANCE.createEParameter();
eParam.setName("foo");
result = fOCL.createQuery(q).evaluate(eParam);
assertEquals("FOO", result);
} catch (ParserException e) {
e.printStackTrace();
fail(e.getLocalizedMessage());
}
}
@Test
public void testImportedOperationOnCollection() throws ParserException {
OCLHelper<EClassifier, EOperation, EStructuralFeature, Constraint> helper = fOCL.createOCLHelper();
helper.setContext(EcorePackage.eINSTANCE.getENamedElement());
try {
helper.setValidating(true);
org.eclipse.ocl.expressions.OCLExpression<EClassifier> q = helper.createQuery(
"let c : Sequence(String) = Sequence { 'foo' } in " +
"c->callOnCollection()->includes('foo')");
assertNull(helper.getProblems());
Object result = evaluate(fOCL.createQuery(q));
assertEquals(Boolean.TRUE, result);
} catch (ParserException e) {
e.printStackTrace();
fail(e.getLocalizedMessage());
}
}
@Test
public void testCallImportedQvtFileWhichCallsJavaLibrary() throws ParserException {
OCLHelper<EClassifier, EOperation, EStructuralFeature, Constraint> helper = fOCL.createOCLHelper();
helper.setContext(EcorePackage.eINSTANCE.getENamedElement());
try {
helper.setValidating(true);
org.eclipse.ocl.expressions.OCLExpression<EClassifier> q = helper.createQuery(
"callImportedQvtFileWhichCallsJavaLibrary('Hello!')");
assertNull(helper.getProblems());
Object result = evaluate(fOCL.createQuery(q));
assertEquals("Hello!", result);
} catch (ParserException e) {
e.printStackTrace();
fail(e.getLocalizedMessage());
}
}
@Test
public void testValidationProblems() throws Exception {
OCLHelper<EClassifier, EOperation, EStructuralFeature, Constraint> helper = fOCL.createOCLHelper();
try {
helper.setContext(EcorePackage.eINSTANCE.getENamedElement());
helper.setValidating(true);
helper.createQuery("let s : String = 1 in true");
fail("Parser error was expected");
} catch (ParserException e) {
assertNotNull(helper.getProblems());
}
}
@Test
public void testParsingProblems() throws Exception {
OCLHelper<EClassifier, EOperation, EStructuralFeature, Constraint> helper = fOCL.createOCLHelper();
try {
helper.setContext(EcorePackage.eINSTANCE.getENamedElement());
helper.setValidating(true);
helper.createQuery("1>++2");
fail("Parser error was expected");
} catch (ParserException e) {
assertNotNull(helper.getProblems() != null);
}
}
}