blob: 593dc3c4f3d2e519aaefa10e21ef48154542bc74 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2019 THALES GLOBAL SERVICES.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.tests.unit.diagram.copier;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.EcoreUtil.EqualityHelper;
import org.eclipse.emf.transaction.RecordingCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.sirius.business.api.dialect.DialectManager;
import org.eclipse.sirius.business.api.query.DRepresentationQuery;
import org.eclipse.sirius.common.tools.api.util.StringUtil;
import org.eclipse.sirius.diagram.DDiagram;
import org.eclipse.sirius.diagram.DDiagramElement;
import org.eclipse.sirius.diagram.DSemanticDiagram;
import org.eclipse.sirius.diagram.description.DiagramDescription;
import org.eclipse.sirius.tests.SiriusTestsPlugin;
import org.eclipse.sirius.tests.support.api.TestsUtil;
import org.eclipse.sirius.tests.unit.diagram.GenericTestCase;
import org.eclipse.sirius.tests.unit.diagram.modelers.uml.UML2ModelerConstants;
import org.eclipse.sirius.ui.business.api.dialect.DialectUIManager;
import org.eclipse.sirius.viewpoint.DRepresentation;
import org.eclipse.sirius.viewpoint.DRepresentationDescriptor;
import org.eclipse.sirius.viewpoint.IdentifiedElement;
import org.eclipse.sirius.viewpoint.description.Viewpoint;
import org.eclipse.ui.IEditorPart;
/**
* Tests for the copy functionality.
*
* @author mchauvin
*/
public class RepresentationCopierTest extends GenericTestCase implements UML2ModelerConstants {
private static final String PLUGIN = "/" + SiriusTestsPlugin.PLUGIN_ID;
private DDiagram originalDiagram;
private DDiagram originalUseCaseDiagram;
private Diagram originalGMFDiagram;
private Diagram originalUseCaseGMFDiagram;
@Override
protected void setUp() throws Exception {
super.setUp();
genericSetUp(PLUGIN + SEMANTIC_MODEL_PATH, PLUGIN + MODELER_PATH);
final Viewpoint vp = viewpoints.iterator().next();
activateViewpoint(vp.getName());
launchRefreshCommand();
DiagramDescription desc = findDiagramDescription("Class Diagram");
DiagramDescription useCaseDesc = findDiagramDescription("Use Case Diagram");
originalDiagram = getFirstDiagram(desc, session);
assertEquals(INITIAL_DIAGRAM_ELEMENT_NUMBER, getNumberOfDiagramElements(originalDiagram));
assertEquals(INITIAL_DNODE_NUMBER, getNumberOfNodes(originalDiagram));
originalUseCaseDiagram = getFirstDiagram(useCaseDesc, session);
assertEquals(INITIAL_USECASE_DNODE_NUMBER, getNumberOfDiagramElements(originalUseCaseDiagram));
final IEditorPart part = DialectUIManager.INSTANCE.openEditor(session, originalDiagram, new NullProgressMonitor());
TestsUtil.synchronizationWithUIThread();
session.save(new NullProgressMonitor());
DialectUIManager.INSTANCE.closeEditor(part, true);
TestsUtil.synchronizationWithUIThread();
final IEditorPart part2 = DialectUIManager.INSTANCE.openEditor(session, originalUseCaseDiagram, new NullProgressMonitor());
TestsUtil.synchronizationWithUIThread();
session.save(new NullProgressMonitor());
DialectUIManager.INSTANCE.closeEditor(part2, true);
TestsUtil.synchronizationWithUIThread();
originalGMFDiagram = getGMFDiagram(originalDiagram, session);
assertEquals(INITIAL_NODE_NUMBER, numberOfNodes(originalGMFDiagram));
originalUseCaseGMFDiagram = getGMFDiagram(originalUseCaseDiagram, session);
assertEquals(INITIAL_USECASE_NODE_NUMBER, numberOfNodes(originalUseCaseGMFDiagram));
}
public void testDiagramCreation() throws Exception {
DiagramDescription desc = originalDiagram.getDescription();
int beforeCopyNumberOfDiagrams = getNumberOfDiagrams(desc);
copyDiagram("test");
int afterCopyNumberOfDiagrams = getNumberOfDiagrams(desc);
assertEquals(beforeCopyNumberOfDiagrams, afterCopyNumberOfDiagrams - 1);
desc = originalUseCaseDiagram.getDescription();
beforeCopyNumberOfDiagrams = getNumberOfDiagrams(desc);
copyUseCaseDiagram("test");
afterCopyNumberOfDiagrams = getNumberOfDiagrams(desc);
assertEquals(beforeCopyNumberOfDiagrams, afterCopyNumberOfDiagrams - 1);
}
public void testSameNumberOfDiagramElements() throws Exception {
DDiagram copy = copyDiagram("test");
/* check that copy has the same number */
assertTrue(originalDiagram != copy);
assertEquals(INITIAL_DIAGRAM_ELEMENT_NUMBER, getNumberOfDiagramElements(copy));
copy = copyUseCaseDiagram("test");
/* check that copy has the same number */
assertTrue(originalUseCaseDiagram != copy);
assertEquals(INITIAL_USECASE_DIAGRAM_ELEMENT_NUMBER, getNumberOfDiagramElements(copy));
}
public void testSameNumberOfGMFViews() throws Exception {
DDiagram copy = copyDiagram("test");
Diagram gmfCopy = getGMFDiagram(copy, session);
/* check that copy has the same number of GMF views */
assertTrue(originalGMFDiagram != gmfCopy);
assertEquals(INITIAL_NODE_NUMBER, numberOfNodes(gmfCopy));
copy = copyUseCaseDiagram("test");
gmfCopy = getGMFDiagram(copy, session);
/* check that copy has the same number of GMF views */
assertTrue(originalUseCaseGMFDiagram != gmfCopy);
assertEquals(INITIAL_USECASE_NODE_NUMBER, numberOfNodes(gmfCopy));
}
public void testNoDuplicationOfSemanticElements() throws Exception {
EObject semanticRoot = EcoreUtil.getRootContainer(((DSemanticDiagram) originalDiagram).getTarget());
int numberOfSemanticElementsBeforeCopy = 1 + numberOfChildren(semanticRoot);
copyDiagram("test");
int numberOfSemanticElementsAfterCopy = 1 + numberOfChildren(semanticRoot);
assertEquals(numberOfSemanticElementsBeforeCopy, numberOfSemanticElementsAfterCopy);
semanticRoot = EcoreUtil.getRootContainer(((DSemanticDiagram) originalUseCaseDiagram).getTarget());
numberOfSemanticElementsBeforeCopy = 1 + numberOfChildren(semanticRoot);
copyUseCaseDiagram("test");
numberOfSemanticElementsAfterCopy = 1 + numberOfChildren(semanticRoot);
assertEquals(numberOfSemanticElementsBeforeCopy, numberOfSemanticElementsAfterCopy);
}
public void testNoDuplicatedUids() throws Exception {
final String newRepresentationName = "New Representation Space Name ";
DDiagram copy = copyDiagram(newRepresentationName);
/* check that copy has the name asked */
assertTrue(originalDiagram != copy);
assertFalse(originalDiagram.getUid().equals(copy.getUid()));
checkContentUids(originalDiagram, copy);
copy = copyUseCaseDiagram(newRepresentationName);
/* check that copy has the name asked */
assertTrue(originalUseCaseDiagram != copy);
assertFalse(originalUseCaseDiagram.getUid().equals(copy.getUid()));
}
private void checkContentUids(DDiagram origin, DDiagram copy) {
List<IdentifiedElement> copied = collectAllIdentifiedElements(originalDiagram);
List<IdentifiedElement> copies = collectAllIdentifiedElements(copy);
assertEquals("Copied and copies lists must have the same size.", copied.size(), copies.size());
// Specific equality helper which does not check id attributes nor containment lists.
// The containments list size/contents validity is ensured by check on the order of the copied/copies lists
// and their computation from the eAllContents methods.
EqualityHelper helper = new EqualityHelper() {
@Override
protected boolean haveEqualAttribute(EObject eObject1, EObject eObject2, EAttribute attribute) {
boolean ignored = attribute.isID();
return ignored || super.haveEqualAttribute(eObject1, eObject2, attribute);
}
};
assertTrue(helper.equals(originalDiagram, copy));
for (int i = 0; i < copied.size(); i++) {
IdentifiedElement copiedElt = copied.get(i);
IdentifiedElement copyElt = copies.get(i);
boolean equality = helper.equals(copiedElt, copyElt);
boolean nullUIds = StringUtil.isEmpty(copiedElt.getUid()) || StringUtil.isEmpty(copyElt.getUid());
boolean duplicatedUids = copiedElt.getUid().equals(copyElt.getUid());
assertTrue("The only difference found between those two elements must be their uid. See " + copiedElt + " and its copy " + copyElt + ".", equality && !nullUIds && !duplicatedUids);
}
}
private List<IdentifiedElement> collectAllIdentifiedElements(DDiagram diagram) {
Iterable<EObject> it = () -> diagram.eAllContents();
List<IdentifiedElement> identifiedElements = StreamSupport.stream(it.spliterator(), false).filter(IdentifiedElement.class::isInstance).map(IdentifiedElement.class::cast)
.collect(Collectors.toList());
return identifiedElements;
}
public void testCopiedRepresentationName() throws Exception {
final String newRepresentationName = "New Representation Space Name ";
String originaleDiagramName = originalDiagram.getName();
DDiagram copy = copyDiagram(newRepresentationName);
/* check that copy has the name asked */
assertTrue(originalDiagram != copy);
assertFalse(originalDiagram.getUid().equals(copy.getUid()));
assertEquals(newRepresentationName, new DRepresentationQuery(copy).getRepresentationDescriptor().getName());
assertEquals(originaleDiagramName, originalDiagram.getName());
String originaleDiagramUseCaseName = originalUseCaseDiagram.getName();
copy = copyUseCaseDiagram(newRepresentationName);
/* check that copy has the name asked */
assertTrue(originalUseCaseDiagram != copy);
assertFalse(originalUseCaseDiagram.getUid().equals(copy.getUid()));
assertEquals(newRepresentationName, new DRepresentationQuery(copy).getRepresentationDescriptor().getName());
assertEquals(originaleDiagramUseCaseName, originalUseCaseDiagram.getName());
}
public void testReferencesFromGMFViewsToDiagramElements() throws Exception {
final DDiagram copy = copyDiagram("test");
final Diagram gmfCopy = getGMFDiagram(copy, session);
Collection<DDiagramElement> orginalDiagramElements = new HashSet<DDiagramElement>();
final Iterator<EObject> i = originalDiagram.eAllContents();
while (i.hasNext()) {
final EObject current = i.next();
if (current instanceof DDiagramElement)
orginalDiagramElements.add((DDiagramElement) current);
}
final Iterator<EObject> gmfDiagramIter = gmfCopy.eAllContents();
while (gmfDiagramIter.hasNext()) {
final EObject current = gmfDiagramIter.next();
if (current instanceof View) {
final View view = (View) current;
final EObject element = view.getElement();
if (orginalDiagramElements.contains(element))
fail();
}
}
final DDiagram useCaseCopy = copyUseCaseDiagram("test");
final Diagram useCaseGmfCopy = getGMFDiagram(useCaseCopy, session);
Collection<DDiagramElement> orginalUseCaseDiagramElements = new HashSet<DDiagramElement>();
final Iterator<EObject> k = originalUseCaseDiagram.eAllContents();
while (k.hasNext()) {
final EObject current = k.next();
if (current instanceof DDiagramElement)
orginalUseCaseDiagramElements.add((DDiagramElement) current);
}
final Iterator<EObject> useCaseGmfDiagramIter = useCaseGmfCopy.eAllContents();
while (useCaseGmfDiagramIter.hasNext()) {
final EObject current = useCaseGmfDiagramIter.next();
if (current instanceof View) {
final View view = (View) current;
final EObject element = view.getElement();
if (orginalUseCaseDiagramElements.contains(element))
fail();
}
}
}
public void testGMFViewsIsSetProperties() throws Exception {
final DDiagram copy = copyDiagram("test");
final Diagram gmfCopy = getGMFDiagram(copy, session);
final Predicate<View> elementIsUnsetPredicate = new Predicate<View>() {
@Override
public boolean apply(final View input) {
if (!input.isSetElement())
return true;
return false;
}
};
final int originalElementIsUnsetNumber = numberOfNodesWithPredicateTrue(originalGMFDiagram, elementIsUnsetPredicate);
final int copyElementIsUnsetNumber = numberOfNodesWithPredicateTrue(gmfCopy, elementIsUnsetPredicate);
assertEquals(originalElementIsUnsetNumber, copyElementIsUnsetNumber);
}
private DDiagram copyDiagram(final String name) {
return copyDiagram(name, new DRepresentationQuery(originalDiagram).getRepresentationDescriptor());
}
private DDiagram copyUseCaseDiagram(final String name) {
return copyDiagram(name, new DRepresentationQuery(originalUseCaseDiagram).getRepresentationDescriptor());
}
private DDiagram copyDiagram(final String name, final DRepresentationDescriptor diagramToCopy) {
TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(diagramToCopy);
RecordingCommand copyCommand = new RecordingCommand(domain) {
private DRepresentation representation;
@Override
protected void doExecute() {
representation = DialectManager.INSTANCE.copyRepresentation(diagramToCopy, name, session, null);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.common.command.AbstractCommand#getResult()
*/
@Override
public Collection<?> getResult() {
Collection<DDiagram> result = new HashSet<DDiagram>();
result.add((DDiagram) representation);
return result;
}
};
domain.getCommandStack().execute(copyCommand);
DDiagram copy = (DDiagram) copyCommand.getResult().iterator().next();
return copy;
}
private int numberOfNodes(final View view) {
return numberOfNodesWithPredicateTrue(view, null);
}
private int numberOfNodesWithPredicateTrue(final View view, final Predicate<View> predicate) {
int sum = 0;
for (final View childView : (List<View>) view.getChildren()) {
if (predicate == null || predicate.apply(childView))
sum += 1;
sum += numberOfNodesWithPredicateTrue(childView, predicate);
}
return sum;
}
private int numberOfChildren(final EObject root) {
int sum = 0;
for (Iterator<EObject> i = root.eAllContents(); i.hasNext(); i.next()) {
sum++;
}
return sum;
}
private static interface Predicate<T> {
boolean apply(T input);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
}