blob: 4d9134cdb997b9f434e8a5c01883032f89176a54 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2013, 2016 Obeo and others.
*
* 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
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.tests;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterators.filter;
import static org.eclipse.emf.ecore.util.EcoreUtil.getAllProperContents;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.compare.ide.ui.tests.workspace.TestProject;
import org.eclipse.emf.compare.ide.utils.StorageTraversal;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.junit.After;
import org.junit.Before;
@SuppressWarnings("nls")
public class CompareTestCase {
protected static final String PROJECT_NAME = "Project-1";
protected static final String PACKAGE_NAME_PREFIX = "package";
protected static final String CLASS1_NAME_PREFIX = "Class_A";
protected static final String CLASS2_NAME_PREFIX = "Class_B";
protected static final String CLASS3_NAME_PREFIX = "Class_C";
protected static final String CLASS4_NAME_PREFIX = "Class_D";
protected TestProject project;
@Before
public void setUp() throws Exception {
project = new TestProject(PROJECT_NAME);
}
@After
public void tearDown() throws Exception {
project.dispose();
}
/**
* The base model for both our files will be one package containing two classes. There are no references
* and no attributes set, save for the name of these objects.
*
* @param nameSuffix
* Suffix that will be appended to all names for this model.
* @return A basic model to be used by these tests.
*/
protected EPackage createBasicModel(String nameSuffix) {
EPackage root = createPackage(null, PACKAGE_NAME_PREFIX + nameSuffix);
createClass(root, CLASS1_NAME_PREFIX + nameSuffix);
createClass(root, CLASS2_NAME_PREFIX + nameSuffix);
return root;
}
protected EPackage createPackage(EPackage parent, String name) {
final EPackage newPackage = EcoreFactory.eINSTANCE.createEPackage();
newPackage.setName(name);
if (parent != null) {
parent.getESubpackages().add(newPackage);
}
return newPackage;
}
protected EClass createClass(EPackage parent, String name) {
final EClass newClass = EcoreFactory.eINSTANCE.createEClass();
newClass.setName(name);
if (parent != null) {
parent.getEClassifiers().add(newClass);
}
return newClass;
}
protected EAttribute createAttribute(EClass parent, String name, EClassifier type) {
final EAttribute newAttribute = EcoreFactory.eINSTANCE.createEAttribute();
newAttribute.setName(name);
newAttribute.setEType(type);
if (parent != null) {
parent.getEAttributes().add(newAttribute);
}
return newAttribute;
}
protected EObject findObject(Resource resource, String namePrefix) {
Iterator<EObject> children = EcoreUtil.getAllProperContents(resource, false);
while (children.hasNext()) {
final EObject child = children.next();
if (child instanceof ENamedElement && ((ENamedElement)child).getName().startsWith(namePrefix)) {
return child;
}
}
return null;
}
/**
* Connects an EMF resource to the given File within the given project. The resource will be created with
* a workspace-relative "{@code platform:/resource}" URI.
*
* @param file
* The file we're attaching an EMF Resource on.
* @param resourceSet
* The resource set in which the new Resource will be created.
* @return The created EMF Resource.
*/
protected Resource connectResource(IFile file, ResourceSet resourceSet) throws CoreException {
URI uri = URI.createPlatformResourceURI(file.getFullPath().toString(), true);
return createResource(uri, resourceSet);
}
private static Resource createResource(URI modelURI, ResourceSet resourceSet) {
final Resource resource = new XMIResourceImpl(modelURI) {
@Override
protected boolean useUUIDs() {
return true;
}
};
resourceSet.getResources().add(resource);
return resource;
}
/**
* This will seek for a random EClass in both given resources, then use the "eSuperTypes" reference of the
* source one to create a reference towards the target.
*
* @param source
* Resource within which we'll search for our source EClass (the class which will have a
* superType).
* @param target
* Resource within which we'll search for our target EClass (the superType).
*/
protected void makeCrossReference(Resource source, Resource target) {
final Iterator<EClass> sourceChildren = filter(getAllProperContents(source, false), EClass.class);
final Iterator<EClass> targetChildren = filter(getAllProperContents(target, false), EClass.class);
assertTrue(sourceChildren.hasNext());
assertTrue(targetChildren.hasNext());
final EClass sourceClass = sourceChildren.next();
final EClass targetClass = targetChildren.next();
sourceClass.getESuperTypes().add(targetClass);
}
/**
* This will seek and break all cross-references from <code>source</code> to <code>target</code>.
*
* @param source
* Resource within which we'll search for our cross-references.
* @param target
* Target of the cross-references to break.
*/
protected void breakCrossReferences(Resource source, Resource target) {
final Iterator<EObject> sourceChildren = getAllProperContents(source, false);
while (sourceChildren.hasNext()) {
final EObject child = sourceChildren.next();
breakCrossReferences(child, target);
}
}
private void breakCrossReferences(EObject source, Resource target) {
for (EReference ref : source.eClass().getEAllReferences()) {
if (ref.isDerived()) {
continue;
}
final Object value = source.eGet(ref);
if (!ref.isMany()) {
if (value instanceof EObject && ((EObject)value).eResource() == target) {
source.eSet(ref, null);
}
} else if (value instanceof Collection<?>) {
final Collection<?> valueList = (Collection<?>)value;
final Iterable<EObject> copy = filter(new ArrayList<Object>(valueList), EObject.class);
for (EObject targetEObject : copy) {
if (targetEObject.eResource() == target) {
valueList.remove(targetEObject);
}
}
}
}
}
/**
* Create a cross-resource reference through the "superType" reference of a given EClass.
* <p>
* The source EClass will be searched within the {@code source} Resource and its name should have a set
* prefix. Similarly, the target EClass will be searched withi the {@code target} Resource.
* </p>
*
* @param source
* Resource within which we'll search for our source EClass (the class which will have a
* superType).
* @param target
* Resource within which we'll search for our target EClass (the superType).
* @param sourceNamePrefix
* Prefix (or exact name) of the source EClass.
* @param targetNamePrefix
* Prefix (or exact name) of the target EClass.
*/
protected void makeCrossReference(Resource source, Resource target, String sourceNamePrefix,
String targetNamePrefix) {
final EObject sourceObject = findObject(source, sourceNamePrefix);
final EObject targetObject = findObject(target, targetNamePrefix);
assertTrue(sourceObject instanceof EClass);
assertTrue(targetObject instanceof EClass);
((EClass)sourceObject).getESuperTypes().add((EClass)targetObject);
}
protected void unload(Resource... resources) {
for (Resource resource : resources) {
resource.getContents().clear();
resource.unload();
}
}
protected void reload(Resource... resources) throws IOException {
unload(resources);
// separate loop to reload so that we are sure everything has been unloaded
for (Resource resource : resources) {
resource.load(Collections.emptyMap());
}
// And a third loop to re-resolve every cross-references between the reloaded resources
for (Resource resource : resources) {
EcoreUtil.resolveAll(resource);
}
}
protected void save(ResourceSet resourceSet) throws IOException, CoreException {
for (Resource resource : resourceSet.getResources()) {
final HashMap<String, Object> options = new HashMap<String, Object>();
options.put(Resource.OPTION_SAVE_ONLY_IF_CHANGED,
Resource.OPTION_SAVE_ONLY_IF_CHANGED_FILE_BUFFER);
resource.save(options);
}
if (project != null) {
IProject prj = project.getProject();
if (prj != null) {
prj.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
}
}
}
protected void save(Resource... resources) throws IOException, CoreException {
for (Resource resource : resources) {
final HashMap<String, Object> options = new HashMap<String, Object>();
options.put(Resource.OPTION_SAVE_ONLY_IF_CHANGED,
Resource.OPTION_SAVE_ONLY_IF_CHANGED_FILE_BUFFER);
resource.save(options);
}
if (project != null) {
IProject prj = project.getProject();
if (prj != null) {
prj.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
}
}
}
protected static void copyFile(File source, File dest) throws IOException {
FileChannel sourceChannel = null;
FileChannel destChannel = null;
FileInputStream fileInputStream = new FileInputStream(source);
sourceChannel = fileInputStream.getChannel();
FileOutputStream fileOutputStream = new FileOutputStream(dest);
destChannel = fileOutputStream.getChannel();
destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
sourceChannel.close();
destChannel.close();
fileInputStream.close();
fileOutputStream.close();
}
protected static void assertContainsExclusively(StorageTraversal traversal, IFile... files) {
Set<? extends IStorage> storages = traversal.getStorages();
assertEquals(files.length, storages.size());
for (IFile file : files) {
assertTrue(storages.contains(file));
}
}
}