/*******************************************************************************
 * Copyright (c) 2008-2011 Chair for Applied Software Engineering,
 * Technische Universitaet Muenchen.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * chodnick
 ******************************************************************************/
package org.eclipse.emf.emfstore.client.changetracking.test.canonization;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.util.List;

import org.eclipse.emf.emfstore.client.test.common.cases.ComparingESTest;
import org.eclipse.emf.emfstore.client.test.common.dsl.Create;
import org.eclipse.emf.emfstore.internal.client.model.CompositeOperationHandle;
import org.eclipse.emf.emfstore.internal.client.model.exceptions.InvalidHandleException;
import org.eclipse.emf.emfstore.internal.client.model.util.EMFStoreCommand;
import org.eclipse.emf.emfstore.internal.common.model.Project;
import org.eclipse.emf.emfstore.internal.common.model.util.ModelUtil;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AbstractOperation;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AttributeOperation;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.CompositeOperation;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.CreateDeleteOperation;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.MultiReferenceOperation;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.util.OperationsCanonizer;
import org.eclipse.emf.emfstore.test.model.TestElement;
import org.junit.Test;

/**
 * Tests canonization of attribute operations.
 *
 * @author chodnick
 */
public class AttributeTest extends ComparingESTest {

	private static final String SOME_NAME = "someName"; //$NON-NLS-1$
	private static final String SOME_NEW_NAME = "some new Name"; //$NON-NLS-1$
	private static final String ORIGINAL_DESCRIPTION2 = "originalDescription2"; //$NON-NLS-1$
	private static final String ORIGINAL_NAME2 = "originalName2"; //$NON-NLS-1$
	private static final String ORIGINAL_DESCRIPTION1 = "originalDescription1"; //$NON-NLS-1$
	private static final String ORIGINAL_NAME1 = "originalName1"; //$NON-NLS-1$
	private static final String ORIGINAL_DESCRIPTION = "originalDescription"; //$NON-NLS-1$
	private static final String ORIGINAL_NAME = "originalName"; //$NON-NLS-1$
	private static final String DESCRIPTION_OF_TEST_ELEMENT2 = "DescriptionOfTestElement2"; //$NON-NLS-1$
	private static final String NAME_OF_TEST_ELEMENT2 = "NameOfTestElement2"; //$NON-NLS-1$
	private static final String DESCRIPTION_OF_TEST_ELEMENT = "DescriptionOfTestElement"; //$NON-NLS-1$
	private static final String NAME_OF_TEST_ELEMENT = "NameOfTestElement"; //$NON-NLS-1$
	private static final String DESC_2 = "desc 2"; //$NON-NLS-1$
	private static final String DESCRIPTION2 = "description"; //$NON-NLS-1$
	private static final String FINAL_DESC = "final desc"; //$NON-NLS-1$
	private static final String SOME_OTHER_DESC = "some other desc"; //$NON-NLS-1$
	private static final String SOME_DESC = "some desc";//$NON-NLS-1$
	private static final String OLD_SECTION = "oldSection";//$NON-NLS-1$
	private static final String HOME = "home";//$NON-NLS-1$
	private static final String MAGGIE = "maggie";//$NON-NLS-1$
	private static final String HOMER = "homer";//$NON-NLS-1$
	private static final String SOME_SECTION = "some section";//$NON-NLS-1$
	private static final String Y_NAME = "Y";//$NON-NLS-1$
	private static final String X_NAME = "X";//$NON-NLS-1$
	private static final String SECTION_CREATION = "sectionCreation";//$NON-NLS-1$
	private static final String DESC_1 = "desc 1";//$NON-NLS-1$
	private static final String NAME = "Name";//$NON-NLS-1$
	private static final String NEW_DESCRIPTION = "newDescription";//$NON-NLS-1$
	private static final String OLD_DESCRIPTION = "oldDescription";//$NON-NLS-1$
	private static final String A_NAME = "A"; //$NON-NLS-1$
	private static final String B_NAME = "B"; //$NON-NLS-1$
	private static final String C_NAME = "C"; //$NON-NLS-1$
	private static final String NEW_NAME = "newName"; //$NON-NLS-1$
	private static final String OLD_NAME = "oldName"; //$NON-NLS-1$

