/*******************************************************************************
 * 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 java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
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.emf.ecore.util.EcoreUtil;
import org.eclipse.ocl.ecore.ExpressionInOCL;
import org.eclipse.ocl.ecore.OCLExpression;
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.After;
import org.junit.Before;
import org.junit.Test;

import company.Company;
import company.CompanyFactory;
import company.Department;
import company.Division;
import company.Employee;
import company.Freelance;
import company.Student;
import junit.framework.AssertionFailedError;


/**
 * Tests whether the right context instances are computed. This is done as follows: A simple instance of the company model is
 * created. Each test tests only one statement. The statement is analyzed and a set of relevant events is generated and reported
 * to IA. The IA compute the affected context instances with the help of the InstanceScopeAnalysis. This set is then compared to a
 * set of expected context instances.
 *
 */
public class RevPathComputationTest extends BaseDepartmentTestWithOCL {

	private Division div;
	private Department dep1;
	private Department dep2;
	private Employee e1;
	private Freelance e2;
	private Employee e3;
	private Freelance e4;
	private Employee boss1;
	private Employee boss2;
	private Employee director;
	private Employee secretary;
	private Student stud1;
	private Student stud2;
	private Company company;

	@Override
	@Before
	public void setUp() {

		super.setUp();
		createInstances();
	}

	@Override
	@After
	public void tearDown() {
		EcoreUtil.delete(this.div);
		EcoreUtil.delete(this.dep1);
		EcoreUtil.delete(this.dep2);
		EcoreUtil.delete(this.e1);
		EcoreUtil.delete(this.e2);
		EcoreUtil.delete(this.e3);
		EcoreUtil.delete(this.e4);
		EcoreUtil.delete(this.boss1);
		EcoreUtil.delete(this.boss2);
		EcoreUtil.delete(this.director);
		EcoreUtil.delete(this.secretary);
		EcoreUtil.delete(this.stud1);
		EcoreUtil.delete(this.stud2);
		super.tearDown();
	}

	@Test
	public void testAnalysisOfASimpleRecursiveOperation() {
		// construct something like "new HumbaClass1().m()"
		final Department d1 = CompanyFactory.eINSTANCE.createDepartment();
		d1.setName("d1");
		d1.setBudget(10000);
		final Department d2 = CompanyFactory.eINSTANCE.createDepartment();
		d2.setName("d2");
		d2.setBudget(10000);
		final Department d3 = CompanyFactory.eINSTANCE.createDepartment();
		d3.setName("d3");
		d3.setBudget(10000);
		final Department d4 = CompanyFactory.eINSTANCE.createDepartment();
		d4.setName("d4");
		d4.setBudget(10000);
		d1.getSubDepartment().add(d2);
		d2.getSubDepartment().add(d3);
		d2.getSubDepartment().add(d4);
		this.comp.eResource().getContents().add(d1);
		Notification noti = NotificationHelper.createAttributeChangeNotification(d4, departmentBudget,
				d4.getBudget(), d4.getBudget()+1000);
		Collection<EObject> instances = computeAffectedInstances(this.getSumBudgetLimitAST(), noti);
		compareInstances(instances, new EObject[] { d1, d2, d4 });
	}

