| /******************************************************************************* |
| * Copyright (c) 2007, 2023 Borland Software Corporation 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: |
| * Borland Software Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.m2m.tests.qvt.oml.transform; |
| |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.ICommand; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IMarker; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IProjectDescription; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspace; |
| import org.eclipse.core.resources.IncrementalProjectBuilder; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.m2m.internal.qvt.oml.common.MDAConstants; |
| import org.eclipse.m2m.internal.qvt.oml.common.MdaException; |
| import org.eclipse.m2m.internal.qvt.oml.common.io.CFile; |
| import org.eclipse.m2m.internal.qvt.oml.common.io.FileUtil; |
| import org.eclipse.m2m.internal.qvt.oml.common.io.eclipse.EclipseFile; |
| import org.eclipse.m2m.internal.qvt.oml.project.QVTOProjectPlugin; |
| import org.eclipse.m2m.internal.qvt.oml.project.builder.QVTOBuilder; |
| import org.eclipse.m2m.internal.qvt.oml.project.builder.QVTOBuilderConfig; |
| import org.eclipse.m2m.internal.qvt.oml.project.nature.NatureUtils; |
| import org.eclipse.m2m.internal.qvt.oml.runtime.launch.QvtLaunchUtil; |
| import org.eclipse.m2m.internal.qvt.oml.runtime.project.QvtTransformation; |
| import org.eclipse.m2m.internal.qvt.oml.runtime.project.QvtTransformation.TransformationParameter; |
| import org.eclipse.m2m.internal.qvt.oml.runtime.project.QvtTransformation.TransformationParameter.DirectionKind; |
| import org.eclipse.m2m.internal.qvt.oml.runtime.project.TransformationUtil; |
| import org.eclipse.m2m.qvt.oml.ExecutionContext; |
| import org.eclipse.m2m.tests.qvt.oml.TestProject; |
| import org.eclipse.m2m.tests.qvt.oml.util.TestUtil; |
| import org.junit.After; |
| import org.junit.Before; |
| |
| import junit.framework.TestCase; |
| |
| |
| public abstract class TestTransformation extends TestCase { |
| private ModelTestData myData; |
| private TestProject myProject; |
| private File myDestFolder; |
| |
| public TestTransformation(ModelTestData data) { |
| super(data.getName()); |
| |
| myData = data; |
| myProject = null; |
| } |
| |
| public IProject getProject() { |
| return myProject.getProject(); |
| } |
| |
| public TestProject getTestProject() { |
| return myProject; |
| } |
| |
| public ModelTestData getData() { |
| return myData; |
| } |
| |
| protected String getProjectName() { |
| return "TransformationTest"; //$NON-NLS-1$ |
| } |
| |
| protected boolean isSaveXmi() { |
| return myData.isUseCompiledXmi(); |
| } |
| |
| @Override |
| @Before |
| public void setUp() throws Exception { |
| TestUtil.turnOffAutoBuilding(); |
| |
| String name = getProjectName(); |
| myProject = TestProject.getExistingProject(name); |
| if(myProject == null) { |
| myProject = new TestProject(name, new String[] {}, 0); |
| myProject.getProject().setDefaultCharset(ModelTestData.ENCODING, null); |
| |
| NatureUtils.addNature(getProject(), QVTOProjectPlugin.NATURE_ID); |
| |
| IProjectDescription description = getProject().getDescription(); |
| ICommand[] buildSpec = description.getBuildSpec(); |
| ICommand buildCommand = NatureUtils.findCommand(buildSpec, QVTOProjectPlugin.BUILDER_ID); |
| |
| assertNotNull(buildCommand); |
| Map<String, String> arguments = buildCommand.getArguments(); |
| arguments.put(QVTOBuilder.SAVE_AST_XMI, Boolean.toString(isSaveXmi())); |
| |
| buildCommand.setArguments(arguments); |
| description.setBuildSpec(buildSpec); |
| getProject().setDescription(description, null); |
| |
| QVTOBuilderConfig.getConfig(getProject()).setSourceContainer(getProject()); |
| } |
| |
| copyModelData(); |
| myData.prepare(myProject); |
| } |
| |
| protected void buildTestProject() throws Exception { |
| getProject().build(IncrementalProjectBuilder.FULL_BUILD, new NullProgressMonitor()); |
| assertBuildOK(getProject()); |
| } |
| |
| protected void assertBuildOK(IProject project) throws Exception { |
| IMarker[] problems = project.findMarkers(QVTOProjectPlugin.PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); |
| StringBuilder buf = new StringBuilder(); |
| IMarker firstError = null; |
| try { |
| for (IMarker next : problems) { |
| if(Integer.valueOf(IMarker.SEVERITY_ERROR).equals(next.getAttribute(IMarker.SEVERITY))) { |
| firstError = next; |
| break; |
| } |
| } |
| |
| if(firstError == null) { |
| return; |
| } |
| |
| IMarker marker = firstError; |
| buf.append(marker.getAttribute(IMarker.MESSAGE)); |
| buf.append(", line:").append(marker.getAttribute(IMarker.LINE_NUMBER)); //$NON-NLS-1$ |
| buf.append(", path:").append(marker.getResource().getProjectRelativePath()); //$NON-NLS-1$ |
| |
| } finally { |
| try { |
| // do clean even if we have failed |
| if(firstError != null) { |
| tearDown(); |
| getProject().refreshLocal(IResource.DEPTH_INFINITE, null); |
| } |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| fail(buf.toString()); |
| } |
| |
| protected void assertEqualContents(String expectedContents, String actualContents) { |
| String lineSeparator = System.getProperty("line.separator"); |
| if (!"\n".equals(lineSeparator)) { |
| expectedContents = expectedContents.replace(lineSeparator, "\n"); |
| actualContents = actualContents.replace(lineSeparator, "\n"); |
| } |
| |
| assertEquals(expectedContents, actualContents); |
| } |
| |
| @Override |
| @After |
| public void tearDown() throws Exception { |
| if (myData == null) { |
| return; |
| } |
| |
| getData().dispose(myProject); |
| if (myDestFolder.exists()) { |
| FileUtil.delete(myDestFolder); |
| } |
| myData = null; |
| } |
| |
| public static interface IChecker { |
| void check(ModelTestData data, IProject project) throws Exception; |
| } |
| |
| public static class TransformationChecker implements IChecker { |
| public TransformationChecker(ITransformer transformer) { |
| myTransformer = transformer; |
| } |
| |
| public void check(ModelTestData data, IProject project) throws Exception { |
| IFile transformation = getIFile(data.getTransformation(project)); |
| |
| try { |
| List<URI> transfResult = myTransformer.transform(transformation, data.getIn(project), data.getTrace(project), data.getContext()); |
| List<URI> expectedResultURIs = data.getExpected(project); |
| |
| ResourceSet rs = data.getResourceSet(project); |
| int i = 0; |
| for (URI actualResultURI : transfResult) { |
| URI expectedURI = expectedResultURIs.get(i++); |
| |
| Resource expectedResource = rs.getResource(expectedURI, true); |
| |
| List<EObject> actualExtentObjects = rs.getResource(actualResultURI, true).getContents(); |
| List<EObject> expectedExtentObjects = expectedResource.getContents(); |
| ModelTestData.compareWithExpected(data.getName(), expectedExtentObjects, actualExtentObjects); |
| } |
| } catch (CoreException e) { |
| assertEquals(data.getExpectedSeverity(), e.getStatus().getSeverity()); |
| assertEquals(data.getExpectedCode(), e.getStatus().getCode()); |
| } |
| } |
| |
| private final ITransformer myTransformer; |
| }; |
| |
| public static interface ITransformer { |
| List<URI> transform(IFile transformation, List<URI> inUris, URI traceUri, ExecutionContext context) throws Exception; |
| } |
| |
| protected void checkTransformation(IChecker checker) throws Exception { |
| checker.check(myData, getProject()); |
| getProject().refreshLocal(IResource.DEPTH_INFINITE, null); |
| } |
| |
| private void copyModelData() throws Exception { |
| File srcFolder = TestUtil.getPluginRelativeFile(myData.getBundle(), myData.getTestDataFolder() + "/models/" + myData.getName()); //$NON-NLS-1$ |
| myDestFolder = new File(getProject().getLocation().toString() + "/models/" + myData.getName()); //$NON-NLS-1$ |
| myDestFolder.mkdirs(); |
| FileUtil.copyFolder(srcFolder, myDestFolder); |
| getProject().refreshLocal(IResource.DEPTH_INFINITE, null); |
| } |
| |
| public static IFile getIFile(File fileUnderWorkspace) { |
| IWorkspace workspace = ResourcesPlugin.getWorkspace(); |
| IPath location = new Path(fileUnderWorkspace.getAbsolutePath()); |
| IFile ifile = workspace.getRoot().getFileForLocation(location); |
| if(ifile == null) { |
| throw new RuntimeException("File not found: " + fileUnderWorkspace); //$NON-NLS-1$ |
| } |
| |
| return ifile; |
| } |
| |
| public static CFile getTraceFile(CFile qvtFile) throws MdaException { |
| String fileName = qvtFile.getUnitName() + MDAConstants.QVTO_TRACEFILE_EXTENSION_WITH_DOT; |
| CFile traceFile = qvtFile.getParent().getFile(fileName); |
| return traceFile; |
| } |
| |
| protected static CFile getModelExtentFile(CFile qvtFile, TransformationParameter transfParam) throws MdaException { |
| String fileExtension = transfParam.getMetamodels().isEmpty() ? TransformationUtil.DEFAULT_RESULT_EXTENSION |
| : transfParam.getMetamodels().get(0).getName(); |
| String fileName = qvtFile.getUnitName() + ".extent_" + transfParam.getName() + '.' + fileExtension; //$NON-NLS-1$ |
| CFile modelExtentFile = qvtFile.getParent().getFile(fileName); |
| return modelExtentFile; |
| } |
| |
| protected static List<URI> launchTransform(IFile transformationFile, List<URI> inUris, URI traceUri, ExecutionContext context, |
| QvtTransformation transf) throws Exception { |
| |
| EclipseFile eclipseFile = new EclipseFile(transformationFile); |
| |
| List<URI> resultUris = new ArrayList<URI>(transf.getParameters().size()); |
| |
| List<URI> paramUris = new ArrayList<URI>(inUris); |
| |
| Iterator<URI> itInUris = inUris.iterator(); |
| for (TransformationParameter transfParam : transf.getParameters()) { |
| URI paramUri = null; |
| if (transfParam.getDirectionKind() == DirectionKind.IN || transfParam.getDirectionKind() == DirectionKind.INOUT) { |
| paramUri = itInUris.next(); |
| } |
| if (transfParam.getDirectionKind() == DirectionKind.OUT || transfParam.getDirectionKind() == DirectionKind.INOUT) { |
| if (paramUri == null) { |
| assertEquals(DirectionKind.OUT, transfParam.getDirectionKind()); |
| CFile outFile = getModelExtentFile(eclipseFile, transfParam); |
| paramUri = URI.createFileURI(outFile.getFullPath()); |
| |
| paramUris.add(paramUri); |
| } |
| |
| resultUris.add(paramUri); |
| } |
| } |
| |
| QvtLaunchUtil.doLaunch(transf, paramUris, traceUri, context, traceUri != null, traceUri != null); |
| |
| transf.cleanup(); |
| return resultUris; |
| } |
| } |