	/**
	 * Tests canonization for consecutive attribute changes on a single feature.
	 *
	 * @throws IOException
	 */
	@Test
	public void consecutiveAttributeChangeSingleFeature() throws IOException {

		final TestElement useCase = Create.testElement();
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(useCase);
				useCase.setName(OLD_NAME);
			}
		}.run(false);

		final Project expectedProject = ModelUtil.clone(getProject());
		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				clearOperations();

				useCase.setName(A_NAME);
				useCase.setName(B_NAME);
				useCase.setName(C_NAME);
				useCase.setName(NEW_NAME);
			}
		}.run(false);

		assertEquals(NEW_NAME, useCase.getName());
		assertEquals(4, forceGetOperations().size());

		final List<AbstractOperation> operations = forceGetOperations();

		new EMFStoreCommand() {

			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		assertEquals(operations.size(), 1);

		final AttributeOperation reverse = (AttributeOperation) operations.get(0).reverse();

		new EMFStoreCommand() {

			@Override
			protected void doRun() {
				reverse.apply(getProject());
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));
	}

	/**
	 * Tests canonization for consecutive attribute changes on a single feature.
	 *
	 * @throws IOException
	 */
	@Test
	public void consecutiveAttributeChangeSingleFeatureToNull() throws IOException {

		final TestElement useCase = Create.testElement();
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(useCase);
				useCase.setName(OLD_NAME);
			}
		}.run(false);

		final Project expectedProject = ModelUtil.clone(getProject());
		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

		new EMFStoreCommand() {

			@Override
			protected void doRun() {
				clearOperations();

				useCase.setName(A_NAME);
				useCase.setName(B_NAME);
				useCase.setName(C_NAME);
				useCase.setName(null);
			}
		}.run(false);

		assertEquals(null, useCase.getName());

		final List<AbstractOperation> operations = forceGetOperations();

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		assertEquals(operations.size(), 1);

		final AttributeOperation reverse = (AttributeOperation) operations.get(0).reverse();
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				reverse.apply(getProject());
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

	}

	/**
	 * Tests canonization for consecutive attribute changes on a single feature.
	 *
	 * @throws IOException
	 */
	@Test
	public void consecutiveAttributeChangeSingleFeatureNullToValue() throws IOException {

		final TestElement useCase = Create.testElement();
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(useCase);
				useCase.setName(null);
			}
		}.run(false);

		final Project expectedProject = ModelUtil.clone(getProject());
		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				clearOperations();

				useCase.setName(A_NAME);
				useCase.setName(B_NAME);
				useCase.setName(C_NAME);
			}
		}.run(false);

		assertEquals(C_NAME, useCase.getName());

		final List<AbstractOperation> operations = forceGetOperations();
		assertEquals(3, operations.size());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		assertEquals(operations.size(), 1);

		final AttributeOperation reverse = (AttributeOperation) operations.get(0).reverse();

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				reverse.apply(getProject());
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));
	}

	/**
	 * Tests canonization for consecutive attribute changes, resulting in a noop.
	 *
	 * @throws IOException
	 */
	@Test
	public void attributeChangeNoOp() throws IOException {

		final TestElement useCase = Create.testElement();
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(useCase);
				useCase.setName(OLD_NAME);
			}
		}.run(false);

		final Project expectedProject = ModelUtil.clone(getProject());
		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				clearOperations();

				useCase.setName(A_NAME);
				useCase.setName(B_NAME);
				useCase.setName(C_NAME);
				useCase.setName(OLD_NAME);
			}
		}.run(false);

		assertEquals(OLD_NAME, useCase.getName());
		final List<AbstractOperation> operations = forceGetOperations();
		assertEquals(4, operations.size());

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

		canonize(operations);

		// should not have created any operations, we were just resetting the name to its original value
		assertEquals(operations.size(), 0);

	}

	/**
	 * Tests canonization for consecutive attribute changes, resulting in a noop.
	 *
	 * @throws IOException
	 */
	@Test
	public void attributeChangeNoOpNull() throws IOException {

		final TestElement useCase = Create.testElement();
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(useCase);
				useCase.setName(null);
			}
		}.run(false);

		final Project expectedProject = ModelUtil.clone(getProject());
		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				clearOperations();

				useCase.setName(A_NAME);
				useCase.setName(B_NAME);
				useCase.setName(C_NAME);
				useCase.setName(null);
			}
		}.run(false);

		assertEquals(null, useCase.getName());
		final List<AbstractOperation> operations = forceGetOperations();
		assertEquals(4, operations.size());

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		// should not have created any operations, we were just resetting the name to its original value
		assertEquals(operations.size(), 0);
	}

	/**
	 * Tests canonization for consecutive attribute changes, resulting in a noop.
	 *
	 * @throws IOException
	 */
	@Test
	public void attributeChangeMultiFeatureNoOp() throws IOException {

		final TestElement useCase = Create.testElement();
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(useCase);
				useCase.setName(OLD_NAME);
				useCase.setDescription(OLD_DESCRIPTION);
			}
		}.run(false);

		final Project expectedProject = ModelUtil.clone(getProject());
		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				clearOperations();

				useCase.setName(A_NAME);
				useCase.setDescription(X_NAME);
				useCase.setName(B_NAME);
				useCase.setDescription(Y_NAME);
				useCase.setName(C_NAME);

				useCase.setDescription(OLD_DESCRIPTION);
				useCase.setName(OLD_NAME);
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));
		final List<AbstractOperation> operations = forceGetOperations();
		assertEquals(7, operations.size());

		canonize(operations);

		// should not have created any operations, we were just resetting everything to its original value
		assertEquals(operations.size(), 0);
	}

	/**
	 * Tests canonization for consecutive attribute changes on multiple features.
	 *
	 * @throws IOException
	 */
	@Test
	public void consecutiveAttributeChangeMultiFeature() throws IOException {

		final TestElement useCase = Create.testElement();
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(useCase);
				useCase.setName(OLD_NAME);
			}
		}.run(false);

		final Project expectedProject = ModelUtil.clone(getProject());
		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				clearOperations();

				useCase.setName(A_NAME);
				useCase.setDescription(OLD_DESCRIPTION);
				useCase.setName(B_NAME);
				useCase.setName(C_NAME);
				useCase.setDescription(NEW_DESCRIPTION);
				useCase.setName(NEW_NAME);
			}
		}.run(false);

		assertEquals(NEW_NAME, useCase.getName());
		final List<AbstractOperation> operations = forceGetOperations();
		assertEquals(6, operations.size());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		assertEquals(operations.size(), 2);

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				for (int i = operations.size() - 1; i >= 0; i--) {
					final AbstractOperation reverse = operations.get(i).reverse();
					reverse.apply(getProject());
				}
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));
	}

	/**
	 * Tests canonization for mixed attribute changes on a single feature.
	 *
	 * @throws IOException
	 */
	@Test
	public void mixedAttributeChangeSingleFeature() throws IOException {

		final TestElement useCase = Create.testElement();
		final TestElement actor = Create.testElement();
		final TestElement section = Create.testElement();

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(useCase);
				getProject().addModelElement(actor);
				getProject().addModelElement(section);

				useCase.setName(OLD_NAME);
				section.setName(SOME_SECTION);
				actor.setName(HOMER);
			}
		}.run(false);

		final Project expectedProject = ModelUtil.clone(getProject());
		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				clearOperations();

				useCase.setName(A_NAME);
				actor.setName(MAGGIE);
				useCase.setName(B_NAME);
				useCase.setNonContained_NTo1(actor);
				useCase.setName(C_NAME);
				section.setName(HOME);
				useCase.setName(NEW_NAME);
			}
		}.run(false);

		final List<AbstractOperation> operations = forceGetOperations();
		assertEquals(7, operations.size());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				for (int i = operations.size() - 1; i >= 0; i--) {
					final AbstractOperation reverse = operations.get(i).reverse();
					reverse.apply(getProject());
				}
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));
	}

	/**
	 * Tests canonization for mixed attribute changes on a single feature.
	 *
	 * @throws IOException
	 */
	@Test
	public void mixedAttributeChangeMultiFeature() throws IOException {

		final TestElement useCase = Create.testElement();
		final TestElement actor = Create.testElement();
		final TestElement section = Create.testElement();
		final TestElement oldSection = Create.testElement();

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(useCase);
				getProject().addModelElement(actor);
				getProject().addModelElement(section);
				getProject().addModelElement(oldSection);

				useCase.setContainer(oldSection);
				actor.setContainer(oldSection);

				useCase.setName(OLD_NAME);
				oldSection.setName(OLD_SECTION);
				section.setName(SOME_SECTION);
				actor.setName(HOMER);
			}
		}.run(false);

		final Project expectedProject = ModelUtil.clone(getProject());
		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				clearOperations();

				useCase.setName(A_NAME);
				actor.setName(MAGGIE);
				useCase.setName(B_NAME);
				useCase.setDescription(SOME_DESC);
				useCase.setNonContained_NTo1(actor);
				useCase.setName(C_NAME);
				section.setName(HOME);
				useCase.setDescription(SOME_OTHER_DESC);
				useCase.setName(NEW_NAME);
				useCase.setDescription(FINAL_DESC);
			}
		}.run(false);

		final List<AbstractOperation> operations = forceGetOperations();
		assertEquals(NEW_NAME, useCase.getName());
		assertEquals(FINAL_DESC, useCase.getDescription());
		assertEquals(HOME, section.getName());
		assertEquals(MAGGIE, actor.getName());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				for (int i = operations.size() - 1; i >= 0; i--) {
					final AbstractOperation reverse = operations.get(i).reverse();
					reverse.apply(getProject());
				}
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));
	}

	/**
	 * Test the creation and completion of a composite operation, that contains attribute changes.
	 *
	 * @throws InvalidHandleException if the test fails
	 * @throws IOException
	 */
	@Test
	public void compositeAttributeChangesACA() throws InvalidHandleException, IOException {

		final TestElement section = Create.testElement();
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(section);
				section.setName(NAME);
				section.setDescription(OLD_DESCRIPTION);
			}
		}.run(false);

		final Project expectedProject = ModelUtil.clone(getProject());
		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				clearOperations();

				section.setDescription(DESC_1);

				final CompositeOperationHandle handle = getProjectSpace().beginCompositeOperation();
				section.setDescription(NEW_DESCRIPTION);
				final TestElement useCase = Create.testElement();
				section.getContainedElements().add(useCase);
				try {
					handle.end(SECTION_CREATION, DESCRIPTION2,
						ModelUtil.getProject(section).getModelElementId(section));
				} catch (final InvalidHandleException e) {
					fail();
				}
				section.setDescription(DESC_2);
			}
		}.run(false);

		final List<AbstractOperation> operations = forceGetOperations();
		assertEquals(DESC_2, section.getDescription());
		assertEquals(3, operations.size());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				for (int i = operations.size() - 1; i >= 0; i--) {
					final AbstractOperation reverse = operations.get(i).reverse();
					reverse.apply(getProject());
				}
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));
	}

	/**
	 * Test the creation and completion of a composite operation, that contains attribute changes.
	 *
	 * @throws InvalidHandleException if the test fails
	 * @throws IOException
	 */
	@Test
	public void compositeAttributeChangesAC() throws InvalidHandleException, IOException {

		final TestElement section = Create.testElement();

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(section);
				section.setName(NAME);
				section.setDescription(OLD_DESCRIPTION);
			}
		}.run(false);

		final Project expectedProject = ModelUtil.clone(getProject());
		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				clearOperations();

				section.setDescription(DESC_1);

				final CompositeOperationHandle handle = getProjectSpace().beginCompositeOperation();
				section.setDescription(NEW_DESCRIPTION);
				final TestElement useCase = Create.testElement();
				section.getContainedElements().add(useCase);
				try {
					handle.end(SECTION_CREATION, DESCRIPTION2,
						ModelUtil.getProject(section).getModelElementId(section));
				} catch (final InvalidHandleException e) {
					fail();
				}
			}
		}.run(false);

		final List<AbstractOperation> operations = forceGetOperations();
		assertEquals(2, operations.size());
		assertEquals(NEW_DESCRIPTION, section.getDescription());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				for (int i = operations.size() - 1; i >= 0; i--) {
					final AbstractOperation reverse = operations.get(i).reverse();
					reverse.apply(getProject());
				}
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));
	}

	/**
	 * Test the creation and completion of a composite operation, that contains attribute changes.
	 *
	 * @throws InvalidHandleException if the test fails
	 * @throws IOException
	 */
	@Test
	public void compositeAttributeChangesCA() throws InvalidHandleException, IOException {

		final TestElement section = Create.testElement();
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(section);
				section.setName(NAME);
				section.setDescription(OLD_DESCRIPTION);
			}
		}.run(false);

		final Project expectedProject = ModelUtil.clone(getProject());
		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				clearOperations();

				final CompositeOperationHandle handle = getProjectSpace().beginCompositeOperation();
				section.setDescription(NEW_DESCRIPTION);
				final TestElement useCase = Create.testElement();
				section.getContainedElements().add(useCase);
				try {
					handle.end(SECTION_CREATION, DESCRIPTION2,
						ModelUtil.getProject(section).getModelElementId(section));
				} catch (final InvalidHandleException e) {
					fail();
				}

				section.setDescription(DESC_2);
			}
		}.run(false);

		final List<AbstractOperation> operations = forceGetOperations();
		assertEquals(2, operations.size());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				for (int i = operations.size() - 1; i >= 0; i--) {
					final AbstractOperation reverse = operations.get(i).reverse();
					reverse.apply(getProject());
				}
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));
	}

	/**
	 * Tests canonization for create and consecutive attribute changes.
	 *
	 * @throws IOException
	 */
	@Test
	public void createAndChangeAttributesSimple() throws IOException {

		final Project originalProject = ModelUtil.clone(getProject());

		final TestElement useCase = Create.testElement();
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(useCase);
				useCase.setName(NAME_OF_TEST_ELEMENT);
				useCase.setDescription(DESCRIPTION_OF_TEST_ELEMENT);
			}
		}.run(false);

		assertEquals(NAME_OF_TEST_ELEMENT, useCase.getName());

		final List<AbstractOperation> operations = forceGetOperations();
		// expecting a create and two attribute operations
		assertEquals(3, operations.size());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		// now expecting only the create with folded in attributes
		assertEquals(operations.size(), 1);
		assertTrue(operations.get(0) instanceof CreateDeleteOperation);

		final CreateDeleteOperation op = (CreateDeleteOperation) operations.get(0);

		assertEquals(((TestElement) op.getModelElement()).getName(), NAME_OF_TEST_ELEMENT);
		assertEquals(((TestElement) op.getModelElement()).getDescription(), DESCRIPTION_OF_TEST_ELEMENT);

		// test if the create is reversible and re-reversible
		final Project expectedProject = ModelUtil.clone(getProject());
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				op.reverse().apply(getProject());
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), originalProject));

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				op.reverse().reverse().apply(getProject());
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));
	}

	/**
	 * Tests canonization for create and consecutive attribute changes.
	 *
	 * @throws IOException
	 */
	@Test
	public void createAndChangeAttributesComplex() throws IOException {

		final Project originalProject = ModelUtil.clone(getProject());

		final TestElement useCase = Create.testElement();
		final TestElement useCase2 = Create.testElement();

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(useCase);
				getProject().addModelElement(useCase2);

				useCase.setName(NAME_OF_TEST_ELEMENT);
				useCase.setDescription(DESCRIPTION_OF_TEST_ELEMENT);

				useCase2.setName(NAME_OF_TEST_ELEMENT2);
				useCase2.setDescription(DESCRIPTION_OF_TEST_ELEMENT2);
			}
		}.run(false);

		assertEquals(NAME_OF_TEST_ELEMENT, useCase.getName());
		assertEquals(NAME_OF_TEST_ELEMENT2, useCase2.getName());
		final List<AbstractOperation> operations = forceGetOperations();
		// expecting a create and two attribute operations per usecase
		assertEquals(6, operations.size());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		// now expecting only the creates with folded in attributes
		assertEquals(2, operations.size());
		assertTrue(operations.get(0) instanceof CreateDeleteOperation);

		final CreateDeleteOperation op = (CreateDeleteOperation) operations.get(0);

		assertEquals(((TestElement) op.getModelElement()).getName(), NAME_OF_TEST_ELEMENT);
		assertEquals(((TestElement) op.getModelElement()).getDescription(), DESCRIPTION_OF_TEST_ELEMENT);

		assertTrue(operations.get(1) instanceof CreateDeleteOperation);

		final CreateDeleteOperation op2 = (CreateDeleteOperation) operations.get(1);

		assertEquals(((TestElement) op2.getModelElement()).getName(), NAME_OF_TEST_ELEMENT2);
		assertEquals(((TestElement) op2.getModelElement()).getDescription(), DESCRIPTION_OF_TEST_ELEMENT2);

		// test reversibility, too

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				op2.reverse().apply(getProject());
				op.reverse().apply(getProject());
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), originalProject));
	}

	/**
	 * Test the creation and completion of a composite operation, that contains attribute changes.
	 *
	 * @throws InvalidHandleException if the test fails
	 * @throws IOException
	 */
	@Test
	public void createAndAttributeChangesACA() throws InvalidHandleException, IOException {

		final Project originalProject = ModelUtil.clone(getProject());

		final TestElement section = Create.testElement();

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(section);
				section.setName(NAME);
				section.setDescription(OLD_DESCRIPTION);

				final CompositeOperationHandle handle = getProjectSpace().beginCompositeOperation();
				section.setDescription(NEW_DESCRIPTION);
				final TestElement useCase = Create.testElement();
				section.getContainedElements().add(useCase);
				try {
					handle.end(SECTION_CREATION, DESCRIPTION2,
						ModelUtil.getProject(section).getModelElementId(section));
				} catch (final InvalidHandleException e) {
					fail();
				}

				section.setDescription(DESC_2);
			}
		}.run(false);

		final List<AbstractOperation> operations = forceGetOperations();

		// expect create, 2 attribute ops, the composite, 1 attribute op
		assertEquals(5, operations.size());
		assertTrue(operations.get(0) instanceof CreateDeleteOperation);
		assertTrue(operations.get(1) instanceof AttributeOperation);
		assertTrue(operations.get(2) instanceof AttributeOperation);
		assertTrue(operations.get(3) instanceof CompositeOperation);
		assertTrue(operations.get(4) instanceof AttributeOperation);

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		// expect create, the composite and 1 attribute op
		assertEquals(3, operations.size());
		assertTrue(operations.get(0) instanceof CreateDeleteOperation);
		assertTrue(operations.get(1) instanceof CompositeOperation);
		assertTrue(operations.get(2) instanceof AttributeOperation);

		final Project expectedProject = ModelUtil.clone(getProject());

		// test reversibility

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				for (int i = operations.size() - 1; i >= 0; i--) {
					final AbstractOperation reverse = operations.get(i).reverse();
					reverse.apply(getProject());
				}
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), originalProject));

		// test redo
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				operations.get(0).apply(getProject());
				operations.get(1).apply(getProject());
				operations.get(2).apply(getProject());
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));
	}

	/**
	 * Tests canonization for consecutive attribute changes followed by a delete.
	 *
	 * @throws IOException
	 */
	@Test
	public void changeAttributesAndDeleteSimple() throws IOException {

		final TestElement useCase = Create.testElement();
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(useCase);
				useCase.setName(ORIGINAL_NAME);
				useCase.setDescription(ORIGINAL_DESCRIPTION);
			}
		}.run(false);
		clearOperations();

		assertTrue(getProjectSpace().getLocalChangePackage().isEmpty());
		assertTrue(forceGetOperations().isEmpty());
		final Project originalProject = ModelUtil.clone(getProject());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				useCase.setName(NAME_OF_TEST_ELEMENT);
				useCase.setDescription(DESCRIPTION_OF_TEST_ELEMENT);
				getProject().deleteModelElement(useCase);
			}
		}.run(false);

		final List<AbstractOperation> operations = forceGetOperations();

		// expecting two attribute operations and a delete
		assertEquals(3, operations.size());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		// now expecting only the delete with folded in attributes
		assertEquals(1, operations.size());
		assertTrue(operations.get(0) instanceof CreateDeleteOperation);

		final CreateDeleteOperation op = (CreateDeleteOperation) operations.get(0);

		assertTrue(op.isDelete());
		assertEquals(((TestElement) op.getModelElement()).getName(), ORIGINAL_NAME);
		assertEquals(((TestElement) op.getModelElement()).getDescription(), ORIGINAL_DESCRIPTION);

		// test if the delete is reversible and re-reversible
		final Project expectedProject = ModelUtil.clone(getProject());
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				op.reverse().apply(getProject());
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), originalProject));

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				op.reverse().reverse().apply(getProject());
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));
	}

	/**
	 * Tests canonization for consecutive attribute changes and delete.
	 *
	 * @throws IOException
	 */
	@Test
	public void changeAttributesAndDeleteComplex() throws IOException {

		final TestElement useCase = Create.testElement();
		final TestElement useCase2 = Create.testElement();
		final TestElement section = Create.testElement();

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(section);
				section.getContainedElements().add(useCase);
				section.getContainedElements().add(useCase2);

				useCase.setName(ORIGINAL_NAME1);
				useCase.setDescription(ORIGINAL_DESCRIPTION1);

				useCase2.setName(ORIGINAL_NAME2);
				useCase2.setDescription(ORIGINAL_DESCRIPTION2);
			}
		}.run(false);
		clearOperations();

		final Project originalProject = ModelUtil.clone(getProject());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {

				useCase.setName(NAME_OF_TEST_ELEMENT);
				useCase.setDescription(DESCRIPTION_OF_TEST_ELEMENT);

				useCase2.setName(NAME_OF_TEST_ELEMENT2);
				useCase2.setDescription(DESCRIPTION_OF_TEST_ELEMENT2);

				assertEquals(NAME_OF_TEST_ELEMENT, useCase.getName());
				assertEquals(NAME_OF_TEST_ELEMENT2, useCase2.getName());

				getProject().deleteModelElement(useCase);
			}
		}.run(false);

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().deleteModelElement(useCase2);
			}
		}.run(false);

		final List<AbstractOperation> operations = forceGetOperations();

		// expecting two attribute operations and a delete per usecase
		assertEquals(6, operations.size());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		// now expecting only the deletes with folded in attributes
		assertEquals(2, operations.size());
		assertTrue(operations.get(0) instanceof CreateDeleteOperation);

		final CreateDeleteOperation op = (CreateDeleteOperation) operations.get(0);

		assertEquals(ORIGINAL_NAME1, ((TestElement) op.getModelElement()).getName());
		assertEquals(ORIGINAL_DESCRIPTION1, ((TestElement) op.getModelElement()).getDescription());

		assertTrue(operations.get(1) instanceof CreateDeleteOperation);

		final CreateDeleteOperation op2 = (CreateDeleteOperation) operations.get(1);

		assertEquals(((TestElement) op2.getModelElement()).getName(), ORIGINAL_NAME2);
		assertEquals(((TestElement) op2.getModelElement()).getDescription(), ORIGINAL_DESCRIPTION2);

		// test reversibility, too
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				op2.reverse().apply(getProject());
				op.reverse().apply(getProject());
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), originalProject));
	}

	/**
	 * Tests canonization for consecutive attribute changes and delete on orphans.
	 */
	// commented out, orphan behaviour is irrelevant at present. This reversibility test currently fails.
	// @Test
	// public void changeAttributesAndDeleteOrphansComplex() {
	//
	// TestElement useCase = Create.testElement();
	// TestElement useCase2 = Create.testElement();
	//
	// getProject().getModelElements().add(useCase);
	// getProject().getModelElements().add(useCase2);
	//
	// useCase.setName("originalName1");
	// useCase.setDescription("originalDescription1");
	//
	// useCase2.setName("originalName2");
	// useCase2.setDescription("originalDescription2");
	//
	// Project originalProject = ModelUtil.clone(getProject());
	//
	// clearOperations();
	//
	// useCase.setName("NameOfTestElement");
	// useCase.setDescription("DescriptionOfTestElement");
	//
	// useCase2.setName("NameOfTestElement2");
	// useCase2.setDescription("DescriptionOfTestElement2");
	//
	// assertEquals("NameOfTestElement", useCase.getName());
	// assertEquals("NameOfTestElement2", useCase2.getName());
	//
	// getProject().deleteModelElement(useCase);
	// getProject().deleteModelElement(useCase2);
	//
	// List<AbstractOperation> operations = forceGetOperations();
	//
	// // expecting two attribute operations and a delete per usecase
	// assertEquals(operations.size(), 6);
	// OperationsCanonizer.canonize(operations);
	//
	// // now expecting only the deletes with folded in attributes
	// assertEquals(operations.size(), 2);
	// assertTrue(operations.get(0) instanceof CreateDeleteOperation);
	//
	// CreateDeleteOperation op = (CreateDeleteOperation) operations.get(0);
	//
	// assertEquals(op.getModelElement().getName(), "originalName1");
	// assertEquals(op.getModelElement().getDescription(), "originalDescription1");
	//
	// assertTrue(operations.get(1) instanceof CreateDeleteOperation);
	//
	// CreateDeleteOperation op2 = (CreateDeleteOperation) operations.get(1);
	//
	// assertEquals(op2.getModelElement().getName(), "originalName2");
	// assertEquals(op2.getModelElement().getDescription(), "originalDescription2");
	//
	// // test reversibility, too
	//
	// op2.reverse().apply(getProject());
	// op.reverse().apply(getProject());
	//
	// assertTrue(ModelUtil.areEqual(getProject(), originalProject));
	//
	// }
	/**
	 * Test the creation and completion of a composite operation, that contains attribute changes.
	 *
	 * @throws InvalidHandleException if the test fails
	 * @throws IOException
	 */
	// BEGIN COMPLEX CODE
	@Test
	public void attributeChangesACAAndDelete() throws InvalidHandleException, IOException {

		final TestElement section = Create.testElement();
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(section);
				section.setName(ORIGINAL_NAME);
				section.setDescription(ORIGINAL_DESCRIPTION);
			}
		}.run(false);

		final Project originalProject = ModelUtil.clone(getProject());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				clearOperations();
				section.setName(SOME_NEW_NAME);

				final CompositeOperationHandle handle = getProjectSpace().beginCompositeOperation();
				section.setDescription(NEW_DESCRIPTION);
				final TestElement useCase = Create.testElement();
				section.getContainedElements().add(useCase);
				try {
					handle.end(SECTION_CREATION, DESCRIPTION2,
						ModelUtil.getProject(section).getModelElementId(section));
				} catch (final InvalidHandleException e) {
					fail();
				}

				section.setDescription(DESC_2);

				getProject().deleteModelElement(section);
			}
		}.run(false);

		final List<AbstractOperation> operations = forceGetOperations();

		// expect 1 attribute op, the composite, 1 attribute op, the delete
		assertEquals(4, operations.size());
		assertTrue(operations.get(0) instanceof AttributeOperation);
		assertTrue(operations.get(1) instanceof CompositeOperation);
		assertTrue(operations.get(2) instanceof AttributeOperation);
		assertTrue(operations.get(3) instanceof CreateDeleteOperation);

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		// expect 1 attribute op, the composite and the delete with folded in attribute
		assertEquals(3, operations.size());
		assertTrue(operations.get(0) instanceof AttributeOperation);
		assertTrue(operations.get(1) instanceof CompositeOperation);
		assertTrue(operations.get(2) instanceof CreateDeleteOperation);

		final CreateDeleteOperation delOp = (CreateDeleteOperation) operations.get(2);
		assertTrue(delOp.isDelete());
		// not folded, interfering composite was inbeetween
		assertEquals(SOME_NEW_NAME, ((TestElement) delOp.getModelElement()).getName());
		// folded, value is oldValue from "newDescription"-> "desc 2"
		assertEquals(NEW_DESCRIPTION, ((TestElement) delOp.getModelElement()).getDescription());

		final Project expectedProject = ModelUtil.clone(getProject());

		// test reversibility

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				for (int i = operations.size() - 1; i >= 0; i--) {
					final AbstractOperation reverse = operations.get(i).reverse();
					reverse.apply(getProject());
				}
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), originalProject));

		// test redo
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				operations.get(0).apply(getProject());
				operations.get(1).apply(getProject());
				operations.get(2).apply(getProject());
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), expectedProject));
	}

	// END COMPLEX CODE

	/**
	 * Tests canonization for create, attribute changes and delete.
	 *
	 * @throws IOException
	 */
	@Test
	public void createChangeAttributeAndDelete() throws IOException {

		final Project originalProject = ModelUtil.clone(getProject());

		final TestElement useCase = Create.testElement();

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(useCase);
				useCase.setName(SOME_NAME);
				useCase.setName(NEW_NAME);
				getProject().deleteModelElement(useCase);
			}
		}.run(false);

		final List<AbstractOperation> operations = forceGetOperations();
		// expect create, 2 attribute ops, delete
		assertEquals(4, operations.size());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				OperationsCanonizer.canonize(operations);
			}
		}.run(false);

		// expect attributes folding into create, and create and delete removed,
		// as they would be directly adjacent to each other
		assertEquals(operations.size(), 0);
		assertTrue(ModelUtil.areEqual(getProject(), originalProject));
	}

	/**
	 * Tests canonization for create, attribute changes and delete.
	 *
	 * @throws IOException
	 */
	@Test
	public void createChangeReferencesAndDelete() throws IOException {

		final TestElement useCase2 = Create.testElement();

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				getProject().addModelElement(useCase2);
			}
		}.run(false);

		final Project originalProject = ModelUtil.clone(getProject());

		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				clearOperations();

				final TestElement useCase = Create.testElement();
				getProject().addModelElement(useCase);
				useCase.setName(SOME_NAME);
				useCase.getReferences().add(useCase2);
				getProject().deleteModelElement(useCase);
			}
		}.run(false);

		final List<AbstractOperation> operations = forceGetOperations();
		// expect create, 1 attribute ops, 1 multiref op, the delete
		assertEquals(4, operations.size());

		canonize(operations);

		// expect attributes folding into create, the multiref and delete remain
		assertEquals(operations.size(), 3);
		assertTrue(operations.get(0) instanceof CreateDeleteOperation);
		assertTrue(operations.get(1) instanceof MultiReferenceOperation);
		assertTrue(operations.get(2) instanceof CreateDeleteOperation);

		// check the folding of the attribute
		final CreateDeleteOperation createOp = (CreateDeleteOperation) operations.get(0);
		assertEquals(SOME_NAME, ((TestElement) createOp.getModelElement()).getName());

		// check reversibility
		new EMFStoreCommand() {
			@Override
			protected void doRun() {
				operations.get(2).reverse().apply(getProject());
				operations.get(1).reverse().apply(getProject());
				operations.get(0).reverse().apply(getProject());
			}
		}.run(false);

		assertTrue(ModelUtil.areEqual(getProject(), originalProject));
	}

}
