org.dresdenocl.essentialocl.expressions.impl.OperationCallExpImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.dresdenocl.essentialocl.expressions.impl.OperationCallExpImpl.java

Source

/**
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright (C) 2007 Matthias Braeuer (braeuer.matthias@web.de).            *
 * All rights reserved.                                                      *
 *                                                                           *
 * This work was done as a project at the Chair for Software Technology,     *
 * Dresden University Of Technology, Germany (http://st.inf.tu-dresden.de).  *
 * It is understood that any modification not identified as such is not      *
 * covered by the preceding statement.                                       *
 *                                                                           *
 * This work is free software; you can redistribute it and/or modify it      *
 * under the terms of the GNU Library General Public License as published    *
 * by the Free Software Foundation; either version 2 of the License, or      *
 * (at your option) any later version.                                       *
 *                                                                           *
 * This work is distributed in the hope that it will be useful, but WITHOUT  *
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     *
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public     *
 * License for more details.                                                 *
 *                                                                           *
 * You should have received a copy of the GNU Library General Public License *
 * along with this library; if not, you can view it online at                *
 * http://www.fsf.org/licensing/licenses/gpl.html.                           *
 *                                                                           *
 * To submit a bug report, send a comment, or get the latest news on this    *
 * project, please visit the website: http://dresden-ocl.sourceforge.net.    *
 * For more information on OCL and related projects visit the OCL Portal:    *
 * http://st.inf.tu-dresden.de/ocl                                           *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 * $Id$
 */
package org.dresdenocl.essentialocl.expressions.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.log4j.Logger;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.util.EObjectContainmentEList;
import org.eclipse.emf.ecore.util.InternalEList;

import org.dresdenocl.essentialocl.expressions.OclExpression;
import org.dresdenocl.essentialocl.expressions.OperationCallExp;
import org.dresdenocl.essentialocl.expressions.WellformednessException;
import org.dresdenocl.essentialocl.types.CollectionType;
import org.dresdenocl.essentialocl.types.TupleType;
import org.dresdenocl.essentialocl.types.TypeType;
import org.dresdenocl.pivotmodel.ComplexGenericType;
import org.dresdenocl.pivotmodel.Feature;
import org.dresdenocl.pivotmodel.Operation;
import org.dresdenocl.pivotmodel.Parameter;
import org.dresdenocl.pivotmodel.PrimitiveType;
import org.dresdenocl.pivotmodel.PrimitiveTypeKind;
import org.dresdenocl.pivotmodel.Property;
import org.dresdenocl.pivotmodel.Type;
import org.dresdenocl.pivotmodel.TypeParameter;

