blob: 8a8556243440fa2896959e3469e29c03612d2041 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2018 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
* Christopher Gerking - bugs 289982, 326871, 427237
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.blackbox.java;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
import org.eclipse.m2m.internal.qvt.oml.NLS;
import org.eclipse.m2m.internal.qvt.oml.QvtPlugin;
import org.eclipse.m2m.internal.qvt.oml.ast.binding.ASTBindingHelper;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalModuleEnv;
import org.eclipse.m2m.internal.qvt.oml.blackbox.BlackboxException;
import org.eclipse.m2m.internal.qvt.oml.blackbox.BlackboxProvider;
import org.eclipse.m2m.internal.qvt.oml.blackbox.BlackboxUnit;
import org.eclipse.m2m.internal.qvt.oml.blackbox.BlackboxUnitDescriptor;
import org.eclipse.m2m.internal.qvt.oml.blackbox.LoadContext;
import org.eclipse.m2m.internal.qvt.oml.blackbox.OperationMatcher;
import org.eclipse.m2m.internal.qvt.oml.common.util.StringLineNumberProvider;
import org.eclipse.m2m.internal.qvt.oml.cst.CSTFactory;
import org.eclipse.m2m.internal.qvt.oml.emf.util.EmfUtilPlugin;
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.internal.qvt.oml.stdlib.CallHandler;
import org.eclipse.m2m.internal.qvt.oml.stdlib.CallHandlerAdapter;
public abstract class JavaBlackboxProvider extends BlackboxProvider {
public static final String CLASS_NAME_SEPARATOR = "."; //$NON-NLS-1$
static InstanceAdapterFactory createInstanceAdapterFactory(final Class<?> javaModuleClass) {
return new InstanceAdapterFactory() {
public Object createAdapter(EObject moduleInstance) {
try {
return javaModuleClass.newInstance();
} catch (InstantiationException e) {
// FIXME - choose a better exception
throw new IllegalArgumentException("Illegal adapter instance", e); //$NON-NLS-1$
} catch (IllegalAccessException e) {
// FIXME - choose a better exception
throw new IllegalArgumentException("Illegal adapter instance", e); //$NON-NLS-1$
}
}
};
}
private JavaModuleLoader createJavaModuleLoader() {
return new JavaModuleLoader() {
JavaMethodHandlerFactory handlerFactory;
@Override
protected void loadModule(QvtOperationalModuleEnv moduleEnv, final Class<?> javaModuleClass) {
handlerFactory = new JavaMethodHandlerFactory(moduleEnv.getOCLStandardLibrary());
Module module = moduleEnv.getModuleContextType();
// FIXME - workaround to make Environment available with the
// module for
// non-transformation execution context
ASTBindingHelper.createCST2ASTBinding(CSTFactory.eINSTANCE.createLibraryCS(), module, moduleEnv);
setInstanceAdapterFactory(module, createInstanceAdapterFactory(javaModuleClass));
}
@Override
protected void loadOperation(EOperation operation, Method javaOperation) {
setOperationHandler(operation, handlerFactory.createHandler(javaOperation), true);
}
};
}
protected static String getPackageNameFromJavaClass(String className) {
int lastSeparatorPos = className.lastIndexOf(CLASS_NAME_SEPARATOR);
if (lastSeparatorPos < 0) {
return null;
}
return className.substring(0, lastSeparatorPos);
}
protected static String getSimpleNameFromJavaClass(String className) {
int lastSeparatorPos = className.lastIndexOf(CLASS_NAME_SEPARATOR);
if (lastSeparatorPos < 0) {
return className;
}
return className.substring(lastSeparatorPos + 1);
}
public abstract class JavaUnitDescriptor extends BlackboxUnitDescriptor {
private BlackboxUnit unit;
private Map<ModuleHandle, Map<String, List<EOperation>>> fModules = new LinkedHashMap<ModuleHandle, Map<String, List<EOperation>>>();
public JavaUnitDescriptor(String unitQualifiedName) {
super(JavaBlackboxProvider.this, unitQualifiedName);
}
protected void addModuleHandle(ModuleHandle moduleHandle) {
fModules.put(moduleHandle, new LinkedHashMap<String, List<EOperation>>());
}
public Collection<CallHandler> getBlackboxCallHandler(ImperativeOperation imperativeOp, QvtOperationalModuleEnv env) {
Set<String> importedLibs = env.getImportedNativeLibs().get(getURI());
Collection<CallHandler> result = Collections.emptyList();
for (Map.Entry<ModuleHandle, Map<String, List<EOperation>>> nextEntry : fModules.entrySet()) {
if (!env.getImportedNativeLibs().isEmpty()) {
if (!importedLibs.contains(nextEntry.getKey().getModuleName())) {
continue;
}
}
List<EOperation> listOp = nextEntry.getValue().get(imperativeOp.getName());
if (listOp == null) {
continue;
}
for (EOperation libraryOp : listOp) {
if (OperationMatcher.matchOperation(env, imperativeOp, libraryOp)) {
if (result.isEmpty()) {
result = new LinkedList<CallHandler>();
}
result.add(CallHandlerAdapter.getDispatcher(libraryOp));
}
}
}
return result;
}
public Collection<CallHandler> getBlackboxCallHandler(OperationalTransformation transformation,
QvtOperationalModuleEnv env) {
Set<String> importedLibs = env.getImportedNativeLibs().get(getURI());
Collection<CallHandler> result = Collections.emptyList();
for (Map.Entry<ModuleHandle, Map<String, List<EOperation>>> nextEntry : fModules.entrySet()) {
if (!env.getImportedNativeLibs().isEmpty()) {
if (!importedLibs.contains(nextEntry.getKey().getModuleName())) {
continue;
}
}
List<EOperation> listOp = nextEntry.getValue().get(transformation.getName());
if (listOp == null) {
continue;
}
for (EOperation libraryOp : listOp) {
if (OperationMatcher.matchOperation(env, transformation, libraryOp)) {
if (result.isEmpty()) {
result = new LinkedList<CallHandler>();
}
result.add(CallHandlerAdapter.getDispatcher(libraryOp));
}
}
}
return result;
}
@Override
public BlackboxUnit load(LoadContext context) throws BlackboxException {
if (unit != null) {
return unit;
}
JavaModuleLoader javaModuleLoader = createJavaModuleLoader();
Resource unitResource = new EcoreResourceFactoryImpl().createResource(getURI());
BasicDiagnostic errors = null;
List<QvtOperationalModuleEnv> loadedModules = new LinkedList<QvtOperationalModuleEnv>();
for (Map.Entry<ModuleHandle, Map<String, List<EOperation>>> nextEntry : fModules.entrySet()) {
Diagnostic diagnostic = javaModuleLoader.loadModule(nextEntry.getKey(), nextEntry.getValue(), context);
if (EmfUtilPlugin.isSuccess(diagnostic)) {
QvtOperationalModuleEnv nextModuleEnv = javaModuleLoader.getLoadedModule();
nextModuleEnv.getTypeResolver().getResource().setURI(getURI());
ASTBindingHelper.createModuleSourceBinding(nextModuleEnv.getModuleContextType(), getURI(),
new StringLineNumberProvider("")); //$NON-NLS-1$
loadedModules.add(nextModuleEnv);
unitResource.getContents().add(nextModuleEnv.getModuleContextType());
if (diagnostic.getSeverity() != Diagnostic.OK) {
QvtPlugin.logDiagnostic(diagnostic);
}
} else {
if (errors == null) {
String message = NLS.bind(JavaBlackboxMessages.BlackboxUnitLoadFailed, getQualifiedName());
errors = DiagnosticUtil.createErrorDiagnostic(message);
}
errors.add(diagnostic);
}
}
if (errors != null) {
final Diagnostic failDiagnostic = errors;
unit = new BlackboxUnit() {
public List<QvtOperationalModuleEnv> getElements() {
return Collections.emptyList();
}
public Diagnostic getDiagnostic() {
return failDiagnostic;
}
};
assert errors.getSeverity() == Diagnostic.ERROR;
throw new BlackboxException(errors);
}
unit = createBlackboxUnit(loadedModules);
return unit;
}
protected void unload() {
for (Map<String, List<EOperation>> operations : fModules.values()) {
operations.clear();
}
unit = null;
}
}
}