blob: a5d10d59351650c9315fb90ac821733774840d2b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016, 2018 Christopher Gerking 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:
* Christopher Gerking - initial API and implementation
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml;
import static org.eclipse.m2m.internal.qvt.oml.emf.util.EmfUtilPlugin.isSuccess;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEnv;
import org.eclipse.m2m.internal.qvt.oml.common.MdaException;
import org.eclipse.m2m.internal.qvt.oml.compiler.CompiledUnit;
import org.eclipse.m2m.internal.qvt.oml.compiler.ExeXMISerializer;
import org.eclipse.m2m.internal.qvt.oml.compiler.QVTOCompiler;
import org.eclipse.m2m.internal.qvt.oml.compiler.UnitProxy;
import org.eclipse.m2m.internal.qvt.oml.compiler.UnitResolverFactory;
import org.eclipse.m2m.internal.qvt.oml.emf.util.EmfUtil;
import org.eclipse.m2m.internal.qvt.oml.expressions.ImperativeOperation;
import org.eclipse.m2m.internal.qvt.oml.expressions.Module;
import org.eclipse.m2m.internal.qvt.oml.expressions.OperationalTransformation;
import org.eclipse.m2m.qvt.oml.ExecutionDiagnostic;
public class CstTransformation implements Transformation {
private URI fURI;
private EPackage.Registry fPackageRegistry;
private CompiledUnit fCompiledUnit;
private ExecutionDiagnostic fLoadDiagnostic;
private OperationalTransformation fTransformation;
private QVTOCompiler fCompiler;
public CstTransformation(URI uri) {
this(uri, EPackage.Registry.INSTANCE);
}
public CstTransformation(URI uri, EPackage.Registry packageRegistry) {
if (uri == null) {
throw new IllegalArgumentException("null transformation URI"); //$NON-NLS-1$
}
fURI = uri;
fPackageRegistry = packageRegistry == null ? EPackage.Registry.INSTANCE : packageRegistry;
}
protected CompiledUnit getCompiledUnit(IProgressMonitor monitor) throws MdaException {
if (ExeXMISerializer.COMPILED_XMI_FILE_EXTENSION.equals(fURI.fileExtension())) {
return new CompiledUnit(fURI, getCompiler().getResourceSet());
}
UnitProxy proxy = UnitResolverFactory.Registry.INSTANCE.getUnit(fURI);
if (proxy == null) {
fLoadDiagnostic = new ExecutionDiagnosticImpl(Diagnostic.ERROR,
ExecutionDiagnostic.TRANSFORMATION_LOAD_FAILED, NLS.bind(
Messages.UnitNotFoundError, fURI));
return null;
}
QVTOCompiler compiler = getCompiler();
return compiler.compile(proxy, null, monitor);
}
private QVTOCompiler getCompiler() {
if (fCompiler == null) {
fCompiler = createCompiler();
}
return fCompiler;
}
protected QVTOCompiler createCompiler() {
if(fPackageRegistry == null) {
return new QVTOCompiler();
}
return new QVTOCompiler(fPackageRegistry);
}
private void doLoad(IProgressMonitor monitor) {
fLoadDiagnostic = ExecutionDiagnosticImpl.createOkInstance();
try {
fCompiledUnit = getCompiledUnit(monitor);
} catch (MdaException e) {
fLoadDiagnostic = new ExecutionDiagnosticImpl(Diagnostic.ERROR,
ExecutionDiagnostic.TRANSFORMATION_LOAD_FAILED, NLS.bind(
Messages.FailedToCompileUnitError, fURI));
fLoadDiagnostic.merge(BasicDiagnostic.toDiagnostic(e.getStatus()));
}
if (fCompiledUnit != null && isSuccess(fLoadDiagnostic)) {
ExecutionDiagnostic compilationDiagnostic = createCompilationDiagnostic(fCompiledUnit);
if (isSuccess(compilationDiagnostic)) {
fLoadDiagnostic.addAll(compilationDiagnostic);
}
else {
compilationDiagnostic.addAll(fLoadDiagnostic);
fLoadDiagnostic = compilationDiagnostic;
return;
}
fTransformation = doGetTransformation();
if (fTransformation == null) {
ExecutionDiagnostic transformationDiagnostic = new ExecutionDiagnosticImpl(
Diagnostic.ERROR,
ExecutionDiagnostic.TRANSFORMATION_LOAD_FAILED,
NLS.bind(Messages.NotTransformationInUnitError,
fURI)
);
transformationDiagnostic.addAll(fLoadDiagnostic);
fLoadDiagnostic = transformationDiagnostic;
return;
}
ExecutionDiagnostic executabilityDiagnostic = checkIsExecutable(fTransformation);
if (isSuccess(executabilityDiagnostic)) {
fLoadDiagnostic.addAll(executabilityDiagnostic);
}
else {
executabilityDiagnostic.addAll(fLoadDiagnostic);
fLoadDiagnostic = executabilityDiagnostic;
}
}
}
private OperationalTransformation doGetTransformation() {
// TODO - cached the transformation selected as main
if(fCompiledUnit == null) {
return null;
}
List<Module> allModules = fCompiledUnit.getModules();
for (Module module : allModules) {
if (module instanceof OperationalTransformation) {
return (OperationalTransformation) module;
}
}
return null;
}
private static ExecutionDiagnostic createCompilationDiagnostic(
CompiledUnit compiledUnit) {
ExecutionDiagnostic mainDiagnostic = ExecutionDiagnosticImpl.createOkInstance();
if (!compiledUnit.getErrors().isEmpty()) {
URI uri = compiledUnit.getURI();
mainDiagnostic = new ExecutionDiagnosticImpl(
Diagnostic.ERROR, ExecutionDiagnostic.VALIDATION, NLS.bind(
Messages.CompilationErrorsFoundInUnit, uri.toString()));
for (Diagnostic error : compiledUnit.getErrors()) {
mainDiagnostic.add(error);
}
}
for (Diagnostic warning : compiledUnit.getWarnings()) {
mainDiagnostic.add(warning);
}
return mainDiagnostic;
}
public OperationalTransformation getTransformation(IProgressMonitor monitor) {
loadTransformation(monitor);
return fTransformation;
}
private static ExecutionDiagnostic checkIsExecutable(
OperationalTransformation transformation) {
if (transformation.isIsBlackbox()) {
return ExecutionDiagnosticImpl.createOkInstance();
}
EList<EOperation> operations = transformation.getEOperations();
for (EOperation oper : operations) {
if (oper instanceof ImperativeOperation
&& QvtOperationalEnv.MAIN.equals(oper.getName())) {
return ExecutionDiagnosticImpl.createOkInstance();
}
}
return new ExecutionDiagnosticImpl(Diagnostic.ERROR,
ExecutionDiagnostic.VALIDATION, NLS.bind(
Messages.NoTransformationEntryPointError,
transformation.getName()));
}
/**
* Attempts to load the transformation referred by this executor and checks
* if it is valid for execution.
* <p>
* <b>Remark:</b></br> Only the first performs the actual transformation
* loading, subsequent calls to this method will return the existing
* diagnostic.
*
* @return the diagnostic indicating possible problems of the load action
*/
private Diagnostic loadTransformation(IProgressMonitor monitor) {
try {
if (fLoadDiagnostic == null) {
doLoad(monitor);
}
return fLoadDiagnostic;
}
finally {
monitor.done();
}
}
public ExecutionDiagnostic getDiagnostic() {
loadTransformation(new NullProgressMonitor());
return fLoadDiagnostic;
}
public URI getURI() {
return fURI;
}
public ResourceSet getResourceSet() {
return getUnit().getResourceSet();
}
public CompiledUnit getUnit() {
loadTransformation(new NullProgressMonitor());
return fCompiledUnit;
}
public void cleanup() {
if (getResourceSet() != null) {
EmfUtil.cleanupResourceSet(getResourceSet());
}
getCompiler().cleanup();
}
}