blob: 0d51d456754a4ba363736d0952c345b24855b782 [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2008 The University of York.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipse.epsilon.eol.dom;
import org.eclipse.epsilon.common.module.IModule;
import org.eclipse.epsilon.common.parse.AST;
import org.eclipse.epsilon.eol.exceptions.EolIllegalOperationException;
import org.eclipse.epsilon.eol.execute.context.IEolContext;
import org.eclipse.epsilon.eol.execute.operations.AbstractOperation;
import org.eclipse.epsilon.eol.execute.operations.DynamicOperation;
import org.eclipse.epsilon.eol.execute.operations.declarative.IAbstractOperationContributor;
import org.eclipse.epsilon.eol.execute.operations.declarative.IAbstractOperationContributorProvider;
import org.eclipse.epsilon.eol.models.IModel;
import org.eclipse.epsilon.eol.types.EolSequence;
public abstract class FeatureCallExpression extends Expression {
protected boolean arrow, safe;
protected Expression targetExpression;
/**
* The feature name expression.
* @since 1.6
*/
protected NameExpression nameExpression;
@Override
public void build(AST cst, IModule module) {
super.build(cst, module);
this.arrow = "->".equals(cst.getText());
this.safe = "?.".equals(cst.getText());
}
static Object wrap(Object o) {
if (o instanceof Object[]) {
Object[] arr = (Object[]) o;
EolSequence<Object> seq = new EolSequence<>();
seq.ensureCapacity(arr.length);
for (Object element : arr) {
seq.add(element);
}
return seq;
}
else return o;
}
protected AbstractOperation getAbstractOperation(Object target, String name, IModel owningModel, IEolContext context) throws EolIllegalOperationException {
AbstractOperation operation = null;
// Objects implementing the IAbstractOperationContributor interface
// can override the default higher-order operation implementations
if (target instanceof IAbstractOperationContributor) {
operation = ((IAbstractOperationContributor) target).getAbstractOperation(name);
if (operation != null) return operation;
}
// Since we don't control the interface of all model elements, models
// can also provide IAbstractOperationContributors for their model elements
if (owningModel != null && owningModel instanceof IAbstractOperationContributorProvider) {
IAbstractOperationContributor contributor = ((IAbstractOperationContributorProvider) owningModel).getAbstractOperationContributor(target);
if (contributor != null) {
operation = contributor.getAbstractOperation(name);
if (operation != null) return operation;
}
}
operation = getOperationFromContext(target, name, owningModel, context);
if (operation == null && nameExpression != null) {
operation = new DynamicOperation();
}
return operation;
}
/**
* Looks for the operation in the EolContext EolOperationFactory.
*
* @param target The object this feature is called on.
* @param name The requested operation name.
* @param owningModel The model (optional).
* @param context The context from which the EolOperationFactory is derived.
* @return The operation.
* @throws EolIllegalOperationException
* @since 1.6
*/
protected AbstractOperation getOperationFromContext(Object target, String name, IModel owningModel, IEolContext context) throws EolIllegalOperationException {
return context.getOperationFactory().getOperationFor(name);
}
public Expression getTargetExpression() {
return targetExpression;
}
public void setTargetExpression(Expression targetExpression) {
this.targetExpression = targetExpression;
}
/**
*
* @param nameExpression
* @since 1.6
*/
public void setNameExpression(NameExpression nameExpression) {
this.nameExpression = nameExpression;
}
/**
*
* @return
* @since 1.6
*/
public NameExpression getNameExpression() {
return nameExpression;
}
/**
* Convenience method for <code>getNameExpression().getName()</code>.
*
* @return The name of the feature call, or <code>null</code> if absent.
* @since 1.6
*/
public String getName() {
return nameExpression != null ? nameExpression.getName() : null;
}
public boolean isArrow() {
return arrow;
}
/**
*
* @return
* @since 2.1
*/
public boolean isNullSafe() {
return safe;
}
public abstract void accept(IEolVisitor visitor);
}