blob: 83575b08aa2f75f1603bc3215c2313f0c2040b8b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2018 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 v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Borland Software Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.stdlib;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEvaluationEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.parser.QvtOperationalParserUtil;
import org.eclipse.m2m.internal.qvt.oml.evaluator.ModuleInstance;
import org.eclipse.ocl.ecore.EcoreEnvironment;
import org.eclipse.ocl.expressions.ExpressionsFactory;
import org.eclipse.ocl.expressions.Variable;
public abstract class AbstractContextualOperations {
protected static final CallHandler UNSUPPORTED_OPER = new CallHandler() {
public Object invoke(ModuleInstance module, Object source,
Object[] args, QvtOperationalEvaluationEnv evalEnv) {
throw new UnsupportedOperationException();
}
};
private final EClassifier fContextType;
private final AbstractQVTStdlib fLib;
protected AbstractContextualOperations(AbstractQVTStdlib lib, EClassifier contextType) {
if(lib == null || contextType == null) {
throw new IllegalArgumentException();
}
fContextType = contextType;
fLib = lib;
}
protected abstract OperationProvider[] getOperations();
public AbstractQVTStdlib getStdlib() {
return fLib;
}
public void define(EcoreEnvironment env) {
for (OperationProvider operation : getOperations()) {
EOperation defOper = operation.define(env);
if(operation.fIsStatic) {
QvtOperationalParserUtil.markAsStaticOperation(defOper);
}
if(CallHandlerAdapter.getDispatcher(defOper) == UNSUPPORTED_OPER) {
QvtOperationalParserUtil.markAsUnsupported(defOper,
(operation.fParamNames != null && operation.fParamNames.length > operation.fParamTypes.length)
? operation.fParamNames[operation.fParamTypes.length] : null);
}
}
}
protected OperationProvider createOwnedStaticOperationProvider(CallHandler dispatcher, String name, String[] parameterNames, EClassifier returnType, EClassifier... paramTypes) {
OperationProvider provider = new OwnedOperationProvider(dispatcher, name, parameterNames, returnType, paramTypes);
provider.fIsStatic = true;
return provider;
}
protected OperationProvider createStaticOperationProvider(CallHandler dispatcher, String name, String[] parameterNames, EClassifier returnType, EClassifier... paramTypes) {
OperationProvider provider = new OperationProvider(dispatcher, name, parameterNames, returnType, paramTypes);
provider.fIsStatic = true;
return provider;
}
protected class OwnedOperationProvider extends OperationProvider {
public OwnedOperationProvider(CallHandler dispatcher, String name,
EClassifier returnType, EClassifier... paramTypes) {
super(dispatcher, name, returnType, paramTypes);
}
public OwnedOperationProvider(CallHandler dispatcher, String name, String[] parameterNames,
EClassifier returnType, EClassifier... paramTypes) {
super(dispatcher, name, parameterNames, returnType, paramTypes);
}
@Override
public EOperation define(EcoreEnvironment env) {
EOperation eOperation = EcoreFactory.eINSTANCE.createEOperation();
eOperation.setName(fName);
int pos = 0;
for (EClassifier cls : fParamTypes) {
EParameter eParam = EcoreFactory.eINSTANCE.createEParameter();
String paramName = cls.getName();
if(fParamNames != null) {
paramName = fParamNames[pos++];
}
eParam.setName(paramName);
eParam.setEType(cls);
eOperation.getEParameters().add(eParam);
}
eOperation.setEType(fReturnType);
assert fContextType instanceof EClass;
((EClass)fContextType).getEOperations().add(eOperation);
CallHandlerAdapter.attach(eOperation, fDispatcher);
setupDeprecated(eOperation);
return eOperation;
}
}
protected class OperationProvider {
protected final String fName;
protected final String[] fParamNames;
protected final EClassifier fReturnType;
protected final EClassifier[] fParamTypes;
protected final CallHandler fDispatcher;
protected boolean fIsStatic;
protected boolean fIsDeprecated;
protected String fDeprecatedBy;
protected OperationProvider(CallHandler dispatcher, String name, String[] paramNames, EClassifier returnType, EClassifier... paramTypes) {
this.fName = name;
this.fReturnType = returnType;
this.fParamTypes = paramTypes;
this.fDispatcher = dispatcher;
this.fIsStatic = false;
if(paramNames != null && paramNames.length < paramTypes.length) {
throw new IllegalArgumentException("Invalid number of parameter names"); //$NON-NLS-1$
}
this.fParamNames = paramNames;
}
protected OperationProvider(CallHandler dispatcher, String name, EClassifier returnType, EClassifier... paramTypes) {
this(dispatcher, name, null /*no parameter names*/, returnType, paramTypes);
}
public OperationProvider deprecateBy(String deprecatingReplacement) {
fIsDeprecated = true;
fDeprecatedBy = deprecatingReplacement;
return this;
}
public OperationProvider deprecate() {
return deprecateBy(null);
}
public CallHandler callDispatcher() {
return fDispatcher;
}
public OperationProvider implentBy(CallHandler dispatch) {
return this;
}
public EOperation define(EcoreEnvironment env) {
List<Variable<EClassifier, EParameter>> argList = new ArrayList<Variable<EClassifier, EParameter>>();
int pos = 0;
for (EClassifier cls : fParamTypes) {
Variable<EClassifier, EParameter> stringVariable = ExpressionsFactory.eINSTANCE.createVariable();
String paramName = cls.getName();
if(fParamNames != null) {
paramName = fParamNames[pos++];
}
stringVariable.setName(paramName);
stringVariable.setType(cls);
argList.add(stringVariable);
}
EOperation result = env.defineOperation(fContextType, fName, fReturnType, argList,
org.eclipse.ocl.ecore.EcoreFactory.eINSTANCE.createConstraint());
CallHandlerAdapter.attach(result, fDispatcher);
setupDeprecated(result);
return result;
}
void setupDeprecated(EOperation result) {
if(fIsDeprecated) {
if(fDeprecatedBy != null) {
QvtOperationalParserUtil.markAsDeprecated(result, fDeprecatedBy);
} else {
QvtOperationalParserUtil.markAsDeprecated(result);
}
}
}
@Override
public String toString() {
return fName + (fParamNames != null ? Arrays.toString(fParamNames) : "");
}
}
}