/*******************************************************************************
* Copyright (c) 2006-2012
* Software Technology Group, Dresden University of Technology
* DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026
*
* 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:
* Software Technology Group - TU Dresden, Germany;
* DevBoost GmbH - Berlin, Germany
* - initial API and implementation
******************************************************************************/
package org.reuseware.coconut.reuseextension.evaluator.ocl;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.eclipse.ocl.EvaluationEnvironment;
import org.eclipse.ocl.ecore.EcoreEvaluationEnvironment;
/**
* The evaluation environment for the enhanced OCL Ecore environment.
*/
public class EnhancedEcoreEvaluationEnvironment extends
EcoreEvaluationEnvironment {
EnhancedEcoreEvaluationEnvironment() {
super();
}
EnhancedEcoreEvaluationEnvironment(
EvaluationEnvironment<EClassifier, EOperation, EStructuralFeature, EClass, EObject> parent) {
super(parent);
}
/**
* Extended to call the additional supported operations
* (see <code>EnhancedEcoreEnvironment</code>).
*
* @param operation the operation to call
* @param opcode the opcode
* @param source the object to call the operation on
* @param args operation call arguments
*
* @return result of the operation call
*/
@Override
public Object callOperation(EOperation operation, int opcode, Object source, Object[] args) {
if (operation.getEAnnotation("JavaMethod") != null) {
if (source instanceof EObject /*might be error object*/) {
return source;
}
String name = operation.getName();
// get the parameter types as java classes
EList<EParameter> parms = operation.getEParameters();
Class<?>[] javaParms = new Class[parms.size()];
for (int i = 0, n = parms.size(); i < n; i++) {
EParameter parm = parms.get(i);
if (parm.isMany()) {
javaParms[i] = EList.class;
} else {
javaParms[i] = parm.getEType().getInstanceClass();
}
}
//replace null with "" to allow operation calls of String attributes set to null
if (source == null) {
source = "";
}
Method javaMethod = null;
try {
javaMethod = String.class.getMethod(name, javaParms);
} catch (NoSuchMethodException e) {
for (int i = 0, n = javaParms.length; i < n; i++) {
if (javaParms[i] == String.class) {
javaParms[i] = CharSequence.class;
}
}
try {
javaMethod = String.class.getMethod(name, javaParms);
} catch (Exception e2) {
e2.printStackTrace();
}
}
try {
Object result = javaMethod.invoke(source, args);
if (result.getClass().isArray()) {
result = Arrays.asList((Object[]) result);
}
return result;
} catch (Exception e) {
e.printStackTrace();
}
throw new UnsupportedOperationException(); // unknown operation
// not our custom regex operation
} else if (operation.getEAnnotation("EContainerOperation") != null) {
if (source instanceof EObject) {
return ((EObject) source).eContainer();
} else {
return null;
}
} else if (operation.getEAnnotation("toStringOperation") != null) {
if (source instanceof EObject /*might be error object*/ || source == null) {
return source;
}
return source.toString();
} else if (operation.getEAnnotation("getValueOperation") != null) {
if (source instanceof FeatureMap.Entry) {
return ((FeatureMap.Entry) source).getValue();
}
return null;
}
return super.callOperation(operation, opcode, source, args);
}
}