/*******************************************************************************
* Copyright (c) 2007, 2009 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 v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Borland Software Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.ast.parser;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EEnumLiteral;
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.m2m.internal.qvt.oml.expressions.Constructor;
import org.eclipse.m2m.internal.qvt.oml.expressions.ConstructorBody;
import org.eclipse.m2m.internal.qvt.oml.expressions.ContextualProperty;
import org.eclipse.m2m.internal.qvt.oml.expressions.EntryOperation;
import org.eclipse.m2m.internal.qvt.oml.expressions.Helper;
import org.eclipse.m2m.internal.qvt.oml.expressions.ImperativeOperation;
import org.eclipse.m2m.internal.qvt.oml.expressions.Library;
import org.eclipse.m2m.internal.qvt.oml.expressions.MappingBody;
import org.eclipse.m2m.internal.qvt.oml.expressions.MappingCallExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.MappingOperation;
import org.eclipse.m2m.internal.qvt.oml.expressions.ModelType;
import org.eclipse.m2m.internal.qvt.oml.expressions.Module;
import org.eclipse.m2m.internal.qvt.oml.expressions.ModuleImport;
import org.eclipse.m2m.internal.qvt.oml.expressions.ObjectExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.OperationBody;
import org.eclipse.m2m.internal.qvt.oml.expressions.ResolveExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.ResolveInExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.VarParameter;
import org.eclipse.m2m.internal.qvt.oml.expressions.util.QVTOperationalVisitor;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.AltExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.AssertExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.AssignExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.BlockExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.BreakExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.CatchExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.ComputeExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.ContinueExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.DictLiteralExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.DictLiteralPart;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.ForExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.ImperativeIterateExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.ImperativeLoopExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.InstantiationExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.LogExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.OrderedTupleLiteralExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.OrderedTupleLiteralPart;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.RaiseExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.ReturnExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.SwitchExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.TryExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.UnlinkExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.UnpackExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.VariableInitExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.WhileExp;
import org.eclipse.ocl.ecore.CallOperationAction;
import org.eclipse.ocl.ecore.Constraint;
import org.eclipse.ocl.ecore.SendSignalAction;
import org.eclipse.ocl.expressions.AssociationClassCallExp;
import org.eclipse.ocl.expressions.BooleanLiteralExp;
import org.eclipse.ocl.expressions.CollectionItem;
import org.eclipse.ocl.expressions.CollectionLiteralExp;
import org.eclipse.ocl.expressions.CollectionLiteralPart;
import org.eclipse.ocl.expressions.CollectionRange;
import org.eclipse.ocl.expressions.EnumLiteralExp;
import org.eclipse.ocl.expressions.IfExp;
import org.eclipse.ocl.expressions.IntegerLiteralExp;
import org.eclipse.ocl.expressions.InvalidLiteralExp;
import org.eclipse.ocl.expressions.IterateExp;
import org.eclipse.ocl.expressions.IteratorExp;
import org.eclipse.ocl.expressions.LetExp;
import org.eclipse.ocl.expressions.MessageExp;
import org.eclipse.ocl.expressions.NullLiteralExp;
import org.eclipse.ocl.expressions.OCLExpression;
import org.eclipse.ocl.expressions.OperationCallExp;
import org.eclipse.ocl.expressions.PropertyCallExp;
import org.eclipse.ocl.expressions.RealLiteralExp;
import org.eclipse.ocl.expressions.StateExp;
import org.eclipse.ocl.expressions.StringLiteralExp;
import org.eclipse.ocl.expressions.TupleLiteralExp;
import org.eclipse.ocl.expressions.TupleLiteralPart;
import org.eclipse.ocl.expressions.TypeExp;
import org.eclipse.ocl.expressions.UnlimitedNaturalLiteralExp;
import org.eclipse.ocl.expressions.UnspecifiedValueExp;
import org.eclipse.ocl.expressions.Variable;
import org.eclipse.ocl.expressions.VariableExp;
import org.eclipse.ocl.utilities.ExpressionInOCL;
import org.eclipse.ocl.utilities.Visitable;
public class QvtOperationalAstWalker implements QVTOperationalVisitor<Object> {
public interface NodeProcessor {
void process(Visitable e, Visitable parent);
}
public QvtOperationalAstWalker(final NodeProcessor processor) {
myNodeProcessor = processor;
myProcessed = new HashSet<Visitable>();
}
public Object visitDictLiteralExp(DictLiteralExp dictLiteralExp) {
for (DictLiteralPart part : dictLiteralExp.getPart()) {
doProcess(part.getKey(), dictLiteralExp);
doProcess(part.getValue(), dictLiteralExp);
}
return null;
}
public Object visitAssignExp(AssignExp assignExp) {
doProcess(assignExp.getLeft(), assignExp);
for (OCLExpression<EClassifier> exp : assignExp.getValue()) {
doProcess(exp, assignExp);
}
return null;
}
public Object visitHelper(Helper helper) {
visitImperativeOperation(helper);
return null;
}
public Object visitEntryOperation(EntryOperation entryOperation) {
return visitImperativeOperation(entryOperation);
}
public Object visitImperativeOperation(ImperativeOperation imperativeOperation) {
doProcess(imperativeOperation.getBody(), imperativeOperation);
return null;
}
public Object visitLibrary(Library library) {
return visitModule(library);
}
public Object visitReturnExp(ReturnExp returnExp) {
if(returnExp.getValue() != null) {
doProcess(returnExp.getValue(), returnExp);
}
return null;
}
public Object visitMappingBody(MappingBody mappingBody) {
for (OCLExpression<EClassifier> exp : mappingBody.getInitSection()) {
doProcess(exp, mappingBody);
}
for (OCLExpression<EClassifier> exp : mappingBody.getContent()) {
doProcess(exp, mappingBody);
}
for (OCLExpression<EClassifier> exp : mappingBody.getEndSection()) {
doProcess(exp, mappingBody);
}
return null;
}
public Object visitMappingCallExp(MappingCallExp mappingCallExp) {
visitOperationCallExp(mappingCallExp);
return null;
}
public Object visitMappingOperation(MappingOperation mappingOperation) {
visitImperativeOperation(mappingOperation);
for (OCLExpression<EClassifier> exp : mappingOperation.getWhen()) {
doProcess(exp, mappingOperation);
}
if (mappingOperation.getWhere() instanceof BlockExp) {
for (OCLExpression<EClassifier> exp : ((BlockExp) mappingOperation.getWhere()).getBody()) {
doProcess(exp, mappingOperation);
}
}
return null;
}
public Object visitModule(Module module) {
myNodeProcessor.process(module, null);
// Remark: using QvtOperationalParserUtil.getOwnedOperations() operation instead of direct
// access to EClass::getEOperations(), as contextual mappings are in owned by the module type
// as it is understood by MDT OCL and would produce wrong behavior in operations lookup
for (EOperation op : new ArrayList<EOperation>(QvtOperationalParserUtil.getOwnedOperations(module))) {
doProcess((ImperativeOperation) op, module);
}
for (EStructuralFeature feature : module.getEStructuralFeatures()) {
if(feature instanceof ContextualProperty) {
ContextualProperty ctxProp = (ContextualProperty) feature;
doProcess(ctxProp, module);
} else {
//propAST = QvtOperationalParserUtil.getLocalPropertyAST(prop);
OCLExpression<EClassifier> initExp = QvtOperationalParserUtil.getInitExpression(feature);
if(initExp != null) {
doProcess(initExp, module);
}
}
}
return null;
}
public Object visitModuleImport(ModuleImport moduleImport) {
return null;
}
public Object visitObjectExp(ObjectExp objectExp) {
if(objectExp.getBody() != null) {
EList<org.eclipse.ocl.ecore.OCLExpression> contents = objectExp.getBody().getContent();
for (OCLExpression<EClassifier> exp : contents) {
doProcess(exp, objectExp);
}
}
return null;
}
public Object visitInstantiationExp(InstantiationExp instantiationExp) {
for (OCLExpression<EClassifier> argExp : instantiationExp.getArgument()) {
doProcess(argExp, argExp);
}
return null;
}
public Object visitOperationBody(OperationBody operationBody) {
for (OCLExpression<EClassifier> exp : operationBody.getContent()) {
doProcess(exp, operationBody);
}
return null;
}
public Object visitVarParameter(VarParameter varParameter) {
return null;
}
public Object visitVariableInitExp(VariableInitExp variableInitExp) {
org.eclipse.ocl.ecore.Variable referredVariable = variableInitExp.getReferredVariable();
if(referredVariable.getInitExpression() != null) {
doProcess(referredVariable.getInitExpression(), variableInitExp);
}
return null;
}
public Object visitBlockExp(BlockExp blockExp) {
for (OCLExpression<EClassifier> exp : blockExp.getBody()) {
doProcess(exp, blockExp);
}
return null;
}
public Object visitComputeExp(ComputeExp computeExp) {
if(computeExp.getReturnedElement() != null) {
doProcess(computeExp.getReturnedElement(), computeExp);
}
if(computeExp.getBody() != null) {
doProcess(computeExp.getBody(), computeExp);
}
return null;
}
public Object visitWhileExp(WhileExp whileExp) {
if (whileExp.getCondition() != null) {
doProcess(whileExp.getCondition(), whileExp);
}
if(whileExp.getBody() != null) {
doProcess(whileExp.getBody(), whileExp);
}
return null;
}
public Object visitAssociationClassCallExp(AssociationClassCallExp<EClassifier, EStructuralFeature> callExp) {
for (OCLExpression<EClassifier> exp : callExp.getQualifier()) {
doProcess(exp, callExp);
}
doProcess(callExp.getSource(), callExp);
return null;
}
public Object visitBooleanLiteralExp(BooleanLiteralExp<EClassifier> literalExp) {
return null;
}
public Object visitCollectionItem(CollectionItem<EClassifier> item) {
doProcess(item.getItem(), item);
return null;
}
public Object visitCollectionLiteralExp(CollectionLiteralExp<EClassifier> literalExp) {
for (CollectionLiteralPart<EClassifier> part : literalExp.getPart()) {
doProcess(part, literalExp);
}
return null;
}
public Object visitCollectionRange(CollectionRange<EClassifier> range) {
doProcess(range.getFirst(), range);
doProcess(range.getLast(), range);
return null;
}
public Object visitConstraint(Constraint constraint) {
doProcess(constraint.getSpecification().getBodyExpression(), constraint.getSpecification());
return null;
}
public Object visitEnumLiteralExp(EnumLiteralExp<EClassifier, EEnumLiteral> literalExp) {
return null;
}
public Object visitExpressionInOCL(ExpressionInOCL<EClassifier, EParameter> expression) {
return null;
}
public Object visitIfExp(IfExp<EClassifier> ifExp) {
doProcess(ifExp.getCondition(), ifExp);
doProcess(ifExp.getThenExpression(), ifExp);
doProcess(ifExp.getElseExpression(), ifExp);
return null;
}
public Object visitIntegerLiteralExp(IntegerLiteralExp<EClassifier> literalExp) {
return null;
}
public Object visitInvalidLiteralExp(InvalidLiteralExp<EClassifier> literalExp) {
return null;
}
public Object visitIterateExp(IterateExp<EClassifier, EParameter> callExp) {
doProcess(callExp.getResult(), callExp);
doProcess(callExp.getBody(), callExp);
return null;
}
public Object visitIteratorExp(IteratorExp<EClassifier, EParameter> callExp) {
if(callExp.getSource() != null) {
doProcess(callExp.getSource(), callExp);
}
doProcess(callExp.getBody(), callExp);
return null;
}
public Object visitLetExp(LetExp<EClassifier, EParameter> letExp) {
doProcess(letExp.getVariable(), letExp);
doProcess(letExp.getIn(), letExp);
return null;
}
public Object visitMessageExp(MessageExp<EClassifier, CallOperationAction, SendSignalAction> messageExp) {
doProcess(messageExp.getTarget(), messageExp);
return null;
}
public Object visitNullLiteralExp(NullLiteralExp<EClassifier> literalExp) {
return null;
}
public Object visitOperationCallExp(OperationCallExp<EClassifier, EOperation> callExp) {
OCLExpression<EClassifier> source = callExp.getSource();
if (source != null) {
doProcess(source, callExp);
}
for (OCLExpression<EClassifier> exp : callExp.getArgument()) {
doProcess(exp, callExp);
}
EOperation referredOperation = callExp.getReferredOperation();
if (referredOperation instanceof Visitable) {
// TODO -
// Should not visit referenced operation, as thesemight com from different top container (Module)
// Should strictly traverse on containment basis, no need to track processed nodes
//doProcess((Visitable) referredOperation, callExp);
}
return null;
}
public Object visitPropertyCallExp(PropertyCallExp<EClassifier, EStructuralFeature> callExp) {
return null;
}
public Object visitRealLiteralExp(RealLiteralExp<EClassifier> literalExp) {
return null;
}
public Object visitStateExp(StateExp<EClassifier, EObject> stateExp) {
return null;
}
public Object visitStringLiteralExp(StringLiteralExp<EClassifier> literalExp) {
return null;
}
public Object visitTupleLiteralExp(TupleLiteralExp<EClassifier, EStructuralFeature> literalExp) {
return null;
}
public Object visitTupleLiteralPart(TupleLiteralPart<EClassifier, EStructuralFeature> part) {
return null;
}
public Object visitTypeExp(TypeExp<EClassifier> typeExp) {
return null;
}
public Object visitUnlimitedNaturalLiteralExp(UnlimitedNaturalLiteralExp<EClassifier> literalExp) {
return null;
}
public Object visitUnspecifiedValueExp(UnspecifiedValueExp<EClassifier> unspecExp) {
return null;
}
public Object visitVariable(Variable<EClassifier, EParameter> variable) {
return null;
}
public Object visitVariableExp(VariableExp<EClassifier, EParameter> variableExp) {
Variable<EClassifier, EParameter> referredVariable = variableExp.getReferredVariable();
if (referredVariable instanceof Visitable) {
doProcess((Visitable) referredVariable, variableExp);
}
return null;
}
public Object visitResolveExp(ResolveExp resolveExp) {
doProcess(resolveExp.getCondition(), resolveExp);
return null;
}
public Object visitResolveInExp(ResolveInExp resolveInExp) {
// do not process 'inMapping' reference, as it is not containment
return visitResolveExp(resolveInExp);
}
public Object visitModelType(ModelType modelType) {
for (OCLExpression<EClassifier> exp : modelType.getAdditionalCondition()) {
doProcess(exp, modelType);
}
return null;
}
public Object visitLogExp(LogExp logExp) {
for (OCLExpression<EClassifier> arg : logExp.getArgument()) {
doProcess(arg, logExp);
}
if(logExp.getCondition() != null) {
doProcess(logExp.getCondition(), logExp);
}
return null;
}
public Object visitAssertExp(AssertExp assertExp) {
if(assertExp.getAssertion() != null) {
doProcess(assertExp.getAssertion(), assertExp);
}
if(assertExp.getLog() != null) {
doProcess(assertExp.getLog(), assertExp);
}
return null;
}
protected NodeProcessor getNodeProcessor() {
return myNodeProcessor;
}
protected void doProcess(Visitable e, Visitable parent) {
if(e != null && !myProcessed.contains(e)) {
myNodeProcessor.process(e, parent);
myProcessed.add(e);
e.accept(this);
}
}
private final NodeProcessor myNodeProcessor;
private final Set<Visitable> myProcessed;
public Object visitAltExp(AltExp altExp) {
doProcess(altExp.getCondition(), altExp);
doProcess(altExp.getBody(), altExp);
return null;
}
public Object visitSwitchExp(SwitchExp switchExp) {
EList<AltExp> alternativePart = switchExp.getAlternativePart();
if (alternativePart != null) {
for (AltExp altExp : alternativePart) {
doProcess(altExp, switchExp);
}
}
doProcess(switchExp.getElsePart(), switchExp);
return null;
}
public Object visitImperativeLoopExp(ImperativeLoopExp imperativeLoopExp) {
if(imperativeLoopExp.getSource() != null) {
doProcess(imperativeLoopExp.getSource(), imperativeLoopExp);
}
doProcess(imperativeLoopExp.getCondition(), imperativeLoopExp);
doProcess(imperativeLoopExp.getBody(), imperativeLoopExp);
return null;
}
public Object visitImperativeIterateExp(ImperativeIterateExp imperativeIterateExp) {
return visitImperativeLoopExp(imperativeIterateExp);
}
public Object visitContextualProperty(ContextualProperty contextualProperty) {
doProcess(contextualProperty.getInitExpression(), contextualProperty);
return null;
}
public Object visitForExp(ForExp forExp) {
return visitImperativeLoopExp(forExp);
}
public Object visitConstructor(Constructor constructor) {
return visitImperativeOperation(constructor);
}
public Object visitConstructorBody(ConstructorBody constructorBody) {
return visitOperationBody(constructorBody);
}
public Object visitBreakExp(BreakExp astNode) {
// TODO Auto-generated method stub
return null;
}
public Object visitCatchtExp(CatchExp catchExp) {
for (OCLExpression<EClassifier> exp : catchExp.getBody()) {
doProcess(exp, catchExp);
}
return null;
}
public Object visitContinueExp(ContinueExp astNode) {
// TODO Auto-generated method stub
return null;
}
public Object visitDictLiteralPart(DictLiteralPart astNode) {
// TODO Auto-generated method stub
return null;
}
public Object visitOrderedTupleLiteralExp(OrderedTupleLiteralExp astNode) {
// TODO Auto-generated method stub
return null;
}
public Object visitOrderedTupleLiteralPart(OrderedTupleLiteralPart astNode) {
// TODO Auto-generated method stub
return null;
}
public Object visitRaiseExp(RaiseExp astNode) {
// TODO Auto-generated method stub
return null;
}
public Object visitTryExp(TryExp tryExp) {
for (OCLExpression<EClassifier> exp : tryExp.getTryBody()) {
doProcess(exp, tryExp);
}
for (CatchExp catchExp : tryExp.getExceptClause()) {
visitCatchtExp(catchExp);
}
return null;
}
public Object visitUnlinkExp(UnlinkExp astNode) {
// TODO Auto-generated method stub
return null;
}
public Object visitUnpackExp(UnpackExp astNode) {
// TODO Auto-generated method stub
return null;
}
}