/*******************************************************************************
* Copyright (c) 2007, 2014 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 v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Borland Software Corporation - initial API and implementation
* Christopher Gerking - bug 427237
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.runtime.project;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.WrappedException;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.m2m.internal.qvt.oml.ExecutionDiagnosticImpl;
import org.eclipse.m2m.internal.qvt.oml.ast.env.InternalEvaluationEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.env.ModelExtentContents;
import org.eclipse.m2m.internal.qvt.oml.ast.env.ModelParameterExtent;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtEvaluationResult;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEnvFactory;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEvaluationEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalFileEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.parser.QvtOperationalParserUtil;
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.QvtCompilerOptions;
import org.eclipse.m2m.internal.qvt.oml.emf.util.EmfUtil;
import org.eclipse.m2m.internal.qvt.oml.emf.util.ModelContent;
import org.eclipse.m2m.internal.qvt.oml.evaluator.ModelInstance;
import org.eclipse.m2m.internal.qvt.oml.evaluator.ModelParameterHelper;
import org.eclipse.m2m.internal.qvt.oml.expressions.ModelParameter;
import org.eclipse.m2m.internal.qvt.oml.expressions.Module;
import org.eclipse.m2m.internal.qvt.oml.expressions.OperationalTransformation;
import org.eclipse.m2m.internal.qvt.oml.library.Context;
import org.eclipse.m2m.internal.qvt.oml.runtime.project.QvtTransformation.TransformationParameter.DirectionKind;
import org.eclipse.m2m.internal.qvt.oml.runtime.project.config.QvtConfigurationProperty;
import org.eclipse.m2m.internal.qvt.oml.trace.Trace;
import org.eclipse.m2m.qvt.oml.ExecutionDiagnostic;
import org.eclipse.m2m.qvt.oml.util.IContext;
import org.eclipse.ocl.EvaluationVisitor;
import org.eclipse.ocl.ecore.CallOperationAction;
import org.eclipse.ocl.ecore.Constraint;
import org.eclipse.ocl.ecore.SendSignalAction;
public class QvtInterpretedTransformation implements QvtTransformation {
public QvtInterpretedTransformation(IFile transformationFile) {
this(new WorkspaceQvtModule(transformationFile));
}
public QvtInterpretedTransformation(QvtModule qvtModule) {
if(qvtModule == null) {
throw new IllegalArgumentException("Null QvtModule"); //$NON-NLS-1$
}
myModule = qvtModule;
}
public QvtModule getModule() {
return myModule;
}
@Deprecated
public ModelContent loadInput(URI inputObjectURI) throws MdaException {
return EmfUtil.loadModel(inputObjectURI, myModule.getResourceSet());
}
public void setQvtCompilerOptions(QvtCompilerOptions options) {
myModule.setQvtCompilerOptions(options);
}
@Deprecated
public org.eclipse.m2m.internal.qvt.oml.runtime.generator.TransformationRunner.Out run(org.eclipse.m2m.internal.qvt.oml.runtime.generator.TransformationRunner.In in) throws MdaException {
Module module = myModule.getModule();
Iterator<TransformationParameter> itrParam = getParameters().iterator();
List<ModelContent> inputs = new ArrayList<ModelContent>(in.getSources().length);
for (ModelContent inSource : in.getSources()) {
TransformationParameter transfParam = null;
while (itrParam.hasNext()) {
transfParam = itrParam.next();
if (transfParam.getDirectionKind() != DirectionKind.OUT) {
break;
}
transfParam = null;
}
EObject mmClass = null;
if (transfParam != null) {
if (transfParam.getEntryType() != null) {
mmClass = transfParam.getEntryType();
}
else if (!transfParam.getMetamodels().isEmpty()) {
mmClass = transfParam.getMetamodels().get(0);
}
}
try {
inputs.add(inSource.getResolvedContent(mmClass));
}
catch (WrappedException e) {
throw new MdaException(e.getCause());
}
}
return evaluate(myModule.getResourceSet(), module, inputs, new Context(in.getContext()));
}
public String getModuleName() throws MdaException {
return myModule.getModule().getName();
}
public URI getURI() {
CompiledUnit unit = getUnit();
return unit != null ? unit.getURI() : URI.createURI(""); //$NON-NLS-1$
}
public List<TransformationParameter> getParameters() throws MdaException {
return myModule.getParameters();
}
public boolean hasEntryOperation() throws MdaException {
return QvtOperationalParserUtil.getMainOperation(myModule.getModule()) != null;
}
public boolean isBlackbox() throws MdaException {
return myModule.getModule().isIsBlackbox();
}
public Set<QvtConfigurationProperty> getConfigurationProperties() throws MdaException {
return myModule.getConfigurationProperties();
}
public ResourceSet getResourceSet() {
return myModule.getResourceSet();
}
public CompiledUnit getUnit() {
try {
return myModule.getUnit();
} catch(MdaException e) {
IStatus status = e.getStatus();
myDiagnostic = new ExecutionDiagnosticImpl(Diagnostic.ERROR, status.getCode(), status.getMessage());
myDiagnostic.addAll(BasicDiagnostic.toDiagnostic(status));
return null;
}
}
public void cleanup() {
myModule.cleanup();
}
protected QvtOperationalEnvFactory getEnvironmentFactory() {
if(myEnvFactory == null) {
myEnvFactory = new QvtOperationalEnvFactory();
}
return myEnvFactory;
}
protected void setEnvironmentFactory(QvtOperationalEnvFactory factory) {
myEnvFactory = factory;
}
@Deprecated
private org.eclipse.m2m.internal.qvt.oml.runtime.generator.TransformationRunner.Out evaluate(ResourceSet rs, Module module, List<ModelContent> args, IContext context) {
QvtOperationalEnvFactory factory = getEnvironmentFactory();
QvtOperationalEvaluationEnv evaluationEnv = factory.createEvaluationEnvironment(context, null);
// FIXME
setArguments(evaluationEnv, (OperationalTransformation) module, args, rs);
CompiledUnit unit;
try {
unit = myModule.getUnit();
} catch (MdaException e) {
// bad but we can not do better until
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=264335 is done
throw new IllegalStateException("unit must be available"); //$NON-NLS-1$
}
QvtOperationalFileEnv rootEnv = factory.createEnvironment(unit.getURI());
EvaluationVisitor<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject>
evaluator = factory.createEvaluationVisitor(rootEnv, evaluationEnv, null);
Trace traces = evaluationEnv.getAdapter(InternalEvaluationEnv.class).getTraces();
Object outObj = module.accept(evaluator);
if (false == outObj instanceof QvtEvaluationResult) {
return new org.eclipse.m2m.internal.qvt.oml.runtime.generator.TransformationRunner.Out(Collections.<ModelExtentContents>emptyList(),
Collections.emptyList(), traces);
}
return new org.eclipse.m2m.internal.qvt.oml.runtime.generator.TransformationRunner.Out(((QvtEvaluationResult) outObj).getModelExtents(),
((QvtEvaluationResult) outObj).getOutParamValues(), traces);
}
private static void setArguments(QvtOperationalEvaluationEnv evalEnv, OperationalTransformation transformation,
List<ModelContent> args, ResourceSet compilerRS) {
List<ModelParameterExtent> tranformArgs = new ArrayList<ModelParameterExtent>();
int argCount = 0;
for (ModelParameter modelParam : transformation.getModelParameter()) {
ModelParameterExtent extent;
if(modelParam.getKind() != org.eclipse.m2m.internal.qvt.oml.expressions.DirectionKind.OUT) {
if(argCount >= args.size()) {
throw new IllegalArgumentException("Invalid count of input arguments"); //$NON-NLS-1$
}
ModelContent nextArg = args.get(argCount++);
if(nextArg == null) {
throw new IllegalArgumentException("Non-null model argument is required"); //$NON-NLS-1$
} else {
extent = new ModelParameterExtent(nextArg.getContent(), compilerRS, modelParam);
}
} else {
extent = new ModelParameterExtent(compilerRS);
}
evalEnv.addModelExtent(extent);
tranformArgs.add(extent);
}
List<ModelInstance> modelArgs = ModelParameterHelper.createModelArguments(transformation, tranformArgs);
evalEnv.getOperationArgs().addAll(modelArgs);
}
@Override
public String toString() {
try {
return getModuleName();
}
catch (MdaException e) {
}
return super.toString();
}
private final QvtModule myModule;
private QvtOperationalEnvFactory myEnvFactory;
private ExecutionDiagnostic myDiagnostic = ExecutionDiagnosticImpl.createOkInstance();
public OperationalTransformation getTransformation(IProgressMonitor monitor) {
try {
Module module = myModule.getModule();
return module instanceof OperationalTransformation ? (OperationalTransformation) module : null;
}
catch(MdaException e) {
IStatus status = e.getStatus();
myDiagnostic = new ExecutionDiagnosticImpl(Diagnostic.ERROR, status.getCode(), status.getMessage());
myDiagnostic.addAll(BasicDiagnostic.toDiagnostic(status));
return null;
}
finally {
monitor.done();
}
}
public ExecutionDiagnostic getDiagnostic() {
return myDiagnostic;
}
}