/** * Copyright (c) 2013-2015 committers of YAKINDU 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: * committers of YAKINDU - initial API and implementation * */ package org.yakindu.sct.simulation.core.sexec.interpreter; import java.lang.reflect.Method; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.emf.common.util.WrappedException; import org.eclipse.xtext.util.PolymorphicDispatcher; import org.yakindu.base.types.Operation; import org.yakindu.sct.commons.WorkspaceClassLoaderFactory; import com.google.common.collect.Lists; import com.google.inject.Inject; import com.google.inject.Singleton; /** * Implementation of {@link IOperationMockup} interface that delegates simulator * operation calls to Java classes. These classes can be specified in the run * configuration tab. * * @author andreas muelder - Initial contribution and API * */ @Singleton public class JavaOperationMockup implements IOperationMockup { @Inject protected IExecutionSlotResolver resolver; private List<Object> callbacks; public void initOperationCallbacks(IProject project, String[] classes) { callbacks = Lists.newArrayList(); ClassLoader classLoader = new WorkspaceClassLoaderFactory().createClassLoader(project, getClass() .getClassLoader()); try { if (classes.length > 0) for (String string : classes) { string = string.trim(); if (string.length() == 0) continue; Class<?> loadClass = classLoader.loadClass(string); callbacks.add(loadClass.newInstance()); } } catch (Exception e) { e.printStackTrace(); } } @Override public boolean canExecute(Operation definition, Object[] parameter) { for (Object callback : callbacks) { Class<?> current = callback.getClass(); while (current != Object.class) { Method[] methods = current.getDeclaredMethods(); for (Method method : methods) { if (hasSignatureMatch(definition, method)) { return true; } } current = current.getSuperclass(); } } return false; } public Object execute(Operation definition, Object[] parameter) { PolymorphicDispatcher<Object> dispatcher = new PolymorphicDispatcher<Object>(definition.getName(), definition .getParameters().size(), definition.getParameters().size(), callbacks); try { return dispatcher.invoke(parameter); } catch (Exception ex) { throw new WrappedException("Error during invocation of operation '" + definition.getName() + "' with params " + definition.getParameters() + " '", ex); } } protected boolean hasSignatureMatch(Operation definition, Method method) { if (!definition.getName().equals(method.getName())) { return false; } if (!(definition.getParameters().size() == method.getParameterTypes().length)) { return false; } // TODO: Check parameter types and return type match. For this a // JavaTypeChecker should be introduced to get a matching Java type for // a YAKINDU Type System type. return true; } }