/******************************************************************************* * Copyright (c) 2007, 2008 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 *******************************************************************************/ /* * Created on Jun 28, 2005 */ package org.eclipse.m2m.internal.qvt.oml.ocl.transformations; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.LinkedList; import java.util.List; import org.eclipse.m2m.internal.qvt.oml.ocl.Logger; import org.eclipse.m2m.internal.qvt.oml.ocl.metainfo.OclMetainfoOperation; class LibraryOperationImpl implements LibraryOperation { public LibraryOperationImpl(OclMetainfoOperation meta, Library library) throws LibraryOperationException, LibraryCreationException { myLibrary = library; myName = meta.getMethod().getName(); myMethod = meta.getMethod(); myContext = meta.getContextType(); myReturnType = meta.getType(); myParameterTypes = new LinkedList<String>(meta.getParameterTypes()); } public Library getLibrary() { return myLibrary; } public void load() throws LibraryOperationException { } public String getContext() { return myContext; } public String getName() { return myName; } public String getReturnType() { return myReturnType; } public List<String> getParameterTypes() { return myParameterTypes; } public List<String> getImplicitParameterNames() { return IMPLICIT_PARAMETERS_LIST; } public Object run(Object context, Object[] explicitParameterValues, Object[] implicitParameterValues, Class<?> returnTypeClass) { Object[] explicitParameterValuesWithContext = getJoinArray( new Object[] { context }, explicitParameterValues); Object[] parameters = getJoinArray(implicitParameterValues, explicitParameterValuesWithContext); if (!isMethodApplicable(parameters, returnTypeClass)) { parameters = explicitParameterValuesWithContext; if (!isMethodApplicable(parameters, returnTypeClass)) { parameters = explicitParameterValues; if (!isMethodApplicable(parameters, returnTypeClass)) { throw new RuntimeException("Unable to execute native method -- incorrect parameters passed: " + Arrays.asList(parameters)); //$NON-NLS-1$ } } } Method method = getMethod(); try { return method.invoke(getLibrary().getLibraryInstance(), parameters); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e.getTargetException()); } } public String getOperationReference(String[] parameterNames) { String className = getLibrary().getLibraryClassName().replaceAll( "\\$", "."); //$NON-NLS-1$ //$NON-NLS-2$ StringBuffer paramString = new StringBuffer(); for (int i = 0, len = parameterNames.length; i < len; i++) { paramString.append(parameterNames[i]); if (i < len - 1) { paramString.append(", "); //$NON-NLS-1$ } } String call = "new " + className + "()." + getName() + "(" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + paramString + ")"; //$NON-NLS-1$ return call; } private Object[] getJoinArray(Object[] first, Object[] second) { Object[] result = new Object[first.length + second.length]; System.arraycopy(first, 0, result, 0, first.length); System.arraycopy(second, 0, result, first.length, second.length); return result; } private boolean isMethodApplicable(Object[] parameterValues, Class<?> returnType) { Class<?>[] parameterClasses = getParameterClasses(parameterValues); Method method = getMethod(); Class<?>[] methodParameters = method.getParameterTypes(); if (parameterClasses.length != methodParameters.length) { return false; } for (int i = 0; i < parameterClasses.length; i++) { // null parameters are conformed to any classes Class<?> required = methodParameters[i]; Class<?> actual = parameterClasses[i]; if (actual != null && !required.isAssignableFrom(actual)) { Logger.getLogger().log(Logger.WARNING, "Type " + required //$NON-NLS-1$ + " is not assignable from " + actual); //$NON-NLS-1$ return false; } } if (returnType != null && !returnType.isAssignableFrom(method.getReturnType())) { Logger.getLogger().log(Logger.SEVERE, "Required return type " + returnType //$NON-NLS-1$ + " is not assignable from method return type " //$NON-NLS-1$ + method.getReturnType()); return false; } return true; } private Class<?>[] getParameterClasses(Object[] parameters) { Collection<Class<?>> parameterClasses = new ArrayList<Class<?>>(); for (Object param : parameters) { // null parameters are conformed to any classes parameterClasses.add(param == null ? null : param.getClass()); } return parameterClasses.toArray(new Class[parameterClasses.size()]); } private Method getMethod() { return myMethod; } @Override public String toString() { return myName + myParameterTypes + "/" + myLibrary; //$NON-NLS-1$ } private Library myLibrary; private String myName; private String myContext; private String myReturnType; private List<String> myParameterTypes; private Method myMethod; private static final List<String> IMPLICIT_PARAMETERS_LIST = new LinkedList<String>(); }