/**
 * <!-- begin-user-doc --> An implementation of the model object '
 * <em><b>Operation Call Exp</b></em>'. <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * <ul>
 *   <li>{@link org.dresdenocl.essentialocl.expressions.impl.OperationCallExpImpl#getArgument <em>Argument</em>}</li>
 *   <li>{@link org.dresdenocl.essentialocl.expressions.impl.OperationCallExpImpl#getReferredOperation <em>Referred Operation</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public class OperationCallExpImpl extends FeatureCallExpImpl implements OperationCallExp {

    /**
     * Logger for this class
     */
    private static final Logger logger = Logger.getLogger(OperationCallExpImpl.class);

    /**
     * The cached value of the '{@link #getArgument() <em>Argument</em>}' containment reference list.
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @see #getArgument()
     * @generated
     * @ordered
     */
    protected EList<OclExpression> argument;

    /**
     * The cached value of the '{@link #getReferredOperation() <em>Referred Operation</em>}' reference.
     * <!-- begin-user-doc --> <!--
     * end-user-doc -->
     * @see #getReferredOperation()
     * @generated
     * @ordered
     */
    protected Operation referredOperation;

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    protected OperationCallExpImpl() {
        super();
    }

    /**
     * Overridden to determine the type of this <code>OperationCallExp</code>.
     * Unfortunately, the OCL Specification does not define any wellformedness
     * rules for the type of an <code>OperationCallExp</code>. As a result, this
     * implementation simply follows the approach taken by the last release of
     * the Dresden OCL2 Toolkit.
     * 
     * <p>
     * There, the type of an Operation Call Expression is the result type of the
     * referred operation or a tuple type comprising the result type of the
     * operation and all out and inout parameters.
     * </p>
     * 
     * @see org.dresdenocl.pivotmodel.impl.TypedElementImpl#getType()
     */
    @Override
    protected Type evaluateType() {

        if (logger.isDebugEnabled()) {
            logger.debug("evaluateType() - enter"); //$NON-NLS-1$
        }

        Type type;

        /*
         * If the referredOperation is null and the name of the OperationCallExp
         * instance is 'atPre' then the method 'withAtPre()' was used before. So
         * in this case we delegate the call to the source expression.
         */
        if (referredOperation == null) {
            if (name.equals("atPre")) {
                return source.getType();
            }
        }

        // check wellformedness of abstract syntax
        if (referredOperation == null) {
            throw new WellformednessException(this,
                    "The referred operation of an OperationCallExp must not be null."); //$NON-NLS-1$
        }

        // if there are any output parameters, the expression type is a tuple
        // type
        else if (referredOperation.getOutputParameter().size() > 0) {
            List<Property> tupleTypeProperties = new ArrayList<Property>();

            // add all output parameters
            for (Parameter parameter : referredOperation.getOutputParameter()) {
                tupleTypeProperties.add(parameter.asProperty());
            }

            // add the return parameter if existing
            if (referredOperation.getReturnParameter() != null) {
                tupleTypeProperties.add(referredOperation.getReturnParameter().asProperty());
            }

            type = getValidOclLibrary().makeTupleType(tupleTypeProperties);
        }

        // otherwise default to the operation's type
        else {
            // TODO: remove explicit references to the OCL Standard Library from
            // code
            String operationName = referredOperation.getName();

            // bind 'allInstances' operation
            if (operationName.equals("allInstances")) { //$NON-NLS-1$
                referredOperation = bindAllInstancesOperation(referredOperation);
            }

            // bind 'asSet' operation
            else if (!(source.getType() instanceof CollectionType) && operationName.equals("asSet")) { //$NON-NLS-1$
                referredOperation = bindAsSetOperation(referredOperation);
            }

            // bind 'oclAsType' operation
            else if (operationName.equals("oclAsType")) { //$NON-NLS-1$
                referredOperation = bindOclAsTypeOperation(referredOperation);
            }

            // bind 'oclType' operation
            else if (operationName.equals("oclType")) { //$NON-NLS-1$
                referredOperation = bindOclTypeOperation(referredOperation);
            }

            // bind 'flatten' operation
            else if (getSourceType() instanceof CollectionType) {

                if (operationName.equals("flatten")) { //$NON-NLS-1$
                    referredOperation = bindFlattenOperation(referredOperation);
                }

                else if (operationName.equals("product")) { //$NON-NLS-1$
                    referredOperation = bindProductOperation(referredOperation);
                }

            }

            /* Bind 'characters' operation. */
            else if (getSourceType() instanceof PrimitiveType
                    && ((PrimitiveType) getSourceType()).getKind() == PrimitiveTypeKind.STRING) {

                if (operationName.equals("characters")) { //$NON-NLS-1$
                    referredOperation = bindCharactersOperation(referredOperation);
                }
                // no else.
            }
            // no else.

            /* Map the operation's type to a corresponding OCL type. */
            type = getOclType(referredOperation.getType());
        }

        if (logger.isDebugEnabled()) {
            logger.debug("evaluateType() - exit - return value=" + type); //$NON-NLS-1$
        }

        return type;
    }

    /**
     * FIXME Claas: Isn't there a general solution to solve the binding of
     * generic operations?
     * 
     * <p>
     * Helper method to bind the <code>String.characters()</code>
     * {@link Operation} .
     * </p>
     * 
     * @param The
     *            <code>String.characters()</code> {@link Operation} that shall
     *            be bound to this {@link OperationCallExp}.
     */
    private Operation bindCharactersOperation(Operation charactersOperation) {

        /* Probably log entry. */
        if (logger.isDebugEnabled()) {
            logger.debug("bindCharactersOperation(charactersOperation=" + charactersOperation //$NON-NLS-1$
                    + ") - enter"); //$NON-NLS-1$
        }
        // no else.

        PrimitiveType sourceType;

        /* It is safe to cast here since we checked in evaluateType. */
        sourceType = (PrimitiveType) getSourceType();

        /* Bind the operation. */
        charactersOperation = charactersOperation.bindTypeParameter(
                new ArrayList<TypeParameter>(((ComplexGenericType) charactersOperation.getGenericType())
                        .getUnboundType().getOwnedTypeParameter()),
                Arrays.asList(sourceType));

        /* Probably log exit. */
        if (logger.isDebugEnabled()) {
            logger.debug("bindCharactersOperation() - exit - return value=" //$NON-NLS-1$
                    + charactersOperation);
        }
        // no else.

        return charactersOperation;
    }

    /**
     * Helper method to bind the 'flatten' operation. The definition is the same
     * for Set, Bag, and Sequence. E.g.:
     * 
     * <p>
     * If the element type is not a collection type, this results in the same
     * self. If the element type is a collection type, the result is the set
     * containing all the elements of all the elements of self.
     * 
     * <pre>
     * post: result = if self.type.elementType.oclIsKindOf(CollectionType) then
     *    self-&gt;iterate(c; acc : Set() = Set{} |
     *      acc-&gt;union(c-&gt;asSet() ) )
     *    else
     *      self
     *    endif
     * </pre>
     * 
     * </p>
     */
    private Operation bindFlattenOperation(Operation flattenOperation) {

        if (logger.isDebugEnabled()) {
            logger.debug("bindFlattenOperation(flattenOperation=" + flattenOperation //$NON-NLS-1$
                    + ") - enter"); //$NON-NLS-1$
        }

        CollectionType sourceType;
        Type elementType;

        // it is safe to cast here since we checked in evaluateType
        sourceType = (CollectionType) getSourceType();
        elementType = sourceType.getElementType();

        elementType = checkForNestedCollection(elementType);

        // bind the operation
        flattenOperation = flattenOperation.bindTypeParameter(
                new ArrayList<TypeParameter>(flattenOperation.getOwnedTypeParameter()), Arrays.asList(elementType));

        if (logger.isDebugEnabled()) {
            logger.debug("bindFlattenOperation() - exit - return value=" //$NON-NLS-1$
                    + flattenOperation);
        }

        return flattenOperation;
    }

    private Type checkForNestedCollection(Type elementType) {

        // check the element type of the source collection type
        if (elementType instanceof CollectionType) {
            elementType = ((CollectionType) elementType).getElementType();
            elementType = checkForNestedCollection(elementType);
        }
        return elementType;
    }

    /**
     * FIXME Claas: Isn't there a general solution to solve the binding of
     * generic operations?
     * 
     * <p>
     * Helper method to bind the <code>OclAny.oclType()</code> {@link Operation}
     * .
     * </p>
     * 
     * @param The
     *            <code>OclAny.asSet()</code> {@link Operation} that shall be
     *            bound to this {@link OperationCallExp}.
     */
    private Operation bindAsSetOperation(Operation asSetOperation) {

        /* Probably log the entry of this method. */
        if (logger.isDebugEnabled()) {
            logger.debug("bindAsSetOperation(oclTypeOperation=" //$NON-NLS-1$
                    + asSetOperation + ") - enter"); //$NON-NLS-1$
        }
        // no else.

        /* Get the source's type. */
        Type elementType;
        elementType = this.getSource().getType();

        /* Check that the type is not null. */
        if (elementType == null) {
            throw new WellformednessException(this, "The source of the 'asSet' operation must be defined."); //$NON-NLS-1$
        }
        // no else.

        /* Check argument size. */
        if (getArgument().size() != 0) {
            throw new WellformednessException(this, "The 'asSet' operation has not to have any argument."); //$NON-NLS-1$
        }
        // no else.

        /* Bind the asSet operation, which will set its return type. */
        asSetOperation = asSetOperation.bindTypeParameter(
                new ArrayList<TypeParameter>(asSetOperation.getOwnedTypeParameter()), Arrays.asList(elementType));

        /* Probably log the exit of this method. */
        if (logger.isDebugEnabled()) {
            logger.debug("bindAsSetOperation() - exit - return value=" //$NON-NLS-1$
                    + asSetOperation);
        }
        // no else.

        return asSetOperation;
    }

    /**
     * Helper method to bind the 'OclAny::oclAsType' operation
     * 
     * TODO: Clean up this implementation with something smarter. The current
     * code is a pretty big hack, because we need to know the signature of the
     * 'oclAsType' operation (i.e., exactly one parameter of type OclType). It
     * would be more clever to implement something like the automatic binding of
     * generic method type parameters in Java. More precisely, we first look for
     * an occurence of the method's type parameter in the (unbound) signature
     * and then find out what type has been bound at this position.
     */
    private Operation bindOclAsTypeOperation(Operation oclAsTypeOperation) {

        if (logger.isDebugEnabled()) {
            logger.debug("bindOclAsTypeOperation(oclAsTypeOperation=" //$NON-NLS-1$
                    + oclAsTypeOperation + ") - enter"); //$NON-NLS-1$
        }

        OclExpression argument;
        TypeType argumentType;
        Type representedType;

        // check arguments
        if (getArgument().size() != 1) {
            throw new WellformednessException(this, "The 'oclAsType' operation must have exactly one argument."); //$NON-NLS-1$
        }

        // get the single argument of the 'oclAsType' operation
        argument = getArgument().get(0);

        // check type of argument
        if (!(argument.getType() instanceof TypeType)) {
            throw new WellformednessException(this,
                    "The operation 'oclAsType' must have an OclType as its argument."); //$NON-NLS-1$
        }

        argumentType = (TypeType) argument.getType();

        // get the type that is represented by the TypeType
        representedType = argumentType.getRepresentedType();

        if (representedType == null) {
            throw new WellformednessException(this,
                    "Unable to determine the type represented by the passed OclType."); //$NON-NLS-1$
        }

        // bind the oclAsType operation, which will set its return type
        oclAsTypeOperation = oclAsTypeOperation.bindTypeParameter(
                new ArrayList<TypeParameter>(oclAsTypeOperation.getOwnedTypeParameter()),
                Arrays.asList(representedType));

        if (logger.isDebugEnabled()) {
            logger.debug("bindOclAsTypeOperation() - exit - return value=" //$NON-NLS-1$
                    + oclAsTypeOperation);
        }

        return oclAsTypeOperation;
    }

    /**
     * FIXME Claas: Isn't there a general solution to solve the binding of
     * generic operations?
     * 
     * <p>
     * Helper method to bind the <code>OclAny.oclType()</code> {@link Operation}
     * .
     * </p>
     * 
     * @param The
     *            <code>OclAny.oclType()</code> {@link Operation} that shall be
     *            bound to this {@link OperationCallExp}.
     */
    private Operation bindOclTypeOperation(Operation oclTypeOperation) {

        /* Probably log the entry of this method. */
        if (logger.isDebugEnabled()) {
            logger.debug("bindOclTypeOperation(oclTypeOperation=" //$NON-NLS-1$
                    + oclTypeOperation + ") - enter"); //$NON-NLS-1$
        }
        // no else.

        /* Get the source's type. */
        Type representedType;
        representedType = this.getSource().getType();

        /* Check that the type is not null. */
        if (representedType == null) {
            throw new WellformednessException(this, "The source of the 'oclType' operation must be defined."); //$NON-NLS-1$
        }
        // no else.

        /* Check argument size. */
        if (getArgument().size() != 0) {
            throw new WellformednessException(this, "The 'oclType' operation has not to have any argument."); //$NON-NLS-1$
        }
        // no else.

        /* Bind the oclType operation, which will set its return type. */
        oclTypeOperation = oclTypeOperation.bindTypeParameter(
                new ArrayList<TypeParameter>(oclTypeOperation.getOwnedTypeParameter()),
                Arrays.asList(representedType));

        /* Probably log the exit of this method. */
        if (logger.isDebugEnabled()) {
            logger.debug("bindOclTypeOperation() - exit - return value=" //$NON-NLS-1$
                    + oclTypeOperation);
        }
        // no else.

        return oclTypeOperation;
    }

    /**
     * FIXME Claas: Isn't there a general solution to solve the binding of
     * generic operations?
     * 
     * <p>
     * Helper method to bind the
     * <code>OclCollection<T1>.product(Collection<T2>)</code> {@link Operation}
     * .
     * </p>
     * 
     * @param The
     *            <code>OclCollection<T1>.product(Collection<T2>)</code>
     *            {@link Operation} that shall be bound to this
     *            {@link OperationCallExp}.
     */
    private Operation bindProductOperation(Operation productOperation) {

        /* Probably log the entry of this method. */
        if (logger.isDebugEnabled()) {
            logger.debug("bindProductOperation(productOperation=" //$NON-NLS-1$
                    + productOperation + ") - enter"); //$NON-NLS-1$
        }
        // no else.

        /* Check argument size. */
        if (getArgument().size() != 1) {
            throw new WellformednessException(this,
                    "The 'product' operation must have exactly one argument that is a collection."); //$NON-NLS-1$
        }
        // no else.

        /* Get the param's type. */
        Type paramType;
        paramType = this.getArgument().get(0).getType();

        /* Check that the type is not null. */
        if (paramType == null) {
            throw new WellformednessException(this,
                    "The params's type of the 'product' operation must be defined."); //$NON-NLS-1$
        }
        // no else.

        if (!(this.getSource().getType() instanceof CollectionType)) {
            throw new WellformednessException(this,
                    "The source's type of the 'product' operation must be a collection type."); //$NON-NLS-1$
        }
        // no else.

        Type paramElementType;
        paramElementType = ((CollectionType) paramType).getElementType();

        /* Bind the product operation, which will set its return type. */
        productOperation = productOperation.bindTypeParameter(
                new ArrayList<TypeParameter>(productOperation.getOwnedTypeParameter()),
                Arrays.asList(paramElementType));

        /* Probably log the exit of this method. */
        if (logger.isDebugEnabled()) {
            logger.debug("bindProductOperation() - exit - return value=" //$NON-NLS-1$
                    + productOperation);
        }
        // no else.

        return productOperation;
    }

    /**
     * Helper method to bind the 'OclAny::allInstances' operation
     */
    private Operation bindAllInstancesOperation(Operation allInstancesOperation) {

        if (logger.isDebugEnabled()) {
            logger.debug("bindAllInstancesOperation(allInstancesOperation=" //$NON-NLS-1$
                    + allInstancesOperation + ") - enter"); //$NON-NLS-1$
        }

        /* Determine the source type. */
        Type srcType = ((TypeType) getSourceType()).getRepresentedType();

        /*
         * allInstances may only refer to types with a finite number of
         * instances.
         */
        if ((srcType instanceof PrimitiveType && ((PrimitiveType) srcType).getKind() != PrimitiveTypeKind.BOOLEAN)
                || srcType instanceof CollectionType || srcType instanceof TupleType) {
            throw new WellformednessException(this, "The 'allInstances' operation cannot be invoked on '" //$NON-NLS-1$
                    + srcType.getName() + "'."); //$NON-NLS-1$
        }

        // now bind the 'allInstances' operation with the source type
        allInstancesOperation = allInstancesOperation.bindTypeParameter(
                new ArrayList<TypeParameter>(allInstancesOperation.getOwnedTypeParameter()),
                Arrays.asList(srcType));

        if (logger.isDebugEnabled()) {
            logger.debug("bindAllInstancesOperation() - exit - return value=" //$NON-NLS-1$
                    + allInstancesOperation);
        }

        return allInstancesOperation;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.dresdenocl.essentialocl.expressions.impl.FeatureCallExpImpl
     * #getFeature()
     */
    @Override
    protected Feature getFeature() {

        return getReferredOperation();
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    public List<OclExpression> getArgument() {
        if (argument == null) {
            argument = new EObjectContainmentEList<OclExpression>(OclExpression.class, this,
                    ExpressionsPackageImpl.OPERATION_CALL_EXP__ARGUMENT);
        }
        return argument;
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    public Operation getReferredOperation() {
        return referredOperation;
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    public void setReferredOperation(Operation newReferredOperation) {
        Operation oldReferredOperation = referredOperation;
        referredOperation = newReferredOperation;
        if (eNotificationRequired())
            eNotify(new ENotificationImpl(this, Notification.SET,
                    ExpressionsPackageImpl.OPERATION_CALL_EXP__REFERRED_OPERATION, oldReferredOperation,
                    referredOperation));
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    @Override
    public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
        switch (featureID) {
        case ExpressionsPackageImpl.OPERATION_CALL_EXP__ARGUMENT:
            return ((InternalEList<?>) getArgument()).basicRemove(otherEnd, msgs);
        }
        return super.eInverseRemove(otherEnd, featureID, msgs);
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    @Override
    public Object eGet(int featureID, boolean resolve, boolean coreType) {
        switch (featureID) {
        case ExpressionsPackageImpl.OPERATION_CALL_EXP__ARGUMENT:
            return getArgument();
        case ExpressionsPackageImpl.OPERATION_CALL_EXP__REFERRED_OPERATION:
            return getReferredOperation();
        }
        return super.eGet(featureID, resolve, coreType);
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    @SuppressWarnings("unchecked")
    @Override
    public void eSet(int featureID, Object newValue) {
        switch (featureID) {
        case ExpressionsPackageImpl.OPERATION_CALL_EXP__ARGUMENT:
            getArgument().clear();
            getArgument().addAll((Collection<? extends OclExpression>) newValue);
            return;
        case ExpressionsPackageImpl.OPERATION_CALL_EXP__REFERRED_OPERATION:
            setReferredOperation((Operation) newValue);
            return;
        }
        super.eSet(featureID, newValue);
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    @Override
    public void eUnset(int featureID) {
        switch (featureID) {
        case ExpressionsPackageImpl.OPERATION_CALL_EXP__ARGUMENT:
            getArgument().clear();
            return;
        case ExpressionsPackageImpl.OPERATION_CALL_EXP__REFERRED_OPERATION:
            setReferredOperation((Operation) null);
            return;
        }
        super.eUnset(featureID);
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    @Override
    public boolean eIsSet(int featureID) {
        switch (featureID) {
        case ExpressionsPackageImpl.OPERATION_CALL_EXP__ARGUMENT:
            return argument != null && !argument.isEmpty();
        case ExpressionsPackageImpl.OPERATION_CALL_EXP__REFERRED_OPERATION:
            return referredOperation != null;
        }
        return super.eIsSet(featureID);
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    @Override
    protected EClass eStaticClass() {
        return ExpressionsPackageImpl.Literals.OPERATION_CALL_EXP;
    }

    /**
     * Overridden for unified toString appearance
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {

        return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).appendSuper(super.toString())
                .append("referredOperation", referredOperation).toString(); //$NON-NLS-1$
    }

} // OperationCallExpImpl