	@Test
	public void testBossHighestSalaryEmployeeSalaryChange() {

		// context Department inv BossHighestSalary:
		// self.employee->select(
		// e|e.salary >= self.boss.salary)->size() <= 1
		debugPrintln("Testing BossHighestSalaryEmployeeSalaryChange\n");
		Notification noti;
		// change salary of an employee
		noti = NotificationHelper.createAttributeChangeNotification(this.e1, this.employeeSalary, this.e1.getSalary(),
				this.e1.getSalary()+1);
		Collection<EObject> instances = computeAffectedInstances(this.getBossHighestSalaryAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });
	}

	@Test
	public void testBossHighestSalaryBossSalaryChange() {

		// context Department inv BossHighestSalary:
		// self.employee->select(
		// e|e.salary >= self.boss.salary)->size() <= 1
		debugPrintln("Testing BossHighestSalaryBossSalaryChange\n");
		Notification noti;

		Collection<EObject> instances;

		// change salary of the boss
		noti = NotificationHelper.createAttributeChangeNotification(this.boss1, this.employeeSalary, this.boss1
				.getSalary(), this.boss1.getSalary()+1);
		instances = computeAffectedInstances(this.getBossHighestSalaryAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });

	}

	@Test
	public void testBossHighestSalaryAddEmployee() {

		// context Department inv BossHighestSalary:
		// self.employee->select(
		// e|e.salary >= self.boss.salary)->size() <= 1
		debugPrintln("Testing BossHighestSalaryAddEmployee\n");
		Notification noti;

		Collection<EObject> instances;
		// add new employee
		noti = NotificationHelper.createReferenceAddNotification(this.dep1, this.employeeRef, CompanyFactory.eINSTANCE
				.createEmployee());
		instances = computeAffectedInstances(this.getBossHighestSalaryAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });
	}

	@Test
	public void testBossHighestSalaryAddBoss() {

		// context Department inv BossHighestSalary:
		// self.employee->select(
		// e|e.salary >= self.boss.salary)->size() <= 1
		debugPrintln("Testing BossHighestSalaryAddBoss\n");
		Notification noti;

		Collection<EObject> instances;

		// add new boss
		noti = NotificationHelper.createReferenceAddNotification(this.dep1, this.bossRef, this.boss2);
		instances = computeAffectedInstances(this.getBossHighestSalaryAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });
		debugPrintln("--------------------------------------------------\n");
	}

	@Test
	public void testBossIsOldestEmployeeAgeChange() {

		// context Employee inv BossIsOldest:
		// self.age <= self.employer.boss.age
		debugPrintln("Testing BossIsOldestEmployeeAgeChange\n");
		Collection<EObject> instances;
		Notification noti;

		// change age of an employee
		noti = NotificationHelper.createAttributeChangeNotification(this.e2, this.employeeAge, this.e2.getAge(),
				this.e2.getAge()+1);
		instances = computeAffectedInstances(this.getBossIsOldestAST(), noti);
		compareInstances(instances, new EObject[] { this.e2 });
	}

	@Test
	public void testBossIsOldestBossAgeChange() {

		// context Employee inv BossIsOldest:
		// self.age <= self.employer.boss.age
		debugPrintln("Testing BossIsOldestBossAgeChange\n");
		Collection<EObject> instances;
		Notification noti;

		// change age of the boss
		noti = NotificationHelper.createAttributeChangeNotification(this.boss1, this.employeeAge, this.boss1.getAge(),
				this.boss1.getAge()+1);
		instances = computeAffectedInstances(this.getBossIsOldestAST(), noti);
		compareInstances(instances, new EObject[] { this.e1, this.e2, this.boss1, this.stud1 });

	}

	@Test
	public void testBossIsOldestAddEmployee() {

		// context Employee inv BossIsOldest:
		// self.age <= self.employer.boss.age
		debugPrintln("Testing BossIsOldestAddEmployee\n");
		Set<EObject> expectedInstances = new HashSet<EObject>();
		expectedInstances.add(this.e2);

		Collection<EObject> instances;
		Notification noti;

		// add new employee
		noti = NotificationHelper.createReferenceAddNotification(this.e1, this.employerRef, this.dep2);
		instances = computeAffectedInstances(this.getBossIsOldestAST(), noti);
		compareInstances(instances, new EObject[] { this.e1 });

	}

	@Test
	public void testBossIsOldestAddBoss() {

		// context Employee inv BossIsOldest:
		// self.age <= self.employer.boss.age
		debugPrintln("Testing BossIsOldestAddBoss\n");
		Set<EObject> expectedInstances = new HashSet<EObject>();
		expectedInstances.add(this.e2);

		Collection<EObject> instances;
		Notification noti;

		// add new boss
		noti = NotificationHelper.createReferenceAddNotification(this.dep1, this.bossRef, this.boss2);
		instances = computeAffectedInstances(this.getBossIsOldestAST(), noti);
		compareInstances(instances, new EObject[] { this.e1, this.e2, this.boss1, this.stud1 });

		debugPrintln("--------------------------------------------------\n");
	}

	@Test
	public void testNotBossFreelance() {

		// context Department
		// inv NotBossFreelance:
		// not self.boss.oclIsTypeOf(Freelance)
		debugPrintln("Testing NotBossFreelance\n");
		Notification noti = null;

		// add new boss
		noti = NotificationHelper.createReferenceAddNotification(this.dep2, this.bossRef, this.boss1);
		Collection<EObject> instances = computeAffectedInstances(this.getNotBossFreelanceAST(), noti);
		compareInstances(instances, new EObject[] { this.dep2 });
		debugPrintln("--------------------------------------------------\n");
	}

	@Test
	public void testOldEmployeeEmployeeAgeChange() {

		// context Department
		// inv OldEmployee:
		// self.employee->exists(e | e.age > 45)
		debugPrintln("Testing OldEmployeeEmployeeAgeChange\n");

		Notification noti;
		Collection<EObject> instances;
		// change age of an employee
		noti = NotificationHelper.createAttributeChangeNotification(this.e2, this.employeeAge, this.e2.getAge(),
				this.e2.getAge()+30);
		instances = computeAffectedInstances(this.getOldEmployeeAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });

	}

	@Test
	public void testOldEmployeeBossAgeChange() {

		// context Department
		// inv OldEmployee:
		// self.employee->exists(e | e.age > 45)
		debugPrintln("Testing OldEmployeeBossAgeChange\n");

		Notification noti;
		Collection<EObject> instances;
		// change age of the boss
		noti = NotificationHelper.createAttributeChangeNotification(this.boss1, this.employeeAge, this.boss1.getAge(),
				this.boss1.getAge()+30);
		instances = computeAffectedInstances(this.getOldEmployeeAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });
	}

	@Test
	public void testOldEmployeeAddEmployee() {

		// context Department
		// inv OldEmployee:
		// self.employee->exists(e | e.age > 45)
		debugPrintln("Testing OldEmployeeAddEmployee\n");

		Notification noti;
		Collection<EObject> instances;

		Employee newEmployee = CompanyFactory.eINSTANCE.createEmployee();
		newEmployee.setAge(46);
		// add new employee
		noti = NotificationHelper.createReferenceAddNotification(this.dep1, this.employeeRef, newEmployee);
		instances = computeAffectedInstances(this.getOldEmployeeAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });
		debugPrintln("--------------------------------------------------\n");
	}

	@Test
	public void testUniqueNamesEmployeeNameChange() {

		// context Employee
		// inv UniqueNames:
		// Employee.allInstances()->forAll(e |
		// e <> self implies e.name <> self.name)
		debugPrintln("Testing UniqueNamesEmployeeNameChange\n");

		// change name of an employee
		// this does not trigger the allInstances change handling
		Notification noti = NotificationHelper.createAttributeChangeNotification(this.e2, this.employeeName, this.e2.getName(),
				this.e2.getName()+"Humba");

		Collection<EObject> instances = computeAffectedInstances(this.getUniqueNamesAST(), noti);
		compareInstances(instances, new EObject[] { this.e1, this.e2, this.e3, this.e4, this.boss1, this.boss2, this.director,
				this.secretary, this.stud1, this.stud2 });
	}

	@Test
	public void testUniqueNamesEmployeeAdd() {

		// context Employee
		// inv UniqueNames:
		// Employee.allInstances()->forAll(e |
		// e <> self implies e.name <> self.name)
		debugPrintln("Testing UniqueNamesEmployeeAdd\n");

		// add a new employee
		Employee newEmployee = CompanyFactory.eINSTANCE.createEmployee();
		Notification noti = NotificationHelper.createElementAddNotification( rs.getResources().iterator().next(), null, newEmployee);

		Collection<EObject> instances = computeAffectedInstances(this.getUniqueNamesAST(), noti);
		compareInstances(instances, new EObject[] { this.e1, this.e2, this.e3, this.e4, this.boss1, this.boss2, this.director,
				this.secretary, this.stud1, this.stud2, newEmployee });
		// remove the added employee to prevent him from appearing in other test cases
		EcoreUtil.delete(newEmployee);
	}

	@Test
	public void testUniqueNamesEmployeeRemove() {
		// context Employee
		// inv UniqueNames:
		// Employee.allInstances()->forAll(e |
		// e <> self implies e.name <> self.name)
		debugPrintln("Testing UniqueNamesEmployeeRemove\n");
		// remove an employee
		Notification noti = NotificationHelper.createElementDeleteNotification( this.e1 );
		Collection<EObject> instances = computeAffectedInstances(this.getUniqueNamesAST(), noti);
		compareInstances(instances, new EObject[] { this.e2, this.e3, this.e4, this.boss1, this.boss2, this.director,
				this.secretary, this.stud1, this.stud2});

		debugPrintln("--------------------------------------------------\n");
	}

	@Test
	public void testValidAssignment() {

		// context Freelance
		// inv ValidAssignment:
		// self.assignment >= 5 and self.assignment <= 30
		debugPrintln("Testing ValidAssignment\n");

		// change age of an employee far enough
		Notification noti = NotificationHelper.createAttributeChangeNotification(this.e4, this.freelanceAssignment,
				this.e4.getAssignment(), 31);
		Collection<EObject> instances = computeAffectedInstances(this.getValidAssignmentAST(), noti);
		compareInstances(instances, new EObject[] { this.e4 });

		// change age of an employee not far enough
		Notification noti2 = NotificationHelper.createAttributeChangeNotification(this.e4, this.freelanceAssignment,
				this.e4.getAssignment(), 29);
		Collection<EObject> instances2 = computeAffectedInstances(this.getValidAssignmentAST(), noti2);
		compareInstances(instances2, new EObject[] { });
		debugPrintln("--------------------------------------------------\n");

	}

	@Test
	public void testMaxJuniorsEmployeeAgeChange() {

		// context Department inv MaxJuniors:
		// self.employee->select(e|e.age < 25)->size() < self.maxJuniors
		debugPrintln("Testing MaxJuniorsEmployeeAgeChange\n");
		Notification noti;
		Collection<EObject> instances;
		// change age of an employee so that it now falls under 25
		noti = NotificationHelper.createAttributeChangeNotification(this.e2, this.employeeAge, this.e2.getAge(),
				23);
		instances = computeAffectedInstances(this.getMaxJuniorsAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });

		// change age of an employee so that it does not fall under 25
		noti = NotificationHelper.createAttributeChangeNotification(this.e2, this.employeeAge, this.e2.getAge(),
				this.e2.getAge()+1);
		instances = computeAffectedInstances(this.getMaxJuniorsAST(), noti);
		compareInstances(instances, new EObject[] { });
	}

	@Test
	public void testMaxJuniorsDepartmentMaxJuniorsChange() {

		// context Department inv MaxJuniors:
		// self.employee->select(e|e.age < 25)->size() < self.maxJuniors
		debugPrintln("Testing MaxJuniorsDepartmentMaxJuniorsChange\n");
		Notification noti;
		Collection<EObject> instances;

		// change maxJuniors of a Department
		noti = NotificationHelper.createAttributeChangeNotification(this.dep1, this.departmentMaxJuniors, this.dep1
				.getMaxJuniors(), this.dep1.getMaxJuniors()+1);
		instances = computeAffectedInstances(this.getMaxJuniorsAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });

	}

	@Test
	public void testMaxJuniorsAddEmployee() {

		// context Department inv MaxJuniors:
		// self.employee->select(e|e.age < 25)->size() < self.maxJuniors
		debugPrintln("Testing MaxJuniorsAddEmployee\n");
		Notification noti;
		Collection<EObject> instances;

		// add new employee
		noti = NotificationHelper.createReferenceAddNotification(this.dep1, this.employeeRef, CompanyFactory.eINSTANCE
				.createEmployee());
		instances = computeAffectedInstances(this.getMaxJuniorsAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });

		debugPrintln("--------------------------------------------------\n");

	}

	@Test
	public void testNastyConstraintAddDepartment() {

		// context Division
		// inv nasty:
		// self.department->collect(d|
		// d.employee->including(d.boss)).salary->sum() < budget";
		debugPrintln("Testing nastyAddDepartment\n");

		Notification noti;
		Collection<EObject> instances;

		// add new department
		noti = NotificationHelper.createReferenceAddNotification(this.div, this.departmentRef, CompanyFactory.eINSTANCE
				.createDepartment());
		instances = computeAffectedInstances(this.getNastyConstraintAST(), noti);
		compareInstances(instances, new EObject[] { this.div });

	}

	@Test
	public void testNastyConstraintAddEmployee() {

		// context Division
		// inv nasty:
		// self.department->collect(d|
		// d.employee->including(d.boss)).salary->sum() < budget";
		debugPrintln("Testing nastyAddEmployee\n");

		Notification noti;
		Collection<EObject> instances;

		// add new employee
		noti = NotificationHelper.createReferenceAddNotification(this.dep1, this.employeeRef, CompanyFactory.eINSTANCE
				.createEmployee());
		instances = computeAffectedInstances(this.getNastyConstraintAST(), noti);
		compareInstances(instances, new EObject[] { this.div });

	}

	@Test
	public void testNastyConstraintAddBoss() {

		// context Division
		// inv nasty:
		// self.department->collect(d|
		// d.employee->including(d.boss)).salary->sum() < budget";
		debugPrintln("Testing nastyAddBoss\n");
		Notification noti;
		Collection<EObject> instances;

		// add new boss
		noti = NotificationHelper.createReferenceAddNotification(this.dep1, this.bossRef, this.boss2);
		instances = computeAffectedInstances(this.getNastyConstraintAST(), noti);
		compareInstances(instances, new EObject[] { this.div });

	}

	@Test
	public void testNastyConstraintEmployeeSalaryChange() {

		// context Division
		// inv nasty:
		// self.department->collect(d|
		// d.employee->including(d.boss)).salary->sum() < budget";
		debugPrintln("Testing nastyEmployeeSalaryChange\n");

		Notification noti;
		Collection<EObject> instances;

		// change salary of an employee
		noti = NotificationHelper.createAttributeChangeNotification(this.e1, this.employeeSalary, this.e1.getSalary(),
				this.e1.getSalary()+1);
		instances = computeAffectedInstances(this.getNastyConstraintAST(), noti);
		compareInstances(instances, new EObject[] { this.div });

	}

	@Test
	public void testNastyConstraintBossSalaryChange() {

		// context Division
		// inv nasty:
		// self.department->collect(d|
		// d.employee->including(d.boss)).salary->sum() < budget";
		debugPrintln("Testing nastyBossSalaryChange\n");
		Notification noti;
		Collection<EObject> instances;

		// change salary of the boss
		noti = NotificationHelper.createAttributeChangeNotification(this.boss1, this.employeeSalary, this.boss1
				.getSalary(), this.boss1.getSalary()+1);
		instances = computeAffectedInstances(this.getNastyConstraintAST(), noti);
		compareInstances(instances, new EObject[] { this.div });

	}

	@Test
	public void testNastyConstraintDivisionBudgetChange() {

		// context Division
		// inv nasty:
		// self.department->collect(d|
		// d.employee->including(d.boss)).salary->sum() < budget";
		debugPrintln("Testing nastyDivisionBudgetChange\n");
		Notification noti;
		Collection<EObject> instances;

		// change budget of the division
		noti = NotificationHelper.createAttributeChangeNotification(this.div, this.divisionBudget,
				this.div.getBudget(), this.div.getBudget()+1);
		instances = computeAffectedInstances(this.getNastyConstraintAST(), noti);
		compareInstances(instances, new EObject[] { this.div });

		debugPrintln("--------------------------------------------------\n");
	}

	@Test
	public void testSecretaryOlderThanBossAddDirector() {

		// context Employee \n"
		// inv secretaryOlderThanBoss: \n"
		// if self.directed->notEmpty() and \n"
		// not self.secretary.oclIsUndefined() then \n"
		// self.age < self.secretary.age \n"
		// else true \n"
		// endif";
		debugPrintln("Testing secretaryOlderThanBossAddDirector\n");
		Notification noti;
		Collection<EObject> instances;

		// add new director
		noti = NotificationHelper.createReferenceAddNotification(this.director, this.directedRef, CompanyFactory.eINSTANCE.createDivision());
		instances = computeAffectedInstances(this.getSecretaryOlderThanBossAST(), noti);
		compareInstances(instances, new EObject[] { this.director });
	}

	@Test
	public void testSecretaryOlderThanBossRemoveDirector() {

		// context Employee \n"
		// inv secretaryOlderThanBoss: \n"
		// if self.directed->notEmpty() and \n"
		// not self.secretary.oclIsUndefined() then \n"
		// self.age < self.secretary.age \n"
		// else true \n"
		// endif";
		debugPrintln("Testing secretaryOlderThanBossRemoveDirector\n");
		Notification noti;
		Collection<EObject> instances;

		// remove director
		noti = NotificationHelper.createReferenceRemoveNotification(this.director, this.directedRef, this.div);
		instances = computeAffectedInstances(this.getSecretaryOlderThanBossAST(), noti);
		compareInstances(instances, new EObject[] { this.director });

	}

	@Test
	public void testSecretaryOlderThanBossDirectorSecretaryChange() {

		// context Employee \n"
		// inv secretaryOlderThanBoss: \n"
		// if self.directed->notEmpty() and \n"
		// not self.secretary.oclIsUndefined() then \n"
		// self.age < self.secretary.age \n"
		// else true \n"
		// endif";
		debugPrintln("Testing secretaryOlderThanBossDirectorSecretaryChange\n");
		Notification noti;
		Collection<EObject> instances;

		// change secretary of the director
		Employee newEmployee = CompanyFactory.eINSTANCE.createEmployee();
		noti = NotificationHelper.createReferenceChangeNotification(this.director, this.employeeSecretary, this.director
				.getSecretary(), newEmployee);
		instances = computeAffectedInstances(this.getSecretaryOlderThanBossAST(), noti);
		compareInstances(instances, new EObject[] { this.director });

	}

	@Test
	public void testSecretaryOlderThanBossSecretaryAgeChange() {

		// context Employee \n"
		// inv secretaryOlderThanBoss: \n"
		// if self.directed->notEmpty() and \n"
		// not self.secretary.oclIsUndefined() then \n"
		// self.age < self.secretary.age \n"
		// else true \n"
		// endif";
		debugPrintln("Testing secretaryOlderThanBossSecretaryAgeChange\n");
		Notification noti;
		Collection<EObject> instances;

		// change age of secretary
		noti = NotificationHelper.createAttributeChangeNotification(this.secretary, this.employeeAge, this.secretary
				.getAge(), this.secretary.getAge()+1);
		instances = computeAffectedInstances(this.getSecretaryOlderThanBossAST(), noti);
		if (OptimizationActivation.getOption().isUnusedDetectionActive()) {
			compareInstances(instances, new EObject[] {} ); // change is in unused if-branch
		} else {
			compareInstances(instances, new EObject[] { this.director, this.secretary });
		}
	}

	@Test
	public void testSecretaryOlderThanBossDirectorAgeChange() {

		// context Employee \n"
		// inv secretaryOlderThanBoss: \n"
		// if self.directed->notEmpty() and \n"
		// not self.secretary.oclIsUndefined() then \n"
		// self.age < self.secretary.age \n"
		// else true \n"
		// endif";
		debugPrintln("Testing secretaryOlderThanBossDirectorAgeChange\n");
		Notification noti;
		Collection<EObject> instances;

		// change age of director
		noti = NotificationHelper.createAttributeChangeNotification(this.director, this.employeeAge, this.director
				.getAge(), this.director.getAge()+1);
		instances = computeAffectedInstances(this.getSecretaryOlderThanBossAST(), noti);
		compareInstances(instances, new EObject[] { this.director });

		debugPrintln("--------------------------------------------------\n");
	}

	@Test
	public void testBoss10YearsOlderThanJuniorEmployeeAgeChange() {

		// context Department \n"
		// inv boss10YearsOlderThanJunior: \n"
		// let t:Tuple(boss:Employee,junior:Employee)="
		// Tuple{boss=self.boss, junior=self.employee->sortedBy(age)->first()} in \n"
		// t.boss.age > t.junior.age + 10";
		debugPrintln("Testing boss10YearsOlderThanJuniorEmployeeAgeChange\n");
		Notification noti;
		Collection<EObject> instances;

		// change age of employee
		noti = NotificationHelper.createAttributeChangeNotification(this.e1, this.employeeAge, 42, 1);
		instances = computeAffectedInstances(this.getBoss10YearsOlderThanJuniorAST(), noti);
		compareInstances(instances, new EObject[] { this.e1.getEmployer() });
	}

	@Test
	public void testBoss10YearsOlderThanJuniorBossAgeChange() {

		// context Department \n"
		// inv boss10YearsOlderThanJunior: \n"
		// let t:Tuple(boss:Employee,junior:Employee)="
		// Tuple{boss=self.boss, junior=self.employee->sortedBy(age)->first()} in \n"
		// t.boss.age > t.junior.age + 10";
		debugPrintln("Testing boss10YearsOlderThanJuniorBossAgeChange\n");
		Notification noti;
		Collection<EObject> instances;

		// change age of boss
		noti = NotificationHelper.createAttributeChangeNotification(this.boss1, this.employeeAge, 42, 52);
		instances = computeAffectedInstances(this.getBoss10YearsOlderThanJuniorAST(), noti);
		compareInstances(instances, new EObject[] { this.e1.getEmployer() });

		debugPrintln("--------------------------------------------------\n");
	}

	@Test
	public void testCompareBossSalaryToJuniorSalaryBossChange() {
		// context Department \n"
		// inv compareBossSalaryToJuniorSalary: \n"
		// let t:Tuple(boss:Tuple(person:Employee, salary:Integer), junior:Tuple(person:Employee, salary:Integer))="
		// Tuple{Tuple{self.boss, self.boss.salary}, Tuple{self.employee->sortedBy(age)->first(),
		// self.employee->sortedBy(age)->first().salary}} in \n"
		// t.boss.person <> t.junior.person implies t.boss.salary > t.junior.salary + 100";
		debugPrintln("Testing compareBossSalaryToJuniorSalaryBossChange\n");
		Notification noti;
		Collection<EObject> instances;

		// change boss of department
		noti = NotificationHelper.createReferenceChangeNotification(this.dep1, this.bossRef, CompanyFactory.eINSTANCE
				.createEmployee(), this.e1);
		instances = computeAffectedInstances(this.getCompareBossSalaryToJuniorSalaryAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });
	}

	@Test
	public void testCompareBossSalaryToJuniorSalaryEmployeeSalaryChange() {
		// context Department \n"
		// inv compareBossSalaryToJuniorSalary: \n"
		// let t:Tuple(boss:Tuple(person:Employee, salary:Integer), junior:Tuple(person:Employee, salary:Integer))="
		// Tuple{Tuple{self.boss, self.boss.salary}, Tuple{self.employee->sortedBy(age)->first(),
		// self.employee->sortedBy(age)->first().salary}} in \n"
		// t.boss.person <> t.junior.person implies t.boss.salary > t.junior.salary + 100";
		debugPrintln("Testing compareBossSalaryToJuniorSalaryEmployeeSalaryChange\n");
		Notification noti;
		Collection<EObject> instances;

		// change salary of employee
		noti = NotificationHelper
				.createAttributeChangeNotification(this.e1, this.employeeSalary, 1234, 12345);
		instances = computeAffectedInstances(this.getCompareBossSalaryToJuniorSalaryAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });
	}

	@Test
	public void testCompareBossSalaryToJuniorSalaryEmployeeAgeChange() {
		// context Department \n"
		// inv compareBossSalaryToJuniorSalary: \n"
		// let t:Tuple(boss:Tuple(person:Employee, salary:Integer), junior:Tuple(person:Employee, salary:Integer))="
		// Tuple{Tuple{self.boss, self.boss.salary}, Tuple{self.employee->sortedBy(age)->first(),
		// self.employee->sortedBy(age)->first().salary}} in \n"
		// t.boss.person <> t.junior.person implies t.boss.salary > t.junior.salary + 100";
		debugPrintln("Testing compareBossSalaryToJuniorSalaryEmployeeAgeChange\n");
		Notification noti;
		Collection<EObject> instances;

		// change age of employee
		noti = NotificationHelper.createAttributeChangeNotification(this.e1, this.employeeAge, 23, 34);
		instances = computeAffectedInstances(this.getCompareBossSalaryToJuniorSalaryAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });
	}

	@Test
	public void testCompareBossSalaryToJuniorSalaryEmployeeAdd() {
		// context Department \n"
		// inv compareBossSalaryToJuniorSalary: \n"
		// let t:Tuple(boss:Tuple(person:Employee, salary:Integer), junior:Tuple(person:Employee, salary:Integer))="
		// Tuple{Tuple{self.boss, self.boss.salary}, Tuple{self.employee->sortedBy(age)->first(),
		// self.employee->sortedBy(age)->first().salary}} in \n"
		// t.boss.person <> t.junior.person implies t.boss.salary > t.junior.salary + 100";
		debugPrintln("Testing compareBossSalaryToJuniorSalaryEmployeeAdd\n");
		Notification noti;
		Collection<EObject> instances;

		// add new employee
		noti = NotificationHelper.createReferenceChangeNotification(this.dep1, this.employeeRef, null, this.e3);
		instances = computeAffectedInstances(this.getCompareBossSalaryToJuniorSalaryAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });
	}

	@Test
	public void testCompareBossSalaryToJuniorSalaryEmployeeRemove() {
		// context Department \n"
		// inv compareBossSalaryToJuniorSalary: \n"
		// let t:Tuple(boss:Tuple(person:Employee, salary:Integer), junior:Tuple(person:Employee, salary:Integer))="
		// Tuple{Tuple{self.boss, self.boss.salary}, Tuple{self.employee->sortedBy(age)->first(),
		// self.employee->sortedBy(age)->first().salary}} in \n"
		// t.boss.person <> t.junior.person implies t.boss.salary > t.junior.salary + 100";
		debugPrintln("Testing compareBossSalaryToJuniorSalaryEmployeeRemove\n");
		Notification noti;
		Collection<EObject> instances;

		// remove employee
		noti = NotificationHelper.createReferenceChangeNotification(this.dep1, this.employeeRef, this.e1, null);
		instances = computeAffectedInstances(this.getCompareBossSalaryToJuniorSalaryAST(), noti);
		compareInstances(instances, new EObject[] { this.dep1 });

		debugPrintln("--------------------------------------------------\n");

	}

	@Test
	public void testEmployeeInSameDepartmentAsInternEmployeeAdd() {
		// context Employee \n"
		// inv employeeInSameDepartmentAsIntern: \n"
		// self.employer = self.intern.employer";

		debugPrintln("Testing employeeInSameDepartmentAsInternEmployeeAdd\n");
		// add Employee
		final Employee newEmployee = CompanyFactory.eINSTANCE.createEmployee();
		final boolean[] result = new boolean[1];
		newEmployee.setIntern(this.stud2);
		newEmployee.eAdapters().add(new AdapterImpl() {
			@Override
			public void notifyChanged(Notification notification) {
				Collection<EObject> instances = computeAffectedInstances(getEmployeeInSameDepartmentAsInternAST(), notification);
				try {
					compareInstances(instances, new EObject[] { newEmployee });
					result[0] = true;
				} catch (AssertionFailedError e) {
					result[0] = false;
				}
			}
		});
		this.dep1.getEmployee().add(newEmployee);
		assertTrue(result[0]);
		// this notification is actually an ElementLifeCycleEvent which is not handled correctly atm
		// noti = NotificationHelper.createReferenceAddNotification(this.dep1, this.employeeRef, newEmployee);
	}

	@Test
	public void testEmployeeInSameDepartmentAsInternEmployeeInternChange() {
		// context Employee \n"
		// inv employeeInSameDepartmentAsIntern: \n"
		// self.employer = self.intern.employer";

		debugPrintln("Testing employeeInSameDepartmentAsInternEmployeeInternChange\n");
		Notification noti;
		Collection<EObject> instances;

		// change intern reference
		Student newStudent = CompanyFactory.eINSTANCE.createStudent();
		newStudent.setEmployer(dep2);
		noti = NotificationHelper.createReferenceChangeNotification(this.e1, this.internRef, this.stud1, newStudent);
		instances = computeAffectedInstances(this.getEmployeeInSameDepartmentAsInternAST(), noti);
		compareInstances(instances, new EObject[] { this.e1 });

	}

	@Test
	public void testEmployeeInSameDepartmentAsInternEmployeeEmployerChange() {
		// context Employee \n"
		// inv employeeInSameDepartmentAsIntern: \n"
		// self.employer = self.intern.employer";

		debugPrintln("Testing employeeInSameDepartmentAsInternEmployeeEmployerChange\n");
		Notification noti;
		Collection<EObject> instances;

		// change employer reference
		noti = NotificationHelper.createReferenceChangeNotification(this.e1, this.employerRef, this.dep1, this.dep2);
		instances = computeAffectedInstances(this.getEmployeeInSameDepartmentAsInternAST(), noti);
		compareInstances(instances, new EObject[] { this.e1 });

	}

	@Test
	public void testEmployeeInSameDepartmentAsInternStudentEmployerChange() {
		// context Employee \n"
		// inv employeeInSameDepartmentAsIntern: \n"
		// self.employer = self.intern.employer";

		debugPrintln("Testing employeeInSameDepartmentAsInternStudentEmployerChange\n");
		Notification noti;
		Collection<EObject> instances;

		// change employer reference
		noti = NotificationHelper.createReferenceChangeNotification(this.stud1, this.employerRef, this.dep1, this.dep2);
		instances = computeAffectedInstances(this.getEmployeeInSameDepartmentAsInternAST(), noti);
		// since student is a subclass of employee (and therefore could have own interns), the impact of the above change also
		// includes stud1
		compareInstances(instances, new EObject[] { this.e1, this.stud1 });

		debugPrintln("--------------------------------------------------\n");

	}

	@Test
	public void testCheckForBob() {

		debugPrintln("Testing checkForBob\n");
		Notification noti;
		Collection<EObject> instances;

		// change employee name
		noti = NotificationHelper.createAttributeChangeNotification(this.e1, this.employeeName, "e1", "Bob");
		instances = computeAffectedInstances(this.getCheckForBobAST(), noti);
		compareInstances(instances, new EObject[] { this.e1 , this.e2, this.e3, this.e4, this.secretary, this.boss1, this.boss2, this.director, this.stud1, this.stud2});

		debugPrintln("--------------------------------------------------\n");

	}

	@Test
	public void testDerivedPropertyHandlingIndirect(){
		debugPrintln("Testing derivedPropertyHandling\n");
		Notification noti;
		Collection<EObject> instances;

		// Make e1 the employee of the month of div by making him the employee of the month of dep1.
		// That should influence the derived property Department.employeesOfTheMonth but this feature isn't implemented by default.
		noti = NotificationHelper.createReferenceAddNotification(this.dep1, this.departmentEmployeeOfTheMonth, this.e1);
		instances = computeAffectedInstances(this.getLimitEmployeesOfTheMonthAST(), noti);
		compareInstances(instances, new EObject[] {this.div});
	}

	@Test
	public void testDerivedPropertyHandlingDirect() {
		Notification noti;

		// Make e1 the employee of the month of div by directly manipulating the derived property.
		// Since the derived property is unmodifiable, this should return null.
		debugPrintln("The following warning is intended.");
		noti = NotificationHelper.createReferenceAddNotification(this.div, this.divisionEmployeesOfTheMonth, this.e1);
		assertTrue(noti == null);
	}

	@Test
	public void testNestedDerivation() {
		Notification noti;
		Collection<EObject> instances;

		// Make e1 the employee of the month of div by making him the employee of the month of dep1.
		// That should influence the derived property Department.employeesOfTheMonth but this feature isn't implemented by default.
		noti = NotificationHelper.createReferenceAddNotification(this.dep1, this.departmentEmployeeOfTheMonth, this.e1);
		instances = computeAffectedInstances(this.getNestedDerivationAST(), noti);
		compareInstances(instances, new EObject[] {this.div});
	}

	@Test
	public void testNonLinearDerivationPositive() {
		Notification noti;
		Collection<EObject> instances;

		//Use a derived property with a derivation expression that contains a branch (Department.biggestNumberOfStudentsOrFreelancers)
		//and see if a change in the unused branch causes an impact.
		//After the instance creation dep2 has 1 freelance.
		//We add another one which will influence the biggestNumberOfStudentsOrFreelancers attribute of dep2 since it has only 1 student.
		noti = NotificationHelper.createReferenceAddNotification(this.dep2, this.employeeRef, this.e2);
		instances = computeAffectedInstances(this.getNonLinearDerivationAST(), noti);
		compareInstances(instances, new EObject[] {this.dep2});
	}

	@Test
	public void testNonLinearDerivationNegative() {
		Notification noti;
		Collection<EObject> instances;

		//Use a derived property with a derivation expression that contains a branch (Department.biggestNumberOfStudentsOrFreelancers)
		//and see if a change in the unused branch causes an impact.
		//After the instance creation dep2 has 1 freelance.
		//We add two more and afterwards we add 1 student which will not influence the biggestNumberOfStudentsOrFreelancers
		//attribute of dep2 since it has more freelancers than students.
		e2.setEmployer(dep2);
		boss1.setEmployer(dep2);

		noti = NotificationHelper.createReferenceAddNotification(this.dep2, this.employeeRef, this.stud1);
		instances = computeAffectedInstances(this.getNonLinearDerivationAST(), noti);
		compareInstances(instances, new EObject[] {/*this.dep2 should not be in the impact since the derived property didn't and couldn't change but this can only be determined if unusedChecks are enabled*/});
		debugPrintln("Enable unusedChecks to get rid of this extra context instance.");
	}

	@Test
	public void testlongNavigationWithDerivation() {
		// derived property handling has so far only been implemented for the traceback-step approach
		if (OptimizationActivation.getOption().isTracebackStepISAActive()) {
			Notification noti;
			Collection<EObject> instances;

			// The tested constraint makes sure, the context of the constraint and of the derivation expression differ.
			// The constraints sorts all departments of all divisions of a company by their biggestNumberOfStudentsOrFreelancers
			// attribute and checks if the last one in the collection has less than 5 students and freelancers.
			// Dep2 initially has 2 freelancers, resulting in the highest value for the biggestNumberOfStudentsOrFreelancers attribute.
			// We add another freelancer to generate an impact for this constraint.

			noti = NotificationHelper.createReferenceAddNotification(this.dep2, this.employeeRef, this.e2);
			instances = computeAffectedInstances(this.getlongNavigationWithDerivationAST(), noti);
			compareInstances(instances, new EObject[] {this.company});

			debugPrintln("--------------------------------------------------\n");
		}
	}

	// @Test
	// public void testDepartmentAlwaysInDivision(){
	//
	// // context Department \n"
	// // inv departmentMustHaveDivision: \n"
	// // self.department2division->notEmpty()";
	// debugPrintln("Testing departmentAlwaysInDivision\n");
	// Set<OCLExpression> stmts = new HashSet<OCLExpression>();
	// stmts.add(this.getdepartmentMustHaveDivisionAST());
	//
	//
	//
	// Notification noti;
	// Collection<EObject> instances;
	//
	// // create new department
	// EObject newElem = this.comp.getEFactoryInstance().create(this.department);
	// noti = NotificationHelper.createNewElementAddToResourceNotification(newElem, rs.getResources().iterator().next());
	// instances = computeAffectedInstances(TODO, noti);
	// compareInstances( instances, new EObject[] { newElem } );
	// // add department to division
	// // remove department from division
	// }

	/**
	 * Creates an instance of the company model ie 2 instances of Department with e employees and one boss each.
	 */
	private void createInstances() {

		this.rs = new ResourceSetImpl();
		Resource r = this.rs.createResource(URI.createURI("http://rev/path/computation/test"));
		r.eAdapters().add(new ECrossReferenceAdapter());
		this.rs.getResources().add(r);

		this.company = CompanyFactory.eINSTANCE.createCompany();
		r.getContents().add(this.company);

		this.div = CompanyFactory.eINSTANCE.createDivision();
		this.div.setBudget(1234567);
		this.div.setName("Div1");
		this.div.setCompany(this.company);
		r.getContents().add(this.div);

		this.director = CompanyFactory.eINSTANCE.createEmployee();
		this.director.setAge(42);
		this.director.setName("Director");
		this.director.setDirected(this.div);
		this.director.setSalary(1234);
		this.div.setDirector(this.director);

		this.secretary = CompanyFactory.eINSTANCE.createEmployee();
		this.secretary.setAge(55);
		this.secretary.setName("Secretary");
		this.secretary.setSalary(1234);
		this.secretary.setEmployer(this.dep1);
		this.director.setSecretary(this.secretary);

		this.dep1 = CompanyFactory.eINSTANCE.createDepartment();
		this.dep1.setName("Dep1");
		this.dep1.setBudget(12345567);
		this.dep1.setMaxJuniors(5);
		this.e1 = CompanyFactory.eINSTANCE.createEmployee();
		this.e1.setAge(42);
		this.e1.setName("e1");
		this.e1.setEmployer(this.dep1);
		this.e1.setSalary(1234);
		this.e2 = CompanyFactory.eINSTANCE.createFreelance();
		this.e2.setAge(42);
		this.e2.setName("e2");
		this.e2.setAssignment(9);
		this.e2.setEmployer(this.dep1);
		this.e2.setSalary(1234);
		this.boss1 = CompanyFactory.eINSTANCE.createFreelance();
		this.boss1.setAge(43);
		this.boss1.setName("boss1");
		this.boss1.setEmployer(this.dep1);
		this.boss1.setManaged(this.dep1);
		this.boss1.setSalary(1234);
		this.dep1.setBoss(this.boss1);

		this.stud1 = CompanyFactory.eINSTANCE.createStudent();
		this.stud1.setAge(22);
		this.stud1.setName("stud1");
		this.stud1.setSalary(234);
		this.stud1.setEmployer(this.dep1);
		this.e1.setIntern(this.stud1);

		this.dep2 = CompanyFactory.eINSTANCE.createDepartment();
		this.dep2.setName("Dep2");
		this.dep2.setBudget(12345567);
		this.dep2.setMaxJuniors(5);

		this.e3 = CompanyFactory.eINSTANCE.createEmployee();
		this.e3.setAge(42);
		this.e3.setName("e3");
		this.e3.setEmployer(this.dep2);
		this.e3.setSalary(1234);
		this.e4 = CompanyFactory.eINSTANCE.createFreelance();
		this.e4.setAge(42);
		this.e4.setName("e4");
		this.e2.setAssignment(9);
		this.e4.setEmployer(this.dep2);
		this.e4.setSalary(1234);
		this.boss2 = CompanyFactory.eINSTANCE.createEmployee();
		this.boss2.setAge(44);
		this.boss2.setName("boss2");
		this.boss2.setEmployer(this.dep2);
		this.boss2.setManaged(this.dep2);
		this.boss2.setSalary(2345);
		this.dep2.setBoss(this.boss2);

		this.stud2 = CompanyFactory.eINSTANCE.createStudent();
		this.stud2.setAge(23);
		this.stud2.setName("stud2");
		this.stud2.setSalary(234);
		this.stud2.setEmployer(this.dep2);
		this.e3.setIntern(this.stud2);

		this.div.getDepartment().add(this.dep1);
		this.div.getDepartment().add(this.dep2);

	}

	/**
	 * Computes the set of affected context instances for event <tt>evt</tt>.
	 *
	 * @param expressions
	 *            list of the effected {@link OCLExpression}s
	 * @param noti
	 *            the event
	 * @param context
	 * @return a Collection of {@link EObject}s representing the affected context instances.
	 */
	private Collection<EObject> computeAffectedInstances(ExpressionInOCL eiocl, Notification noti) {
		return ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer((OCLExpression) eiocl.getBodyExpression(),
				(EClass) eiocl.getContextVariable().getType(), /* notifyOnNewContextElements */ false,
				OCLFactory.getInstance())
				.getContextObjects(noti);
	}

	/**
	 * @param instances
	 * @param expectedInstances
	 */
	private void compareInstances(Collection<EObject> instances, EObject[] expectedInstances) {
		Set<EObject> expected = new HashSet<EObject>();
		for (int i = 0; i < expectedInstances.length; i++) {
			expected.add(expectedInstances[i]);
		}
		if (instances.containsAll(expected) && instances.size() == expected.size()) {
			debugPrintln(">> SUCCESS exact match\n");
		} else if (instances.containsAll(expected) && instances.size() != expected.size()) {
			debugPrintln(">> SUCCESS \n excess context instances:\n");
			instances.removeAll(expected);
			for (Iterator<EObject> i = instances.iterator(); i.hasNext();) {
				debugPrintln(i.next() + "\n");
			}
		} else {
			debugPrintln(">> FAILURE\n");
			expected.removeAll(instances);
			for (EObject o : expected) {
				debugPrint(o + " not in result");
			}
			debugPrintln("");
			fail("Returned instances does not match expected instances!");
		}
	}

	// /**
	// * Unfortunately not all features can be tested with the department model
	// */
	// private void extendModel( ) {
	//
	// for some tests we need some additional classes
	// MofClass a = this.mofPackage.getModel().getMofClass().createMofClass();
	// a.setName("A");
	// MofClass b = this.mofPackage.getModel().getMofClass().createMofClass();
	// a.setName("B");
	// MofClass c = this.mofPackage.getModel().getMofClass().createMofClass();
	// a.setName("C");
	// MofClass d = this.mofPackage.getModel().getMofClass().createMofClass();
	// a.setName("D");
	// // B is a subtype of A
	// b.getSupertypes().add(a);
	// // D-B-Association
	// Association db = this.mofPackage.getModel().getAssociation().createAssociation();
	// db.setName("DB-Assocation");
	// AssociationEnd toB = this.mofPackage.getModel().getAssociationEnd().createAssociationEnd();
	// toB.setName("toB");
	// toB.setType(b);
	// toB.setMultiplicity(this.mofPackage.getModel().createMultiplicityType(0,-1,true,true));
	// db.getContents().add(toB);
	// AssociationEnd toD = this.mofPackage.getModel().getAssociationEnd().createAssociationEnd();
	// toB.setName("toD");
	// toB.setType(d);
	// toB.setMultiplicity(this.mofPackage.getModel().createMultiplicityType(0,-1,true,true));
	// db.getContents().add(toD);
	// // A-C-Association
	// Association ac = this.mofPackage.getModel().getAssociation().createAssociation();
	// ac.setName("DB-Assocation");
	// AssociationEnd toC = this.mofPackage.getModel().getAssociationEnd().createAssociationEnd();
	// toC.setName("toC");
	// toC.setType(c);
	// toC.setMultiplicity(this.mofPackage.getModel().createMultiplicityType(0,-1,true,true));
	// ac.getContents().add(toC);
	// AssociationEnd toA = this.mofPackage.getModel().getAssociationEnd().createAssociationEnd();
	// toA.setName("toA");
	// toA.setType(a);
	// toA.setMultiplicity(this.mofPackage.getModel().createMultiplicityType(0,-1,true,true));
	// ac.getContents().add(toA);
	// this.companyPackage.getContents().add(a);
	// this.companyPackage.getContents().add(b);
	// this.companyPackage.getContents().add(c);
	// this.companyPackage.getContents().add(d);
	// this.companyPackage.getContents().add(ac);
	// this.companyPackage.getContents().add(db);
	// }
}
