blob: ca4ff2040611a58d2ae333e57f13d3699be71281 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2015 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
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.runtime.launch;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
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.util.FeatureMapUtil;
import org.eclipse.m2m.internal.qvt.oml.ModelExtentHelper;
import org.eclipse.m2m.internal.qvt.oml.ast.env.ModelExtentContents;
import org.eclipse.m2m.internal.qvt.oml.common.MdaException;
import org.eclipse.m2m.internal.qvt.oml.common.launch.BaseProcess;
import org.eclipse.m2m.internal.qvt.oml.common.launch.BaseProcess.IRunnable;
import org.eclipse.m2m.internal.qvt.oml.common.launch.IQvtLaunchConstants;
import org.eclipse.m2m.internal.qvt.oml.common.launch.SafeRunner;
import org.eclipse.m2m.internal.qvt.oml.common.launch.TargetUriData;
import org.eclipse.m2m.internal.qvt.oml.emf.util.EmfException;
import org.eclipse.m2m.internal.qvt.oml.emf.util.EmfUtil;
import org.eclipse.m2m.internal.qvt.oml.emf.util.Logger;
import org.eclipse.m2m.internal.qvt.oml.emf.util.ModelContent;
import org.eclipse.m2m.internal.qvt.oml.emf.util.StatusUtil;
import org.eclipse.m2m.internal.qvt.oml.emf.util.WorkspaceUtils;
import org.eclipse.m2m.internal.qvt.oml.library.Context;
import org.eclipse.m2m.internal.qvt.oml.runtime.generator.TraceSerializer;
import org.eclipse.m2m.internal.qvt.oml.runtime.generator.TransformationRunner;
import org.eclipse.m2m.internal.qvt.oml.runtime.launch.QvtValidator.ValidationType;
import org.eclipse.m2m.internal.qvt.oml.runtime.project.QvtModule;
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.internal.qvt.oml.runtime.util.MiscUtil;
import org.eclipse.m2m.internal.qvt.oml.trace.Trace;
import org.eclipse.m2m.qvt.oml.util.IContext;
import org.eclipse.m2m.qvt.oml.util.WriterLog;
import org.eclipse.osgi.util.NLS;
public abstract class QvtLaunchConfigurationDelegateBase extends LaunchConfigurationDelegate {
@Override
protected IProject[] getProjectsForProblemSearch(ILaunchConfiguration configuration, String mode) throws CoreException {
IFile moduleFile = getModuleFile(configuration);
if (moduleFile == null || !moduleFile.exists()) {
return new IProject[0];
}
return new IProject[] { moduleFile.getProject() };
}
public static QvtModule getQvtModule(ILaunchConfiguration configuration) throws CoreException {
try {
String moduleUri = QvtLaunchUtil.getTransformationURI(configuration);
return TransformationUtil.getQvtModule(EmfUtil.makeUri(moduleUri));
} catch (MdaException e) {
IStatus errorStatus = MiscUtil.makeErrorStatus(e.getMessage());
throw new CoreException(errorStatus);
}
}
public static IFile getModuleFile(ILaunchConfiguration configuration) throws CoreException {
String moduleFileName = configuration.getAttribute(IQvtLaunchConstants.MODULE, ""); //$NON-NLS-1$
URI moduleUri = URI.createURI(moduleFileName);
IFile moduleFile = WorkspaceUtils.getWorkspaceFile(moduleUri);
if(moduleFile == null) {
//IStatus errorStatus = MiscUtil.makeErrorStatus(
// NLS.bind(Messages.QvtLaunchConfigurationDelegate_transformationFileNotFound, moduleFileName));
//throw new CoreException(errorStatus);
}
return moduleFile;
}
public static IStatus validate(QvtTransformation transformation, ILaunchConfiguration configuration) throws CoreException {
List<TargetUriData> targetUris = QvtLaunchUtil.getTargetUris(configuration);
String traceFile = configuration.getAttribute(IQvtLaunchConstants.TRACE_FILE, ""); //$NON-NLS-1$
boolean useTraceFile = configuration.getAttribute(IQvtLaunchConstants.USE_TRACE_FILE, false);
boolean isIncrementalUpdate = configuration.getAttribute(IQvtLaunchConstants.IS_INCREMENTAL_UPDATE, false);
try {
return QvtValidator.validateTransformation(transformation, targetUris, traceFile, useTraceFile,
isIncrementalUpdate, ValidationType.FULL_VALIDATION);
}
catch (MdaException ex) {
throw new CoreException(StatusUtil.makeErrorStatus(ex.getMessage(), ex));
}
}
public static BaseProcess.IRunnable getSafeRunnable(QvtTransformation transformation, IRunnable r) throws CoreException {
return SafeRunner.getSafeRunnable(r);
}
public static void doLaunch(QvtTransformation transformation, ILaunchConfiguration configuration, IContext context) throws Exception {
List<ModelContent> inObjects = new ArrayList<ModelContent>();
List<TargetUriData> targetData = new ArrayList<TargetUriData>();
List<TargetUriData> targetUris = QvtLaunchUtil.getTargetUris(configuration);
Iterator<TargetUriData> itrTargetData = targetUris.iterator();
for (TransformationParameter transfParam : transformation.getParameters()) {
if (!itrTargetData.hasNext()) {
throw new MdaException(NLS.bind(Messages.QvtValidator_EmptyInputTransfParam,
transfParam.getName()));
}
TargetUriData nextUri = itrTargetData.next();
if (transfParam.getDirectionKind() == DirectionKind.IN || transfParam.getDirectionKind() == DirectionKind.INOUT) {
ModelContent inModel = null;
if (nextUri.getContentProvider() != null) {
inModel = new ModelContent(nextUri.getContentProvider().getContents());
}
else {
URI inUri = toUri(nextUri.getUriString());
inModel = transformation.loadInput(inUri);
}
inObjects.add(inModel);
}
if (transfParam.getDirectionKind() == DirectionKind.OUT || transfParam.getDirectionKind() == DirectionKind.INOUT) {
targetData.add(nextUri);
}
}
boolean saveTrace = configuration.getAttribute(IQvtLaunchConstants.USE_TRACE_FILE, false);
String traceFile = configuration.getAttribute(IQvtLaunchConstants.TRACE_FILE, ""); //$NON-NLS-1$
boolean isIncrementalUpdate = configuration.getAttribute(IQvtLaunchConstants.IS_INCREMENTAL_UPDATE, false);
if (isIncrementalUpdate && traceFile != null) {
ModelContent traceContent = EmfUtil.safeLoadModel(URI.createURI(traceFile), transformation.getResourceSet());
if (traceContent != null) {
context.getTrace().setTraceContent(traceContent.getContent());
}
}
doLaunch(transformation, inObjects, targetData, saveTrace ? traceFile : null, context);
}
public static void doLaunch(QvtTransformation transformation, List<ModelContent> inObjs, Map<String, Object> configProps,
List<ModelExtentContents> outExtents, List<EObject> outMainParams, List<Trace> outTraces, List<String> outConsole) throws MdaException {
IStatus status = QvtValidator.validateTransformation(transformation, inObjs, null);
if (status.getSeverity() > IStatus.WARNING) {
throw new MdaException(status);
}
Context context = QvtLaunchUtil.createContext(configProps);
final StringWriter consoleLogger = new StringWriter();
context.setLog(new WriterLog(consoleLogger));
TransformationRunner.In in = new TransformationRunner.In(inObjs.toArray(new ModelContent[inObjs.size()]), context);
TransformationRunner.Out out = transformation.run(in);
outExtents.addAll(out.getExtents());
for (Object outValue : out.getOutParamValues()) {
if (outValue instanceof EObject) {
outMainParams.add((EObject) outValue);
}
else {
outMainParams.add(null);
}
}
if (out.getTrace() != null) {
outTraces.add(out.getTrace());
}
outConsole.add(consoleLogger.getBuffer().toString());
}
public static List<URI> doLaunch(final QvtTransformation transformation, final List<ModelContent> inObjs,
List<TargetUriData> targetData, final String traceFileName, IContext context) throws Exception {
TransformationRunner.In in = new TransformationRunner.In(inObjs.toArray(new ModelContent[inObjs.size()]), context);
TransformationRunner.Out out = transformation.run(in);
ResourceSet resSet = transformation.getResourceSet();
if(resSet == null) {
for (ModelContent inModel : inObjs) {
resSet = inModel.getResourceSet();
if(resSet != null) {
break;
}
}
}
if(resSet == null) {
resSet = EmfUtil.getOutputResourceSet();
}
Iterator<ModelExtentContents> itrExtent = out.getExtents().iterator();
for (TargetUriData outUriData : targetData) {
if (!itrExtent.hasNext()) {
throw new MdaException("Incomplete transformation results"); //$NON-NLS-1$
}
saveTransformationResult(itrExtent.next(), outUriData, resSet);
}
List<URI> result = new ArrayList<URI>(out.getOutParamValues().size());
for (Object outValue : out.getOutParamValues()) {
if (outValue instanceof EObject) {
result.add(EcoreUtil.getURI((EObject) outValue));
}
else {
result.add(null);
}
}
if(out.getTrace() != null) {
if(traceFileName != null) {
URI traceUri = EmfUtil.makeUri(traceFileName);
TraceSerializer traceSerializer = new TraceSerializer(out.getTrace());
traceSerializer.saveTraceModel(traceUri);
traceSerializer.markUnboundObjects(traceUri);
}
//context.getTrace().setTraceContent(Collections.singletonList(out.getTrace()));
}
return result;
}
@SuppressWarnings("unchecked")
private static void saveTransformationResult(ModelExtentContents extent, TargetUriData targetData, ResourceSet resSet) throws MdaException {
if (targetData.getContentProvider() != null) {
targetData.getContentProvider().setContents(extent.getAllRootElements());
return;
}
URI outUri = toUri(targetData.getUriString());
switch(targetData.getTargetType()) {
case NEW_MODEL: {
try {
ModelExtentHelper.saveExtentToResources(extent.getAllRootElements(), resSet, outUri);
}
catch(EmfException e) {
throw new MdaException(e);
}
break;
}
case EXISTING_CONTAINER: {
ModelContent loadModel = EmfUtil.loadModel(outUri, resSet);
EObject container = (loadModel != null && !loadModel.getContent().isEmpty() ? loadModel.getContent().get(0) : null);
if(container == null) {
throw new MdaException("No object at " + outUri); //$NON-NLS-1$
}
EStructuralFeature feature = container.eClass().getEStructuralFeature(targetData.getFeature());
if (feature == null) {
throw new MdaException("Reference " + targetData.getFeature() + " not found in " + container); //$NON-NLS-1$ //$NON-NLS-2$
}
if (targetData.isClearContents() && FeatureMapUtil.isMany(container, feature)) {
List<EObject> value = (List<EObject>) container.eGet(feature);
if (value != null) {
value.clear();
}
}
for (EObject out : extent.getAllRootElements()) {
if (FeatureMapUtil.isMany(container, feature)) {
List<EObject> value = (List<EObject>) container.eGet(feature);
try {
value.add(out);
}
catch (RuntimeException ex) {
throw new MdaException(NLS.bind(Messages.QvtLaunchConfigurationDelegateBase_FeatureSetFailure,
EmfUtil.getFullName(out.eClass()), targetData.getFeature()));
}
}
else {
container.eSet(feature, out);
}
}
try {
saveResource(container);
}
catch(IOException e) {
throw new MdaException(e.getMessage(), e);
}
break;
}
case INPLACE: {
throw new MdaException(Messages.QvtValidator_InplaceConfigNotSupported);
}
}
org.eclipse.m2m.internal.qvt.oml.emf.util.URIUtils.refresh(outUri);
}
private static void saveResource(EObject obj) throws IOException {
Resource resource = obj.eResource();
if(resource == null) {
Logger.getLogger().warning("Object has no resource: " + obj); //$NON-NLS-1$
return;
}
resource.save(EmfUtil.DEFAULT_SAVE_OPTIONS);
}
private static URI toUri(String uriString) throws MdaException {
URI uri = URI.createURI(uriString);
if(uri == null) {
throw new MdaException(NLS.bind(Messages.QvtValidator_InvalidUri, uriString));
}
return uri;
}
}