blob: ee93a08c5fc11fd095371635dd45c9df9a7ea97b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2018 Willink Transformations 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:
* C.Damus, K.Hussey, E.D.Willink - Initial API and implementation
* E.D.Willink - Bug 306079, 322159, 353171
* K.Hussey - Bug 331143
*******************************************************************************/
package org.eclipse.ocl.ecore.tests;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.EMFPlugin;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.DiagnosticChain;
import org.eclipse.emf.common.util.ECollections;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.Enumerator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAnnotation;
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.EFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EOperation.Internal.InvocationDelegate;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EPackage.Registry;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EStructuralFeature.Internal.SettingDelegate;
import org.eclipse.emf.ecore.EValidator;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.plugin.EcorePlugin;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.Diagnostician;
import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
import org.eclipse.emf.ecore.util.EObjectValidator;
import org.eclipse.emf.ecore.util.QueryDelegate;
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
import org.eclipse.ocl.ParserException;
import org.eclipse.ocl.common.OCLCommon;
import org.eclipse.ocl.common.OCLConstants;
import org.eclipse.ocl.common.delegate.DelegateResourceSetAdapter;
import org.eclipse.ocl.common.internal.delegate.OCLDelegateException;
import org.eclipse.ocl.common.internal.options.CommonOptions;
import org.eclipse.ocl.ecore.BooleanLiteralExp;
import org.eclipse.ocl.ecore.EcoreFactory;
import org.eclipse.ocl.ecore.EvaluationVisitorImpl;
import org.eclipse.ocl.ecore.NullLiteralExp;
import org.eclipse.ocl.ecore.OCL;
import org.eclipse.ocl.ecore.OCL.Helper;
import org.eclipse.ocl.ecore.OCLExpression;
import org.eclipse.ocl.ecore.OperationCallExp;
import org.eclipse.ocl.ecore.PropertyCallExp;
import org.eclipse.ocl.ecore.delegate.DelegateDomain;
import org.eclipse.ocl.ecore.delegate.InvocationBehavior;
import org.eclipse.ocl.ecore.delegate.OCLDelegateDomain;
import org.eclipse.ocl.ecore.delegate.OCLDelegateDomainFactory;
import org.eclipse.ocl.ecore.delegate.OCLInvocationDelegateFactory;
import org.eclipse.ocl.ecore.delegate.OCLQueryDelegateFactory;
import org.eclipse.ocl.ecore.delegate.OCLSettingDelegateFactory;
import org.eclipse.ocl.ecore.delegate.OCLValidationDelegateFactory;
import org.eclipse.ocl.ecore.delegate.SettingBehavior;
import org.eclipse.ocl.ecore.delegate.ValidationBehavior;
import org.eclipse.ocl.ecore.delegate.ValidationDelegate;
import org.eclipse.ocl.ecore.opposites.DefaultOppositeEndFinder;
import org.eclipse.ocl.ecore.opposites.EcoreEnvironmentFactoryWithHiddenOpposites;
import org.eclipse.ocl.ecore.tests.extlibrary.EXTLibraryFactory;
import org.eclipse.ocl.ecore.tests.extlibrary.EXTLibraryPackage;
import org.eclipse.ocl.ecore.tests.extlibrary.Library;
import org.eclipse.ocl.internal.l10n.OCLMessages;
import org.eclipse.osgi.util.NLS;
import company.Bug418716;
import company.CompanyFactory;
import company.CompanyPackage;
import company.Employee;
import company.util.CompanyValidator;
import noreflectioncompany.NoreflectioncompanyPackage;
/**
* Tests for the OCL delegate implementations.
*/
@SuppressWarnings("nls")
public class DelegatesTest extends AbstractTestSuite
{
protected static final String COMPANY_XMI = "/model/Company.xmi";
protected static final String NO_REFLECTION_COMPANY_XMI = "/model/NoReflectionCompany.xmi";
protected static final String MODEL_WITH_ERRORS_XMI = "/model/ModelWithErrors.xmi";
public Resource testResource;
public EPackage companyPackage;
public EFactory companyFactory;
public EClass companyClass;
public EAttribute companyName;
public EReference companyEmployees;
public EAttribute companySize;
public EClass employeeClass;
public EAttribute employeeName;
public EReference employeeManager;
public EReference employeeDirectReports;
public EReference employeeAllReports;
public EOperation employeeReportsTo;
public EEnum sizeKind;
public Enumerator sizeSmall;
public Enumerator sizeMedium;
public Enumerator sizeLarge;
public EObject acme;
public Map<String, EObject> employees;
public EClass badClassClass;
public EReference companyDetritus;
public Map<Object, Object> context = new HashMap<Object, Object>();
public boolean eclipseIsRunning;
public boolean usedLocalRegistry;
//
// Test framework
//
@Override
protected void setUp() {
super.setUp();
eclipseIsRunning = EMFPlugin.IS_ECLIPSE_RUNNING;
usedLocalRegistry = false;
initializeResourceSet(OCLConstants.OCL_DELEGATE_URI_LPG);
OCLDelegateDomain.initializeMappingFrom(null, OCLConstants.OCL_DELEGATE_URI);
}
protected void initializeResourceSet(String oclDelegateURI) {
if (!eclipseIsRunning) { // Install the 'plugin' registrations
EOperation.Internal.InvocationDelegate.Factory.Registry.INSTANCE.put(oclDelegateURI,
new OCLInvocationDelegateFactory.Global());
EStructuralFeature.Internal.SettingDelegate.Factory.Registry.INSTANCE.put(oclDelegateURI,
new OCLSettingDelegateFactory.Global());
EValidator.ValidationDelegate.Registry.INSTANCE.put(oclDelegateURI,
new OCLValidationDelegateFactory.Global());
QueryDelegate.Factory.Registry.INSTANCE.put(oclDelegateURI,
new OCLQueryDelegateFactory.Global());
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(
"xmi", new EcoreResourceFactoryImpl());
EPackage.Registry.INSTANCE.remove(CompanyPackage.eNS_URI); // Reference and nullify the side effect of the reference
resourceSet.getPackageRegistry().remove(CompanyPackage.eNS_URI); // In case previous test failed
EPackage.Registry.INSTANCE.remove(NoreflectioncompanyPackage.eNS_URI); // Reference and nullify the side effect of the reference
resourceSet.getPackageRegistry().remove(NoreflectioncompanyPackage.eNS_URI); // In case previous test failed
}
// Install a DelegateResourceSetAdapter to supervise local registries and resource post-loading
DelegateResourceSetAdapter adapter = DelegateResourceSetAdapter.getAdapter(resourceSet);
// Install a local DelegateDomain.Factory
DelegateDomain.Factory.Registry.Impl delegateDomainFactory =
new DelegateDomain.Factory.Registry.Impl();
delegateDomainFactory.put(oclDelegateURI, new OCLDelegateDomainFactory());
adapter.putRegistry(DelegateDomain.Factory.Registry.class, delegateDomainFactory);
// Install a local ValidationDelegate.Factory
ValidationDelegate.Factory.Registry validationDelegateFactoryRegistry =
new ValidationDelegate.Factory.Registry.Impl();
validationDelegateFactoryRegistry.put(oclDelegateURI, new OCLValidationDelegateFactory(oclDelegateURI) {
@Override
public ValidationDelegate createValidationDelegate(EClassifier classifier) {
usedLocalRegistry = true;
return super.createValidationDelegate(classifier);
}
});
adapter.putRegistry(ValidationDelegate.Factory.Registry.class, validationDelegateFactoryRegistry);
// Install a local SettingDelegate.Factory
EStructuralFeature.Internal.SettingDelegate.Factory.Registry settingDelegateFactoryRegistry =
new EStructuralFeature.Internal.SettingDelegate.Factory.Registry.Impl();
settingDelegateFactoryRegistry.put(oclDelegateURI, new OCLSettingDelegateFactory(oclDelegateURI) {
@Override
public SettingDelegate createSettingDelegate(EStructuralFeature structuralFeature) {
usedLocalRegistry = true;
return super.createSettingDelegate(structuralFeature);
}
});
adapter.putRegistry(EStructuralFeature.Internal.SettingDelegate.Factory.Registry.class, settingDelegateFactoryRegistry);
// Install a local InvocationDelegate.Factory
EOperation.Internal.InvocationDelegate.Factory.Registry invocationDelegateFactoryRegistry =
new EOperation.Internal.InvocationDelegate.Factory.Registry.Impl();
invocationDelegateFactoryRegistry.put(oclDelegateURI, new OCLInvocationDelegateFactory(oclDelegateURI) {
@Override
public InvocationDelegate createInvocationDelegate(EOperation operation) {
usedLocalRegistry = true;
return super.createInvocationDelegate(operation);
}
});
adapter.putRegistry(EOperation.Internal.InvocationDelegate.Factory.Registry.class, invocationDelegateFactoryRegistry);
// Install a local QueryDelegate.Factory
QueryDelegate.Factory.Registry queryDelegateFactoryRegistry =
new QueryDelegate.Factory.Registry.Impl();
queryDelegateFactoryRegistry.put(oclDelegateURI, new OCLQueryDelegateFactory(oclDelegateURI) {
@Override
public QueryDelegate createQueryDelegate(EClassifier context,
Map<String, EClassifier> parameters, String expression) {
usedLocalRegistry = true;
return super.createQueryDelegate(context, parameters, expression);
}});
adapter.putRegistry(QueryDelegate.Factory.Registry.class, queryDelegateFactoryRegistry);
}
protected void initModel(String testModelName) {
URI uri = getTestModelURI(testModelName);
testResource = resourceSet.getResource(uri, true);
acme = testResource.getContents().get(0);
companyClass = acme.eClass();
companyPackage = companyClass.getEPackage();
companyFactory = companyPackage.getEFactoryInstance();
companyName = (EAttribute) companyClass.getEStructuralFeature("name");
companyEmployees = (EReference) companyClass
.getEStructuralFeature("employees");
companySize = (EAttribute) companyClass.getEStructuralFeature("size");
employeeClass = companyEmployees.getEReferenceType();
employeeName = (EAttribute) employeeClass.getEStructuralFeature("name");
employeeManager = (EReference) employeeClass
.getEStructuralFeature("manager");
employeeDirectReports = (EReference) employeeClass
.getEStructuralFeature("directReports");
employeeAllReports = (EReference) employeeClass
.getEStructuralFeature("allReports");
employeeReportsTo = getOperation(employeeClass, "reportsTo");
sizeKind = (EEnum) companySize.getEAttributeType();
sizeSmall = sizeKind.getEEnumLiteral("small").getInstance();
sizeMedium = sizeKind.getEEnumLiteral("medium").getInstance();
sizeLarge = sizeKind.getEEnumLiteral("large").getInstance();
employees = new java.util.HashMap<String, EObject>();
}
protected void initModelWithErrors() {
URI uri = getTestModelURI(MODEL_WITH_ERRORS_XMI);
testResource = resourceSet.getResource(uri, true);
acme = testResource.getContents().get(0);
companyClass = acme.eClass();
companyPackage = companyClass.getEPackage();
companyFactory = companyPackage.getEFactoryInstance();
badClassClass = (EClass) companyPackage.getEClassifier("BadClass");
companyDetritus = (EReference) companyClass .getEStructuralFeature("detritus");
}
protected void initPackageRegistrations() {
if (!eclipseIsRunning) {
resourceSet.getPackageRegistry().put(CompanyPackage.eNS_URI, CompanyPackage.eINSTANCE);
resourceSet.getPackageRegistry().put(NoreflectioncompanyPackage.eNS_URI, NoreflectioncompanyPackage.eINSTANCE);
}
}
public void doTest_allInstances(String modelName) {
initModel(modelName);
EList<EObject> amyAllReports = allReports(employee("Amy"));
assertEquals(5, amyAllReports.size());
assertTrue(amyAllReports.contains(employee("Bob")));
assertTrue(amyAllReports.contains(employee("Jane")));
assertTrue(amyAllReports.contains(employee("Fred")));
assertTrue(amyAllReports.contains(employee("Norbert")));
assertTrue(amyAllReports.contains(employee("Sally")));
// change the set of all instances of Employee
set(create(acme, companyEmployees, employeeClass, "Manuel"),
employeeManager, employee("Bob"));
amyAllReports = allReports(employee("Amy"));
assertEquals(6, amyAllReports.size());
assertTrue(amyAllReports.contains(employee("Manuel")));
}
public void doTest_constraintValidation(String modelName) {
initModel(modelName);
EObject employee = create(acme, companyEmployees, employeeClass, null);
set(employee, employeeManager, employee("Bob"));
validateConstraintWithError("mustHaveName", employee);
set(employee, employeeName, "Joe");
validateWithoutError(employee);
validateWithoutError(acme);
}
public void doTest_eAttributeDerivation(String modelName) {
initModel(modelName);
assertSame(sizeSmall, size(acme));
// add a load of employees
EList<EObject> emps = employees(acme);
for (int i = 0; i < 60; i++) {
emps.add(companyFactory.create(employeeClass));
}
assertSame(sizeMedium, size(acme));
// and another bunch
for (int i = 0; i < 1000; i++) {
emps.add(companyFactory.create(employeeClass));
}
assertSame(sizeLarge, size(acme));
}
public void doTest_eReferenceDerivation(String modelName) {
initModel(modelName);
EList<EObject> amyReports = directReports(employee("Amy"));
assertEquals(3, amyReports.size());
assertTrue(amyReports.contains(employee("Bob")));
assertTrue(amyReports.contains(employee("Jane")));
assertTrue(amyReports.contains(employee("Fred")));
EList<EObject> bobReports = directReports(employee("Bob"));
assertEquals(2, bobReports.size());
assertTrue(bobReports.contains(employee("Norbert")));
assertTrue(bobReports.contains(employee("Sally")));
EList<EObject> sallyReports = directReports(employee("Sally"));
assertEquals(0, sallyReports.size());
}
public void doTest_invariantValidation(String modelName, boolean hasInvariants) {
initModel(modelName);
EObject joe = create(acme, companyEmployees, employeeClass, "Joe");
if (hasInvariants) {
validateInvariantWithError("noManagerImpliesDirectReports", joe);
}
else {
validateConstraintWithError("noManagerImpliesDirectReports", joe);
}
set(employee("Amy"), employeeManager, joe);
validateWithoutError(joe);
}
public void doTest_operationInvocation(String modelName) {
initModel(modelName);
EObject amy = employee("Amy");
// allReports is implemented using reportsTo()
EList<EObject> amyAllReports = allReports(amy);
assertEquals(5, amyAllReports.size());
for (EObject next : amyAllReports) {
assertTrue(this.<Boolean> invoke(next, employeeReportsTo, amy));
}
}
public void doTest_queryExecution(String modelName) {
initModel(modelName);
QueryDelegate.Factory factory = QueryDelegate.Factory.Registry.INSTANCE
.getFactory(OCLConstants.OCL_DELEGATE_URI_LPG);
String n = "n";
String expression = "self.employees->select(employee | employee.manager <> null and employee.manager.name = n)";
EObject amy = employee("Amy");
Map<String, EClassifier> parameters = new HashMap<String, EClassifier>();
parameters.put(n, EcorePackage.Literals.ESTRING);
QueryDelegate delegate = factory.createQueryDelegate(companyClass,
parameters, expression);
executeWithException(delegate, amy, null,
OCLMessages.WrongContextClassifier_ERROR_, amy.eClass().getName(), acme.eClass().getName());
Map<String, Object> arguments = new HashMap<String, Object>();
arguments.put(n, "Amy");
Collection<?> amyReports = (Collection<?>) execute(delegate, acme, arguments);
assertEquals(3, amyReports.size());
assertTrue(amyReports.contains(employee("Bob")));
assertTrue(amyReports.contains(employee("Jane")));
assertTrue(amyReports.contains(employee("Fred")));
executeWithException(delegate, employee("Bob"), null,
OCLMessages.WrongContextClassifier_ERROR_, amy.eClass().getName(), acme.eClass().getName());
arguments = new HashMap<String, Object>();
arguments.put(n, "Bob");
Collection<?> bobReports = (Collection<?>) execute(delegate, acme, arguments);
assertEquals(2, bobReports.size());
assertTrue(bobReports.contains(employee("Norbert")));
assertTrue(bobReports.contains(employee("Sally")));
executeWithException(delegate, employee("Sally"), null,
OCLMessages.WrongContextClassifier_ERROR_, amy.eClass().getName(), acme.eClass().getName());
arguments = new HashMap<String, Object>();
arguments.put(n, "Sally");
Collection<?> sallyReports = (Collection<?>) execute(delegate, acme, arguments);
assertEquals(0, sallyReports.size());
}
public void doTest_queryExecutionWithExceptions(String modelName) throws InvocationTargetException {
initModel(modelName);
QueryDelegate.Factory factory = QueryDelegate.Factory.Registry.INSTANCE
.getFactory(OCLConstants.OCL_DELEGATE_URI_LPG);
String okName = "ok";
String badName = "xyzzy";
EObject amy = employee("Amy");
Map<String, Object> okBindings = new HashMap<String, Object>();
okBindings.put(okName, Integer.valueOf(123));
Map<String, EClassifier> variables = new HashMap<String, EClassifier>();
variables.put(okName, EcorePackage.Literals.ESTRING);
QueryDelegate delegate;
//
// Syntax error in expression
//
delegate = factory.createQueryDelegate(companyClass, null, "n=");
executeWithException(delegate, amy, null,
"2:2:2:2 \"relationalNotLetCS\" expected after \"=\"");
//
// Undeclared variable
//
delegate = factory.createQueryDelegate(companyClass, variables, badName);
executeWithException(delegate, acme, null,
OCLMessages.UnrecognizedVar_ERROR_, badName);
//
// Definition of undeclared variable
//
delegate = factory.createQueryDelegate(companyClass, variables, "self");
Map<String, Object> bindings = new HashMap<String, Object>();
bindings.put(okName, "xx");
bindings.put(badName, Integer.valueOf(123));
executeWithException(delegate, acme, bindings,
OCLMessages.ExtraArg_ERROR_, badName);
//
// Mis-definition of context
//
delegate = factory.createQueryDelegate(companyClass, variables, "self");
delegate.prepare();
executeWithException(delegate, amy, okBindings,
OCLMessages.WrongContextClassifier_ERROR_, amy.eClass().getName(), acme.eClass().getName());
//
// Mis-definition of variable
//
delegate = factory.createQueryDelegate(companyClass, variables, "self");
delegate.prepare();
executeWithException(delegate, acme, okBindings,
OCLMessages.TypeConformanceInit_ERROR_, okName);
}
public void test_allInstances() {
doTest_allInstances(COMPANY_XMI);
assertEquals(!eclipseIsRunning, usedLocalRegistry);
}
public void test_allInstances_registered() {
initPackageRegistrations();
doTest_allInstances(COMPANY_XMI);
assertFalse(usedLocalRegistry);
}
public void test_attributeDefinedWithDerivationAndInitial() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
Object actual = get(badClassInstance, (EAttribute)badClassClass.getEStructuralFeature("attributeDefinedWithDerivationAndInitial"));
assertEquals(42, actual);
}
public void test_attributeDefinedWithInitial() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
Object actual = get(badClassInstance, (EAttribute)badClassClass.getEStructuralFeature("attributeDefinedWithInitial"));
assertEquals(-42, actual);
}
public void test_attributeDefinedWithoutDerivation() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
getWithException(badClassInstance, "attributeDefinedWithoutDerivation",
OCLMessages.MissingDerivationForSettingDelegate_ERROR_, "modelWithErrors::BadClass.attributeDefinedWithoutDerivation");
}
public void test_attributeDefinedWithoutDerivationBody() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
getWithException(badClassInstance, "attributeDefinedWithoutDerivationBody",
OCLMessages.MissingDerivationForSettingDelegate_ERROR_, "modelWithErrors::BadClass.attributeDefinedWithoutDerivationBody");
}
public void test_attributeEvaluatingToInvalid() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
getWithException(badClassInstance, "attributeEvaluatingToInvalid",
OCLMessages.EvaluationResultIsInvalid_ERROR_, "modelWithErrors::BadClass.attributeEvaluatingToInvalid");
}
public void test_attributeEvaluatingToNull() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
EStructuralFeature eStructuralFeature = badClassInstance.eClass().getEStructuralFeature("attributeEvaluatingToNull");
assertEquals(null, get(badClassInstance, eStructuralFeature));
}
public void test_attributeEvaluatingToWrongType() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
getWithException(badClassInstance, "attributeEvaluatingToWrongType",
OCLMessages.InitOrDerConstraintConformance_ERROR_, "String", "attributeEvaluatingToWrongType", "Boolean");
}
public void test_attributeParsingToLexicalError() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
getWithException(badClassInstance, "attributeParsingToLexicalError",
OCLMessages.OCLParseErrorCodes_LEX_ERROR, "2:2", "\"#\"");
}
public void test_attributeParsingToSemanticError() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
getWithException(badClassInstance, "attributeParsingToSemanticError",
OCLMessages.OperationNotFound_ERROR_, "and(Integer)", "String");
}
public void test_attributeParsingToSyntacticError() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
getWithException(badClassInstance, "attributeParsingToSyntacticError",
OCLMessages.OCLParseErrorCodes_DELETION, "2:9:2:12", "\"null\"");
}
/**
* Ensures that {@link InvocationBehavior#getOperationBody(OCL, EOperation)}
* consistently returns <code>null</code> for stdlib operations that don't
* have a body defined at all instead of returning an <code>invalid</code> literal.
* @throws ParserException
*/
public void test_attributeNotDefinedInOCLRemainsNull() throws ParserException {
helper.setContext(EcorePackage.eINSTANCE.getEClassifier());
OCLExpression expr = (OCLExpression) helper.createQuery("self.name");
assertTrue(expr instanceof PropertyCallExp);
PropertyCallExp pce = (PropertyCallExp) expr;
EStructuralFeature p = pce.getReferredProperty();
OCLExpression body = SettingBehavior.INSTANCE.getFeatureBody((OCL) ocl, p);
assertNull(body);
// and again, now reading from cache
OCLExpression bodyStillNull = SettingBehavior.INSTANCE.getFeatureBody((OCL) ocl, p);
assertNull(bodyStillNull);
}
public void test_changeableNonVolatileAttribute_418716() {
Bug418716 m = CompanyFactory.eINSTANCE.createBug418716();
assertEquals(0, m.getAttributeWithoutInitital());
assertEquals(100, m.getAttributeWithInitital());
m.setAttributeWithInitital(200);
assertEquals(0, m.getAttributeWithoutInitital());
assertEquals(200, m.getAttributeWithInitital());
}
public void test_constraintValidation() {
doTest_constraintValidation(COMPANY_XMI);
assertEquals(!eclipseIsRunning, usedLocalRegistry);
}
public void test_constraintValidation_withoutReflection() {
doTest_constraintValidation(NO_REFLECTION_COMPANY_XMI);
}
public void test_constraintValidation_registered() {
initPackageRegistrations();
doTest_constraintValidation(COMPANY_XMI);
assertFalse(usedLocalRegistry);
}
public void test_defaultIsLPG() { // Even though Pivot is the default, Pivot is not on the classpath so we get LPG
assertEquals(OCLConstants.OCL_DELEGATE_URI_LPG, CommonOptions.DEFAULT_DELEGATION_MODE.getPreferredValue());
}
public void test_eAttributeDerivation() {
doTest_eAttributeDerivation(COMPANY_XMI);
}
public void test_eAttributeDerivation_registered() {
initPackageRegistrations();
doTest_eAttributeDerivation(COMPANY_XMI);
}
public void test_eReferenceDerivation() {
doTest_eReferenceDerivation(COMPANY_XMI);
}
public void test_eReferenceDerivation_registered() {
initPackageRegistrations();
doTest_eReferenceDerivation(COMPANY_XMI);
}
/**
* Caches an operation AST in the annotation used by the {@link SettingBehavior} implementation
* and ensures that it's used by the delegate as well as the {@link EvaluationVisitorImpl}
* @throws ParserException
* @throws InvocationTargetException
*/
public void test_eReferenceDerivationUsedFromCache() throws ParserException, InvocationTargetException {
initModel(COMPANY_XMI);
EObject company = companyFactory.create(companyClass);
EObject manager = companyFactory.create(employeeClass);
manager.eSet(employeeClass.getEStructuralFeature("company"), company);
EObject employee = companyFactory.create(employeeClass);
employee.eSet(employeeClass.getEStructuralFeature("company"), company);
employee.eSet(employeeClass.getEStructuralFeature("manager"), manager);
OCL ocl = OCL.newInstance();
Helper helper = ocl.createOCLHelper();
helper.setContext(employeeClass);
OCLExpression expr = helper.createQuery("self.directReports");
assertTrue(((Collection<?>) ocl.evaluate(manager, expr)).contains(employee));
EStructuralFeature directReportsRef = employeeClass.getEStructuralFeature("directReports");
// Now cache a NullLiteralExp as the derivation expression for directReports:
NullLiteralExp nullLiteralExp = EcoreFactory.eINSTANCE.createNullLiteralExp();
EAnnotation directReportsAnn = OCLCommon.getDelegateAnnotation(directReportsRef);
assertTrue(directReportsAnn.getDetails().containsKey(SettingBehavior.DERIVATION_CONSTRAINT_KEY));
String derivationExpression = directReportsAnn.getDetails().get(SettingBehavior.DERIVATION_CONSTRAINT_KEY);
try {
directReportsAnn.getDetails().removeKey(SettingBehavior.DERIVATION_CONSTRAINT_KEY);
// ensure that the plugin cache doesn't have an expression cached:
SettingBehavior.INSTANCE.cacheOCLExpression(directReportsRef, nullLiteralExp);
assertNull(ocl.evaluate(manager, expr));
} finally {
directReportsAnn.getDetails().put(SettingBehavior.DERIVATION_CONSTRAINT_KEY, derivationExpression);
SettingBehavior.INSTANCE.cacheOCLExpression(directReportsRef, null);
}
}
public void test_hiddenOppositeInOperationDefault() throws InvocationTargetException {
URI uri = getTestModelURI("/model/HiddenOpposites.ecore");
Resource res = resourceSet.getResource(uri, true);
res.eAdapters().add(new ECrossReferenceAdapter());
EPackage hiddenOppositesPackage = (EPackage) res.getContents().get(0);
resourceSet.getPackageRegistry().put(hiddenOppositesPackage.getNsURI(), hiddenOppositesPackage);
EFactory hiddenOppositesFactory = hiddenOppositesPackage.getEFactoryInstance();
EClass sup2 = (EClass) hiddenOppositesPackage.getEClassifier("Sup2");
EClass unrelated = (EClass) hiddenOppositesPackage.getEClassifier("Unrelated");
EObject unrelatedObj = hiddenOppositesFactory.create(unrelated);
EObject sup2Obj = hiddenOppositesFactory.create(sup2);
res.getContents().add(unrelatedObj);
res.getContents().add(sup2Obj);
unrelatedObj.eSet(unrelated.getEStructuralFeature("forward"), sup2Obj);
EOperation getUnrelated = null;
for (EOperation eo : sup2.getEOperations()) {
if (eo.getName().equals("getUnrelated")) {
getUnrelated = eo;
break;
}
}
assertNotNull(getUnrelated);
Object o = sup2Obj.eInvoke(getUnrelated, null);
assertEquals(unrelatedObj, o);
}
public static class LocalOppositeEndFinder extends DefaultOppositeEndFinder {
public static boolean localOppositeEndFinderUsed = false;
public LocalOppositeEndFinder(Registry registry) {
super(registry);
localOppositeEndFinderUsed = true;
}
}
public static class LocalEnvironmentFactory extends EcoreEnvironmentFactoryWithHiddenOpposites {
public static boolean localEnvironmentFactoryUsed = false;
public LocalEnvironmentFactory(Registry registry) {
super(registry, new LocalOppositeEndFinder(registry));
localEnvironmentFactoryUsed = true;
}
}
public void test_hiddenOppositeInOperationDefinedToLocalEnvironmentFactory() throws InvocationTargetException {
URI uri = getTestModelURI("/model/HiddenOpposites.ecore");
Resource res = resourceSet.getResource(uri, true);
res.eAdapters().add(new ECrossReferenceAdapter());
EPackage hiddenOppositesPackage = (EPackage) res.getContents().get(0);
EAnnotation anno = OCLCommon.getDelegateAnnotation(hiddenOppositesPackage);
anno.getDetails().put("environmentFactoryClass", getClass().getName()+"$LocalEnvironmentFactory");
resourceSet.getPackageRegistry().put(hiddenOppositesPackage.getNsURI(), hiddenOppositesPackage);
EFactory hiddenOppositesFactory = hiddenOppositesPackage.getEFactoryInstance();
EClass sup2 = (EClass) hiddenOppositesPackage.getEClassifier("Sup2");
EClass unrelated = (EClass) hiddenOppositesPackage.getEClassifier("Unrelated");
EObject unrelatedObj = hiddenOppositesFactory.create(unrelated);
EObject sup2Obj = hiddenOppositesFactory.create(sup2);
res.getContents().add(unrelatedObj);
res.getContents().add(sup2Obj);
unrelatedObj.eSet(unrelated.getEStructuralFeature("forward"), sup2Obj);
EOperation getUnrelated = null;
for (EOperation eo : sup2.getEOperations()) {
if (eo.getName().equals("getUnrelated")) {
getUnrelated = eo;
break;
}
}
assertNotNull(getUnrelated);
Object o = sup2Obj.eInvoke(getUnrelated, null);
assertEquals(unrelatedObj, o);
assertTrue("The configured local environment factory was not used",
LocalEnvironmentFactory.localEnvironmentFactoryUsed);
assertTrue("The configured local opposite end finder was not used",
LocalOppositeEndFinder.localOppositeEndFinderUsed);
}
public void test_invariantCacheBeingUsed() throws ParserException {
initPackageRegistrations();
initModel(COMPANY_XMI);
EAnnotation annotation = OCLCommon.getDelegateAnnotation(employeeClass);
DiagnosticChain diagnostics = new BasicDiagnostic();
// first ensure that contents are padded up to where we need it:
assertTrue("Expecting \"Amy\" to be a valid name",
CompanyValidator.INSTANCE.validateEmployee_mustHaveName((Employee) employee("Amy"), diagnostics, context));
final String constraintName = "mustHaveName";
String mustHaveNameConstraint = annotation.getDetails().get(constraintName);
Helper helper = OCL.newInstance().createOCLHelper();
helper.setContext(employeeClass);
OCLExpression query = helper.createQuery("false"); // a constraint always returning false
try {
annotation.getDetails().removeKey(constraintName);
ValidationBehavior.INSTANCE.cacheOCLExpression(employeeClass,
constraintName, query);
assertFalse(
"Expected the always-false cached constraint to be used",
CompanyValidator.INSTANCE.validateEmployee_mustHaveName(
(Employee) employee("Amy"), diagnostics, context));
} finally {
// restore annotation detail and removes the cached query
annotation.getDetails().put(constraintName, mustHaveNameConstraint);
ValidationBehavior.INSTANCE.cacheOCLExpression(employeeClass, constraintName, null);
}
}
public void test_invariantCachingForFirst() {
initPackageRegistrations();
initModel(COMPANY_XMI);
DiagnosticChain diagnostics = new BasicDiagnostic();
ValidationBehavior.INSTANCE.cacheOCLExpression(employeeClass, "mustHaveName", null);
CompanyValidator.INSTANCE.validateEmployee_mustHaveName((Employee) employee("Amy"), diagnostics, context);
OCLExpression cached = ValidationBehavior.INSTANCE.getCachedOCLExpression(employeeClass, "mustHaveName");
assertTrue("Expected to find compiled expression in cache",
cached != null && !ValidationBehavior.isNoOCLDefinition(cached));
}
public void test_invariantCachingForSecond() {
initPackageRegistrations();
initModel(COMPANY_XMI);
DiagnosticChain diagnostics = new BasicDiagnostic();
ValidationBehavior.INSTANCE.cacheOCLExpression(employeeClass, "mustHaveNonEmptyName", null);
CompanyValidator.INSTANCE.validateEmployee_mustHaveNonEmptyName((Employee) employee("Amy"), diagnostics, context);
OCLExpression cached = ValidationBehavior.INSTANCE.getCachedOCLExpression(employeeClass, "mustHaveNonEmptyName");
assertTrue("Expected to find compiled expression in cache",
cached != null && !ValidationBehavior.isNoOCLDefinition(cached));
}
public void test_invariantValidation() {
doTest_invariantValidation(COMPANY_XMI, true);
assertEquals(!eclipseIsRunning, usedLocalRegistry);
}
public void test_invariantValidation_registered() {
initPackageRegistrations();
doTest_invariantValidation(COMPANY_XMI, true);
assertFalse(usedLocalRegistry);
}
public void test_invariantValidation_withoutReflection() {
doTest_invariantValidation(NO_REFLECTION_COMPANY_XMI, true);
}
public void test_invariantValidation_withoutReflection_registered() {
initPackageRegistrations();
doTest_invariantValidation(NO_REFLECTION_COMPANY_XMI, true);
}
public void test_operationDefinedWithoutBody() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
invokeWithException(badClassInstance, "operationDefinedWithoutBody",
OCLMessages.MissingBodyForInvocationDelegate_ERROR_, "modelWithErrors::BadClass.operationDefinedWithoutBody");
}
public void test_operationDefinedWithoutBodyBody() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
invokeWithException(badClassInstance, "operationDefinedWithoutBodyBody",
OCLMessages.MissingBodyForInvocationDelegate_ERROR_, "modelWithErrors::BadClass.operationDefinedWithoutBodyBody");
}
public void test_operationEvaluatingToInvalid() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
invokeWithException(badClassInstance, "operationEvaluatingToInvalid",
OCLMessages.EvaluationResultIsInvalid_ERROR_, "modelWithErrors::BadClass.operationEvaluatingToInvalid");
}
public void test_operationEvaluatingToNull() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
EOperation operation = getOperation(badClassInstance.eClass(), "operationEvaluatingToNull");
assertEquals(null, invoke(badClassInstance, operation));
}
public void test_operationEvaluatingToWrongType() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
invokeWithException(badClassInstance, "operationEvaluatingToWrongType",
OCLMessages.BodyConditionConformance_ERROR_, "operationEvaluatingToWrongType", "Integer", "Boolean");
}
public void test_operationInvocation() {
doTest_operationInvocation(COMPANY_XMI);
assertEquals(!eclipseIsRunning, usedLocalRegistry);
}
public void test_operationInvocation_registered() {
initPackageRegistrations();
doTest_operationInvocation(COMPANY_XMI);
assertFalse(usedLocalRegistry);
}
public void test_operationParsingToLexicalError() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
invokeWithException(badClassInstance, "operationParsingToLexicalError",
OCLMessages.OCLParseErrorCodes_DELETION, "2:1:2:2", "\"@@\"");
}
public void test_operationParsingToSemanticError() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
invokeWithException(badClassInstance, "operationParsingToSemanticError",
OCLMessages.OperationNotFound_ERROR_, "oclIsInvalid(Integer)", "Set(BadClass)");
}
public void test_operationParsingToSyntacticError() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
invokeWithException(badClassInstance, "operationParsingToSyntacticError",
OCLMessages.OCLParseErrorCodes_DELETION, "2:5:2:6", "\"in\"");
}
/**
* Ensures that {@link InvocationBehavior#getOperationBody(OCL, EOperation)}
* consistently returns <code>null</code> for stdlib operations that don't
* have a body defined at all instead of returning an <code>invalid</code> literal.
* @throws ParserException
*/
public void test_operationDefinedInStdlibBodyRemainsNull() throws ParserException {
helper.setContext(EcorePackage.eINSTANCE.getEClassifier());
OCLExpression expr = (OCLExpression) helper.createQuery("'abc'.oclAsType(String)");
assertTrue(expr instanceof OperationCallExp);
OperationCallExp oce = (OperationCallExp) expr;
EOperation o = oce.getReferredOperation();
OCLExpression body = InvocationBehavior.INSTANCE.getOperationBody((OCL) ocl, o);
assertNull(body);
// and again, now reading from cache
OCLExpression bodyStillNull = InvocationBehavior.INSTANCE.getOperationBody((OCL) ocl, o);;
assertTrue(bodyStillNull == null || InvocationBehavior.isNoOCLDefinition(bodyStillNull));
}
/**
* Caches an operation AST in the annotation used by the {@link InvocationBehavior} implementation
* and ensures that it's used by the delegate as well as the {@link EvaluationVisitorImpl}.
* Implicitly, the test ensures that no modification is applied to the original textual annotation,
* so that the annotation's contents are <em>not</em> used to cache the compiled AST because that
* may make some clients expecting the metamodel resources to remain unchanged angry.
*
* @throws ParserException
* @throws InvocationTargetException
*/
public void test_operationUsedFromCache() throws ParserException, InvocationTargetException {
initModel(COMPANY_XMI);
EObject manager = companyFactory.create(employeeClass);
EObject employee = companyFactory.create(employeeClass);
employee.eSet(employeeClass.getEStructuralFeature("manager"), manager);
helper.setContext(employeeClass);
OCLExpression expr = (OCLExpression) helper.createQuery("self.reportsTo(self.manager)");
assertTrue((Boolean) ocl.evaluate(employee, expr)); // by the default impl, employee reports to manager
EOperation reportsToOp = employeeClass.getEOperation(CompanyPackage.EMPLOYEE___REPORTS_TO__EMPLOYEE);
// Now cache a BooleanLiteralExp with the "false" literal as the implementation for reportsTo:
BooleanLiteralExp falseLiteralExp = EcoreFactory.eINSTANCE.createBooleanLiteralExp();
falseLiteralExp.setBooleanSymbol(false);
EAnnotation reportsToAnn = OCLCommon.getDelegateAnnotation(reportsToOp);
assertTrue(reportsToAnn.getDetails().containsKey(InvocationBehavior.BODY_CONSTRAINT_KEY));
String body = reportsToAnn.getDetails().get(InvocationBehavior.BODY_CONSTRAINT_KEY);
try {
reportsToAnn.getDetails().removeKey(InvocationBehavior.BODY_CONSTRAINT_KEY);
// ensure that the plugin cache doesn't have an expression cached:
InvocationBehavior.INSTANCE.cacheOCLExpression(reportsToOp, falseLiteralExp);
assertFalse((Boolean) ocl.evaluate(employee, expr));
} finally {
reportsToAnn.getDetails().put(InvocationBehavior.BODY_CONSTRAINT_KEY, body);
InvocationBehavior.INSTANCE.cacheOCLExpression(reportsToOp, null);
}
}
public void test_performanceOfCacheRetrieval() throws ParserException {
initModel(COMPANY_XMI);
EObject manager = companyFactory.create(employeeClass);
EObject employee = companyFactory.create(employeeClass);
employee.eSet(employeeClass.getEStructuralFeature("manager"), manager);
OCL ocl = OCL.newInstance();
Helper helper = ocl.createOCLHelper();
helper.setContext(employeeClass);
String expression = "self.reportsTo(self.manager)";
OCLExpression expr = helper.createQuery(expression);
final int TIMES = 1;
final int REPEAT = 1;
for (int r = 0; r < REPEAT; r++) {
long start = System.currentTimeMillis();
for (int i = 0; i < TIMES; i++) {
ocl.evaluate(employee, expr);
}
long end = System.currentTimeMillis();
debugPrintln("Executing " + expression + " " + TIMES
+ " times took " + (end - start) + "ms");
}
}
public void test_queryExecution() {
doTest_queryExecution(COMPANY_XMI);
assertEquals(!eclipseIsRunning, usedLocalRegistry);
}
public void test_queryExecution_registered() {
initPackageRegistrations();
doTest_queryExecution(COMPANY_XMI);
assertFalse(usedLocalRegistry);
}
public void test_queryExecutionWithExceptions() throws InvocationTargetException {
doTest_queryExecutionWithExceptions(COMPANY_XMI);
assertEquals(!eclipseIsRunning, usedLocalRegistry);
}
public void test_queryExecutionWithExceptions_registered() throws InvocationTargetException {
initPackageRegistrations();
doTest_queryExecutionWithExceptions(COMPANY_XMI);
assertFalse(usedLocalRegistry);
}
/**
* Verify that query delegates work independently of other EAnnotation declared delegates.
*/
public void test_queryExecution_Bug353171() {
QueryDelegate.Factory factory = QueryDelegate.Factory.Registry.INSTANCE
.getFactory(OCLConstants.OCL_DELEGATE_URI_LPG);
String n = "n";
String expression = "self.name";
Library library = EXTLibraryFactory.eINSTANCE.createLibrary();
library.setName("test");
Map<String, EClassifier> parameters = new HashMap<String, EClassifier>();
parameters.put(n, EcorePackage.Literals.ESTRING);
QueryDelegate delegate = factory.createQueryDelegate(EXTLibraryPackage.Literals.LIBRARY,
parameters, expression);
Map<String, Object> bindings = new HashMap<String, Object>();
bindings.put(n, "test");
Object result = execute(delegate, library, bindings);
assertEquals(result, "test");
}
/**
* EObjectValidator .validateDelegatedConstraints just skips over missing constraints.
*
public void test_validationOfMissingConstraint() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, badClassClass, null);
validateConstraintWithError("MissingConstraint", badClassInstance);
} */
/**
* EObjectValidator .validateDelegatedConstraints just skips over null bodies.
*
public void test_validationOfMissingConstraintBody() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, (EClass) companyPackage.getEClassifier("MissingConstraintBody"), null);
validateConstraintWithError("MissingConstraint", badClassInstance);
} */
public void test_validationEvaluatingToInvalid() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, (EClass) companyPackage.getEClassifier("ValidationEvaluatingToInvalid"), null);
String message = NLS.bind(OCLMessages.ValidationResultIsInvalid_ERROR_, "evaluatingToInvalid");
validateWithError("evaluatingToInvalid", "_UI_ConstraintDelegateException_diagnostic", badClassInstance,
"evaluatingToInvalid", EObjectValidator.getObjectLabel(badClassInstance, context), message,
org.eclipse.ocl.ecore.delegate.OCLDelegateException.class.getName());
}
public void test_validationEvaluatingToNull() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, (EClass) companyPackage.getEClassifier("ValidationEvaluatingToNull"), null);
String message = NLS.bind(OCLMessages.ValidationResultIsNull_ERROR_, "evaluatingToNull");
validateWithError("evaluatingToNull", "_UI_ConstraintDelegateException_diagnostic", badClassInstance,
"evaluatingToNull", EObjectValidator.getObjectLabel(badClassInstance, context), message,
org.eclipse.ocl.ecore.delegate.OCLDelegateException.class.getName());
}
public void test_validationEvaluatingToWrongType() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, (EClass) companyPackage.getEClassifier("ValidationEvaluatingToWrongType"), null);
String message = NLS.bind(OCLMessages.InvariantConstraintBoolean_ERROR_, "ValidationEvaluatingToWrongType");
validateWithError("evaluatingToWrongType", "_UI_ConstraintDelegateException_diagnostic", badClassInstance,
"evaluatingToWrongType", EObjectValidator.getObjectLabel(badClassInstance, context), message,
org.eclipse.ocl.ecore.delegate.OCLDelegateException.class.getName());
}
public void test_validationParsingToLexicalError() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, (EClass) companyPackage.getEClassifier("ValidationParsingToLexicalError"), null);
String message = NLS.bind(OCLMessages.OCLParseErrorCodes_INVALID_TOKEN, "1:4", "\"'part\"");
validateWithError("parsingToLexicalError", "_UI_ConstraintDelegateException_diagnostic", badClassInstance,
"parsingToLexicalError", EObjectValidator.getObjectLabel(badClassInstance, context), message,
org.eclipse.ocl.ecore.delegate.OCLDelegateException.class.getName());
}
public void test_validationParsingToSemanticError() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, (EClass) companyPackage.getEClassifier("ValidationParsingToSemanticError"), null);
String message = NLS.bind(OCLMessages.OperationNotFound_ERROR_, "not()", "String");
validateWithError("parsingToSemanticError", "_UI_ConstraintDelegateException_diagnostic", badClassInstance,
"parsingToSemanticError", EObjectValidator.getObjectLabel(badClassInstance, context), message,
org.eclipse.ocl.ecore.delegate.OCLDelegateException.class.getName());
}
public void test_validationParsingToSyntacticError() {
initModelWithErrors();
EObject badClassInstance = create(acme, companyDetritus, (EClass) companyPackage.getEClassifier("ValidationParsingToSyntacticError"), null);
String message = NLS.bind(OCLMessages.OCLParseErrorCodes_INVALID_TOKEN, "2:1:2:4", "\"else\"");
validateWithError("parsingToSyntacticError", "_UI_ConstraintDelegateException_diagnostic", badClassInstance,
"parsingToSyntacticError", EObjectValidator.getObjectLabel(badClassInstance, context), message,
org.eclipse.ocl.ecore.delegate.OCLDelegateException.class.getName());
}
void add(EObject owner, EStructuralFeature feature, Object value) {
this.<EList<Object>> get(owner, feature).add(value);
}
EList<EObject> allReports(EObject employee) {
return get(employee, employeeAllReports);
}
EObject create(EObject owner, EReference containment, EClass type,
String name) {
EObject result = companyFactory.create(type);
if (containment.isMany()) {
add(owner, containment, result);
} else {
set(owner, containment, result);
}
if (name != null) {
set(result, type.getEStructuralFeature("name"), name);
}
return result;
}
EList<EObject> directReports(EObject employee) {
return get(employee, employeeDirectReports);
}
EObject employee(String name) {
EObject result = employees.get(name);
if (result == null) {
EList<EObject> emps = get(acme, companyEmployees);
for (EObject next : emps) {
if (name.equals(name(next))) {
result = next;
employees.put(name, result);
break;
}
}
}
return result;
}
EList<EObject> employees(EObject company) {
return get(company, companyEmployees);
}
@SuppressWarnings("unchecked")
<T> T get(EObject owner, EStructuralFeature feature) {
return (T) owner.eGet(feature);
}
public EOperation getOperation(EClass eClass, String name) {
for (EOperation eOperation : eClass.getEOperations()) {
if (name.equals(eOperation.getName())) {
return eOperation;
}
}
fail("Expected to find operation: " + name);
return null;
}
public void getWithException(EObject eObject, String featureName, String messageTemplate, Object... bindings) {
EClass eClass = eObject.eClass();
EAttribute eAttribute = (EAttribute) eClass.getEStructuralFeature(featureName);
String expectedMessage = NLS.bind(messageTemplate, bindings);
try {
@SuppressWarnings("unused")
Object object = get(eObject, eAttribute);
fail("Expected to catch OCLDelegateException: " + expectedMessage);
} catch (OCLDelegateException e) {
assertEquals("OCLDelegateException: ", expectedMessage, e.getLocalizedMessage());
}
}
@SuppressWarnings("unchecked")
<T> T invoke(EObject target, EOperation operation, Object... arguments) {
try {
return (T) target.eInvoke(operation, (arguments.length == 0)
? ECollections.<Object> emptyEList()
: new BasicEList.UnmodifiableEList<Object>(arguments.length,
arguments));
} catch (InvocationTargetException ite) {
fail("Failed to invoke operation: " + ite.getLocalizedMessage());
return null;
}
}
public void invokeWithException(EObject eObject, String name,
String messageTemplate, Object... bindings) {
EClass eClass = eObject.eClass();
String expectedMessage = NLS.bind(messageTemplate, bindings);
for (EOperation eOperation : eClass.getEOperations()) {
if (name.equals(eOperation.getName())) {
try {
@SuppressWarnings("unused")
Object object = invoke(eObject, eOperation);
fail("Expected to catch OCLDelegateException: " + expectedMessage);
} catch (OCLDelegateException e) {
assertEquals("OCLDelegateException: ", expectedMessage, e.getLocalizedMessage());
return;
}
}
}
fail("Expected to find: " + name);
}
Object execute(QueryDelegate delegate, Object target,
Map<String, Object> bindings) {
try {
return delegate.execute(target, bindings);
} catch (InvocationTargetException ite) {
fail("Failed to execute query: " + ite.getCause().getLocalizedMessage());
return null;
}
}
public void executeWithException(QueryDelegate delegate, Object target,
Map<String, Object> bindings, String messageTemplate,
Object... messageBindings) {
String expectedMessage = NLS.bind(messageTemplate, messageBindings);
try {
@SuppressWarnings("unused")
Object object = delegate.execute(target, bindings);
fail("Expected to catch InvocationTargetException: " + expectedMessage);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
assertEquals(cause + ": ", expectedMessage, cause.getLocalizedMessage());
}
}
<T> EList<T> list(T... element) {
return new BasicEList<T>(Arrays.asList(element));
}
EObject manager(EObject employee) {
return get(employee, employeeManager);
}
String name(EObject employeeOrCompany) {
EAttribute name = employeeClass.isInstance(employeeOrCompany)
? employeeName
: companyName;
return get(employeeOrCompany, name);
}
void set(EObject owner, EStructuralFeature feature, Object value) {
owner.eSet(feature, value);
}
Enumerator size(EObject company) {
return get(company, companySize);
}
protected void validateWithoutError(EObject eObject) {
Diagnostic validation = Diagnostician.INSTANCE.validate(eObject, context);
if (validation.getSeverity() != Diagnostic.OK) {
List<Diagnostic> diagnostics = validation.getChildren();
if (!diagnostics.isEmpty()) {
StringBuilder s = new StringBuilder();
for (Diagnostic diagnostic : diagnostics) {
s.append(diagnostic.getMessage());
s.append("\n");
}
fail(s.toString());
}
}
assertEquals("Validation severity:", Diagnostic.OK, validation.getSeverity());
List<Diagnostic> diagnostics = validation.getChildren();
assertEquals("Validation child count:", 0, diagnostics.size());
}
protected void validateConstraintWithError(String constraintName, EObject eObject) {
Diagnostic validation = Diagnostician.INSTANCE.validate(eObject, context);
assertEquals("Validation of '" + constraintName + "' severity:", Diagnostic.ERROR, validation.getSeverity());
List<Diagnostic> diagnostics = validation.getChildren();
assertEquals("Validation of '" + constraintName + "' child count:", 1, diagnostics.size());
Diagnostic diagnostic = diagnostics.get(0);
assertEquals("Validation of '" + constraintName + "' data count:", 1, diagnostic.getData().size());
assertEquals("Validation of '" + constraintName + "' data object:", eObject, diagnostic.getData().get(0));
Object objectLabel = EObjectValidator.getObjectLabel(eObject, context);
String messageTemplate = EcorePlugin.INSTANCE.getString("_UI_GenericConstraint_diagnostic");
String message = NLS.bind(messageTemplate, constraintName, objectLabel);
assertEquals("Validation of '" + constraintName + "' message:", message, diagnostic.getMessage());
}
protected void validateInvariantWithError(String constraintName, EObject eObject) {
validateWithError(constraintName, "_UI_GenericInvariant_diagnostic", eObject, constraintName, EObjectValidator.getObjectLabel(eObject, context));
}
protected void validateWithError(String constraintName, String errorKey, EObject eObject, Object... bindings) {
Diagnostic validation = Diagnostician.INSTANCE.validate(eObject, context);
assertEquals("Validation of '" + constraintName + "' severity:", Diagnostic.ERROR, validation.getSeverity());
List<Diagnostic> diagnostics = validation.getChildren();
assertEquals("Validation of '" + constraintName + "' child count:", 1, diagnostics.size());
Diagnostic diagnostic = diagnostics.get(0);
List<?> data = diagnostic.getData();
int size = data.size();
if (size == 2) { // EMF 2.10.0M3 and later
assertEquals("Validation of '" + constraintName + "' exception:", org.eclipse.ocl.ecore.delegate.OCLDelegateException.class, data.get(1).getClass());
}
else if (size != 1) { // EMF 2.10.0M2 and earlier
fail("Validation of '" + constraintName + "' child count: " + size);
}
assertEquals("Validation of '" + constraintName + "' data object:", eObject, diagnostic.getData().get(0));
String messageTemplate = EcorePlugin.INSTANCE.getString(errorKey);
if (diagnostics.get(0).getData().size() >= 2) { // EMF 2.10.0M3 and later
messageTemplate = messageTemplate.replaceAll("\\{2\\}", "{3}: {2}");
}
String message = NLS.bind(messageTemplate, bindings);
assertEquals("Validation of '" + constraintName + "' message:", message, diagnostic.getMessage());
}
}