/*******************************************************************************
 * Copyright (c) 2009, 2018 SAP AG 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:
 *     SAP AG - initial API and implementation
 ******************************************************************************/
package org.eclipse.ocl.examples.impactanalyzer.tests.instanceScope;

import java.util.Collection;

import modelmanagement.ModelmanagementFactory;
import modelmanagement.ModelmanagementPackage;

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.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
import org.eclipse.ocl.common.OCLConstants;
import org.eclipse.ocl.common.internal.options.CommonOptions;
import org.eclipse.ocl.ecore.OCL;
import org.eclipse.ocl.ecore.OCLExpression;
import org.eclipse.ocl.examples.impactanalyzer.ImpactAnalyzer;
import org.eclipse.ocl.examples.impactanalyzer.ImpactAnalyzerFactory;
import org.eclipse.ocl.examples.impactanalyzer.benchmark.preparation.notifications.NotificationHelper;
import org.eclipse.ocl.examples.impactanalyzer.configuration.OptimizationActivation;
import org.eclipse.ocl.examples.impactanalyzer.testutils.BaseDepartmentTestWithOCL;
import org.eclipse.ocl.examples.impactanalyzer.util.OCLFactory;
import org.junit.Test;

import behavioral.actions.ActionsFactory;
import data.classes.Association;
import data.classes.AssociationEnd;
import data.classes.ClassTypeDefinition;
import data.classes.ClassesFactory;
import data.classes.ClassesPackage;
import data.classes.MethodSignature;
import data.classes.Parameter;
import data.classes.SapClass;
import data.classes.SignatureImplementation;
import data.classes.TypeAdapter;
import dataaccess.expressions.ExpressionsFactory;
import dataaccess.expressions.ExpressionsPackage;
import dataaccess.expressions.MethodCallExpression;
import dataaccess.expressions.ObjectCreationExpression;
import dataaccess.expressions.VariableExpression;
import dataaccess.expressions.literals.LiteralsFactory;
import dataaccess.expressions.literals.LiteralsPackage;
import dataaccess.expressions.literals.ObjectLiteral;
import dataaccess.expressions.literals.StringLiteral;

public class OclIaTest extends BaseDepartmentTestWithOCL {

    private static final String testAnalysisOfRecursiveOperationWithSelf = "context dataaccess::expressions::MethodCallExpression \n"
            + "inv testAnalysisOfRecursiveOperationWithSelf: \n"
            + "self.object.getType().getInnermost().oclAsType(data::classes::ClassTypeDefinition).clazz.allSignatures() \n"
            + "->select(s | s.name = 'testMethod')";

    private static final String testAllInstancesSelectClassName = "context data::classes::ClassTypeDefinition \n"
            + "inv testAllInstancesSelectClassName:\n" + "data::classes::SapClass.allInstances()->select(c | c.name = 'Bob')";

    private static final String testVerySimpleTracerBasedInstanceScopeAnalysisWithNewClassScopeAnalysis = "context data::classes::SapClass \n"
            + "inv testVerySimpleTracerBasedInstanceScopeAnalysisWithNewClassScopeAnalysis: \n"
            + "self.oclAsType(data::classes::SapClass).name";

    private static final String testLongRunningNavigationPathExpression = "context data::classes::AssociationEnd inv LongRunningNavigationPath: \n "
            + "'.'.concat(self.oclAsType(data::classes::AssociationEnd).name)";

    private static final String testLowerMultiplicityPropagationForMethodCall = "context data::classes::ClassTypeDefinition \n"
            + "inv testLowerMultiplicityPropagationForMethodCallOnParameterUsage: \n"
            + "self.ownerTypedElement.oclAsType(dataaccess::expressions::MethodCallExpression).methodSignature.output.lowerMultiplicity * \n"
            + "self.ownerTypedElement.oclAsType(dataaccess::expressions::MethodCallExpression).object.getType().lowerMultiplicity";

    private static final String testInstanceScopeAnalysisForRecursiveOperation = "context data::classes::SapClass \n"
            + "inv testInstanceScopeAnalysisForRecursiveOperation: \n" + "self.adapters->forAll(a | self.conformsTo(a.to))";

    private static final String testVerySimpleInstanceScopeAnalysisWithTupleUsingSelf = "context data::classes::SapClass \n"
            + "inv testVerySimpleInstanceScopeAnalysisWithTupleUsingSelf: \n" + "Tuple{cls=self}.cls.name";

    private static final String testVerySimpleInstanceScopeAnalysisWithTuple = "context data::classes::SapClass \n"
            + "inv testVerySimpleInstanceScopeAnalysisWithTuple: \n" + "Tuple{name=self.name}.name";

    private static final String testForIA2 = "context dataaccess::expressions::literals::ObjectLiteral \n" + "inv testForIA2: \n"
            + "self.oclAsType(dataaccess::expressions::literals::ObjectLiteral).valueClass.getAssociationEnds().otherEnd()"
            + "->select(ae|ae.name='Assoc_to_Bob_changed')";
    
    private EPackage cp;
    private ResourceSetImpl rs;

    @Override
    public void setUp() {
		CommonOptions.DEFAULT_DELEGATION_MODE.setDefaultValue(OCLConstants.OCL_DELEGATE_URI_LPG);
        this.cp = ClassesPackage.eINSTANCE;
        this.rs = new ResourceSetImpl();
        this.rs.eAdapters().add(new ECrossReferenceAdapter());
        this.rs.getResources().add(this.cp.eResource());
    }

    @Override
    public void tearDown() {
        this.rs = null;
        this.cp = null;
    }

