/**
 * 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.expressions.interpreter.IExecutionSlotResolver;
import org.yakindu.base.expressions.interpreter.IOperationMockup;
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;
	}
}

@@ -503,16 +503,52 @@
 il.List;
+%0Aimport java.util.stream.Collectors;
 %0A%0Aimport
@@ -929,16 +929,73 @@
 Factory;
+%0Aimport org.yakindu.sct.model.stext.stext.InterfaceScope;
 %0A%0Aimport
@@ -1715,17 +1715,21 @@
 project,
- 
+%0A%09%09%09%09
 getClass
@@ -1730,21 +1730,16 @@
 tClass()
-%0A%09%09%09%09
 .getClas
@@ -2570,16 +2570,354 @@
 eter) %7B%0A
+%09%09List%3CObject%3E targets = callbacks;%0A%09%09if (definition.eContainer() instanceof InterfaceScope) %7B%0A%09%09%09String className = ((InterfaceScope) definition.eContainer()).getName();%0A%09%09%09if (className != null) %7B%0A%09%09%09%09targets = callbacks.stream().filter(c -%3E className.equals(c.getClass().getSimpleName()))%0A%09%09%09%09%09%09.collect(Collectors.toList());%0A%09%09%09%7D%0A%09%09%7D%0A
 %09%09Polymo
@@ -3004,25 +3004,29 @@
 n.getName(),
- 
+%0A%09%09%09%09
 definition%0A%09
@@ -3023,21 +3023,16 @@
 finition
-%0A%09%09%09%09
 .getPara
@@ -3082,16 +3082,51 @@
 .size(),
+%0A%09%09%09%09targets.size() %3E 0 ? targets :
  callbac

Check first for class names with same name as interface #2095 (#2101)