/** * <copyright> Copyright (c) 2008-2009 Jonas Helming, Maximilian Koegel. 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 </copyright> */ package org.eclipse.emf.emfstore.client.test.changeTracking.operations; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.List; import java.util.Set; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.emfstore.client.model.exceptions.UnsupportedNotificationException; import org.eclipse.emf.emfstore.client.model.util.EMFStoreCommand; import org.eclipse.emf.emfstore.client.test.WorkspaceTest; import org.eclipse.emf.emfstore.client.test.model.document.DocumentFactory; import org.eclipse.emf.emfstore.client.test.model.document.LeafSection; import org.eclipse.emf.emfstore.client.test.model.rationale.Issue; import org.eclipse.emf.emfstore.client.test.model.rationale.Proposal; import org.eclipse.emf.emfstore.client.test.model.rationale.RationaleFactory; import org.eclipse.emf.emfstore.client.test.model.rationale.RationalePackage; import org.eclipse.emf.emfstore.client.test.model.requirement.Actor; import org.eclipse.emf.emfstore.client.test.model.requirement.RequirementFactory; import org.eclipse.emf.emfstore.client.test.model.requirement.UseCase; import org.eclipse.emf.emfstore.common.model.ModelElementId; import org.eclipse.emf.emfstore.common.model.util.ModelUtil; import org.eclipse.emf.emfstore.server.model.versioning.operations.AbstractOperation; import org.eclipse.emf.emfstore.server.model.versioning.operations.CompositeOperation; import org.eclipse.emf.emfstore.server.model.versioning.operations.CreateDeleteOperation; import org.eclipse.emf.emfstore.server.model.versioning.operations.MultiReferenceOperation; import org.eclipse.emf.emfstore.server.model.versioning.operations.ReferenceOperation; import org.eclipse.emf.emfstore.server.model.versioning.operations.SingleReferenceOperation; import org.eclipse.emf.emfstore.server.model.versioning.operations.impl.MultiReferenceOperationImpl; import org.junit.Test; /** * Tests the SingleReferenceOperation. * * @author koegel */ public class SingleReferenceOperationTest extends WorkspaceTest { private EObject expectedProject; /** * Change a single reference and check the generated operation. * * @throws UnsupportedOperationException on test fail * @throws UnsupportedNotificationException on test fail */ @Test public void changeSingleReference() throws UnsupportedOperationException, UnsupportedNotificationException { final UseCase useCase = RequirementFactory.eINSTANCE.createUseCase(); final Actor actor = RequirementFactory.eINSTANCE.createActor(); new EMFStoreCommand() { @Override protected void doRun() { getProject().addModelElement(useCase); getProject().addModelElement(actor); clearOperations(); useCase.setInitiatingActor(actor); assertEquals(actor, useCase.getInitiatingActor()); EList<UseCase> initiatedUseCases = actor.getInitiatedUseCases(); assertEquals(1, initiatedUseCases.size()); assertEquals(useCase, initiatedUseCases.get(0)); } }.run(false); List<AbstractOperation> operations = getProjectSpace().getOperations(); assertEquals(1, operations.size()); AbstractOperation operation = operations.get(0); assertEquals(true, operation instanceof CompositeOperation); EList<AbstractOperation> subOperations = ((CompositeOperation) operation).getSubOperations(); assertEquals(2, subOperations.size()); operation = subOperations.get(0); assertEquals(true, operation instanceof MultiReferenceOperationImpl); MultiReferenceOperation multiReferenceOperation = (MultiReferenceOperation) operation; assertEquals("initiatedUseCases", multiReferenceOperation.getFeatureName()); assertEquals("initiatingActor", multiReferenceOperation.getOppositeFeatureName()); ModelElementId useCaseId = ModelUtil.getProject(useCase).getModelElementId(useCase); ModelElementId actorId = ModelUtil.getProject(actor).getModelElementId(actor); assertEquals(useCaseId, multiReferenceOperation.getReferencedModelElements().get(0)); assertEquals(actorId, multiReferenceOperation.getModelElementId()); assertTrue(multiReferenceOperation.isBidirectional()); assertTrue(multiReferenceOperation.isAdd()); assertEquals(1, multiReferenceOperation.getOtherInvolvedModelElements().size()); operation = subOperations.get(1); assertEquals(true, operation instanceof SingleReferenceOperation); SingleReferenceOperation singleReferenceOperation = (SingleReferenceOperation) operation; assertEquals(null, singleReferenceOperation.getOldValue()); assertEquals(actorId, singleReferenceOperation.getNewValue()); assertEquals("initiatingActor", singleReferenceOperation.getFeatureName()); assertEquals(useCaseId, singleReferenceOperation.getModelElementId()); assertEquals("initiatedUseCases", singleReferenceOperation.getOppositeFeatureName()); assertEquals(true, singleReferenceOperation.isBidirectional()); Set<ModelElementId> otherInvolvedModelElements = singleReferenceOperation.getOtherInvolvedModelElements(); assertEquals(1, otherInvolvedModelElements.size()); assertEquals(actorId, otherInvolvedModelElements.iterator().next()); } /** * Change an single reference twice and check the generated operation. * * @throws UnsupportedOperationException on test fail * @throws UnsupportedNotificationException on test fail */ // commented out, single reference operations are not canonized at present // @Test // public void changeSingleReferenceTwice() throws UnsupportedOperationException, UnsupportedNotificationException { // UseCase useCase = RequirementFactory.eINSTANCE.createUseCase(); // getProject().addModelElement(useCase); // Actor oldActor = RequirementFactory.eINSTANCE.createActor(); // getProject().addModelElement(oldActor); // Actor newActor = RequirementFactory.eINSTANCE.createActor(); // getProject().addModelElement(newActor); // // clearOperations(); // // useCase.setInitiatingActor(oldActor); // assertEquals(oldActor, useCase.getInitiatingActor()); // EList<UseCase> initiatedUseCases = oldActor.getInitiatedUseCases(); // assertEquals(1, initiatedUseCases.size()); // assertEquals(useCase, initiatedUseCases.get(0)); // // useCase.setInitiatingActor(newActor); // assertEquals(newActor, useCase.getInitiatingActor()); // initiatedUseCases = newActor.getInitiatedUseCases(); // assertEquals(1, initiatedUseCases.size()); // assertEquals(useCase, initiatedUseCases.get(0)); // // List<AbstractOperation> operations = getProjectSpace().getOperations(); // // assertEquals(1, operations.size()); // AbstractOperation operation = operations.get(0); // assertEquals(true, operation instanceof SingleReferenceOperation); // SingleReferenceOperation singleReferenceOperation = (SingleReferenceOperation) operation; // // assertEquals(null, singleReferenceOperation.getOldValue()); // assertEquals(newActor.getModelElementId(), singleReferenceOperation.getNewValue()); // assertEquals("initiatingActor", singleReferenceOperation.getFeatureName()); // assertEquals(useCase.getModelElementId(), singleReferenceOperation.getModelElementId()); // assertEquals("initiatedUseCases", singleReferenceOperation.getOppositeFeatureName()); // assertEquals(true, singleReferenceOperation.isBidirectional()); // Set<ModelElementId> otherInvolvedModelElements = singleReferenceOperation.getOtherInvolvedModelElements(); // assertEquals(1, otherInvolvedModelElements.size()); // assertEquals(newActor.getModelElementId(), otherInvolvedModelElements.iterator().next()); // } /** * Change an single reference and reverse it. * * @throws UnsupportedOperationException on test fail * @throws UnsupportedNotificationException on test fail */ @Test public void reverseSingleReference() throws UnsupportedOperationException, UnsupportedNotificationException { final UseCase useCase = RequirementFactory.eINSTANCE.createUseCase(); final Actor oldActor = RequirementFactory.eINSTANCE.createActor(); final Actor newActor = RequirementFactory.eINSTANCE.createActor(); new EMFStoreCommand() { @Override protected void doRun() { getProject().addModelElement(useCase); getProject().addModelElement(oldActor); getProject().addModelElement(newActor); useCase.setInitiatingActor(oldActor); assertEquals(oldActor, useCase.getInitiatingActor()); EList<UseCase> initiatedUseCases = oldActor.getInitiatedUseCases(); assertEquals(1, initiatedUseCases.size()); assertEquals(useCase, initiatedUseCases.get(0)); clearOperations(); useCase.setInitiatingActor(newActor); assertEquals(newActor, useCase.getInitiatingActor()); initiatedUseCases = newActor.getInitiatedUseCases(); assertEquals(1, initiatedUseCases.size()); assertEquals(useCase, initiatedUseCases.get(0)); } }.run(false); List<AbstractOperation> operations = getProjectSpace().getOperations(); assertEquals(1, operations.size()); assertEquals(1, operations.size()); if (operations.get(0) instanceof CompositeOperation) { operations = ((CompositeOperation) operations.get(0)).getSubOperations(); } else { fail("composite operation expected"); } assertEquals(3, operations.size()); // note: skipping multireferenceop at index 0 in test, as it is not interesting in this context AbstractOperation operation = operations.get(2); assertEquals(true, operation instanceof SingleReferenceOperation); SingleReferenceOperation singleReferenceOperation = (SingleReferenceOperation) operation; ModelElementId useCaseId = ModelUtil.getProject(useCase).getModelElementId(useCase); ModelElementId oldActorId = ModelUtil.getProject(oldActor).getModelElementId(oldActor); ModelElementId newActorId = ModelUtil.getProject(newActor).getModelElementId(newActor); assertEquals(oldActorId, singleReferenceOperation.getOldValue()); assertEquals(newActorId, singleReferenceOperation.getNewValue()); assertEquals("initiatingActor", singleReferenceOperation.getFeatureName()); assertEquals(useCaseId, singleReferenceOperation.getModelElementId()); assertEquals("initiatedUseCases", singleReferenceOperation.getOppositeFeatureName()); assertEquals(true, singleReferenceOperation.isBidirectional()); Set<ModelElementId> otherInvolvedModelElements = singleReferenceOperation.getOtherInvolvedModelElements(); assertEquals(2, otherInvolvedModelElements.size()); assertEquals(true, otherInvolvedModelElements.contains(oldActorId)); assertEquals(true, otherInvolvedModelElements.contains(newActorId)); AbstractOperation reverse = singleReferenceOperation.reverse(); assertEquals(true, reverse instanceof SingleReferenceOperation); final SingleReferenceOperation reversedSingleReferenceOperation = (SingleReferenceOperation) reverse; new EMFStoreCommand() { @Override protected void doRun() { reversedSingleReferenceOperation.apply(getProject()); } }.run(false); assertEquals(oldActor, useCase.getInitiatingActor()); assertEquals(newActorId, reversedSingleReferenceOperation.getOldValue()); assertEquals(oldActorId, reversedSingleReferenceOperation.getNewValue()); assertEquals("initiatingActor", reversedSingleReferenceOperation.getFeatureName()); assertEquals(useCaseId, reversedSingleReferenceOperation.getModelElementId()); assertEquals("initiatedUseCases", reversedSingleReferenceOperation.getOppositeFeatureName()); assertEquals(true, reversedSingleReferenceOperation.isBidirectional()); otherInvolvedModelElements = reversedSingleReferenceOperation.getOtherInvolvedModelElements(); assertEquals(2, otherInvolvedModelElements.size()); assertEquals(true, otherInvolvedModelElements.contains(oldActorId)); assertEquals(true, otherInvolvedModelElements.contains(newActorId)); } /** * Tests reversibility of 1:n single reference feature. */ @Test public void containmentSingleReferenceReversibilityTest() { final UseCase useCase = RequirementFactory.eINSTANCE.createUseCase(); final Actor actor = RequirementFactory.eINSTANCE.createActor(); final LeafSection section = DocumentFactory.eINSTANCE.createLeafSection(); final LeafSection oldSection = DocumentFactory.eINSTANCE.createLeafSection(); new EMFStoreCommand() { @Override protected void doRun() { getProject().addModelElement(useCase); getProject().addModelElement(actor); getProject().addModelElement(section); getProject().addModelElement(oldSection); useCase.setLeafSection(oldSection); actor.setLeafSection(oldSection); expectedProject = ModelUtil.clone(getProject()); assertTrue(ModelUtil.areEqual(getProject(), expectedProject)); clearOperations(); useCase.setLeafSection(section); } }.run(false); final List<AbstractOperation> operations = getProjectSpace().getOperations(); // composite operation containing a multiref operation and a singleref operation expected assertEquals(operations.size(), 1); new EMFStoreCommand() { @Override protected void doRun() { AbstractOperation reverse = operations.get(0).reverse(); reverse.apply(getProject()); } }.run(false); assertTrue(ModelUtil.areEqual(getProject(), expectedProject)); } /** * Move a containee to another container. * * @throws UnsupportedOperationException on test fail * @throws UnsupportedNotificationException on test fail */ @Test public void moveContainmentReference() throws UnsupportedOperationException, UnsupportedNotificationException { final Issue oldIssue = RationaleFactory.eINSTANCE.createIssue(); final Issue newIssue = RationaleFactory.eINSTANCE.createIssue(); final Proposal proposal = RationaleFactory.eINSTANCE.createProposal(); new EMFStoreCommand() { @Override protected void doRun() { getProject().addModelElement(oldIssue); getProject().addModelElement(newIssue); getProject().addModelElement(proposal); proposal.setIssue(oldIssue); clearOperations(); assertEquals(0, newIssue.getProposals().size()); assertEquals(1, oldIssue.getProposals().size()); assertEquals(proposal, oldIssue.getProposals().get(0)); assertEquals(oldIssue, proposal.getIssue()); proposal.setIssue(newIssue); assertEquals(0, oldIssue.getProposals().size()); assertEquals(1, newIssue.getProposals().size()); assertEquals(proposal, newIssue.getProposals().get(0)); assertEquals(newIssue, proposal.getIssue()); } }.run(false); List<AbstractOperation> operations = getProjectSpace().getOperations(); assertEquals(1, operations.size()); if (operations.get(0) instanceof CompositeOperation) { operations = ((CompositeOperation) operations.get(0)).getSubOperations(); } else { fail("composite operation expected"); } assertEquals(3, operations.size()); AbstractOperation op0 = operations.get(0); assertTrue(op0 instanceof MultiReferenceOperation); MultiReferenceOperation multiReferenceOperation = (MultiReferenceOperation) op0; ModelElementId oldIssueId = ModelUtil.getProject(oldIssue).getModelElementId(oldIssue); ModelElementId proposalId = ModelUtil.getProject(proposal).getModelElementId(proposal); ModelElementId newIssueId = ModelUtil.getProject(newIssue).getModelElementId(newIssue); assertEquals(multiReferenceOperation.getModelElementId(), oldIssueId); assertFalse(multiReferenceOperation.isAdd()); assertEquals(multiReferenceOperation.getReferencedModelElements().get(0), proposalId); assertEquals(multiReferenceOperation.getReferencedModelElements().size(), 1); assertEquals(multiReferenceOperation.getIndex(), 0); AbstractOperation op1 = operations.get(1); assertTrue(op1 instanceof MultiReferenceOperation); multiReferenceOperation = (MultiReferenceOperation) op1; assertEquals(multiReferenceOperation.getModelElementId(), newIssueId); assertTrue(multiReferenceOperation.isAdd()); assertEquals(multiReferenceOperation.getReferencedModelElements().get(0), proposalId); assertEquals(multiReferenceOperation.getReferencedModelElements().size(), 1); assertEquals(multiReferenceOperation.getIndex(), 0); AbstractOperation operation = operations.get(2); assertEquals(true, operation instanceof SingleReferenceOperation); SingleReferenceOperation singleReferenceOperation = (SingleReferenceOperation) operation; assertEquals(oldIssueId, singleReferenceOperation.getOldValue()); assertEquals(newIssueId, singleReferenceOperation.getNewValue()); assertEquals(RationalePackage.eINSTANCE.getProposal_Issue().getName(), singleReferenceOperation.getFeatureName()); assertEquals(proposalId, singleReferenceOperation.getModelElementId()); assertEquals(RationalePackage.eINSTANCE.getIssue_Proposals().getName(), singleReferenceOperation.getOppositeFeatureName()); assertEquals(true, singleReferenceOperation.isBidirectional()); Set<ModelElementId> otherInvolvedModelElements = singleReferenceOperation.getOtherInvolvedModelElements(); assertEquals(2, otherInvolvedModelElements.size()); assertEquals(true, otherInvolvedModelElements.contains(newIssueId)); assertEquals(true, otherInvolvedModelElements.contains(oldIssueId)); } /** * Test containment removing. * * @throws UnsupportedOperationException on test fail */ @Test public void removeContainment() throws UnsupportedOperationException { final Issue issue = RationaleFactory.eINSTANCE.createIssue(); final Proposal proposal = RationaleFactory.eINSTANCE.createProposal(); new EMFStoreCommand() { @Override protected void doRun() { proposal.setName("proposal"); getProject().addModelElement(issue); getProject().addModelElement(proposal); proposal.setIssue(issue); clearOperations(); assertEquals(1, issue.getProposals().size()); assertEquals(proposal, issue.getProposals().get(0)); assertEquals(issue, proposal.getIssue()); assertEquals(true, getProject().containsInstance(issue)); assertEquals(true, getProject().containsInstance(proposal)); assertEquals(getProject(), ModelUtil.getProject(issue)); assertEquals(getProject(), ModelUtil.getProject(proposal)); assertEquals(issue, proposal.eContainer()); } }.run(false); ModelElementId proposalId = ModelUtil.getProject(proposal).getModelElementId(proposal); new EMFStoreCommand() { @Override protected void doRun() { proposal.setIssue(null); } }.run(false); assertEquals(true, getProject().containsInstance(issue)); assertEquals(false, getProject().containsInstance(proposal)); assertEquals(getProject(), ModelUtil.getProject(issue)); // assertEquals(null, ModelUtil.getProject(proposal)); assertEquals(0, issue.getProposals().size()); assertEquals(null, proposal.getIssue()); // assertEquals(null, proposal.eContainer()); List<AbstractOperation> operations = getProjectSpace().getOperations(); assertEquals(1, operations.size()); ModelElementId issueId = ModelUtil.getProject(issue).getModelElementId(issue); assertEquals(true, operations.get(0) instanceof CreateDeleteOperation); CreateDeleteOperation deleteOperation = (CreateDeleteOperation) operations.get(0); assertEquals(true, deleteOperation.isDelete()); assertEquals(true, deleteOperation.getModelElement() instanceof Proposal); assertEquals("proposal", ((Proposal) deleteOperation.getModelElement()).getName()); assertEquals(proposalId, deleteOperation.getModelElementId()); List<ReferenceOperation> subOperations = ((CreateDeleteOperation) operations.get(0)).getSubOperations(); assertEquals(2, subOperations.size()); AbstractOperation op0 = subOperations.get(0); assertTrue(op0 instanceof MultiReferenceOperation); MultiReferenceOperation multiReferenceOperation = (MultiReferenceOperation) op0; assertEquals(multiReferenceOperation.getModelElementId(), issueId); assertFalse(multiReferenceOperation.isAdd()); assertEquals(multiReferenceOperation.getReferencedModelElements().get(0), proposalId); assertEquals(multiReferenceOperation.getReferencedModelElements().size(), 1); assertEquals(multiReferenceOperation.getIndex(), 0); AbstractOperation operation = subOperations.get(1); assertEquals(true, operation instanceof SingleReferenceOperation); SingleReferenceOperation singleReferenceOperation = (SingleReferenceOperation) operation; assertEquals(issueId, singleReferenceOperation.getOldValue()); assertEquals(null, singleReferenceOperation.getNewValue()); assertEquals(RationalePackage.eINSTANCE.getProposal_Issue().getName(), singleReferenceOperation.getFeatureName()); assertEquals(proposalId, singleReferenceOperation.getModelElementId()); assertEquals(RationalePackage.eINSTANCE.getIssue_Proposals().getName(), singleReferenceOperation.getOppositeFeatureName()); assertEquals(true, singleReferenceOperation.isBidirectional()); Set<ModelElementId> otherInvolvedModelElements = singleReferenceOperation.getOtherInvolvedModelElements(); assertEquals(1, otherInvolvedModelElements.size()); assertEquals(true, otherInvolvedModelElements.contains(issueId)); } }