    @Test
    public void testSelectByType() {
        OCLExpression expression = (OCLExpression) parse(
                "context data::classes::SapClass inv testSelectByType:\n" +
                "self.ownedSignatures.implementation->selectByType(data::classes::LinkSetting).implements_.output"+
                ".oclAsType(data::classes::ClassTypeDefinition).clazz.name",
                this.cp).iterator().next().getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(expression);
        SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
        c1.setName("c1");
        MethodSignature ms1 = ClassesFactory.eINSTANCE.createMethodSignature();
        ms1.setName("ms1");
        c1.getOwnedSignatures().add(ms1);
        SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
        c2.setName("c2");
        MethodSignature ms2 = ClassesFactory.eINSTANCE.createMethodSignature();
        ms2.setName("ms2");
        c2.getOwnedSignatures().add(ms2);
        SignatureImplementation ms1Impl = ActionsFactory.eINSTANCE.createBlock();
        ms1.setImplementation(ms1Impl);
        SignatureImplementation ms2Impl = ClassesFactory.eINSTANCE.createLinkSetting();
        ms2.setImplementation(ms2Impl);
        SapClass output = ClassesFactory.eINSTANCE.createSapClass();
        output.setName("Output");
        ClassTypeDefinition outputCtdForMs1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        ClassTypeDefinition outputCtdForMs2 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        outputCtdForMs1.setClazz(output);
        outputCtdForMs2.setClazz(output);
        ms1.setOutput(outputCtdForMs1);
        ms2.setOutput(outputCtdForMs2);
        
        Collection<?> resultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
        assertTrue(resultOnC1.isEmpty());
        Collection<?> resultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
        assertEquals(1, resultOnC2.size());
        assertTrue(resultOnC2.contains("Output"));

        final Notification[] noti = new Notification[1];
        Adapter adapter = new AdapterImpl() {
            @Override
            public void notifyChanged(Notification msg) {
                noti[0] = msg;
            }
        };
        output.eAdapters().add(adapter);
        
        output.setName("NewOutput");
        Collection<?> newResultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
        assertTrue(newResultOnC1.isEmpty());
        Collection<?> newResultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
        assertEquals(1, newResultOnC2.size());
        assertTrue(newResultOnC2.contains("NewOutput"));
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
                .getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti[0]);
        assertEquals(1, impact.size()); // expecting only c2 to be impacted because c1's ms1 implementation has the wrong type
        assertFalse(impact.contains(c1));
        assertTrue(impact.contains(c2));
    }

    @Test
    public void testSelectByTypeForSubclass() {
        OCLExpression expression = (OCLExpression) parse(
                "context data::classes::SapClass inv testSelectByTypeForSubclass:\n" +
                "self.ownedSignatures.implementation->selectByType(data::classes::SignatureImplementation).implements_.output"+
                ".oclAsType(data::classes::ClassTypeDefinition).clazz.name",
                this.cp).iterator().next().getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(expression);
        SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
        c1.setName("c1");
        MethodSignature ms1 = ClassesFactory.eINSTANCE.createMethodSignature();
        ms1.setName("ms1");
        c1.getOwnedSignatures().add(ms1);
        SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
        c2.setName("c2");
        MethodSignature ms2 = ClassesFactory.eINSTANCE.createMethodSignature();
        ms2.setName("ms2");
        c2.getOwnedSignatures().add(ms2);
        SignatureImplementation ms1Impl = ActionsFactory.eINSTANCE.createBlock();
        ms1.setImplementation(ms1Impl);
        SignatureImplementation ms2Impl = ClassesFactory.eINSTANCE.createLinkSetting();
        ms2.setImplementation(ms2Impl);
        SapClass output = ClassesFactory.eINSTANCE.createSapClass();
        output.setName("Output");
        ClassTypeDefinition outputCtdForMs1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        ClassTypeDefinition outputCtdForMs2 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        outputCtdForMs1.setClazz(output);
        outputCtdForMs2.setClazz(output);
        ms1.setOutput(outputCtdForMs1);
        ms2.setOutput(outputCtdForMs2);
        
        Collection<?> resultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
        assertTrue(resultOnC1.isEmpty());
        Collection<?> resultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
        assertTrue(resultOnC2.isEmpty());

        final Notification[] noti = new Notification[1];
        Adapter adapter = new AdapterImpl() {
            @Override
            public void notifyChanged(Notification msg) {
                noti[0] = msg;
            }
        };
        output.eAdapters().add(adapter);
        
        output.setName("NewOutput");
        Collection<?> newResultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
        assertTrue(newResultOnC1.isEmpty());
        Collection<?> newResultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
        assertTrue(newResultOnC2.isEmpty());
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
                .getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti[0]);
        assertTrue(impact.isEmpty()); // expecting neither c1 nor c2 to be in
                                      // the result because neither Block nor
                                      // LinkSetting has exactly type
                                      // SignatureImplementation
    }

    @Test
    public void testSelectByKind() {
        OCLExpression expression = (OCLExpression) parse(
                "context data::classes::SapClass inv testSelectByKind:\n" +
                "self.ownedSignatures.implementation->selectByKind(data::classes::LinkSetting).implements_.output"+
                ".oclAsType(data::classes::ClassTypeDefinition).clazz.name",
                this.cp).iterator().next().getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(expression);
        SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
        c1.setName("c1");
        MethodSignature ms1 = ClassesFactory.eINSTANCE.createMethodSignature();
        ms1.setName("ms1");
        c1.getOwnedSignatures().add(ms1);
        SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
        c2.setName("c2");
        MethodSignature ms2 = ClassesFactory.eINSTANCE.createMethodSignature();
        ms2.setName("ms2");
        c2.getOwnedSignatures().add(ms2);
        SignatureImplementation ms1Impl = ActionsFactory.eINSTANCE.createBlock();
        ms1.setImplementation(ms1Impl);
        SignatureImplementation ms2Impl = ClassesFactory.eINSTANCE.createLinkSetting();
        ms2.setImplementation(ms2Impl);
        SapClass output = ClassesFactory.eINSTANCE.createSapClass();
        output.setName("Output");
        ClassTypeDefinition outputCtdForMs1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        ClassTypeDefinition outputCtdForMs2 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        outputCtdForMs1.setClazz(output);
        outputCtdForMs2.setClazz(output);
        ms1.setOutput(outputCtdForMs1);
        ms2.setOutput(outputCtdForMs2);
        
        Collection<?> resultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
        assertTrue(resultOnC1.isEmpty());
        Collection<?> resultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
        assertEquals(1, resultOnC2.size());
        assertTrue(resultOnC2.contains("Output"));

        final Notification[] noti = new Notification[1];
        Adapter adapter = new AdapterImpl() {
            @Override
            public void notifyChanged(Notification msg) {
                noti[0] = msg;
            }
        };
        output.eAdapters().add(adapter);
        
        output.setName("NewOutput");
        Collection<?> newResultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
        assertTrue(newResultOnC1.isEmpty());
        Collection<?> newResultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
        assertEquals(1, newResultOnC2.size());
        assertTrue(newResultOnC2.contains("NewOutput"));
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
                .getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti[0]);
        assertEquals(1, impact.size()); // expecting only c2 to be impacted because c1's ms1's implementation's type doesn't match
        assertTrue(impact.contains(c2));
    }

    @Test
    public void testSelectByKindForSubclass() {
        OCLExpression expression = (OCLExpression) parse(
                "context data::classes::SapClass inv testSelectByKindForSubclass:\n" +
                "self.ownedSignatures.implementation->selectByKind(data::classes::SignatureImplementation).implements_.output"+
                ".oclAsType(data::classes::ClassTypeDefinition).clazz.name",
                this.cp).iterator().next().getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(expression);
        SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
        c1.setName("c1");
        MethodSignature ms1 = ClassesFactory.eINSTANCE.createMethodSignature();
        ms1.setName("ms1");
        c1.getOwnedSignatures().add(ms1);
        SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
        c2.setName("c2");
        MethodSignature ms2 = ClassesFactory.eINSTANCE.createMethodSignature();
        ms2.setName("ms2");
        c2.getOwnedSignatures().add(ms2);
        SignatureImplementation ms1Impl = ActionsFactory.eINSTANCE.createBlock();
        ms1.setImplementation(ms1Impl);
        SignatureImplementation ms2Impl = ClassesFactory.eINSTANCE.createLinkSetting();
        ms2.setImplementation(ms2Impl);
        SapClass output = ClassesFactory.eINSTANCE.createSapClass();
        output.setName("Output");
        ClassTypeDefinition outputCtdForMs1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        ClassTypeDefinition outputCtdForMs2 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        outputCtdForMs1.setClazz(output);
        outputCtdForMs2.setClazz(output);
        ms1.setOutput(outputCtdForMs1);
        ms2.setOutput(outputCtdForMs2);
        
        Collection<?> resultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
        assertEquals(1, resultOnC1.size());
        assertTrue(resultOnC1.contains("Output"));
        Collection<?> resultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
        assertEquals(1, resultOnC2.size());
        assertTrue(resultOnC2.contains("Output"));

        final Notification[] noti = new Notification[1];
        Adapter adapter = new AdapterImpl() {
            @Override
            public void notifyChanged(Notification msg) {
                noti[0] = msg;
            }
        };
        output.eAdapters().add(adapter);
        
        output.setName("NewOutput");
        Collection<?> newResultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
        assertEquals(1, newResultOnC1.size());
        assertTrue(newResultOnC1.contains("NewOutput"));
        Collection<?> newResultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
        assertEquals(1, newResultOnC2.size());
        assertTrue(newResultOnC2.contains("NewOutput"));
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
                .getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti[0]);
        assertEquals(2, impact.size()); // expecting both, c1 and c2, to be impacted
        assertTrue(impact.contains(c1));
        assertTrue(impact.contains(c2));
    }

    @Test
    public void testSimpleClosure() {
        OCLExpression expression = (OCLExpression) parse(
                "context data::classes::SapClass inv testSimpleClosure:\n" +
                "self->closure(i | i.ownedSignatures.input.ownedTypeDefinition." +
                          "oclAsType(data::classes::ClassTypeDefinition).clazz)",
                this.cp).iterator().next().getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(expression);
        SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
        c1.setName("c1");
        MethodSignature ms1 = ClassesFactory.eINSTANCE.createMethodSignature();
        ms1.setName("ms1");
        c1.getOwnedSignatures().add(ms1);
        Parameter p1 = ClassesFactory.eINSTANCE.createParameter();
        p1.setName("p1");
        ms1.getInput().add(p1);
        ClassTypeDefinition ctd1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        p1.setOwnedTypeDefinition(ctd1);

        SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
        ctd1.setClazz(c2);
        c2.setName("c2");
        MethodSignature ms2 = ClassesFactory.eINSTANCE.createMethodSignature();
        ms2.setName("ms2");
        c2.getOwnedSignatures().add(ms2);
        Parameter p2 = ClassesFactory.eINSTANCE.createParameter();
        p2.setName("p2");
        ms2.getInput().add(p2);
        ClassTypeDefinition ctd2 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        p2.setOwnedTypeDefinition(ctd2);

        SapClass c3 = ClassesFactory.eINSTANCE.createSapClass();
        ctd2.setClazz(c3);
        c3.setName("c3");
        MethodSignature ms3 = ClassesFactory.eINSTANCE.createMethodSignature();
        ms3.setName("ms3");
        c3.getOwnedSignatures().add(ms3);
        Parameter p3 = ClassesFactory.eINSTANCE.createParameter();
        p3.setName("p3");
        ms3.getInput().add(p3);
        ClassTypeDefinition ctd3 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        p3.setOwnedTypeDefinition(ctd3);

        SapClass c4 = ClassesFactory.eINSTANCE.createSapClass();
        ctd3.setClazz(c4);
        c4.setName("c4");
        MethodSignature ms4 = ClassesFactory.eINSTANCE.createMethodSignature();
        ms3.setName("ms4");
        c4.getOwnedSignatures().add(ms4);
        
        Collection<?> resultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
        assertTrue(resultOnC1.contains(c2));
        assertTrue(resultOnC1.contains(c3));
        assertTrue(resultOnC1.contains(c4));

        final Notification[] noti = new Notification[1];
        Adapter adapter = new AdapterImpl() {
            @Override
            public void notifyChanged(Notification msg) {
                noti[0] = msg;
            }
        };
        ms2.eAdapters().add(adapter);
        
        // now add another parameter p22 with new type c5 to ms2; this should change expression
        // for c2 and c1 whose ms1 argument p1 is using c2
        SapClass c5 = ClassesFactory.eINSTANCE.createSapClass();
        c5.setName("c5");
        Parameter p22 = ClassesFactory.eINSTANCE.createParameter();
        p22.setName("p22");
        ClassTypeDefinition ctd22 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        p22.setOwnedTypeDefinition(ctd22);
        ctd22.setClazz(c5);
        ms2.getInput().add(p22);
        Collection<?> newResultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
        assertTrue(newResultOnC1.contains(c2));
        assertTrue(newResultOnC1.contains(c3));
        assertTrue(newResultOnC1.contains(c4));
        assertTrue(newResultOnC1.contains(c5));
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
                .getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti[0]);
        assertEquals(2, impact.size()); // expecting c1 and c2 to be impacted
        assertTrue(impact.contains(c1));
        assertTrue(impact.contains(c2));
    }

    @Test
    public void testResultUseInIterate() {
        OCLExpression expression = (OCLExpression) parse(
                "context data::classes::SapClass inv testMoveWithoutImpact:\n" +
                "Sequence{1, 2, 3}->iterate(i; result:Set(data::classes::SapClass)=Set{self} | result.ownedSignatures.output.oclAsType(data::classes::ClassTypeDefinition).clazz)",
                this.cp).iterator().next().getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(expression);
        SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
        c1.setName("c1");
        SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
        c2.setName("c2");
        SapClass c3 = ClassesFactory.eINSTANCE.createSapClass();
        c3.setName("c3");
        SapClass c4 = ClassesFactory.eINSTANCE.createSapClass();
        c4.setName("c4");
        SapClass c5 = ClassesFactory.eINSTANCE.createSapClass();
        c5.setName("c5");
        SapClass c6 = ClassesFactory.eINSTANCE.createSapClass();
        c6.setName("c6");

        connectWithMethodOutput(c1, c2);
        connectWithMethodOutput(c2, c3);
        connectWithMethodOutput(c3, c4);
        connectWithMethodOutput(c4, c5);

        this.cp.eResource().getContents().add(c1);
        this.cp.eResource().getContents().add(c2);
        this.cp.eResource().getContents().add(c3);
        this.cp.eResource().getContents().add(c4);
        this.cp.eResource().getContents().add(c5);
        final Notification[] noti = new Notification[1];
        Adapter adapter = new AdapterImpl() {
            @Override
            public void notifyChanged(Notification msg) {
                noti[0] = msg;
            }
        };
        c5.eAdapters().add(adapter);
        connectWithMethodOutput(c5, c6);
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
                .getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti[0]);
        assertEquals(5, impact.size()); // expecting all c1..c6 to be impacted
        assertFalse(impact.contains(c6));
    }

    private void connectWithMethodOutput(SapClass c1, SapClass c2) {
        MethodSignature m1 = ClassesFactory.eINSTANCE.createMethodSignature();
        m1.setName("m1");
        ClassTypeDefinition ctd1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        ctd1.setClazz(c2);
        m1.setOutput(ctd1);
        c1.getOwnedSignatures().add(m1);
    }

    @Test
    public void testMoveWithoutImpact() {
        OCLExpression expression = (OCLExpression) parse(
                "context data::classes::SapClass inv testMoveWithoutImpact:\n" + "self.ownedSignatures->at(3).name = 'm3'",
                this.cp).iterator().next().getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(expression);
        SapClass c = ClassesFactory.eINSTANCE.createSapClass();
        MethodSignature m1 = ClassesFactory.eINSTANCE.createMethodSignature();
        m1.setName("m1");
        c.getOwnedSignatures().add(m1);
        MethodSignature m2 = ClassesFactory.eINSTANCE.createMethodSignature();
        m2.setName("m2");
        c.getOwnedSignatures().add(m2);
        MethodSignature m3 = ClassesFactory.eINSTANCE.createMethodSignature();
        m1.setName("m3");
        c.getOwnedSignatures().add(m3);
        this.cp.eResource().getContents().add(c);
        c.setName("C");
        final Notification[] noti = new Notification[1];
        Adapter adapter = new AdapterImpl() {
            @Override
            public void notifyChanged(Notification msg) {
                noti[0] = msg;
            }
        };
        c.eAdapters().add(adapter);
        c.getOwnedSignatures().move(0, 1); // swap first two signatures
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
                .getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti[0]);
        assertEquals(0, impact.size());
        c.getOwnedSignatures().move(1, 2); // not the name of the element at position 3 should have changed
        Collection<EObject> impact2 = ia.getContextObjects(noti[0]);
        assertEquals(1, impact2.size());
        assertTrue(impact2.contains(c));
    }

    @Test
    public void testTupleLiteralUsedTwice() {
        OCLExpression expression = (OCLExpression) parse(
                "context data::classes::SapClass inv testTupleLiteralUsedTwice:\n"
                        + "let t:Tuple(c:data::classes::SapClass, d:data::classes::SapClass) = Tuple{c=self, d=self.adapters.to->first()} in\n"
                        + "Set{t.c.name, t.d.name}", this.cp).iterator().next().getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(expression);
        SapClass c = ClassesFactory.eINSTANCE.createSapClass();
        SapClass d = ClassesFactory.eINSTANCE.createSapClass();
        d.setName("D");
        this.cp.eResource().getContents().add(c);
        c.setName("oldName");
        TypeAdapter ta = ClassesFactory.eINSTANCE.createTypeAdapter();
        ta.setAdapted(c);
        ta.setTo(d);
        EAttribute att = (EAttribute) c.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
        Notification noti = NotificationHelper.createAttributeChangeNotification(c, att, "oldName", "newName");
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
                .getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);
        assertEquals(1, impact.size());
        assertTrue(impact.contains(c));
        Notification noti2 = NotificationHelper.createAttributeChangeNotification(d, att, "D", "newD");
        Collection<EObject> impact2 = ia.getContextObjects(noti2);
        assertTrue(impact2.size() == 2 && impact2.contains(c) && impact2.contains(d));
    }

    @Test
    public void testTupleLiteralWithImmediatePropertyCall() {
        OCLExpression expression = (OCLExpression) parse(
                "context data::classes::SapClass inv testTupleLiteralWithImmediatePropertyCall:\n" + "Tuple{c=self}.c.name",
                this.cp).iterator().next().getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(expression);
        SapClass c = ClassesFactory.eINSTANCE.createSapClass();
        this.cp.eResource().getContents().add(c);
        c.setName("oldName");
        EAttribute att = (EAttribute) c.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
        Notification noti = NotificationHelper.createAttributeChangeNotification(c, att, "oldName", "newName");
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
                .getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);
        assertEquals(1, impact.size());
        assertTrue(impact.contains(c));
    }

    @Test
    public void testTupleLiteralPassedThroughLetVariable() {
        OCLExpression expression = (OCLExpression) parse(
                "context data::classes::SapClass inv testTupleLiteralPassedThroughLetVariable:\n"
                        + "let t:Tuple(c:data::classes::SapClass) = Tuple{c=self} in\n" + "t.c.name", this.cp).iterator().next()
                .getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(expression);
        SapClass c = ClassesFactory.eINSTANCE.createSapClass();
        this.cp.eResource().getContents().add(c);
        c.setName("oldName");
        EAttribute att = (EAttribute) c.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
        Notification noti = NotificationHelper.createAttributeChangeNotification(c, att, "oldName", "newName");
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
                .getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);
        assertEquals(1, impact.size());
        assertTrue(impact.contains(c));
    }

    @Test
    public void testTupleLiteralPassedThroughTwoLetVariables() {
        OCLExpression expression = (OCLExpression) parse(
                "context data::classes::SapClass inv testTupleLiteralPassedThroughLetVariable:\n"
                        + "let t1:Tuple(c:data::classes::SapClass) = Tuple{c=self} in\n"
                        + "let t2:Tuple(c:data::classes::SapClass) = t1 in\n" + "t2.c.name", this.cp).iterator().next()
                .getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(expression);
        SapClass c = ClassesFactory.eINSTANCE.createSapClass();
        this.cp.eResource().getContents().add(c);
        c.setName("oldName");
        EAttribute att = (EAttribute) c.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
        Notification noti = NotificationHelper.createAttributeChangeNotification(c, att, "oldName", "newName");
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
                .getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);
        assertEquals(1, impact.size());
        assertTrue(impact.contains(c));
    }

    @Test
    public void testNestedTupleLiteral() {
        OCLExpression expression = (OCLExpression) parse(
                "context data::classes::SapClass inv testNestedTupleLiteral:\n"
                        + "Tuple{c:Tuple(d:data::classes::SapClass)=Tuple{d=self}}.c.d.name", this.cp).iterator().next()
                .getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(expression);
        SapClass c = ClassesFactory.eINSTANCE.createSapClass();
        this.cp.eResource().getContents().add(c);
        c.setName("oldName");
        EAttribute att = (EAttribute) c.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
        Notification noti = NotificationHelper.createAttributeChangeNotification(c, att, "oldName", "newName");
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
                .getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);
        assertEquals(1, impact.size());
        assertTrue(impact.contains(c));
    }

    @Test
    public void testLongRunningNavigationPathConstruction() {
        OCLExpression expression = (OCLExpression) parse(testLongRunningNavigationPathExpression, this.cp).iterator().next()
                .getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(expression);
        AssociationEnd ae = ClassesFactory.eINSTANCE.createAssociationEnd();
        this.cp.eResource().getContents().add(ae);
        EAttribute att = (EAttribute) ae.eClass().getEStructuralFeature(ClassesPackage.ASSOCIATION_END__NAME);
        Notification noti = NotificationHelper.createAttributeChangeNotification(ae, att, "oldName", "newName");
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
                .getAssociationEnd(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);
        assertTrue(impact.size() == 1 && impact.contains(ae));
    }

    /**
     * self.ownerTypedElement.oclAsType(MethodCallExpression).methodSignature.output.lowerMultiplicity *
     * self.ownerTypedElement.oclAsType(MethodCallExpression).object.getType().lowerMultiplicity
     */

    @Test
    public void testLowerMultiplicityPropagationForMethodCallOnParameterUsage() {
        OCLExpression exp = (OCLExpression) parse(testLowerMultiplicityPropagationForMethodCall, this.cp).iterator().next()
                .getSpecification().getBodyExpression();
        Resource r = this.cp.eResource();
        r.eAdapters().add(new ECrossReferenceAdapter());
        r.getContents().add(exp);
        // construct something like "abc".length(), then change multiplicity of "abc" from 1..1 to 0..1
        MethodSignature length = ClassesFactory.eINSTANCE.createMethodSignature();
        r.getContents().add(length);
        length.setName("length");
        SapClass numberClass = ClassesFactory.eINSTANCE.createSapClass();
        r.getContents().add(numberClass);
        numberClass.setName("Number");
        ClassTypeDefinition msOutput = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        msOutput.setClazz(numberClass);
        msOutput.setLowerMultiplicity(1);
        msOutput.setUpperMultiplicity(1);
        length.setOutput(msOutput);
        ClassTypeDefinition ctd = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        ctd.setClazz(numberClass);
        ctd.setLowerMultiplicity(1);
        ctd.setUpperMultiplicity(1);
        MethodCallExpression mce = ExpressionsFactory.eINSTANCE.createMethodCallExpression();
        r.getContents().add(mce);
        mce.setOwnedTypeDefinition(ctd);
        mce.setMethodSignature(length);
        Parameter p = ClassesFactory.eINSTANCE.createParameter();
        r.getContents().add(p);
        p.setName("p");
        SapClass stringClass = ClassesFactory.eINSTANCE.createSapClass();
        r.getContents().add(stringClass);
        stringClass.setName("String");
        ClassTypeDefinition otDef = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        otDef.setClazz(stringClass);
        otDef.setUpperMultiplicity(1);
        otDef.setLowerMultiplicity(1);
        p.setOwnedTypeDefinition(otDef);
        VariableExpression ve = ExpressionsFactory.eINSTANCE.createVariableExpression();
        ve.setVariable(p); // this should infer the variable expression's multiplicity to that of p
        mce.setObject(ve);

        assertEquals(1, ve.getType().getLowerMultiplicity());

        OCL ocl = org.eclipse.ocl.examples.impactanalyzer.util.OCL.newInstance();
        Object oldResult = ocl.evaluate(ctd, exp);
        Notification noti = NotificationHelper.createChangeLowerMultiplicityNotification(p.getOwnedTypeDefinition(), 0);
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE
                .getClassTypeDefinition(), /* notifyOnNewContextElements */ false,
                OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);
        Object newResult = ocl.evaluate(ctd, exp);

        assertEquals(0, p.getOwnedTypeDefinition().getLowerMultiplicity());
        assertFalse("expected " + oldResult + " and " + newResult + " to be different but were equal", oldResult
                .equals(newResult));
        assertEquals(1, impact.size());
        assertTrue(impact.contains(ctd));

    }

    /**
     * self.ownerTypedElement.oclAsType(MethodCallExpression).methodSignature.output.lowerMultiplicity *
     * self.ownerTypedElement.oclAsType(MethodCallExpression).object.getType().lowerMultiplicity
     */
    @Test
    public void testLowerMultiplicityPropagationForMethodCall() {
        OCLExpression exp = (OCLExpression) parse(testLowerMultiplicityPropagationForMethodCall, this.cp).iterator().next()
                .getSpecification().getBodyExpression();
        Resource r = this.cp.eResource();
        r.getContents().add(exp);
        // construct something like "abc".length(), then change multiplicity of "abc" from 1..1 to 0..1
        MethodSignature length = ClassesFactory.eINSTANCE.createMethodSignature();
        length.setName("length");
        SapClass numberClass = ClassesFactory.eINSTANCE.createSapClass();
        numberClass.setName("Number");
        ClassTypeDefinition msOutput = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        msOutput.setClazz(numberClass);
        msOutput.setLowerMultiplicity(1);
        msOutput.setUpperMultiplicity(1);
        length.setOutput(msOutput);
        ClassTypeDefinition ctd1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        ctd1.setClazz(numberClass);
        ctd1.setLowerMultiplicity(1);
        ctd1.setUpperMultiplicity(1);
        MethodCallExpression mce = ExpressionsFactory.eINSTANCE.createMethodCallExpression();
        mce.setOwnedTypeDefinition(ctd1);
        mce.setMethodSignature(length);
        StringLiteral sl = LiteralsFactory.eINSTANCE.createStringLiteral();
        sl.setLiteral("abc");
        SapClass stringClass = ClassesFactory.eINSTANCE.createSapClass();
        ClassTypeDefinition ctd2 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        ctd2.setClazz(stringClass);
        ctd2.setLowerMultiplicity(1);
        ctd2.setUpperMultiplicity(1);
        sl.setOwnedTypeDefinition(ctd2);
        mce.setObject(sl);

        r.getContents().add(mce);
        r.getContents().add(length);
        r.getContents().add(numberClass);
        r.getContents().add(stringClass);

        assertEquals(1, sl.getOwnedTypeDefinition().getLowerMultiplicity());

        Notification noti = NotificationHelper.createChangeLowerMultiplicityNotification(sl.getOwnedTypeDefinition(), 0);
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE
                .getClassTypeDefinition(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);

        assertEquals(0, sl.getOwnedTypeDefinition().getLowerMultiplicity());
        assertEquals(1, impact.size());
        assertTrue(impact.contains(ctd1));

    }

    /**
     * data::classes::SapClass.allInstances()->select(c | c.name = 'something'
     */
    @Test
    public void testAnalysisOfRecursiveOperationWithSelf() {
        OCLExpression exp = (OCLExpression) parse(testAnalysisOfRecursiveOperationWithSelf, this.cp).iterator().next()
                .getSpecification().getBodyExpression();
        Resource r = this.cp.eResource();

        r.eAdapters().add(new ECrossReferenceAdapter());
        r.getContents().add(exp);

        // construct something like "new HumbaClass1().m()"
        final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
        cl1.setName("Alice");
        MethodSignature ms = ClassesFactory.eINSTANCE.createMethodSignature();
        ms.setName("testMethod");
        cl1.getOwnedSignatures().add(ms);
        final ClassTypeDefinition ctd = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        ctd.setLowerMultiplicity(1);
        ctd.setUpperMultiplicity(1);
        ctd.setClazz(null);
        final MethodCallExpression mce = ExpressionsFactory.eINSTANCE.createMethodCallExpression();
        final ObjectCreationExpression oce = ExpressionsFactory.eINSTANCE.createObjectCreationExpression();
        oce.setClassToInstantiate(cl1);
        oce.setOwnedTypeDefinition(ctd);
        mce.setObject(oce);

        r.getContents().add(cl1);
        r.getContents().add(mce);

        Notification noti = NotificationHelper.createChangeClazzNotification(ctd, cl1);
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ExpressionsPackage.eINSTANCE
                .getMethodCallExpression(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);

        assertEquals(1, impact.size());
        assertTrue(impact.contains(mce) && !impact.contains(ctd));

    }

    /**
     * data::classes::SapClass.allInstances()->select(c | c.name = 'something'
     */
    @Test
    public void testAllInstancesSelectClassName() {
        Resource r = this.cp.eResource();
        OCLExpression exp = (OCLExpression) parse(testAllInstancesSelectClassName, this.cp).iterator().next().getSpecification()
                .getBodyExpression();
        r.getContents().add(exp);
        final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
        cl1.setName("Alice");
        r.getContents().add(cl1);
        final ClassTypeDefinition ctd = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        ctd.setClazz(cl1);
        r.getContents().add(ctd);

        EAttribute att = (EAttribute) cl1.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
        Notification noti = NotificationHelper.createAttributeChangeNotification(cl1, att, "Alice", "Bob");
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp,
                ClassesPackage.eINSTANCE.getClassTypeDefinition(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);
        // The expression has as its context ClassTypeDefinition. Therefore, the SapClass must not be returned
        // as impacted object. However, the change affects the ->select clause after allInstances(), so
        // all context objects of type ClassTypeDefinition are affected. That's what we want to assert now:
        assertTrue(impact.size() > 0 && impact.contains(ctd) && !impact.contains(cl1));
    }

    /**
     * The ->select lets only classes pass whose name is 'Bob'. Therefore, a class named 'Alice'
     * should not be produced by any context.
     */
    @Test
    public void testFindContextElementsForResultForAllInstances() {
        Resource r = this.cp.eResource();
        OCLExpression exp = (OCLExpression) parse(testAllInstancesSelectClassName, this.cp).iterator().next().getSpecification()
                .getBodyExpression();
        r.getContents().add(exp);
        final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
        cl1.setName("Alice");
        r.getContents().add(cl1);
        final ClassTypeDefinition ctd = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        ctd.setClazz(cl1);
        r.getContents().add(ctd);
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp,
                ClassesPackage.eINSTANCE.getClassTypeDefinition(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> contexts = ia.getContextObjects(cl1);
        assertTrue(contexts.isEmpty());
    }

    /**
     * The ->select lets only classes pass whose name is 'Bob'. Therefore, a class named 'Bob'
     * should be produced by all possible contexts
     */
    @Test
    public void testFindAllContextElementsForResultForAllInstances() {
        Resource r = this.cp.eResource();
        OCLExpression exp = (OCLExpression) parse(testAllInstancesSelectClassName, this.cp).iterator().next().getSpecification()
                .getBodyExpression();
        r.getContents().add(exp);
        final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
        cl1.setName("Bob");
        r.getContents().add(cl1);
        final ClassTypeDefinition ctd = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        ctd.setClazz(cl1);
        r.getContents().add(ctd);
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp,
                ClassesPackage.eINSTANCE.getClassTypeDefinition(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> contexts = ia.getContextObjects(cl1);
        assertTrue(!contexts.isEmpty());
        assertTrue(contexts.contains(ctd));
    }

    /**
     * data::classes::SapClass.allInstances()->select(c | c.name = 'something'
     */
    @Test
    public void testTriggeringAllInstancesByDirectResourceContainment() {
        Resource r = this.cp.eResource();
        OCLExpression exp = (OCLExpression) parse(testAllInstancesSelectClassName, this.cp).iterator().next().getSpecification()
                .getBodyExpression();
        r.getContents().add(exp);
        final ClassTypeDefinition ctd = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        r.getContents().add(ctd);
        final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
        cl1.setName("Bob");
        final Notification[] notifications = new Notification[1];
        Adapter a = new AdapterImpl() {
            @Override
            public void notifyChanged(Notification n) {
                if (n.getEventType() != Notification.REMOVING_ADAPTER) {
                    if (notifications[0] != null) {
                        fail("didn't expect to receive two notifications");
                    }
                    notifications[0] = n;
                }
            }
        };
        r.eAdapters().add(a);
        cl1.eAdapters().add(a);
        r.getContents().add(cl1);
        assertNotNull("Expected to receive one notification", notifications[0]);
        r.eAdapters().remove(a);
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getClassTypeDefinition(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(notifications[0]);
        // The expression has as its context ClassTypeDefinition. Therefore, the SapClass must not be returned
        // as impacted object. However, the change affects the ->select clause after allInstances(), so
        // all context objects of type ClassTypeDefinition are affected. That's what we want to assert now:
        assertTrue(impact.size() > 0 && impact.contains(ctd) && !impact.contains(cl1));
    }

    @Test
    public void testVerySimpleTracerBasedInstanceScopeAnalysisWithNewClassScopeAnalysis() {
        Resource r = this.cp.eResource();
        OCLExpression exp = (OCLExpression) parse(testVerySimpleTracerBasedInstanceScopeAnalysisWithNewClassScopeAnalysis,
                this.cp).iterator().next().getSpecification().getBodyExpression();
        r.getContents().add(exp);

        final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
        cl1.setName("Alice");
        r.getContents().add(cl1);

        EAttribute att = (EAttribute) cl1.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
        Notification noti = NotificationHelper.createAttributeChangeNotification(cl1, att, "Alice", "Bob");
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);

        assertTrue(impact.size() == 1 && impact.contains(cl1));
    }

    @Test
    public void testInstanceScopeAnalysisForRecursiveOperation() {
        Resource r = this.cp.eResource();
        OCLExpression exp = (OCLExpression) parse(testInstanceScopeAnalysisForRecursiveOperation, this.cp).iterator().next()
                .getSpecification().getBodyExpression();
        r.getContents().add(exp);

        final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
        cl1.setName("Alice");
        r.getContents().add(cl1);
        SapClass cl2 = ClassesFactory.eINSTANCE.createSapClass();
        ;
        cl2.setName("Bob");
        r.getContents().add(cl2);
        TypeAdapter adapter = ClassesFactory.eINSTANCE.createTypeAdapter();
        adapter.setName("Alice_to_Bob_Adapter");
        adapter.setAdapted(cl1);
        // the adapted reference already is a container
        // r.getContents().add(adapter);

        EReference ref1 = (EReference) adapter.eClass().getEStructuralFeature(ClassesPackage.TYPE_ADAPTER__TO);
        Notification noti1 = NotificationHelper.createReferenceChangeNotification(adapter, ref1, null, cl2);
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact1 = ia.getContextObjects(noti1);

        assertTrue(impact1.size() == 1 && impact1.contains(cl1));
    }

    @Test
    public void testVerySimpleInstanceScopeAnalysisWithTupleUsingSelf() {
        Resource r = this.cp.eResource();
        OCLExpression exp = (OCLExpression) parse(testVerySimpleInstanceScopeAnalysisWithTupleUsingSelf, this.cp).iterator()
                .next().getSpecification().getBodyExpression();
        r.getContents().add(exp);

        final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
        cl1.setName("Alice");
        r.getContents().add(cl1);

        EAttribute att = (EAttribute) cl1.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
        Notification noti = NotificationHelper.createAttributeChangeNotification(cl1, att, "Alice", "Bob");
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);
        assertEquals(1, impact.size());
        assertTrue(impact.contains(cl1));
    }

    @Test
    public void testVerySimpleInstanceScopeAnalysisWithTuple() {
        Resource r = this.cp.eResource();
        OCLExpression exp = (OCLExpression) parse(testVerySimpleInstanceScopeAnalysisWithTuple, this.cp).iterator().next()
                .getSpecification().getBodyExpression();
        r.getContents().add(exp);

        final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
        cl1.setName("Alice");
        r.getContents().add(cl1);

        EAttribute att = (EAttribute) cl1.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
        Notification noti = NotificationHelper.createAttributeChangeNotification(cl1, att, "Alice", "Bob");
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);

        assertTrue(impact.size() == 1 && impact.contains(cl1));
    }

    @Test
    public void testGetFloorTokenNull() {
        Resource r = this.cp.eResource();
        OCLExpression exp = (OCLExpression) parse(testForIA2, this.cp).iterator().next().getSpecification().getBodyExpression();

        SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
        r.getContents().add(cl1);
        cl1.setName("Alice");
        cl1.setValueType(true);

        ClassTypeDefinition ctd1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        r.getContents().add(ctd1);
        ctd1.setClazz(cl1);
        ctd1.setLowerMultiplicity(1);
        ctd1.setUpperMultiplicity(1);
        ctd1.setOrdered(false);
        ctd1.setUnique(false);

        SapClass cl2 = ClassesFactory.eINSTANCE.createSapClass();
        r.getContents().add(cl2);
        cl2.setName("Bob");

        ClassTypeDefinition ctd2 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
        r.getContents().add(ctd2);
        ctd2.setClazz(cl2);
        ctd2.setLowerMultiplicity(1);
        ctd2.setUpperMultiplicity(1);
        ctd2.setOrdered(false);
        ctd2.setUnique(false);

        ObjectLiteral ol1 = LiteralsFactory.eINSTANCE.createObjectLiteral();
        r.getContents().add(ol1);
        ol1.setValueClass(cl1);

        AssociationEnd ae1 = ClassesFactory.eINSTANCE.createAssociationEnd();
        r.getContents().add(ae1);
        ae1.setName("Assoc_to_Alice");
        ae1.setType(ctd1);

        AssociationEnd ae2 = ClassesFactory.eINSTANCE.createAssociationEnd();
        r.getContents().add(ae2);
        ae2.setName("Assoc_to_Bob");
        ae2.setType(ctd2);

        Association a = ClassesFactory.eINSTANCE.createAssociation();
        r.getContents().add(a);
        a.setName("Assoc");
        a.getEnds().add(ae1);
        a.getEnds().add(ae2);

        EAttribute att = (EAttribute) ae1.eClass().getEStructuralFeature(ClassesPackage.ASSOCIATION_END__NAME);
        Notification noti = NotificationHelper.createAttributeChangeNotification(ae2, att, "Assoc_to_Bob",
                "Assoc_to_Bob_changed");
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE
                .createImpactAnalyzer(exp, LiteralsPackage.eINSTANCE.getObjectLiteral(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);
        assertEquals(1, impact.size());
        assertTrue(impact.contains(ol1));
    }

    @Test
    public void testPredicateEvaluation() {
        OCLExpression exp = (OCLExpression) parse(
                "context data::classes::SapClass inv testPredicateEvaluation:\n"
                        + "self.ownedSignatures->select(s|s.sideEffectFree)->size() > 1", this.cp).iterator().next()
                .getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(exp);
        SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
        c1.setName("c1");
        SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
        c2.setName("c2");
        SapClass c3 = ClassesFactory.eINSTANCE.createSapClass();
        c3.setName("c3");
        MethodSignature m1 = ClassesFactory.eINSTANCE.createMethodSignature();
        m1.setName("Signature 1");
        m1.setSideEffectFree(true);
        MethodSignature m2 = ClassesFactory.eINSTANCE.createMethodSignature();
        m2.setName("Signature 2");
        m2.setSideEffectFree(false);
        MethodSignature m3 = ClassesFactory.eINSTANCE.createMethodSignature();
        m3.setName("Signature 3");
        m3.setSideEffectFree(true);

        c1.getOwnedSignatures().add(m1);
        c2.getOwnedSignatures().add(m2);
        c3.getOwnedSignatures().add(m3);

        EAttribute att = (EAttribute) m3.eClass().getEStructuralFeature(ClassesPackage.METHOD_SIGNATURE__SIDE_EFFECT_FREE);
        Notification noti = NotificationHelper.createAttributeChangeNotification(m3, att, true, false);
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);
        assertTrue(impact.size() == 1 && impact.contains(c3));

        noti = NotificationHelper.createAttributeChangeNotification(m3, att, false, true);
        impact = ia.getContextObjects(noti);
        assertTrue(impact.size() == 1 && impact.contains(c3));

        noti = NotificationHelper.createAttributeChangeNotification(m3, att, false, false);
        impact = ia.getContextObjects(noti);
        assertTrue(impact.size() == 0);

        noti = NotificationHelper.createAttributeChangeNotification(m3, att, true, true);
        impact = ia.getContextObjects(noti);
        assertTrue(impact.size() == 0);
    }

    @Test
    public void testDeltaPropagationForAllInstances() {
        OCLExpression exp = (OCLExpression) parse(
                "context data::classes::SapClass inv testDeltaPropagationForAllInstances:\n"
                        + "data::classes::SapClass.allInstances()->select(name='Humba')->size() = 0", this.cp).iterator().next()
                .getSpecification().getBodyExpression();
        this.cp.eResource().getContents().add(exp);
        SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
        c1.setName("Trala");
        SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
        c2.setName("Humba");
        modelmanagement.Package pkg = ModelmanagementFactory.eINSTANCE.createPackage();
        pkg.setName("Pkg");
        this.cp.eResource().getContents().add(pkg);
        Notification noti = NotificationHelper.createReferenceAddNotification(pkg, ModelmanagementPackage.eINSTANCE
                .getPackage_Classes(), c1);
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);
        assertEquals(0, impact.size());

        noti = NotificationHelper.createReferenceAddNotification(pkg, ModelmanagementPackage.eINSTANCE.getPackage_Classes(), c2);
        impact = ia.getContextObjects(noti);
        assertTrue(impact.size() >= 2); // we don't know the exact size because of all the other test elements created for fixture
        assertTrue(impact.contains(c1) && impact.contains(c2));
    }

    @Test
    public void testSimpleUnusedCheckWithIfConditionAlwaysFalse() {
        Resource r = this.cp.eResource();
        OCLExpression exp = (OCLExpression) parse("context data::classes::SapClass inv testSimpleUnusedCheckWithIfClause:\n"+
                "if false then self.valueType else true endif", this.cp).iterator().next()
                .getSpecification().getBodyExpression();
        r.getContents().add(exp);

        final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
        cl1.setValueType(false);
        r.getContents().add(cl1);

        EAttribute att = (EAttribute) cl1.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__VALUE_TYPE);
        Notification noti = NotificationHelper.createAttributeChangeNotification(cl1, att, false, true);
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);

        if (OptimizationActivation.getOption().isTracebackStepISAActive() && OptimizationActivation.getOption().isUnusedDetectionActive()) {
            // expecting no impact because the then clause affected by the change is unused
            assertEquals(0, impact.size());
        } else {
            assertEquals(1, impact.size());
            assertEquals(cl1, impact.iterator().next());
        }
    }

    @Test
    public void testSimpleUnusedCheckWithIteratorSourceAlwaysEmpty() {
        Resource r = this.cp.eResource();
        // the idea: while self.valueType changes for cl1, self.adapters is always empty for the changed object
        OCLExpression exp = (OCLExpression) parse("context data::classes::SapClass inv testSimpleUnusedCheckWithIfClause:\n"+
                "self.adapters->select(a | a.to.valueType = self.valueType)", this.cp).iterator().next()
                .getSpecification().getBodyExpression();
        r.getContents().add(exp);

        final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
        cl1.setValueType(false);
        r.getContents().add(cl1);

        EAttribute att = (EAttribute) cl1.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__VALUE_TYPE);
        Notification noti = NotificationHelper.createAttributeChangeNotification(cl1, att, false, true);
        ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
        Collection<EObject> impact = ia.getContextObjects(noti);

        if (OptimizationActivation.getOption().isUnusedDetectionActive()) {
            // expecting no impact because the then clause affected by the change is unused
            assertEquals(0, impact.size());
        } else {
            assertEquals(1, impact.size());
            assertEquals(cl1, impact.iterator().next());
        }
    }

}
