/**
* Copyright (c) 2008 Borland Software Corp.
*
* 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:
* Alexander Shatalin (Borland) - initial API and implementation
*/
package org.eclipse.gmf.internal.xpand.xtend.ast;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.gmf.internal.xpand.model.AnalysationIssue;
import org.eclipse.gmf.internal.xpand.model.ExecutionContext;
import org.eclipse.m2m.internal.qvt.oml.expressions.Helper;
import org.eclipse.m2m.internal.qvt.oml.runtime.util.HelperOperationCall;
public class QvtExtension implements GenericExtension {
private QvtResource qvtResource;
private List<String> parameterNames;
private List<EClassifier> parameterTypes;
private String fileName;
private HelperOperationCall helperCall;
public QvtExtension(HelperOperationCall helperOperationCall, QvtFile qvtFile, String fileName) {
this.helperCall = helperOperationCall;
qvtResource = qvtFile;
this.fileName = fileName;
}
public void setQvtResource(QvtResource resource) {
qvtResource = resource;
}
public QvtResource getQvtResource() {
return qvtResource;
}
public Object evaluate(Object[] parameters, ExecutionContext ctx) {
try {
if (helperCall.isContextual()) {
// TODO: this is a proper way to get context variable (self) for
// now
// getting this variable from the parameters array in accordance
// with OperationCall.evaluateInternal() implementation
// Variable selfVariable =
// ctx.getVariable(ExecutionContext.IMPLICIT_VARIABLE);
assert parameters.length > 0;
Object self = parameters[0];
Object[] actualParameters = new Object[parameters.length - 1];
System.arraycopy(parameters, 1, actualParameters, 0, parameters.length - 1);
return helperCall.invoke(self, actualParameters);
} else {
return helperCall.invoke(parameters);
}
} catch (IllegalArgumentException e) {
throw new RuntimeException("Illigal arguments in QVT helper (" + getSignature(helperCall.getOperation()) + ") call: " + e.getMessage());
} catch (InvocationTargetException e) {
throw new RuntimeException("Invocation target exception in QVT helper (" + getSignature(helperCall.getOperation()) + ") call: " + e.getMessage());
}
}
private String getSignature(Helper operation) {
StringBuilder sb = new StringBuilder();
if (operation.getContext() != null) {
sb.append(operation.getContext().getEType().getName());
sb.append("::");
}
sb.append(operation.getName());
sb.append("(");
for (EParameter parameter : operation.getEParameters()) {
if (sb.lastIndexOf("(") != sb.length() - 1) {
sb.append(",");
}
sb.append(parameter.getName());
sb.append(":");
sb.append(parameter.getEType().getName());
}
sb.append(")");
sb.append(":");
sb.append(operation.getEType().getName());
return sb.toString();
}
public String getName() {
return getHelper().getName();
}
public List<EClassifier> getParameterTypes() {
if (parameterTypes == null) {
parameterTypes = new ArrayList<EClassifier>();
// TODO: we should be able to distinguish between static and
// context-specific queries
if (getHelper().getContext() != null) {
parameterTypes.add(getHelper().getContext().getEType());
}
for (EParameter parameter : getHelper().getEParameters()) {
parameterTypes.add(parameter.getEType());
}
parameterTypes = Collections.unmodifiableList(parameterTypes);
}
return parameterTypes;
}
public List<String> getParameterNames() {
if (parameterNames == null) {
parameterNames = new ArrayList<String>();
for (EParameter parameter : getHelper().getEParameters()) {
parameterNames.add(parameter.getName());
}
parameterNames = Collections.unmodifiableList(parameterNames);
}
return parameterNames;
}
// FIXME what's this method for? can't find a use...
public EClassifier getReturnType(EClassifier[] parameters, ExecutionContext ctx, Set<AnalysationIssue> issues) {
// TODO: deduce return type here? (need another visitor?)
return getHelper().getEType();
}
public void init(ExecutionContext ctx) {
// TODO nothing to do here? Call QVT to preparse AST?..
}
public String getFileName() {
return fileName;
}
private Helper getHelper() {
return helperCall.getOperation();
}
public EClassifier getContext() {
return helperCall.getContextType();
}
public EOperation getOperation() {
return helperCall.getOperation();
}
}