blob: d5126bc7ec3b05c39dbf5dfe743ad14468e619b9 [file] [log] [blame]
/*******************************************************************************
*
* 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.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
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.EPackage;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.m2m.internal.qvt.oml.QvtPlugin;
import org.eclipse.m2m.internal.qvt.oml.ast.binding.ASTBindingHelper;
import org.eclipse.m2m.internal.qvt.oml.ast.binding.ASTSyntheticNode;
import org.eclipse.m2m.internal.qvt.oml.ast.binding.ASTSyntheticNodeAccess;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalFileEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalModuleEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalStdLibrary;
import org.eclipse.m2m.internal.qvt.oml.common.io.CFile;
import org.eclipse.m2m.internal.qvt.oml.common.io.CFolder;
import org.eclipse.m2m.internal.qvt.oml.compiler.BlackboxModuleHelper;
import org.eclipse.m2m.internal.qvt.oml.compiler.IntermediateClassFactory;
import org.eclipse.m2m.internal.qvt.oml.compiler.ParsedModuleCS;
import org.eclipse.m2m.internal.qvt.oml.compiler.QvtCompiler;
import org.eclipse.m2m.internal.qvt.oml.compiler.QvtCompilerKernel;
import org.eclipse.m2m.internal.qvt.oml.compiler.QvtCompilerOptions;
import org.eclipse.m2m.internal.qvt.oml.cst.AssertExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.AssignStatementCS;
import org.eclipse.m2m.internal.qvt.oml.cst.BlockExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ClassifierDefCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ClassifierPropertyCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ComputeExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ConfigPropertyCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ContextualPropertyCS;
import org.eclipse.m2m.internal.qvt.oml.cst.DirectionKindEnum;
import org.eclipse.m2m.internal.qvt.oml.cst.ExpressionStatementCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ForExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ImperativeIterateExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ImportCS;
import org.eclipse.m2m.internal.qvt.oml.cst.LibraryCS;
import org.eclipse.m2m.internal.qvt.oml.cst.LibraryImportCS;
import org.eclipse.m2m.internal.qvt.oml.cst.LocalPropertyCS;
import org.eclipse.m2m.internal.qvt.oml.cst.LogExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingBodyCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingCallExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingDeclarationCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingExtensionCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingExtensionKindCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingInitCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingMethodCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingModuleCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingQueryCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingRuleCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingSectionCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingSectionsCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ModelTypeCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ModulePropertyCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MultiplicityDefCS;
import org.eclipse.m2m.internal.qvt.oml.cst.NewRuleCallExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.OppositePropertyCS;
import org.eclipse.m2m.internal.qvt.oml.cst.OutExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.PackageRefCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ParameterDeclarationCS;
import org.eclipse.m2m.internal.qvt.oml.cst.QualifierKindCS;
import org.eclipse.m2m.internal.qvt.oml.cst.RenameCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ResolveExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ResolveInExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ReturnExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.SwitchAltExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.SwitchExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.TransformationHeaderCS;
import org.eclipse.m2m.internal.qvt.oml.cst.TypeSpecCS;
import org.eclipse.m2m.internal.qvt.oml.cst.VariableInitializationCS;
import org.eclipse.m2m.internal.qvt.oml.cst.WhileExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.parser.AbstractQVTParser;
import org.eclipse.m2m.internal.qvt.oml.cst.temp.ErrorCallExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.temp.ScopedNameCS;
import org.eclipse.m2m.internal.qvt.oml.emf.util.mmregistry.EmfMmUtil;
import org.eclipse.m2m.internal.qvt.oml.emf.util.mmregistry.MetamodelRegistry;
import org.eclipse.m2m.internal.qvt.oml.expressions.AltExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.AssertExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.AssignExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.BlockExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.ComputeExp;
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.DirectionKind;
import org.eclipse.m2m.internal.qvt.oml.expressions.EntryOperation;
import org.eclipse.m2m.internal.qvt.oml.expressions.ExpressionsFactory;
import org.eclipse.m2m.internal.qvt.oml.expressions.ExpressionsPackage;
import org.eclipse.m2m.internal.qvt.oml.expressions.ForExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.ImperativeIterateExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.ImperativeOperation;
import org.eclipse.m2m.internal.qvt.oml.expressions.InstantiationExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.Library;
import org.eclipse.m2m.internal.qvt.oml.expressions.LogExp;
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.MappingParameter;
import org.eclipse.m2m.internal.qvt.oml.expressions.ModelParameter;
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.OperationalTransformation;
import org.eclipse.m2m.internal.qvt.oml.expressions.Rename;
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.ReturnExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.SeverityKind;
import org.eclipse.m2m.internal.qvt.oml.expressions.SwitchExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.VarParameter;
import org.eclipse.m2m.internal.qvt.oml.expressions.VariableInitExp;
import org.eclipse.m2m.internal.qvt.oml.expressions.WhileExp;
import org.eclipse.m2m.internal.qvt.oml.library.QvtResolveUtil;
import org.eclipse.m2m.internal.qvt.oml.stdlib.QVTUMLReflection;
import org.eclipse.m2m.qvt.oml.blackbox.LoadContext;
import org.eclipse.m2m.qvt.oml.blackbox.ResolutionContextImpl;
import org.eclipse.ocl.Environment;
import org.eclipse.ocl.SemanticException;
import org.eclipse.ocl.Environment.Internal;
import org.eclipse.ocl.cst.CSTFactory;
import org.eclipse.ocl.cst.CSTNode;
import org.eclipse.ocl.cst.CallExpCS;
import org.eclipse.ocl.cst.CollectionTypeCS;
import org.eclipse.ocl.cst.DotOrArrowEnum;
import org.eclipse.ocl.cst.FeatureCallExpCS;
import org.eclipse.ocl.cst.IfExpCS;
import org.eclipse.ocl.cst.IteratorExpCS;
import org.eclipse.ocl.cst.LiteralExpCS;
import org.eclipse.ocl.cst.NullLiteralExpCS;
import org.eclipse.ocl.cst.OCLExpressionCS;
import org.eclipse.ocl.cst.OperationCallExpCS;
import org.eclipse.ocl.cst.PathNameCS;
import org.eclipse.ocl.cst.PrimitiveTypeCS;
import org.eclipse.ocl.cst.SimpleNameCS;
import org.eclipse.ocl.cst.SimpleTypeEnum;
import org.eclipse.ocl.cst.StringLiteralExpCS;
import org.eclipse.ocl.cst.TupleTypeCS;
import org.eclipse.ocl.cst.TypeCS;
import org.eclipse.ocl.cst.VariableCS;
import org.eclipse.ocl.cst.VariableExpCS;
import org.eclipse.ocl.ecore.CallExp;
import org.eclipse.ocl.ecore.CallOperationAction;
import org.eclipse.ocl.ecore.Constraint;
import org.eclipse.ocl.ecore.EcoreFactory;
import org.eclipse.ocl.ecore.SendSignalAction;
import org.eclipse.ocl.ecore.StringLiteralExp;
import org.eclipse.ocl.expressions.BooleanLiteralExp;
import org.eclipse.ocl.expressions.CollectionKind;
import org.eclipse.ocl.expressions.CollectionLiteralExp;
import org.eclipse.ocl.expressions.FeatureCallExp;
import org.eclipse.ocl.expressions.IfExp;
import org.eclipse.ocl.expressions.IntegerLiteralExp;
import org.eclipse.ocl.expressions.InvalidLiteralExp;
import org.eclipse.ocl.expressions.IteratorExp;
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.TypeExp;
import org.eclipse.ocl.expressions.UnlimitedNaturalLiteralExp;
import org.eclipse.ocl.expressions.Variable;
import org.eclipse.ocl.expressions.VariableExp;
import org.eclipse.ocl.internal.l10n.OCLMessages;
import org.eclipse.ocl.parser.AbstractOCLAnalyzer;
import org.eclipse.ocl.parser.OCLLexer;
import org.eclipse.ocl.parser.OCLParser;
import org.eclipse.ocl.types.BagType;
import org.eclipse.ocl.types.CollectionType;
import org.eclipse.ocl.types.OCLStandardLibrary;
import org.eclipse.ocl.types.OrderedSetType;
import org.eclipse.ocl.types.SequenceType;
import org.eclipse.ocl.types.SetType;
import org.eclipse.ocl.types.TypeType;
import org.eclipse.ocl.util.OCLUtil;
import org.eclipse.ocl.util.TypeUtil;
import org.eclipse.ocl.utilities.ASTNode;
import org.eclipse.ocl.utilities.UMLReflection;
import org.eclipse.osgi.util.NLS;
public class QvtOperationalVisitorCS
extends AbstractOCLAnalyzer<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject,
CallOperationAction, SendSignalAction, Constraint, EClass, EObject> { // FIXME - changed in M3.4 migration
private final QvtCompilerOptions myCompilerOptions;
/* TODO -
* Groups all late resolve expression encountered during CST analysis for later validation.
* At the moment when resolve expression is visited it has not its container connect yet, which
* required for validation. Should be replaced by introducing a validation visitor.
*/
private List<ResolveExp> myLateResolveExps;
public QvtOperationalVisitorCS(
OCLLexer lexStream,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> environment, QvtCompilerOptions options) {
super(new OCLParser(lexStream));
myCompilerOptions = options;
}
public QvtOperationalVisitorCS(AbstractQVTParser parser, QvtCompilerOptions options) {
super(parser);
myCompilerOptions = options;
}
public QvtCompilerOptions getCompilerOptions() {
return myCompilerOptions;
}
@Override
protected void initStartEndPositions(ASTNode astNode, CSTNode cstNode) {
// FIXME - temp workaround after OCL 1.2 migration
astNode.setStartPosition(cstNode.getStartOffset());
astNode.setEndPosition(cstNode.getEndOffset());
}
protected InstantiationExp instantiationExpCS(NewRuleCallExpCS newCallExp,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
InstantiationExp instantiationExp = ExpressionsFactory.eINSTANCE.createInstantiationExp();
initStartEndPositions(instantiationExp, newCallExp);
PathNameCS scopedIdentifierCS = newCallExp.getScopedIdentifier();
EClassifier instantiatedClass = typeCS(scopedIdentifierCS, env);
instantiationExp.setType(instantiatedClass);
if(instantiatedClass instanceof EClass) {
instantiationExp.setInstantiatedClass((EClass)instantiatedClass);
instantiationExp.setName(instantiatedClass.getName());
}
for (OCLExpressionCS nextArgCS : newCallExp.getArguments()) {
OCLExpression<EClassifier> nextArgAST = oclExpressionCS(nextArgCS, env);
if(nextArgAST != null) {
instantiationExp.getArgument().add(nextArgAST);
}
}
return instantiationExp;
}
@Override
protected EClassifier tupleTypeCS(TupleTypeCS tupleTypeCS, Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
EClassifier type = null;
try {
type = super.tupleTypeCS(tupleTypeCS, env);
} catch (Exception e) {
// catch MDT OCL exception related to unresolved types used in Tuples, and report error
String message = NLS.bind(ValidationMessages.UnknownClassifierType, QvtOperationalParserUtil.getStringRepresentation(tupleTypeCS), tupleTypeCS);
QvtOperationalUtil.reportError(env, message, tupleTypeCS);
}
return type;
}
@Override
protected EClassifier typeCS(TypeCS typeCS, Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
EClassifier type = super.typeCS(typeCS, env);
if(type == getOclVoid() && typeCS instanceof PrimitiveTypeCS == false) {
if(typeCS instanceof PathNameCS) {
// check whether Void synonym was used
PathNameCS pathNameCS = (PathNameCS) typeCS;
if(QvtOperationalStdLibrary.INSTANCE.lookupClassifier(pathNameCS.getSequenceOfNames()) == getOclVoid()) {
return type;
}
}
// FIXME - workaround for migration to OCL 1.2 => non primitive type but
// resolved as OclVoid in super impl. indicates actually a type unresolved by the fEnv.
return null;
}
// MDT OCL does not check for nested type whether they are resolved
// do it here if element type is null
if(type instanceof CollectionType && typeCS instanceof CollectionTypeCS) {
CollectionType<?, ?> collectionType = (CollectionType<?, ?>)type;
if(collectionType.getElementType() == null) {
CollectionTypeCS collectionTypeCS = (CollectionTypeCS)typeCS;
QvtOperationalUtil.reportError(env, NLS.bind(ValidationMessages.UnknownClassifierType, new Object[] {
QvtOperationalParserUtil.getStringRepresentation(collectionTypeCS.getTypeCS())}),
collectionTypeCS.getTypeCS());
}
}
if(type != null) {
if(myCompilerOptions.isGenerateCompletionData()) {
// bind Module type only, for now
if(type instanceof Module) {
ASTBindingHelper.createCST2ASTBindingUnidirectional(typeCS, type);
}
}
}
return type;
}
private EClassifier visitTypeCS(TypeCS typeCS, DirectionKind directionKind,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
EClassifier type = typeCS(typeCS, env);
if (type == null) {
// FIXME - M3.4 not needed, already reported above in #typeCS(typeCS, fEnv);
/*fEnv.reportError(NLS.bind(ValidationMessages.UnknownClassifierType, new Object[] {
QvtOperationalParserUtil.getStringRepresentation(typeCS)}),
typeCS); */
}
return type;
}
@Override
protected Variable<EClassifier, EParameter> lookupImplicitSourceForOperation(
CSTNode cstNode,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env,
List<OCLExpression<EClassifier>> args, String operationName) {
Variable<EClassifier, EParameter> source = super.lookupImplicitSourceForOperation(cstNode, env, args, operationName);
if(source == null) {
// FIXME - why is this done?, looks like a workaround for MDT OCL,
// it's a legal contract for the lookupXXX operation to return null
source = EcoreFactory.eINSTANCE.createVariable();
initASTMapping(env, source, cstNode);
}
return source;
}
private EClassifier visitTypeCSInModelType(TypeSpecCS typeSpecCS, ModelType modelType,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
EClassifier type = typeCS(typeSpecCS.getTypeCS(), env);
if (type == null) {
// FIXME - M3.4 not needed, already reported above in #typeCS(typeCS, fEnv);
/*fEnv.reportError(NLS.bind(ValidationMessages.UnknownClassifierType, new Object[] {
QvtOperationalParserUtil.getStringRepresentation(typeSpecCS.getTypeCS())}),
typeSpecCS.getTypeCS());*/
}
return type;
}
private static class TypeSpecPair {
public EClassifier myType;
public ModelParameter myExtent;
}
private ModelParameter lookupModelParameter(SimpleNameCS nameCS, DirectionKind directionKind, QvtOperationalEnv env) {
QvtOperationalModuleEnv moduleEnv = getModuleContextEnv(env);
ModelParameter modelParam = moduleEnv.lookupModelParameter(nameCS.getValue(), directionKind);
if(modelParam == null) {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_extentWrongName,
new Object[] { nameCS.getValue(), moduleEnv.getAllExtentNames(directionKind) }), nameCS);
}
return modelParam;
}
private TypeSpecPair visitTypeSpecCS(TypeSpecCS typeSpecCS, DirectionKind directionKind,
QvtOperationalEnv env) {
TypeSpecPair result = new TypeSpecPair();
if (typeSpecCS.getSimpleNameCS() != null) {
result.myExtent = lookupModelParameter(typeSpecCS.getSimpleNameCS(), directionKind, env);
if (result.myExtent != null && result.myExtent.getEType() instanceof ModelType) {
result.myType = visitTypeCSInModelType(typeSpecCS, (ModelType) result.myExtent.getEType(), env);
return result;
}
}
result.myType = visitTypeCS(typeSpecCS.getTypeCS(), directionKind, env);
return result;
}
private String visitLiteralExpCS(StringLiteralExpCS stringLiteralExpCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env)
throws SemanticException {
// stringLiteralExpCS() is not called directly for AST-CST binding creation done in literalExpCS()
OCLExpression<EClassifier> literalExpCS = literalExpCS(stringLiteralExpCS, env);
StringLiteralExp stringLiteralExp = (StringLiteralExp) literalExpCS;
return stringLiteralExp.getStringSymbol();
}
@Override
protected IfExp<EClassifier> ifExpCS(
IfExpCS ifExpCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
boolean isElseMissed = false;
if (ifExpCS.getElseExpression() == null) {
isElseMissed = true;
// FIXME - !!!!! What a strange hack found during migration to OCL 1.2
NullLiteralExpCS nullCS = CSTFactory.eINSTANCE.createNullLiteralExpCS();
nullCS.setSymbol("null"); //$NON-NLS-1$
//
ifExpCS.setElseExpression(nullCS); //$NON-NLS-1$
}
IfExp<EClassifier> ifExp = super.ifExpCS(ifExpCS, env);
EObject container = ifExpCS.eContainer();
if (container instanceof VariableInitializationCS) {
if (isElseMissed) {
QvtOperationalUtil.reportWarning(env, NLS.bind(ValidationMessages.QvtOperationalVisitorCS_ifExpWithoutElseAssignment,
new Object[] { }), ifExpCS);
}
}
return ifExp;
}
/**
* Produces AST Node from the given CST and performs validation on it.
*/
public OCLExpression<EClassifier> analyzeExpressionCS(OCLExpressionCS oclExpressionCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) throws SemanticException {
OCLExpression<EClassifier> result = oclExpressionCS(oclExpressionCS, env);
validate(env);
return result;
}
@Override
protected OCLExpression<EClassifier> oclExpressionCS(OCLExpressionCS oclExpressionCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature,
EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction,
Constraint, EClass, EObject> env) {
try {
if (oclExpressionCS instanceof BlockExpCS) {
return visitBlockExpCS((BlockExpCS) oclExpressionCS, env);
}
if (oclExpressionCS instanceof ComputeExpCS) {
return visitComputeExpCS((ComputeExpCS) oclExpressionCS, env);
}
if (oclExpressionCS instanceof WhileExpCS) {
return visitWhileExpCS((WhileExpCS) oclExpressionCS, env);
}
if (oclExpressionCS instanceof SwitchExpCS) {
return visitSwitchExpCS((SwitchExpCS) oclExpressionCS, env);
}
if (oclExpressionCS instanceof OutExpCS) {
return visitOutExpCS((OutExpCS) oclExpressionCS, toQVTOperationalEnv(env), true);
}
if (oclExpressionCS instanceof AssignStatementCS) {
return visitAssignStatementCS((AssignStatementCS) oclExpressionCS, env);
}
if (oclExpressionCS instanceof VariableInitializationCS) {
return visitVariableInitializationCS((VariableInitializationCS) oclExpressionCS, env);
}
if (oclExpressionCS instanceof ExpressionStatementCS) {
return visitExpressionStatementCS((ExpressionStatementCS) oclExpressionCS, env);
}
if (oclExpressionCS instanceof ResolveInExpCS) {
return visitResolveInExpCS((ResolveInExpCS) oclExpressionCS, toQVTOperationalEnv(env));
}
if (oclExpressionCS instanceof ResolveExpCS) {
return visitResolveExpCS((ResolveExpCS) oclExpressionCS, toQVTOperationalEnv(env));
}
if(oclExpressionCS instanceof LogExpCS) {
return logExp((LogExpCS) oclExpressionCS, env);
}
if(oclExpressionCS instanceof AssertExpCS) {
return assertExp((AssertExpCS) oclExpressionCS, env);
}
if (oclExpressionCS instanceof ForExpCS) {
return visitForExp((ForExpCS) oclExpressionCS, env);
}
if (oclExpressionCS instanceof ImperativeIterateExpCS) {
return visitImperativeIterateExp((ImperativeIterateExpCS) oclExpressionCS, env);
}
if (oclExpressionCS instanceof ReturnExpCS) {
return visitReturnExpCS((ReturnExpCS) oclExpressionCS, env);
}
if(oclExpressionCS instanceof NewRuleCallExpCS) {
return instantiationExpCS((NewRuleCallExpCS)oclExpressionCS, env);
}
if (oclExpressionCS instanceof TypeCS) {
EClassifier type = typeCS((TypeCS) oclExpressionCS, env);
if (type == null) {
QvtOperationalUtil.reportError(env, OCLMessages.bind(
OCLMessages.UnrecognizedType_ERROR_,
QvtOperationalUtil.getStringRepresentation((TypeCS) oclExpressionCS)), oclExpressionCS);
}
else {
TypeExp<EClassifier> typeExp = env.getOCLFactory().createTypeExp();
typeExp.setReferredType(type);
typeExp.setType(TypeUtil.resolveTypeType(env, type));
return typeExp;
}
}
else {
OCLExpression<EClassifier> result = super.oclExpressionCS(oclExpressionCS, env);
if (oclExpressionCS instanceof OperationCallExpCS) {
if (result instanceof OperationCallExp) {
validateOperationCall((OperationCallExpCS) oclExpressionCS,
(OperationCallExp<EClassifier, EOperation>) result, env);
}
if (result instanceof IteratorExp
&& ((IteratorExp<EClassifier, EOperation>) result).getBody() instanceof OperationCallExp) {
validateOperationCall((OperationCallExpCS) oclExpressionCS,
(OperationCallExp<EClassifier, EOperation>) ((IteratorExp<EClassifier, EOperation>) result).getBody(),
env);
}
}
return result;
}
}
catch (NullPointerException ex) {
QvtPlugin.log(ex);
QvtOperationalUtil.reportError(env, ValidationMessages.QvtOperationalVisitorCS_oclParseNPE, oclExpressionCS);
}
catch (RuntimeException ex) {
//QvtPlugin.log(ex);
QvtOperationalUtil.reportError(env, ValidationMessages.QvtOperationalVisitorCS_oclParseNPE, oclExpressionCS);
}
return null;
}
@Override
protected OCLExpression<EClassifier> literalExpCS(
LiteralExpCS literalExpCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
OCLExpression<EClassifier> literalExp = super.literalExpCS(literalExpCS, env);
// AST binding
if(myCompilerOptions.isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(literalExpCS, literalExp);
}
//
return literalExp;
}
protected AssertExp assertExp(AssertExpCS assertExpCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
AssertExp assertAST = ExpressionsFactory.eINSTANCE.createAssertExp();
assertAST.setStartPosition(assertExpCS.getStartOffset());
assertAST.setEndPosition(assertExpCS.getEndOffset());
if(getCompilerOptions().isSourceLineNumbersEnabled()) {
int startOffset = assertAST.getStartPosition();
if(startOffset < getLexer().getInputChars().length) {
assertAST.setLine(getLexer().getLineNumberOfCharAt(assertAST.getStartPosition()));
}
}
if(assertExpCS.getAssertion() != null) {
assertAST.setAssertion(oclExpressionCS(assertExpCS.getAssertion(), env));
}
if(assertExpCS.getSeverity() != null) {
String severityCSVal = assertExpCS.getSeverity().getValue();
if(severityCSVal != null) {
SeverityKind actualSeverity = SeverityKind.get(severityCSVal);
if(actualSeverity != null) {
assertAST.setSeverity(actualSeverity);
} else {
CSTNode errorNode = assertExpCS.getSeverity();
QvtOperationalUtil.reportError(env, NLS.bind(ValidationMessages.UknownSeverityKindError, severityCSVal), errorNode);
}
}
}
if(assertExpCS.getLog() != null) {
assertAST.setLog(logExp(assertExpCS.getLog(), env));
}
validateAssertExp(assertAST, env);
return assertAST;
}
private void validateAssertExp(AssertExp assertExp,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
EClassifier boolType = env.getOCLStandardLibrary().getBoolean();
if(assertExp.getAssertion() == null || assertExp.getAssertion().getType() != boolType) {
ASTNode errNode = assertExp.getAssertion() != null ? assertExp.getAssertion() : assertExp;
QvtOperationalUtil.reportError(env, ValidationMessages.BooleanTypeAssertConditionError,
errNode.getStartPosition(), errNode.getEndPosition());
}
LogExp logExp = assertExp.getLog();
if(logExp != null) {
validateLogExp(logExp, env);
}
}
private void validateLogExp(LogExp logExp,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
EList<OCLExpression<EClassifier>> allArgs = logExp.getArgument();
if(allArgs.isEmpty()) {
QvtOperationalUtil.reportError(env, ValidationMessages.MissingMessageLogExpArgumentError, logExp.getStartPosition(), logExp.getEndPosition());
}
int pos = 1;
for (OCLExpression<EClassifier> arg : allArgs) {
switch (pos) {
case 1:
EClassifier stringType = env.getOCLStandardLibrary().getString();
if(stringType != arg.getType()) {
QvtOperationalUtil.reportError(env, ValidationMessages.StringTypeMessageLogArgumentError, arg.getStartPosition(), arg.getEndPosition());
}
break;
case 2:
// anything accepted here
break;
case 3:
EClassifier intType = env.getOCLStandardLibrary().getInteger();
if(intType != arg.getType()) {
QvtOperationalUtil.reportError(env, ValidationMessages.LogLevelNumberArgumentError, arg.getStartPosition(), arg.getEndPosition());
}
break;
default:
QvtOperationalUtil.reportError(env, NLS.bind(ValidationMessages.UnsupportedLogExpArgumentError, pos), arg.getStartPosition(), arg.getEndPosition());
}
pos++;
}
OCLExpression<EClassifier> condition = logExp.getCondition();
if(condition != null && condition.getType() != env.getOCLStandardLibrary().getBoolean()) {
QvtOperationalUtil.reportError(env, ValidationMessages.LogExpBooleanTypeConditionError,
condition.getStartPosition(), condition.getEndPosition());
}
}
protected LogExp logExp(LogExpCS logExpCS, Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
LogExp logAST = ExpressionsFactory.eINSTANCE.createLogExp();
logAST.setStartPosition(logExpCS.getStartOffset());
logAST.setEndPosition(logExpCS.getEndOffset());
logAST.setName("log"); //$NON-NLS-1$
for (OCLExpressionCS argCS : logExpCS.getArguments() ) {
OCLExpression<EClassifier> arg = this.oclExpressionCS(argCS, env);
if(arg != null) {
logAST.getArgument().add(arg);
}
}
if(logExpCS.getCondition() != null) {
logAST.setCondition(oclExpressionCS(logExpCS.getCondition(), env));
}
validateLogExp(logAST, env);
return logAST;
}
@Override
protected Variable<EClassifier, EParameter> variableDeclarationCS(VariableCS variableDeclarationCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env,
boolean addToEnvironment) {
Variable<EClassifier, EParameter> varDecl = super.variableDeclarationCS(variableDeclarationCS, env, addToEnvironment);
if ((varDecl.getType() == null) && (varDecl.getInitExpression() != null)) {
varDecl.setType(varDecl.getInitExpression().getType());
}
// AST binding
if(myCompilerOptions.isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(variableDeclarationCS, varDecl);
}
//
return varDecl;
}
@Override
protected OCLExpression<EClassifier> propertyCallExpCS(CallExpCS propertyCallExpCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env)
{
if (propertyCallExpCS instanceof ErrorCallExpCS) {
OCLExpressionCS sourceExpCS = propertyCallExpCS.getSource();
if (sourceExpCS != null) {
if (propertyCallExpCS.getAccessor() == DotOrArrowEnum.ARROW_LITERAL) {
getCollectionSourceExpression(sourceExpCS, env);
} else {
oclExpressionCS(sourceExpCS, env);
}
}
return null;
}
OCLExpression<EClassifier> result = super.propertyCallExpCS(propertyCallExpCS, env);
if(result != null) {
// AST binding
if(myCompilerOptions.isGenerateCompletionData()) {
createPropertyCallASTBinding(propertyCallExpCS, result, env);
}
}
return result;
}
@Override
protected OCLExpression<EClassifier> simpleNameCS(
SimpleNameCS simpleNameCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env,
OCLExpression<EClassifier> source) {
OCLExpression<EClassifier> result = customSimpleNameCS(simpleNameCS, env, source);
// AST binding
if(myCompilerOptions.isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(simpleNameCS, result);
}
//
return result;
}
@Override
protected OCLExpression<EClassifier> operationCallExpCS(
OperationCallExpCS operationCallExpCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
OCLExpression<EClassifier> result = super.operationCallExpCS(operationCallExpCS, env);
if(result instanceof OperationCallExp) {
OperationCallExp<EClassifier, EOperation> opCallExp = (OperationCallExp<EClassifier, EOperation>) result;
OCLExpression<EClassifier> source = opCallExp.getSource();
if (source != null) {
if (isArrowAccessToCollection(operationCallExpCS, source)) {
// FIXME - use OCL TypeChecker::isStdLibOperation()
// Is it a standard operation like "select"?
// In other words, did lookupOperation() in genOperationCallExp() return something?
List<EOperation> operations = TypeUtil.getOperations(env, source.getType());
boolean isStdOperation = (operations != null)
&& (opCallExp.getReferredOperation() != null)
&& operations.contains(opCallExp.getReferredOperation());
if (!isStdOperation) {
result = createImplicitXCollect(source, opCallExp, env, operationCallExpCS);
}
}
}
DeprecatedImplicitSourceCallHelper.validateCallExp(operationCallExpCS, opCallExp, env);
}
return result;
}
@Override
protected OperationCallExp<EClassifier, EOperation> genOperationCallExp(
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env,
OperationCallExpCS operationCallExpCS, String rule,
String operName, OCLExpression<EClassifier> source,
EClassifier ownerType, List<OCLExpression<EClassifier>> args) {
EClassifier operationSourceType = ownerType;
if (isArrowAccessToCollection(operationCallExpCS, source)
&& (lookupOperation(operationCallExpCS, env, ownerType, operName, args) == null)) {
@SuppressWarnings("unchecked") //$NON-NLS-1$
CollectionType<EClassifier, EOperation> sourceType = (CollectionType<EClassifier, EOperation>) ownerType;
operationSourceType = sourceType.getElementType();
}
return super.genOperationCallExp(env, operationCallExpCS, rule, operName,
source, operationSourceType, args);
}
/**
* Creates an implicit <code>xcollect</code> iterator expression for a
* property call on a collection-type source expression.
*
* @param source the property call source expression
* @param propertyCall the property call expression
* @param fEnv the current environment
*
* @return the xcollect expression
* @throws TerminateException
*/
protected ImperativeIterateExp createImplicitXCollect(OCLExpression<EClassifier> source,
FeatureCallExp<EClassifier> propertyCall,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature,
EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint,
EClass, EObject> env,
CSTNode cstNode) {
@SuppressWarnings("unchecked") //$NON-NLS-1$
EClassifier sourceElementType = ((CollectionType<EClassifier, EOperation>) source.getType())
.getElementType();
ImperativeIterateExp result = ExpressionsFactory.eINSTANCE.createImperativeIterateExp();
initASTMapping(env, result, cstNode);
Variable<EClassifier, EParameter> itervar =
genVariableDeclaration(cstNode, "modelPropertyCallCS", env,//$NON-NLS-1$
null, sourceElementType, null, false, true, false);
List<Variable<EClassifier, EParameter>> iters = result.getIterator();
iters.add(itervar);
result.setBody(propertyCall);
result.setName("xcollect");//$NON-NLS-1$
VariableExp<EClassifier, EParameter> vexp = oclFactory.createVariableExp();
initASTMapping(env, vexp, cstNode);
vexp.setType(itervar.getType());
vexp.setReferredVariable(itervar);
vexp.setName(itervar.getName());
/* adjust the source variable for the body expression to be the
newly generated implicit iterator variable */
propertyCall.setSource(vexp);
if (!(propertyCall instanceof OperationCallExp)) {
// the overall start and end positions are the property positions
propertyCall.setStartPosition(propertyCall.getPropertyStartPosition());
propertyCall.setEndPosition(propertyCall.getPropertyEndPosition());
}
result.setSource(source);
EClassifier bodyType = propertyCall.getType();
if (source.getType() instanceof SequenceType ||
source.getType() instanceof OrderedSetType) {
EClassifier c = getCollectionType(
env,
CollectionKind.SEQUENCE_LITERAL,
bodyType);
result.setType(c);
} else {
EClassifier c = getCollectionType(
env,
CollectionKind.BAG_LITERAL,
bodyType);
result.setType(c);
}
env.deleteElement(itervar.getName());
return result;
}
private boolean isArrowAccessToCollection(CallExpCS callExpCS, OCLExpression<EClassifier> source) {
if (source == null) {
return false;
}
return (callExpCS.getAccessor().getValue() == DotOrArrowEnum.ARROW)
&& (source.getType() instanceof CollectionType);
}
@Override
protected OCLExpression<EClassifier> variableExpCS(
VariableExpCS variableExpCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
OCLExpression<EClassifier> result = super.variableExpCS(variableExpCS, env);
if(result instanceof PropertyCallExp) {
DeprecatedImplicitSourceCallHelper.validateCallExp(variableExpCS, (PropertyCallExp<EClassifier, ?>)result, env);
}
// AST binding
if(myCompilerOptions.isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(variableExpCS, result);
}
//
return result;
}
private OCLExpression<EClassifier> visitOclExpressionCS(OCLExpressionCS expressionCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
OCLExpression<EClassifier> result = oclExpressionCS(expressionCS, env);
if (expressionCS instanceof MappingCallExpCS) {
if (result instanceof OperationCallExp) {
MappingCallExp mappingCallExp = createMappingCallExp((MappingCallExpCS) expressionCS, result);
if (mappingCallExp != null) {
return mappingCallExp;
}
} else if (result instanceof IteratorExp) {
IteratorExp<EClassifier, EParameter> iteratorExp = (IteratorExp<EClassifier, EParameter>) result;
MappingCallExp mappingCallExp = createMappingCallExp((MappingCallExpCS) expressionCS, iteratorExp.getBody());
if (mappingCallExp != null) {
iteratorExp.setBody(mappingCallExp);
return iteratorExp;
}
} else if (result instanceof ImperativeIterateExp) {
ImperativeIterateExp imperativeIterateExp = (ImperativeIterateExp) result;
MappingCallExp mappingCallExp = createMappingCallExp((MappingCallExpCS) expressionCS, imperativeIterateExp.getBody());
if (mappingCallExp != null) {
imperativeIterateExp.setBody(mappingCallExp);
return imperativeIterateExp;
}
}
QvtOperationalUtil.reportError(env, ValidationMessages.mappingOperationExpected, expressionCS);
return null;
}
return result;
}
private OCLExpression<EClassifier> visitBlockExpCS(BlockExpCS expressionCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
Collection<Variable<EClassifier, EParameter>> beginScopeVars = null;
if(expressionCS.eContainer() instanceof ImperativeOperation == false) {
// variables defined in the scope of operation handled by environment scope
beginScopeVars = env.getVariables();
}
try {
return doVisitBlockExpCS(expressionCS, env);
}
finally {
if(beginScopeVars != null) {
// remove variables of this scope when leaving it, only successfully added variables into fEnv
// in this block scope will be removed, so we can not remove outer scope
// existing variables.
// Note: nested block scopes have done their clean-up already so we remove
// only our stuff
Collection<Variable<EClassifier, EParameter>> endScopeVars = env.getVariables();
for (Variable<EClassifier, EParameter> nextVar : endScopeVars) {
// remove those new in the scope
if(!beginScopeVars.contains(nextVar)) {
env.deleteElement(nextVar.getName());
}
}
}
}
}
private OCLExpression<EClassifier> doVisitBlockExpCS(BlockExpCS expressionCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
BlockExp result = ExpressionsFactory.eINSTANCE.createBlockExp();
result.setStartPosition(expressionCS.getStartOffset());
result.setEndPosition(expressionCS.getEndOffset());
result.setType(env.getOCLStandardLibrary().getOclVoid());
for (OCLExpressionCS oclExpCS : expressionCS.getBodyExpressions()) {
OCLExpression<EClassifier> bodyExp = visitOclExpressionCS(oclExpCS, env);
if (bodyExp != null) {
result.getBody().add(bodyExp);
}
}
return result;
}
private OCLExpression<EClassifier> visitComputeExpCS(ComputeExpCS computeExpCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
ComputeExp result = ExpressionsFactory.eINSTANCE.createComputeExp();
result.setStartPosition(computeExpCS.getStartOffset());
result.setEndPosition(computeExpCS.getEndOffset());
Variable<EClassifier, EParameter> returnedElementExp = variableDeclarationCS(computeExpCS.getReturnedElement(), env, true);
result.setReturnedElement(returnedElementExp);
result.setType(returnedElementExp.getType());
OCLExpression<EClassifier> bodyExp = visitOclExpressionCS(computeExpCS.getBody(), env);
result.setBody(bodyExp);
if (returnedElementExp != null) {
env.deleteElement(returnedElementExp.getName());
}
return result;
}
private OCLExpression<EClassifier> visitSwitchExpCS(SwitchExpCS switchExpCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
SwitchExp switchExp = ExpressionsFactory.eINSTANCE.createSwitchExp();
switchExp.setStartPosition(switchExpCS.getStartOffset());
switchExp.setEndPosition(switchExpCS.getEndOffset());
List<EClassifier> allPartTypes = new ArrayList<EClassifier>();
if (switchExpCS.getAlternativePart() != null) {
for (SwitchAltExpCS altExpCS : switchExpCS.getAlternativePart()) {
AltExp altExp = visitSwitchAltExpCS(altExpCS, env);
switchExp.getAlternativePart().add((AltExp) altExp);
allPartTypes.add(altExp.getBody() != null ? altExp.getBody().getType() : null);
}
}
if (switchExpCS.getElsePart() != null) {
OCLExpression<EClassifier> elsePart = visitOclExpressionCS(switchExpCS.getElsePart(), env);
switchExp.setElsePart(elsePart);
allPartTypes.add(elsePart.getType());
}
if (allPartTypes.isEmpty()) {
switchExp.setType(getOclVoid());
}
else if (allPartTypes.size() == 1) {
switchExp.setType(allPartTypes.get(0));
}
else {
EClassifier type = null;
for (int i = 0; i+1 < allPartTypes.size(); ++i) {
type = TypeUtil.commonSuperType(switchExpCS, env,
allPartTypes.get(i), allPartTypes.get(i+1));
if (type == null) {
break;
}
}
switchExp.setType(type == null ? getOclVoid() : type);
}
return switchExp;
}
private AltExp visitSwitchAltExpCS(SwitchAltExpCS altExpCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
AltExp altExp = ExpressionsFactory.eINSTANCE.createAltExp();
altExp.setStartPosition(altExpCS.getStartOffset());
altExp.setEndPosition(altExpCS.getEndOffset());
OCLExpression<EClassifier> condition = visitOclExpressionCS(altExpCS.getCondition(), env);
altExp.setCondition(condition);
OCLExpression<EClassifier> body = visitOclExpressionCS(altExpCS.getBody(), env);
altExp.setBody(body);
return altExp;
}
private OCLExpression<EClassifier> visitWhileExpCS(WhileExpCS expressionCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
WhileExp result = ExpressionsFactory.eINSTANCE.createWhileExp();
result.setStartPosition(expressionCS.getStartOffset());
result.setEndPosition(expressionCS.getEndOffset());
String resultVarName = null;
if(expressionCS.getResultVar() != null) {
VariableCS varCS = expressionCS.getResultVar();
Variable<EClassifier, EParameter> var = null;
Variable<EClassifier, EParameter> prevVar = env.lookup(varCS.getName());
var = variableDeclarationCS(varCS, env, true);
if(prevVar != null) {
env.addElement(varCS.getName(), prevVar, true);
} else {
resultVarName = varCS.getName();
}
result.setResultVar(var);
result.setType(var.getType());
} else if(expressionCS.getResult() != null) {
// report usage of legacy while
QvtOperationalUtil.reportWarning(env, ValidationMessages.QvtOperationalVisitorCS_deprecatedWhileExp, expressionCS);
OCLExpression<EClassifier> resExp = visitOclExpressionCS(expressionCS.getResult(), env);
result.setType(resExp.getType());
result.setResult(resExp);
} else {
result.setType(env.getOCLStandardLibrary().getOclVoid());
}
OCLExpression<EClassifier> condExp = visitOclExpressionCS(expressionCS.getCondition(), env);
result.setCondition(condExp);
if(condExp != null) {
EClassifier condType = condExp.getType();
if(env.getOCLStandardLibrary().getBoolean() != condExp.getType()) {
if(condType == null) {
condType = env.getOCLStandardLibrary().getOclVoid();
}
String message = NLS.bind(ValidationMessages.QvtOperationalVisitorCS_booleanTypeExpressionExpected, env.getUMLReflection().getName(condType));
if(expressionCS.getResult() == null) {
QvtOperationalUtil.reportError(env, message, expressionCS.getCondition());
} else {
// warn for legacy code to keep compilable, as it was not reported at all
QvtOperationalUtil.reportWarning(env, message, expressionCS.getCondition());
}
}
}
List<OCLExpressionCS> bodyCS = result.getBody() instanceof BlockExpCS ? ((BlockExpCS)result.getBody()).getBodyExpressions() : Collections.<OCLExpressionCS>singletonList(expressionCS.getBody());
BlockExp body = ExpressionsFactory.eINSTANCE.createBlockExp();
for (OCLExpressionCS oclExpCS : bodyCS) {
OCLExpression<EClassifier> bodyExp = visitOclExpressionCS(oclExpCS, env);
if (bodyExp != null) {
body.getBody().add(bodyExp);
}
}
result.setBody(body);
if(resultVarName != null) {
env.deleteElement(resultVarName);
}
return result;
}
private static MappingDeclarationCS findOwningMappingDeclarationCS(OutExpCS outExpCS) {
EObject eContainer = outExpCS.eContainer();
if (eContainer instanceof MappingBodyCS) {
eContainer = eContainer.eContainer();
if (eContainer instanceof MappingSectionsCS) {
eContainer = eContainer.eContainer();
if (eContainer instanceof MappingRuleCS) {
MappingRuleCS mappingCS = (MappingRuleCS) eContainer;
return mappingCS.getMappingDeclarationCS();
}
}
}
return null;
}
private ObjectExp visitOutExpCS(OutExpCS outExpCS, QvtOperationalEnv env, boolean isValidationChecked) {
MappingDeclarationCS topLevelInMapping = findOwningMappingDeclarationCS(outExpCS);
if(topLevelInMapping != null && topLevelInMapping.getResult().isEmpty() && topLevelInMapping.getContextType() == null) {
//return null; FIXME - review this, ommitted to get better error reporting for AST
}
TypeSpecCS typeSpecCS = null;
if (outExpCS.getTypeSpecCS() != null) {
typeSpecCS = outExpCS.getTypeSpecCS();
}
ObjectExp objectExp = ExpressionsFactory.eINSTANCE.createObjectExp();
objectExp.setStartPosition(outExpCS.getStartOffset());
objectExp.setEndPosition(outExpCS.getEndOffset());
if(typeSpecCS != null) {
TypeSpecPair objectTypeSpec = visitTypeSpecCS(typeSpecCS, DirectionKind.OUT, env);
objectExp.setType(objectTypeSpec.myType);
if(objectTypeSpec.myType instanceof EClass) {
// skip DataTypes as the instantiatedClass property expects Class
// let's make AST validation to complain on missing class.
// Note: Still can be derived from the referred object if specified explicitly
objectExp.setInstantiatedClass((EClass)objectTypeSpec.myType);
}
objectExp.setExtent(objectTypeSpec.myExtent);
} else if(topLevelInMapping != null) {
// TODO - support multiple result parameters, for now take the first as the grammar does not allow this yet
boolean isContextInOut = topLevelInMapping.getDirectionKindCS() != null ?
topLevelInMapping.getDirectionKindCS().getDirectionKind() == DirectionKindEnum.INOUT : false;
assert env.getContextOperation() instanceof ImperativeOperation;
ImperativeOperation owningOperation = (ImperativeOperation)env.getContextOperation();
if(owningOperation.getResult().isEmpty()) {
if(isContextInOut && owningOperation.getContext() != null) {
objectExp.setType(owningOperation.getContext().getEType());
}
}
}
if(outExpCS.getSimpleNameCS() != null) {
// a referred object has been explicitly specified
String varName = outExpCS.getSimpleNameCS().getValue();
Variable<EClassifier, EParameter> referredObject = varName != null ? env.lookup(varName) : null;
if(referredObject == null) {
// variable not resolved
env.reportError(NLS.bind(ValidationMessages.unresolvedNameError, varName), outExpCS.getSimpleNameCS());
} else {
// TODO - implicit variables should follow multiplicity [1] referredObject and should always be created
// for now, only explicit variables are recorded
objectExp.setName(varName);
objectExp.setReferredObject(referredObject);
}
}
if(objectExp.getReferredObject() != null && objectExp.getType() == null) {
objectExp.setType(objectExp.getReferredObject().getType());
}
if(objectExp.getType() instanceof EClass) {
objectExp.setInstantiatedClass((EClass)objectExp.getType());
}
// try to derive extent from referred variable, if not retrieved from explicit TypeSpec yet
if (objectExp.getExtent() == null) {
Variable<EClassifier, EParameter> referredObject = objectExp.getReferredObject();
if(referredObject != null) {
if(referredObject.getRepresentedParameter() instanceof MappingParameter) {
MappingParameter mappingPar = (MappingParameter) referredObject.getRepresentedParameter();
objectExp.setExtent(mappingPar.getExtent());
}
}
if (objectExp.getExtent() == null && objectExp.getType() != null) {
QvtOperationalModuleEnv moduleEnv = getModuleContextEnv(env);
objectExp.setExtent(moduleEnv.resolveModelParameter(objectExp.getType(), DirectionKind.OUT));
}
}
EObject rootEObj = EcoreUtil.getRootContainer(outExpCS);
Module module = null;
if (env.getInternalParent() instanceof QvtOperationalFileEnv && rootEObj instanceof MappingModuleCS) {
// FIXME - revisit this hack bellow
module = ((QvtOperationalFileEnv) env.getInternalParent()).getKernel().getModule((MappingModuleCS) rootEObj);
}
if (objectExp.getExtent() == null && module != null && !getModelParameter(module).isEmpty()) {
QvtOperationalModuleEnv moduleEnv = getModuleContextEnv(env);
boolean isInvalidForExtentResolve = false;
if (objectExp.getReferredObject() == null) {
isInvalidForExtentResolve = (objectExp.getType() == null || !moduleEnv.isMayBelongToExtent(objectExp.getType()));
}
else {
if (IntermediateClassFactory.isIntermediateClass(objectExp.getReferredObject().getType())) {
isInvalidForExtentResolve = true;
}
else {
isInvalidForExtentResolve = !QVTUMLReflection.isUserModelElement(objectExp.getReferredObject().getType());
}
}
if(!isInvalidForExtentResolve) {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_extentFailToInfer,
QvtOperationalTypesUtil.getTypeFullName(objectExp.getType())),
typeSpecCS != null ? typeSpecCS : outExpCS);
}
}
ConstructorBody body = ExpressionsFactory.eINSTANCE.createConstructorBody();
body.setStartPosition(outExpCS.getStartOffset());
body.setEndPosition(outExpCS.getEndOffset());
objectExp.setBody(body);
QvtOperationalEnv tempEnv = env.getFactory().createEnvironment(env);
Variable<EClassifier, EParameter> elem = objectExp.getReferredObject();
if (elem == null) { // new object creation
elem = EcoreFactory.eINSTANCE.createVariable();
elem.setType(objectExp.getType());
objectExp.setReferredObject(elem);
}
String varName = (objectExp.getName() == null) ? env.generateTemporaryName() : objectExp.getName();
objectExp.setName(varName);
tempEnv.addImplicitVariableForProperties(varName, elem);
for (OCLExpressionCS expCS : outExpCS.getExpressions()) {
OCLExpression<EClassifier> exp = visitOclExpressionCS(expCS, tempEnv);
if (exp != null) {
body.getContent().add(exp);
}
}
if(myCompilerOptions.isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(outExpCS, objectExp, env);
}
if (isValidationChecked) {
validateObjectExp(objectExp, outExpCS, env);
}
return objectExp;
}
public Module visitMappingModule(ParsedModuleCS parsedModuleCS, QvtOperationalFileEnv env, QvtCompiler compiler) throws SemanticException {
MappingModuleCS moduleCS = parsedModuleCS.getModuleCS();
Module module = env.getKernel().getModule(moduleCS);
if (module != null) {
return module;
}
module = QvtOperationalParserUtil.createModule(moduleCS);
env.getKernel().setModule(module, moduleCS);
module.setStartPosition(moduleCS.getStartOffset());
module.setEndPosition(moduleCS.getEndOffset());
// AST binding
if(myCompilerOptions.isGenerateCompletionData()) {
ASTBindingHelper.createModuleBinding(moduleCS, module, env, parsedModuleCS.getSource());
}
//
for (ModelTypeCS modelTypeCS : moduleCS.getMetamodels()) {
ModelType modelType = visitModelTypeCS(modelTypeCS, env, module, compiler.getResourceSet());
if (modelType == null) {
continue;
}
module.getEClassifiers().add(modelType);
module.getUsedModelType().add(modelType);
if (modelType.getName().length() > 0) {
ModelType existingModelType = env.getModelType(Collections.singletonList(modelType.getName()));
if(existingModelType == null) {
env.registerModelType(modelType);
} else {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_modeltypeAlreadyDefined,
new Object[] { modelType.getName() }),
modelTypeCS.getIdentifierCS());
}
}
else {
env.registerModelType(modelType);
env.reportWarning(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_modeltypeDeprecatedSyntax, new Object[] { }),
modelTypeCS);
}
}
visitTransformationHeaderCS(moduleCS.getHeaderCS(), env, module, parsedModuleCS.getSource());
env.setContextModule(module);
visitIntermediateClassesCS(env, moduleCS, module);
importsCS(parsedModuleCS, module, env, compiler);
for (RenameCS renameCS : moduleCS.getRenamings()) {
Rename rename = visitRenameCS(renameCS, env);
if (rename != null) {
module.getOwnedRenaming().add(rename);
}
}
createModuleProperties(module, moduleCS, env);
HashMap<MappingMethodCS, ImperativeOperation> methodMap = new LinkedHashMap<MappingMethodCS, ImperativeOperation>(moduleCS.getMethods().size());
// declare module operations as they are required to analyze rules' contents
for (MappingMethodCS methodCS : moduleCS.getMethods()) {
String name = ""; //$NON-NLS-1$
if(methodCS.getMappingDeclarationCS() != null) {
SimpleNameCS methodNameCS = methodCS.getMappingDeclarationCS().getSimpleNameCS();
if(methodNameCS != null) {
name = methodNameCS.getValue(); //$NON-NLS-1$
}
}
boolean isMapping = methodCS instanceof MappingRuleCS;
ImperativeOperation operation = isMapping ? ExpressionsFactory.eINSTANCE.createMappingOperation() :
(QvtOperationalEnv.MAIN.equals(name) ? ExpressionsFactory.eINSTANCE.createEntryOperation() : ExpressionsFactory.eINSTANCE.createHelper());
if (visitMappingDeclarationCS(methodCS, env, operation)) {
EOperation imperativeOp = env.defineImperativeOperation(operation, methodCS instanceof MappingRuleCS, true);
if(imperativeOp != null) {
methodMap.put(methodCS, (ImperativeOperation)imperativeOp);
}
}
}
// Handle the case of legacy constructs which allows for signature-less
// transformation definition
DeprecatedSignaturelessTransf.patchModule(module);
boolean moduleEntryFound = false;
for (MappingMethodCS methodCS : methodMap.keySet()) {
ImperativeOperation imperativeOp = methodMap.get(methodCS);
if(imperativeOp == null) {
continue;
}
visitMappingMethodCS(methodCS, env, imperativeOp);
if(myCompilerOptions.isGenerateCompletionData()) {
//ASTBindingHelper.createCST2ASTBinding(methodCS, imperativeOp, env);
}
if ((!QvtOperationalEnv.MAIN.equals(imperativeOp.getName()) ||
getModelParameter(env.getModuleContextType()).isEmpty()) == false) {
checkMainMappingConformance(env, imperativeOp);
}
if (false == moduleCS instanceof LibraryCS
&& QvtOperationalEnv.MAIN.equals(imperativeOp.getName())) {
if (moduleEntryFound) {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_entryPointShouldBeDeclOnce,
QvtOperationalEnv.MAIN), methodCS);
}
moduleEntryFound = true;
}
}
for (ModuleImport moduleImport : module.getModuleImport()) {
for (EOperation operation : QvtOperationalParserUtil.getOwnedOperations(moduleImport.getImportedModule())) {
if(operation instanceof MappingOperation) {
MappingOperation mappingOperation = (MappingOperation) operation;
env.registerMappingOperation(mappingOperation);
}
}
}
env.resolveResolveInExpInMappings();
ImperativeOperation mainMethod = QvtOperationalParserUtil.getMainOperation(module);
if(mainMethod instanceof EntryOperation) {
module.setEntry((EntryOperation)mainMethod);
}
validate(env);
return module;
}
private void visitIntermediateClassesCS(QvtOperationalEnv env, MappingModuleCS moduleCS, Module module) throws SemanticException {
Map<String, EClass> createdIntermClasses = new LinkedHashMap<String, EClass>(moduleCS.getClassifierDefCS().size());
final Map<EClass, CSTNode> cstIntermClassesMap = new LinkedHashMap<EClass, CSTNode>();
for (ClassifierDefCS classifierDefCS : moduleCS.getClassifierDefCS()) {
if (createdIntermClasses.containsKey(classifierDefCS.getSimpleNameCS().getValue())) {
env.reportError(NLS.bind(ValidationMessages.DuplicateClassifier,
new Object[] { classifierDefCS.getSimpleNameCS().getValue() }), classifierDefCS.getSimpleNameCS());
continue;
}
org.eclipse.m2m.internal.qvt.oml.expressions.Class eClassifier = IntermediateClassFactory.getFactory(module).createIntermediateClassifier();
eClassifier.setStartPosition(classifierDefCS.getStartOffset());
eClassifier.setEndPosition(classifierDefCS.getEndOffset());
eClassifier.setName(classifierDefCS.getSimpleNameCS().getValue());
createdIntermClasses.put(eClassifier.getName(), eClassifier);
cstIntermClassesMap.put(eClassifier, classifierDefCS.getSimpleNameCS());
}
if (!createdIntermClasses.isEmpty()) {
IntermediateClassFactory.getFactory(module).registerModelType(env);
}
for (ClassifierDefCS classifierDefCS : moduleCS.getClassifierDefCS()) {
String className = classifierDefCS.getSimpleNameCS().getValue();
EClass rootClass = createdIntermClasses.get(className);
for (TypeCS typeCS : classifierDefCS.getExtends()) {
if (typeCS instanceof PathNameCS && ((PathNameCS) typeCS).getSequenceOfNames().size() == 1) {
EClass extClass = createdIntermClasses.get(((PathNameCS) typeCS).getSequenceOfNames().get(0));
if (extClass != null) {
rootClass.getESuperTypes().add(extClass);
continue;
}
}
EClassifier extendType = visitTypeCS(typeCS, null, env);
if (extendType == null) {
// error reported by visitTypeCS(..)
continue;
}
else if (!QVTUMLReflection.isUserModelElement(extendType)) {
env.reportError(NLS.bind(ValidationMessages.InvalidClassifierForExtend,
QvtOperationalTypesUtil.getTypeFullName(extendType)),
typeCS);
}
else {
rootClass.getESuperTypes().add((EClass) extendType);
}
}
}
Map<ClassifierPropertyCS, EStructuralFeature> createdProperties = new IdentityHashMap<ClassifierPropertyCS, EStructuralFeature>();
for (ClassifierDefCS classifierDefCS : moduleCS.getClassifierDefCS()) {
String className = classifierDefCS.getSimpleNameCS().getValue();
if (!createdIntermClasses.containsKey(className)) {
continue;
}
visitClassifierDefCS(classifierDefCS, createdIntermClasses.get(className), module, createdProperties, env);
}
for (ClassifierDefCS classifierDefCS : moduleCS.getClassifierDefCS()) {
String className = classifierDefCS.getSimpleNameCS().getValue();
if (!createdIntermClasses.containsKey(className)) {
continue;
}
initClassifierDefCS(createdIntermClasses.get(className), module, createdProperties, env);
}
class CycleChecker {
boolean checkClass(EClass cls) {
myVisitedClasses.clear();
return checkClassImpl(cls);
}
private boolean checkClassImpl(EClass cls) {
myVisitedClasses.add(cls);
for (EClass superCls : cls.getESuperTypes()) {
// check only intermediate hierarchy
if (!cstIntermClassesMap.containsKey(superCls)) {
continue;
}
if (myVisitedClasses.contains(superCls)) {
return false;
}
if (!checkClassImpl(superCls)) {
return false;
}
}
return true;
}
final Set<EClass> myVisitedClasses = new HashSet<EClass>(2);
}
CycleChecker cycleChecker = new CycleChecker();
for (EClass nextClass : cstIntermClassesMap.keySet()) {
if (!cycleChecker.checkClass(nextClass)) {
env.reportError(NLS.bind(ValidationMessages.CycleInIntermHierarchy,
QvtOperationalTypesUtil.getTypeFullName(nextClass)),
cstIntermClassesMap.get(nextClass));
}
//nextClass.getESuperTypes().add(EcorePackage.Literals.ECLASS);
Map<String, EStructuralFeature> ownFeatures = new HashMap<String, EStructuralFeature>(nextClass.getEStructuralFeatures().size());
for (EStructuralFeature nextFeature : nextClass.getEStructuralFeatures()) {
ownFeatures.put(nextFeature.getName(), nextFeature);
}
for (EStructuralFeature nextFeature : nextClass.getEAllStructuralFeatures()) {
EStructuralFeature ownFeature = ownFeatures.get(nextFeature.getName());
if (ownFeature != null && ownFeature != nextFeature) {
env.reportError(NLS.bind(ValidationMessages.HidingProperty,
nextFeature.getName()),
cstIntermClassesMap.get(nextClass));
}
}
// org.eclipse.emf.common.util.Diagnostic validate = new org.eclipse.emf.ecore.util.Diagnostician().validate(nextClass);
// if (validate.getSeverity() != org.eclipse.emf.common.util.Diagnostic.OK) {
// System.err.println(validate.getMessage());
// }
}
}
private EClass visitClassifierDefCS(ClassifierDefCS classifierDefCS, EClass eClassifier, Module module,
Map<ClassifierPropertyCS, EStructuralFeature> createdProperties, QvtOperationalEnv env) throws SemanticException {
class PropertyPair {
final EStructuralFeature myEFeature;
final ClassifierPropertyCS myPropCS;
PropertyPair(EStructuralFeature eFeature, ClassifierPropertyCS propCS) {
myEFeature = eFeature;
myPropCS = propCS;
}
}
Map<String, List<PropertyPair>> classifierProperties = new LinkedHashMap<String, List<PropertyPair>>(classifierDefCS.getProperties().size());
// first pass for creation
for (ClassifierPropertyCS propCS : classifierDefCS.getProperties()) {
EStructuralFeature eFeature = visitClassifierPropertyCS(propCS, env);
if (eFeature == null) {
continue;
}
eClassifier.getEStructuralFeatures().add(eFeature);
List<PropertyPair> properties = classifierProperties.get(eFeature.getName());
if (properties == null) {
properties = new ArrayList<PropertyPair>(2);
classifierProperties.put(eFeature.getName(), properties);
}
properties.add(new PropertyPair(eFeature, propCS));
createdProperties.put(propCS, eFeature);
}
for (String propName : classifierProperties.keySet()) {
List<PropertyPair> properties = classifierProperties.get(propName);
if (properties.size() == 1) {
continue;
}
for (PropertyPair propPair : properties) {
HiddenElementAdapter.markAsHidden(propPair.myEFeature);
env.reportError(NLS.bind(ValidationMessages.DuplicateProperty,
new Object[] { eClassifier.getName() + '.' + propPair.myEFeature.getName() }), propPair.myPropCS.getSimpleNameCS());
}
}
return eClassifier;
}
private void initClassifierDefCS(EClass eClassifier, Module module,
Map<ClassifierPropertyCS, EStructuralFeature> createdProperties, QvtOperationalEnv env) throws SemanticException {
// second pass for initialization parts and opposite properties
for (ClassifierPropertyCS propCS : createdProperties.keySet()) {
EStructuralFeature eFeature = createdProperties.get(propCS);
if (eClassifier != eFeature.eContainer()) {
continue;
}
initClassifierPropertyCS(propCS, eFeature, env);
OCLExpression<EClassifier> initExp = QvtOperationalParserUtil.getInitExpression(eFeature);
if (initExp != null) {
IntermediateClassFactory.getFactory(module).addClassifierPropertyInit(eClassifier, eFeature, initExp);
}
}
}
private void initClassifierPropertyCS(ClassifierPropertyCS propCS, EStructuralFeature eFeature, QvtOperationalEnv env) {
// handle initialization expression
OCLExpression<EClassifier> initExpression = null;
if (propCS.getOclExpressionCS() != null) {
initExpression = visitOclExpressionCS(propCS.getOclExpressionCS(), env);
QvtOperationalParserUtil.setInitExpression(eFeature, initExpression);
}
if (eFeature.getEType() == null && initExpression != null) {
eFeature.setEType(initExpression.getType());
}
if (initExpression != null) {
EClassifier realType = initExpression.getType();
EClassifier declaredType = env.getUMLReflection().getOCLType(eFeature);
if (!QvtOperationalParserUtil.isAssignableToFrom(env, declaredType, realType)) {
env.reportError(NLS.bind(ValidationMessages.SemanticUtil_17,
new Object[] { QvtOperationalTypesUtil.getTypeFullName(declaredType), QvtOperationalTypesUtil.getTypeFullName(realType) }),
propCS.getStartOffset(), propCS.getEndOffset());
}
}
// handle opposite property
OppositePropertyCS oppositeCS = propCS.getOpposite();
if (oppositeCS != null) {
if (eFeature instanceof EReference) {
if (oppositeCS.getMultiplicity() != null) {
MultiplicityDef multiplcityDef = visitMultiplicityDefCS(oppositeCS.getMultiplicity(), env);
}
if (oppositeCS.getSimpleNameCS() != null) {
String oppositeName = oppositeCS.getSimpleNameCS().getValue();
EReference oppositeRef = null;
EClassifier eFeatureType = eFeature.getEType();
if (eFeatureType instanceof EClass) {
for (EReference nextRef : ((EClass) eFeatureType).getEAllReferences()) {
if (oppositeName.equals(nextRef.getName())) {
oppositeRef = nextRef;
break;
}
}
if (oppositeRef != null) {
((EReference) eFeature).setEOpposite(oppositeRef);
}
else {
env.reportError(NLS.bind(ValidationMessages.IntermClassifier_invalideOppositeName,
new Object[] { oppositeName, QvtOperationalTypesUtil.getTypeFullName(eFeatureType) }),
oppositeCS.getSimpleNameCS());
}
}
else {
env.reportError(NLS.bind(ValidationMessages.IntermClassifier_invalideOppositeType,
new Object[] { QvtOperationalTypesUtil.getTypeFullName(eFeatureType) }), oppositeCS);
}
}
}
else {
env.reportError(NLS.bind(ValidationMessages.IntermClassifier_oppositeOnlyForReferences,
new Object[] { }), oppositeCS);
}
}
}
private EStructuralFeature visitClassifierPropertyCS(ClassifierPropertyCS propCS, QvtOperationalEnv env) {
EClassifier propertyEType = null;
if (propCS.getTypeCS() != null) {
propertyEType = visitTypeCS(propCS.getTypeCS(), null, env);
}
EStructuralFeature eFeature = createESFeature(propertyEType);
eFeature.setName(propCS.getSimpleNameCS().getValue());
eFeature.setEType(propertyEType);
ASTSyntheticNode astNode = ASTSyntheticNodeAccess.createASTNode(eFeature);
astNode.setStartPosition(propCS.getStartOffset());
astNode.setEndPosition(propCS.getEndOffset());
// handle stereotype qualifiers
Set<String> handledStereotypes = new HashSet<String>(2);
for (SimpleNameCS nameCS : propCS.getStereotypeQualifiers()) {
String qualifName = nameCS.getValue();
if ("id".equals(qualifName)) { //$NON-NLS-1$
if (eFeature instanceof EAttribute) {
((EAttribute) eFeature).setID(true);
}
else {
env.reportError(NLS.bind(ValidationMessages.IntermClassifier_unapplicableStereotypeQualifier,
new Object[] { qualifName }), nameCS);
}
}
else {
env.reportWarning(NLS.bind(ValidationMessages.IntermClassifier_unknownStereotypeQualifier,
new Object[] { qualifName }), nameCS);
}
if (handledStereotypes.contains(qualifName)) {
env.reportWarning(NLS.bind(ValidationMessages.IntermClassifier_duplicatedStereotypeQualifier,
new Object[] { qualifName }), nameCS);
}
handledStereotypes.add(qualifName);
}
// handle feature keys
Set<String> handledFeatureKeys = new HashSet<String>(2);
for (SimpleNameCS nameCS : propCS.getFeatureKeys()) {
String keyName = nameCS.getValue();
if ("composes".equals(keyName)) { //$NON-NLS-1$
if (eFeature instanceof EReference) {
((EReference) eFeature).setContainment(true);
}
else {
env.reportError(NLS.bind(ValidationMessages.IntermClassifier_referenceOnlyFeatureKey,
new Object[] { keyName }), nameCS);
}
}
else if ("references".equals(keyName)) { //$NON-NLS-1$
if (eFeature instanceof EReference) {
((EReference) eFeature).setContainment(false);
}
else {
env.reportError(NLS.bind(ValidationMessages.IntermClassifier_referenceOnlyFeatureKey,
new Object[] { keyName }), nameCS);
}
}
else if ("readonly".equals(keyName)) { //$NON-NLS-1$
eFeature.setChangeable(false);
}
else if ("derived".equals(keyName)) { //$NON-NLS-1$
env.reportWarning(NLS.bind(ValidationMessages.IntermClassifier_unsupportedFeatureKey,
new Object[] { keyName }), nameCS);
}
else if ("static".equals(keyName)) { //$NON-NLS-1$
env.reportWarning(NLS.bind(ValidationMessages.IntermClassifier_unsupportedFeatureKey,
new Object[] { keyName }), nameCS);
}
if (handledFeatureKeys.contains(keyName)) {
env.reportWarning(NLS.bind(ValidationMessages.IntermClassifier_duplicatedFeatureKey,
new Object[] { keyName }), nameCS);
}
handledFeatureKeys.add(keyName);
}
if (propCS.getMultiplicity() != null) {
MultiplicityDef multiplcityDef = visitMultiplicityDefCS(propCS.getMultiplicity(), env);
eFeature.setLowerBound(multiplcityDef.lower);
eFeature.setUpperBound(multiplcityDef.upper);
}
eFeature.setOrdered(propCS.isIsOrdered());
return eFeature;
}
private static class MultiplicityDef {
public int lower = 0;
public int upper = 1;
}
private MultiplicityDef visitMultiplicityDefCS(MultiplicityDefCS multiplicityCS, QvtOperationalEnv env) {
MultiplicityDef multiplicityDef = new MultiplicityDef();
try {
multiplicityDef.lower = Integer.valueOf(multiplicityCS.getLowerBound().getSymbol());
if ("*".equals(multiplicityCS.getUpperBound().getSymbol())) {
multiplicityDef.upper = -1;
}
else {
multiplicityDef.upper = Integer.valueOf(multiplicityCS.getUpperBound().getSymbol());
}
// check UML constraints [7.3.32]
if (multiplicityDef.lower < 0) {
throw new NumberFormatException(ValidationMessages.IntermClassifier_multiplicityInvalidLowerBound);
}
if (multiplicityDef.upper >= 0 && multiplicityDef.lower > multiplicityDef.upper) {
throw new NumberFormatException(ValidationMessages.IntermClassifier_multiplicityInvalidRange);
}
if (multiplicityDef.upper == 0 && multiplicityDef.lower == 0) {
throw new NumberFormatException(ValidationMessages.IntermClassifier_multiplicityEmptyRange);
}
}
catch (NumberFormatException ex) {
env.reportError(ex.getLocalizedMessage(), multiplicityCS);
// default multiplicity from specification [8.4.6]
multiplicityDef = new MultiplicityDef();
}
return multiplicityDef;
}
private void importsCS(ParsedModuleCS parsedModuleCS, Module module, QvtOperationalFileEnv env, QvtCompiler compiler) {
List<ImportCS> importsToProcessCopy = new ArrayList<ImportCS>(parsedModuleCS.getModuleCS().getImports());
for (ParsedModuleCS importedModuleCS : parsedModuleCS.getParsedImports()) {
// Check for duplicate imports is handled by QvtCompiler
Module importedModule = compiler.analyse(importedModuleCS, myCompilerOptions).getModule().getModule();
if (importedModule == null) {
continue;
}
ModuleImport moduleImport = ExpressionsFactory.eINSTANCE.createModuleImport();
moduleImport.setImportedModule(importedModule);
module.getModuleImport().add(moduleImport);
ImportCS cstImport = null;
for (ImportCS nextImport : parsedModuleCS.getModuleCS().getImports()) {
if(nextImport.getPathNameCS() != null && parsedModuleCS.getParsedImport(nextImport.getPathNameCS()) == importedModuleCS) {
cstImport = nextImport;
if(myCompilerOptions.isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(nextImport, moduleImport);
}
}
}
if (cstImport != null) {
importsToProcessCopy.remove(cstImport);
moduleImport.setStartPosition(cstImport.getStartOffset());
moduleImport.setEndPosition(cstImport.getEndOffset());
}
if(module instanceof OperationalTransformation && importedModule instanceof OperationalTransformation) {
validateImportedSignature(env, (OperationalTransformation) module, (OperationalTransformation) importedModule, moduleImport);
}
}
// - handle the unparsed modules - either not found or black-box
// - ignore those not found, as this is handled by the compiler and report only
// black-box loading failures.
BlackboxModuleHelper blackboxUnitHelper = compiler.getBlackboxUnitHelper();
blackboxUnitHelper.setContext(
new ResolutionContextImpl(env.getFile()),
new LoadContext(env.getEPackageRegistry()));
for (ImportCS importCS : importsToProcessCopy) {
if(importCS instanceof LibraryImportCS) {
continue;
}
PathNameCS pathNameCS = importCS.getPathNameCS();
if(pathNameCS != null) {
List<Module> bboxModules = blackboxUnitHelper.getModules(pathNameCS.getSequenceOfNames());
if(bboxModules != null) {
for (Module nextBboxModule : bboxModules) {
QvtOperationalModuleEnv bboxModuleEnv = blackboxUnitHelper.getModuleEnvironment(nextBboxModule);
assert bboxModuleEnv != null;
if(!env.getSiblings().contains(bboxModuleEnv)) {
env.addSibling(bboxModuleEnv);
}
// FIXME - module import bellow should not represent the CST import statement
// but rather module_access_decl (access, extends), which is not yet supported
ModuleImport moduleImport = ExpressionsFactory.eINSTANCE.createModuleImport();
moduleImport.setImportedModule(nextBboxModule);
module.getModuleImport().add(moduleImport);
module.setStartPosition(pathNameCS.getStartOffset());
module.setEndPosition(pathNameCS.getEndOffset());
}
} else if(blackboxUnitHelper.loadFailed(pathNameCS.getSequenceOfNames())) {
env.reportError(wrappInSeeErrorLogMessage(NLS.bind(ValidationMessages.FailedToLoadLibrary,
new Object[] { QvtOperationalParserUtil.getStringRepresentation(pathNameCS, ".") })), pathNameCS); //$NON-NLS-1$
}
}
}
if(parsedModuleCS.getModuleCS() != null) {
DeprecatedLibraryImportSupport deprecatedLibraryImportSupport = new DeprecatedLibraryImportSupport(
env, parsedModuleCS.getModuleCS(), compiler.getBlackboxUnitHelper());
module.getModuleImport().addAll(deprecatedLibraryImportSupport.analyzeLibraryImports());
}
}
private void createModuleProperties(Module module, MappingModuleCS moduleCS, QvtOperationalFileEnv env) throws SemanticException {
for (ModulePropertyCS propCS : moduleCS.getProperties()) {
EStructuralFeature prop = visitModulePropertyCS(propCS, env);
if (prop == null) {
continue;
}
EStructuralFeature eFeature = null;
if (propCS instanceof ContextualPropertyCS) {
EClass ctxType = ((ContextualProperty) prop).getContext();
if (ctxType != null && env.lookupProperty(ctxType, prop.getName()) != null) {
// need to check now for duplicates, as MDT OCL lookup now returns the most specific
// redefinition [244886], so further checking lookup might not reach the original valid feature
// being redefined (thus no collision would be detectable)
HiddenElementAdapter.markAsHidden(prop);
}
if (module instanceof OperationalTransformation) {
((OperationalTransformation) module).getIntermediateProperty().add(prop);
}
eFeature = prop;
// using AST-CST map as this mapping is not optional but always required
env.getASTNodeToCSTNodeMap().put(prop, propCS);
} else {
//eFeature = env.getUMLReflection().createProperty(prop.getName(), prop.getEType());
eFeature = prop;
//QvtOperationalParserUtil.addLocalPropertyAST(eFeature, prop);
if (env.lookupProperty(module, prop.getName()) != null) {
HiddenElementAdapter.markAsHidden(eFeature);
env.reportError(NLS.bind(ValidationMessages.ModulePropertyAlreadyDefined, new Object[] { prop.getName() }), propCS.getSimpleNameCS());
}
if (propCS instanceof ConfigPropertyCS) {
module.getConfigProperty().add(eFeature);
}
}
module.getEStructuralFeatures().add(eFeature);
}
if (module instanceof OperationalTransformation) {
IntermediatePropertyHierarchy intermPropDefHierarchy = ((OperationalTransformation) module).getIntermediateProperty().isEmpty() ? null : new IntermediatePropertyHierarchy(module, env);
for (EStructuralFeature prop : ((OperationalTransformation) module).getIntermediateProperty()) {
if (prop instanceof ContextualProperty) {
ContextualProperty ctxProperty = (ContextualProperty) prop;
EClass ctxType = ctxProperty.getContext();
EStructuralFeature lookupProperty = ctxType != null ? env.lookupProperty(ctxType, prop.getName()) : null;
boolean isAlreadyDefined = (lookupProperty != null && lookupProperty != ctxProperty) |
HiddenElementAdapter.isMarkedAsHidden(ctxProperty);
if(isAlreadyDefined || intermPropDefHierarchy.hasHierarchyClashes(ctxProperty)) {
HiddenElementAdapter.markAsHidden(ctxProperty);
String message = NLS.bind(ValidationMessages.IntermediatePropertyAlreadyDefined, prop.getName());
int startPos = ctxProperty.getStartPosition();
int endPos = ctxProperty.getEndPosition();
CSTNode cstNode = QvtOperationalParserUtil.getPropertyProblemNode(prop, env);
if(cstNode != null) {
startPos = cstNode.getStartOffset();
endPos = cstNode.getEndOffset();
}
env.reportError(message, startPos, endPos);
}
}
}
}
}
/** FIXME */
private static String getExpectedPackageName(QvtCompilerKernel kernel, CFile sourceFile) {
CFolder parent = sourceFile.getParent();
if(parent == null) {
// the default namespace
return ""; //$NON-NLS-1$
}
return kernel.getExpectedPackageName(parent);
}
protected void visitTransformationHeaderCS(TransformationHeaderCS headerCS,
QvtOperationalFileEnv env, Module module, CFile sourceFile) {
if (!headerCS.getQualifiers().isEmpty()) {
env.reportWarning(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_transfQualifiersNotSupported,
new Object[] { }),
headerCS.getQualifiers().get(0).getStartOffset(),
headerCS.getQualifiers().get(headerCS.getQualifiers().size()-1).getEndOffset());
}
if(!QvtOperationalParserUtil.hasSimpleName(headerCS)) {
env.reportError(NLS.bind(ValidationMessages.moduleNameMustBeSimpleIdentifierError, new Object[] {
QvtOperationalParserUtil.getMappingModuleQualifiedName(headerCS) }), headerCS.getPathNameCS());
}
String unitSimpleName = QvtOperationalParserUtil.getMappingModuleSimpleName(headerCS);
String unitNamespace = getExpectedPackageName(env.getKernel(), sourceFile);
module.setName(unitSimpleName);
module.setNsPrefix(unitNamespace);
if (module instanceof OperationalTransformation) {
visitOperationalTransformationSignature(headerCS, env, (OperationalTransformation) module);
} else if (module instanceof Library) {
visitLibrarySignature(headerCS, env, (Library) module);
} else {
throw new RuntimeException("Unknown module type: " + module); //$NON-NLS-1$
}
if (headerCS.getTransformationRefineCS() != null) {
env.reportWarning(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_transfRefineNotSupported,
new Object[] { }), headerCS.getTransformationRefineCS());
}
if (!headerCS.getModuleUsages().isEmpty()) {
env.reportWarning(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_transfUsagesNotSupported,
new Object[] { }),
headerCS.getModuleUsages().get(0).getStartOffset(),
headerCS.getModuleUsages().get(headerCS.getModuleUsages().size()-1).getEndOffset());
}
}
protected void visitOperationalTransformationSignature(TransformationHeaderCS headerCS,
QvtOperationalFileEnv env, OperationalTransformation module) {
Set<String> paramNames = new LinkedHashSet<String>();
for (ParameterDeclarationCS paramCS : headerCS.getParameters()) {
EClassifier type = null;
TypeCS paramTypeCS = (paramCS.getTypeSpecCS() != null) ? paramCS.getTypeSpecCS().getTypeCS() : null;
boolean isSimpleName = false;
if (paramTypeCS instanceof PathNameCS) {
PathNameCS typePathNameCS = (PathNameCS) paramTypeCS;
isSimpleName = typePathNameCS.getSequenceOfNames().size() == 1;
type = env.getModelType(typePathNameCS.getSequenceOfNames());
}
if (type == null || !isSimpleName) {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_transfParamWrongType,
new Object[] { }), paramTypeCS);
}
ModelParameter varParam = ExpressionsFactory.eINSTANCE.createModelParameter();
varParam.setRepresentedParameter(varParam);
varParam.setStartPosition(paramCS.getStartOffset());
varParam.setEndPosition(paramCS.getEndOffset());
if(paramCS.getSimpleNameCS() != null) {
varParam.setName(paramCS.getSimpleNameCS().getValue());
} else {
varParam.setName(""); //$NON-NLS-1$
}
varParam.setEType(type);
DirectionKindEnum directionKind = paramCS.getDirectionKind();
if (directionKind == DirectionKindEnum.DEFAULT) {
directionKind = DirectionKindEnum.IN;
}
varParam.setKind((DirectionKind) ExpressionsFactory.eINSTANCE.createFromString(
ExpressionsPackage.eINSTANCE.getDirectionKind(), directionKind.getLiteral()));
if (paramNames.contains(varParam.getName())) {
env.reportError(NLS.bind(ValidationMessages.SameParamName, new Object[] { varParam.getName() }),
(paramCS.getSimpleNameCS() == null || paramCS.getSimpleNameCS().getValue().length() == 0) ? paramCS : paramCS.getSimpleNameCS());
}
paramNames.add(varParam.getName());
module.getModelParameter().add(varParam);
if(myCompilerOptions.isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(paramCS, varParam);
}
}
}
private void visitLibrarySignature(TransformationHeaderCS headerCS,
QvtOperationalFileEnv env, Library module) {
Set<ModelType> usedModelTypes = new HashSet<ModelType>();
for (ParameterDeclarationCS paramCS : headerCS.getParameters()) {
TypeCS paramTypeCS = (paramCS.getTypeSpecCS() != null) ? paramCS.getTypeSpecCS().getTypeCS() : null;
if ((paramCS.getTypeSpecCS() != null) && (paramCS.getTypeSpecCS().getSimpleNameCS() != null)) {
env.reportError(ValidationMessages.QvtOperationalVisitorCS_LibrarySignatureErrorModelExtentSpecified, paramCS.getTypeSpecCS().getSimpleNameCS());
}
if ((paramCS.getDirectionKind() != null) && (paramCS.getDirectionKind() != DirectionKindEnum.DEFAULT)) {
env.reportError(ValidationMessages.QvtOperationalVisitorCS_LibrarySignatureErrorDirectionKindSpecified, paramCS);
}
if (paramCS.getSimpleNameCS() != null) {
env.reportError(ValidationMessages.QvtOperationalVisitorCS_LibrarySignatureErrorParameterNameSpecified, paramCS);
}
ModelType modelType = null;
if (paramTypeCS instanceof PathNameCS) {
PathNameCS typePathNameCS = (PathNameCS) paramTypeCS;
if (typePathNameCS.getSequenceOfNames().size() == 1) {
modelType = env.getModelType(typePathNameCS.getSequenceOfNames());
if (!usedModelTypes.add(modelType)) {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_LibrarySignatureErrorDuplicateModelType,
new Object[] { typePathNameCS.getSequenceOfNames().get(0) }), paramCS);
}
}
}
if (modelType == null) {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_transfParamWrongType,
new Object[] { }), paramCS);
} else if (!module.getUsedModelType().contains(modelType)) {
module.getUsedModelType().add(modelType); // Normally, all used model types are
// already present in the Library AST node
}
}
}
protected ModelType visitModelTypeCS(ModelTypeCS modelTypeCS, QvtOperationalFileEnv env,
Module module, ResourceSet resolutionRS) throws SemanticException {
if (modelTypeCS == null) {
return null;
}
SimpleNameCS identifierCS = modelTypeCS.getIdentifierCS();
ModelType modelType = QvtOperationalStdLibrary.INSTANCE.createModel(identifierCS != null ? identifierCS.getValue() : null);
module.getEClassifiers().add(modelType);
if(myCompilerOptions.isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(modelTypeCS, modelType);
}
modelType.setStartPosition(modelTypeCS.getStartOffset());
modelType.setEndPosition(modelTypeCS.getEndOffset());
if (modelTypeCS.getComplianceKindCS() != null) {
String complianceKind = visitLiteralExpCS(modelTypeCS.getComplianceKindCS(), env);
if (complianceKind.length() > 0 && !QvtOperationalEnv.METAMODEL_COMPLIANCE_KIND_STRICT.equals(complianceKind)) {
env.reportWarning(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_unsupportedMetamodelComplianceKind,
new Object[] { complianceKind }), modelTypeCS.getComplianceKindCS());
}
modelType.setConformanceKind(complianceKind);
}
for (int i = 0, n = modelTypeCS.getPackageRefs().size(); i < n; ++i) {
PackageRefCS packageRefCS = modelTypeCS.getPackageRefs().get(i);
EPackage resolvedMetamodel = null;
if (packageRefCS.getUriCS() != null) {
String metamodelUri = visitLiteralExpCS(packageRefCS.getUriCS(), env);
resolvedMetamodel = resolveMetamodel(env, metamodelUri, Collections.<String>emptyList(), packageRefCS.getUriCS(), resolutionRS);
}
PathNameCS pathNameCS = packageRefCS.getPathNameCS();
if (pathNameCS != null && !pathNameCS.getSequenceOfNames().isEmpty()) {
String metamodelName = QvtOperationalParserUtil.getStringRepresentation(
pathNameCS, QvtOperationalTypesUtil.TYPE_NAME_SEPARATOR);
if (resolvedMetamodel == null) {
resolvedMetamodel = resolveMetamodel(env, null, pathNameCS.getSequenceOfNames(), pathNameCS, resolutionRS);
}
else {
resolvedMetamodel = checkMetamodelPath(env, resolvedMetamodel, pathNameCS, metamodelName);
}
}
if (resolvedMetamodel != null) {
validateMetamodel(env, resolvedMetamodel, modelType, module, packageRefCS);
modelType.getMetamodel().add(resolvedMetamodel);
for (++i; i < n; ++i) {
packageRefCS = modelTypeCS.getPackageRefs().get(i);
env.reportWarning(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_metamodelSinglePackageRefSupported,
new Object[] { }), packageRefCS);
}
break;
}
}
if (!modelTypeCS.getWhereStatements().isEmpty()) {
int startOffset = modelTypeCS.getWhereStatements().get(0).getStartOffset();
int endOffset = modelTypeCS.getWhereStatements().get(modelTypeCS.getWhereStatements().size()-1).getEndOffset();
env.reportWarning(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_metamodelConditionsNotSupported,
new Object[] { }), startOffset, endOffset);
}
if (modelType.getMetamodel().isEmpty()) {
return null;
}
return modelType;
}
private EPackage checkMetamodelPath(QvtOperationalFileEnv env, EPackage resolvedMetamodel,
PathNameCS pathNameCS, String metamodelName) {
EList<String> path = pathNameCS.getSequenceOfNames();
// lookup nested package started from package specified by URI
EPackage localPackage = EmfMmUtil.lookupPackage(resolvedMetamodel, path);
if (localPackage != null) {
return localPackage;
}
// lookup nested package started from root package of package specified by URI
EPackage rootMetamodel = resolvedMetamodel;
while (true) {
if (rootMetamodel.getESuperPackage() == null) {
break;
}
rootMetamodel = rootMetamodel.getESuperPackage();
}
if (rootMetamodel != resolvedMetamodel) {
localPackage = EmfMmUtil.lookupPackage(rootMetamodel, path);
boolean isContainedBy = false;
EPackage curPkg = localPackage;
while (curPkg != null) {
if (curPkg == resolvedMetamodel) {
isContainedBy = true;
break;
}
curPkg = curPkg.getESuperPackage();
}
if (localPackage != null && isContainedBy) {
return localPackage;
}
}
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_metamodelPackageRefInconsistent,
new Object[] { metamodelName }), pathNameCS);
return null;
}
private void validateMetamodel(QvtOperationalFileEnv env, EPackage resolvedMetamodel,
ModelType modelType, Module module, CSTNode cstNode) throws SemanticException {
String metamodelName = (resolvedMetamodel.getNsURI() == null ? resolvedMetamodel.getName() : resolvedMetamodel.getNsURI());
List<EPackage> metamodels = modelType.getMetamodel();
if (metamodels.contains(resolvedMetamodel)) {
env.reportWarning(NLS.bind(ValidationMessages.DuplicateMetamodelImport,
new Object[] { metamodelName }), cstNode);
}
if (module.getUsedModelType().contains(resolvedMetamodel)) {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_metamodelAlreadyUsed,
new Object[] { metamodelName }), cstNode);
}
}
private EPackage resolveMetamodel(QvtOperationalFileEnv env, String metamodelUri, List<String> packagePath,
CSTNode cstNode, ResourceSet resolutionRS) throws SemanticException {
EPackage resolvedMetamodel = null;
String metamodelName = (packagePath.isEmpty() ? metamodelUri : packagePath.toString());
try {
MetamodelRegistry metamodelRegistry = env.getKernel().getMetamodelRegistry(env.getFile());
List<EPackage> registerMetamodels = MetamodelResolutionHelper.registerMetamodel(
env, metamodelUri, packagePath, resolutionRS,
metamodelRegistry, myCompilerOptions);
if (registerMetamodels.isEmpty()) {
env.reportError(NLS.bind(ValidationMessages.failedToResolveMetamodelError,
new Object[] { metamodelName }), cstNode);
}
else {
resolvedMetamodel = registerMetamodels.get(0);
}
if (registerMetamodels.size() > 1) {
List<String> uriList = new ArrayList<String>(registerMetamodels.size());
for (EPackage pack : registerMetamodels) {
uriList.add(pack.getNsURI());
}
env.reportWarning(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_metamodelNameAmbiguous,
new Object[] { metamodelName, uriList }), cstNode);
}
} catch (RuntimeException e) {
env.reportError(NLS.bind(ValidationMessages.failedToResolveMetamodelError,
new Object[] { metamodelName }), cstNode);
}
return resolvedMetamodel;
}
protected Rename visitRenameCS(RenameCS renameCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) throws SemanticException {
EClassifier type = visitTypeCS(renameCS.getTypeCS(), null, env);
if (type == null) {
return null;
}
String originalName = visitLiteralExpCS(renameCS.getOriginalName(), env);
String newName = renameCS.getSimpleNameCS().getValue();
EStructuralFeature originalProperty = env.lookupProperty(type, originalName);
if (originalProperty == null) {
QvtOperationalUtil.reportError(env, NLS.bind(ValidationMessages.noPropertyInTypeError, originalName, QvtOperationalTypesUtil
.getTypeFullName(type)), renameCS);
return null;
}
EStructuralFeature newProperty = env.lookupProperty(type, newName);
if (newProperty != null) {
QvtOperationalUtil.reportError(env, NLS.bind(ValidationMessages.propertyAlreadyExistsInTypeError, newName,
QvtOperationalTypesUtil.getTypeFullName(type)), renameCS);
return null;
}
Variable<EClassifier, EParameter> var = EcoreFactory.eINSTANCE.createVariable();
var.setName(newName);
var.setType(originalProperty.getEType());
Constraint constraint = EcoreFactory.eINSTANCE.createConstraint();
constraint.setStereotype(QvtOperationalEnv.RENAMED_PROPERTY_STEREOTYPE);
constraint.getConstrainedElements().add(originalProperty);
EStructuralFeature feature = env.defineAttribute(type, var, constraint);
feature.setLowerBound(originalProperty.getLowerBound());
feature.setUpperBound(originalProperty.getUpperBound());
Rename rename = ExpressionsFactory.eINSTANCE.createRename();
rename.setStartPosition(renameCS.getStartOffset());
rename.setEndPosition(renameCS.getEndOffset());
rename.setName(originalName);
rename.setNewName(newName);
rename.setEType(type);
return rename;
}
private List<OCLExpression<EClassifier>> visitMappingSectionCS(MappingSectionCS mappingSectionCS,
QvtOperationalEnv env) throws SemanticException {
List<OCLExpression<EClassifier>> statements = new ArrayList<OCLExpression<EClassifier>>(mappingSectionCS
.getStatements().size());
for (OCLExpressionCS statementCS : mappingSectionCS.getStatements()) {
if (statementCS == null) {
continue;
}
OCLExpression<EClassifier> statement = visitOclExpressionCS(statementCS, env);
if (statement != null) {
statements.add(statement);
}
}
return statements;
}
protected void visitMappingMethodCS(MappingMethodCS methodCS, QvtOperationalEnv env, ImperativeOperation declaredOperation)
throws SemanticException {
if (methodCS instanceof MappingRuleCS) {
visitMappingRuleCS((MappingRuleCS) methodCS, env, (MappingOperation)declaredOperation);
}
else {
visitMappingQueryCS((MappingQueryCS) methodCS, env, declaredOperation);
}
// process operation qualifiers
EList<QualifierKindCS> qualifiersCS = (methodCS.getMappingDeclarationCS() == null) ? null
: methodCS.getMappingDeclarationCS().getQualifiers();
if(declaredOperation instanceof MappingOperation) {
if (qualifiersCS != null) {
for (QualifierKindCS nextQualifierCS : qualifiersCS) {
if(nextQualifierCS != QualifierKindCS.ABSTRACT) {
// only 'abstract' qualifier for mapping is currently supported
String errMessage = NLS.bind(ValidationMessages.QvtOperationalVisitorCS_unsupportedQualifierOnOperation,
nextQualifierCS.getName(), QvtOperationalParserUtil.getMappingStringRepresentation(methodCS));
env.reportError(errMessage, QvtOperationalParserUtil.getImperativeOperationProblemNode(methodCS));
} else {
QvtOperationalParserUtil.markAsAbstractMappingOperation((MappingOperation) declaredOperation);
}
}
}
}
Collection<QualifierKindCS> qualifierDups = QvtOperationalParserUtil.selectDuplicateQualifiers(qualifiersCS);
for(QualifierKindCS duplicate : qualifierDups) {
String errMessage = NLS.bind(ValidationMessages.QvtOperationalVisitorCS_duplicateQualifierOnOperation,
duplicate.getName(), QvtOperationalParserUtil.getMappingStringRepresentation(methodCS));
env.reportError(errMessage, QvtOperationalParserUtil.getImperativeOperationProblemNode(methodCS));
}
}
private ImperativeOperation visitMappingRuleCS(MappingRuleCS methodCS, QvtOperationalEnv env, final MappingOperation operation)
throws SemanticException {
env.registerMappingOperation(operation);
operation.setEndPosition(methodCS.getEndOffset());
if (QvtOperationalParserUtil.isContextual(operation) && operation.getContext().getKind() == DirectionKind.OUT) {
env.reportError(ValidationMessages.ContextParamMustBeInOrInout, methodCS.getMappingDeclarationCS()
.getDirectionKindCS());
}
QvtOperationalEnv newEnv = env.getFactory().createOperationContext(env, operation);
if(myCompilerOptions.isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(methodCS, operation, newEnv);
}
OCLExpression<EClassifier> guard;
if (methodCS.getGuard() != null) {
guard = visitOclExpressionCS(methodCS.getGuard(), newEnv);
if (guard != null) {
EClassifier guardType = guard.getType();
if (guardType != newEnv.getOCLStandardLibrary().getBoolean()) {
newEnv.reportError(NLS.bind(ValidationMessages.mappingGuardNotBooleanError,
new Object[] { QvtOperationalTypesUtil.getTypeFullName(guardType) }), methodCS.getGuard());
guard = null;
}
}
} else {
guard = null;
}
List<OCLExpression<EClassifier>> inits = Collections.emptyList();
if ((methodCS.getMappingBody() != null) && (methodCS.getMappingBody().getMappingInitCS() != null)) {
inits = visitMappingSectionCS(methodCS.getMappingBody().getMappingInitCS(), newEnv);
}
MappingBody body = null;
MappingBodyCS mappingBodyCS = (methodCS.getMappingBody() == null) ? null : methodCS.getMappingBody().getMappingBodyCS();
if (mappingBodyCS != null) {
body = visitMappingBodyCS(mappingBodyCS, newEnv, methodCS);
if (body != null) {
EClassifier returnType = operation.getEType();
EClassifier bodyType = (body.getContent().size() == 1
&& body.getContent().get(0) instanceof ObjectExp ? body.getContent().get(0).getType()
: null);
// TODO : Rewrite this when re-implementing ObjectExp
if (bodyType != null && !QvtOperationalParserUtil.isAssignableToFrom(env, bodyType, returnType)) {
/* checked by validation
newEnv.reportError(NLS.bind(ValidationMessages.bodyTypeNotCompatibleWithReturnTypeError,
new Object[] { QvtOperationalTypesUtil.getTypeFullName(bodyType), QvtOperationalTypesUtil.getTypeFullName(returnType) }),
methodCS.getMappingDeclarationCS());
*/
}
}
} else {
body = ExpressionsFactory.eINSTANCE.createMappingBody();
body.setStartPosition(mappingBodyCS == null ? methodCS.getStartOffset() : mappingBodyCS.getStartOffset());
body.setEndPosition(mappingBodyCS == null ? methodCS.getEndOffset() : mappingBodyCS.getEndOffset());
}
List<OCLExpression<EClassifier>> ends = Collections.emptyList();
if ((methodCS.getMappingBody() != null) && (methodCS.getMappingBody().getMappingEndCS() != null)) {
ends = visitMappingSectionCS(methodCS.getMappingBody().getMappingEndCS(), newEnv);
}
if (guard != null) {
operation.getWhen().add(guard);
}
operation.setBody(body);
if (body != null) {
body.getInitSection().addAll(inits);
body.getEndSection().addAll(ends);
}
checkAbstractOutParamsInitialized(operation.getResult(), methodCS, env);
processMappingExtensions(methodCS, operation, env);
// adjust implicit variables for serialization
consolidateImplicitVariables(newEnv);
//
return operation;
}
private static void consolidateImplicitVariables(QvtOperationalEnv newEnv) {
EOperation eOperation = newEnv.getContextOperation();
OperationBody body = null;
if(eOperation instanceof ImperativeOperation) {
body = ((ImperativeOperation)eOperation).getBody();
}
if(body == null) {
return;
}
for (Variable<EClassifier, EParameter> var : newEnv.getImplicitVariables()) {
if(var.eContainer() == null) {
body.getVariable().add((org.eclipse.ocl.ecore.Variable)var);
}
}
for (Variable<EClassifier, EParameter> var : newEnv.getVariables()) {
if(var.eContainer() == null) {
body.getVariable().add((org.eclipse.ocl.ecore.Variable)var);
}
}
}
private void visitMappingQueryCS(MappingQueryCS methodCS, QvtOperationalEnv env, ImperativeOperation helper)
throws SemanticException {
helper.setEndPosition(methodCS.getEndOffset());
if (QvtOperationalParserUtil.isContextual(helper) && helper.getContext().getKind() != DirectionKind.IN) {
env.reportError(ValidationMessages.ContextParamMustBeIn, methodCS.getMappingDeclarationCS()
.getSimpleNameCS());
}
QvtOperationalEnv newEnv = env.getFactory().createOperationContext(env, helper);
//newEnv.defineOperationParameters(helper);
if(myCompilerOptions.isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(methodCS, helper, newEnv);
}
OperationBody body = ExpressionsFactory.eINSTANCE.createOperationBody();
helper.setBody(body);
// FIXME - use CST info to set the flag
//helper.setIsQuery(true);
body.setStartPosition(methodCS.getMappingDeclarationCS().getEndOffset());
body.setEndPosition(methodCS.getEndOffset());
List<OCLExpression<EClassifier>> expressions = new ArrayList<OCLExpression<EClassifier>>();
for (OCLExpressionCS exprCS : methodCS.getExpressions()) {
if (exprCS == null) {
continue;
}
OCLExpression<EClassifier> expr = visitOclExpressionCS(exprCS, newEnv);
if (expr != null) {
expressions.add(expr);
}
}
body.getContent().addAll(expressions);
EClassifier returnType = (helper.getResult().isEmpty() ? helper.getEType() : helper.getResult().get(0).getEType());
EClassifier helperType = body.getContent().isEmpty() == false ? body.getContent().get(body.getContent().size() - 1).getType() : null;
if (QvtOperationalEnv.MAIN.equals(helper.getName())
&& (returnType == null || returnType == env.getOCLStandardLibrary().getOclVoid())) {
// OK
}
else if (helperType != null && !QvtOperationalParserUtil.isAssignableToFrom(env, returnType, helperType)) {
env.reportError(NLS.bind(ValidationMessages.bodyTypeNotCompatibleWithReturnTypeError, new Object[] {
QvtOperationalTypesUtil.getTypeFullName(helperType),
QvtOperationalTypesUtil.getTypeFullName(returnType)
}),
methodCS.getMappingDeclarationCS());
}
// adjust implicit variables for serialization
consolidateImplicitVariables(newEnv);
//
}
/**
* TODO - make a common resolution operation, reusable in for ResolveExp too.
*/
private List<EOperation> resolveMappingOperationReference(ScopedNameCS identifierCS, QvtOperationalEnv env) {
List<EOperation> result = Collections.emptyList();
TypeCS typeCS = identifierCS.getTypeCS();
EClassifier owningType = null;
if(typeCS != null) {
owningType = visitTypeCS(typeCS, null, env);
if(owningType != null && identifierCS.getName() != null) {
result = env.lookupMappingOperations(TypeUtil.resolveType(env, owningType), identifierCS.getName());
}
} else if(identifierCS.getName() != null) {
// TODO - review why lookup does not return MappingOperation type collection
owningType = env.getModuleContextType();
result = env.lookupMappingOperations(owningType, identifierCS.getName());
}
// filter out inherited mappings
if(!result.isEmpty()) {
List<EOperation> ownerLocalOpers = new ArrayList<EOperation>(result.size());
for (EOperation operation : result) {
EClassifier owner = env.getUMLReflection().getOwningClassifier(operation);
if ((typeCS == null && owner == null) || (TypeUtil.resolveType(env, owner) == owningType)) {
ownerLocalOpers.add(operation);
}
}
result = ownerLocalOpers;
}
// validate the result
if(result.isEmpty()) {
if(owningType != null) {
// unresolved type reported above by visiTypeCS(...)
String errMessage = NLS.bind(ValidationMessages.QvtOperationalVisitorCS_unresolvedMappingOperationReference,
QvtOperationalParserUtil.getStringRepresentation(identifierCS));
env.reportError(errMessage, identifierCS);
}
} else if(result.size() > 1) {
String errMessage = NLS.bind(ValidationMessages.QvtOperationalVisitorCS_ambiguousMappingOperationReference,
QvtOperationalParserUtil.getStringRepresentation(identifierCS));
env.reportError(errMessage, identifierCS);
}
return result;
}
private void processMappingExtensions(MappingRuleCS mappingCS, MappingOperation operation, QvtOperationalEnv env) {
if((mappingCS.getMappingDeclarationCS() != null) && !mappingCS.getMappingDeclarationCS().getMappingExtension().isEmpty()) {
for (MappingExtensionCS extensionCS : mappingCS.getMappingDeclarationCS().getMappingExtension()) {
MappingExtensionKindCS kind = extensionCS.getKind();
for (ScopedNameCS identifierCS : extensionCS.getMappingIdentifiers()) {
List<EOperation> mappings = resolveMappingOperationReference(identifierCS, env);
if(mappings.size() == 1) {
boolean isAdded = false;
MappingOperation extendedMapping = (MappingOperation)mappings.get(0);
if(kind == MappingExtensionKindCS.INHERITS) {
isAdded = operation.getInherited().add(extendedMapping);
MappingExtensionHelper.bind2SourceElement(operation, identifierCS, kind);
}
else if(kind == MappingExtensionKindCS.MERGES) {
isAdded = operation.getMerged().add(extendedMapping);
MappingExtensionHelper.bind2SourceElement(operation, identifierCS, kind);
}
else if(kind == MappingExtensionKindCS.DISJUNCTS) {
isAdded = operation.getDisjunct().add(extendedMapping);
MappingExtensionHelper.bind2SourceElement(operation, identifierCS, kind);
}
if(!isAdded) {
// Note: duplicates checked here as the mapping AST is {unique, ordered}
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_duplicateMappingRereferenceInExtensionKind,
kind.getName(), QvtOperationalParserUtil.getStringRepresentation(identifierCS)),
identifierCS);
}
if(getCompilerOptions().isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(identifierCS, extendedMapping, false, null);
}
}
}
}
}
}
protected boolean visitMappingDeclarationCS(MappingMethodCS mappingMethodCS, QvtOperationalModuleEnv env, ImperativeOperation operation) throws SemanticException {
MappingDeclarationCS mappingDeclarationCS = mappingMethodCS.getMappingDeclarationCS();
if (mappingDeclarationCS == null) {
return false;
}
operation.setIsBlackbox(mappingMethodCS.isBlackBox());
operation.setStartPosition(mappingDeclarationCS.getStartOffset());
operation.setEndPosition(mappingDeclarationCS.getEndOffset());
operation.setName(mappingDeclarationCS.getSimpleNameCS().getValue());
DirectionKind contextDirection = DirectionKind.IN;
if ((mappingDeclarationCS.getDirectionKindCS() != null) && (mappingDeclarationCS.getDirectionKindCS().getDirectionKind() != DirectionKindEnum.DEFAULT)) {
contextDirection = (DirectionKind) ExpressionsFactory.eINSTANCE.createFromString(
ExpressionsPackage.eINSTANCE.getDirectionKind(), mappingDeclarationCS.getDirectionKindCS()
.getDirectionKind().getLiteral());
}
EClassifier contextType;
if (mappingDeclarationCS.getContextType() != null) {
contextType = visitTypeCS(mappingDeclarationCS.getContextType(), contextDirection, env);
if (contextType == null) {
contextType = env.getModuleContextType();
}
} else {
contextType = env.getModuleContextType();
}
boolean isEntryPoint = QvtOperationalEnv.MAIN.equals(mappingDeclarationCS.getSimpleNameCS().getValue());
boolean isMapping = ExpressionsPackage.eINSTANCE.getMappingOperation().getClassifierID() ==
operation.eClass().getClassifierID();
boolean createMappingParams = isEntryPoint || isMapping;
List<EParameter> params = operation.getEParameters();
for (ParameterDeclarationCS paramCS : mappingDeclarationCS.getParameters()) {
VarParameter param = visitParameterDeclarationCS(paramCS, createMappingParams, env, isEntryPoint);
if (param == null) {
return false;
}
params.add(param);
}
if (mappingDeclarationCS.getContextType() != null) {
MappingParameter mappingParam = createMappingParams ? ExpressionsFactory.eINSTANCE.createMappingParameter() : null;
VarParameter varContext = createMappingParams ? mappingParam : ExpressionsFactory.eINSTANCE.createVarParameter();
varContext.setRepresentedParameter(varContext);
varContext.setName(Environment.SELF_VARIABLE_NAME);
varContext.setStartPosition(mappingDeclarationCS.getContextType().getStartOffset());
varContext.setEndPosition(mappingDeclarationCS.getContextType().getEndOffset());
varContext.setEType(contextType);
varContext.setKind(contextDirection);
if(mappingParam != null) {
if (mappingParam.getExtent() == null) {
mappingParam.setExtent(env.resolveModelParameter(contextType, varContext.getKind()));
}
}
operation.setContext(varContext);
}
EList<ParameterDeclarationCS> resultParams = mappingDeclarationCS.getResult();
for(ParameterDeclarationCS nextResultParamCS : resultParams) {
TypeSpecPair nextResultTypeSpec = visitTypeSpecCS(nextResultParamCS.getTypeSpecCS(), DirectionKind.OUT, env);
if (nextResultTypeSpec.myType == null) {
nextResultTypeSpec.myType = env.getOCLStandardLibrary().getOclVoid();
}
VarParameter varResult = createMappingResultParam(nextResultParamCS, createMappingParams, nextResultTypeSpec, env);
if(resultParams.size() == 1) {
varResult.setName(Environment.RESULT_VARIABLE_NAME);
if(nextResultParamCS.getSimpleNameCS() != null) {
String message = NLS.bind(ValidationMessages.QvtOperationalVisitorCS_resultParamNameNotAllowed, nextResultParamCS.getSimpleNameCS().getValue());
env.reportError(message, nextResultParamCS.getSimpleNameCS());
}
if(nextResultParamCS.isSetDirectionKind()) {
env.reportError(ValidationMessages.QvtOperationalVisitorCS_resultParamNameDirectionNotAllowed, nextResultParamCS);
}
}
operation.getResult().add(varResult);
if (isEntryPoint) {
env.reportWarning(ValidationMessages.QvtOperationalVisitorCS_entryPointReturnDeprecated,
nextResultParamCS.getTypeSpecCS());
}
}
// set operation return type
if(resultParams.isEmpty()) {
// no result parameter should exist
operation.setEType(env.getOCLStandardLibrary().getOclVoid());
} else if(resultParams.size() > 1) {
// create extra tuple-type the result type
operation.setEType(createResultTupleType(operation, env));
} else {
operation.setEType(operation.getResult().get(0).getEType());
}
return true;
}
private EClassifier createResultTupleType(ImperativeOperation operation, QvtOperationalEnv env) {
EList<VarParameter> resultParams = operation.getResult();
assert resultParams.size() > 1;
List<Variable<EClassifier, EParameter>> parts = new ArrayList<Variable<EClassifier,EParameter>>(resultParams.size());
for(VarParameter resultParam : resultParams) {
Variable<EClassifier, EParameter> var = oclFactory.createVariable();
uml.setName(var, resultParam.getName());
uml.setType(var, resultParam.getEType());
parts.add(var);
}
return env.getTypeResolver().resolve((EClassifier)env.getOCLFactory().createTupleType(parts));
}
private VarParameter createMappingResultParam(ParameterDeclarationCS paramCS, boolean createMappingParam, TypeSpecPair typeSpec, QvtOperationalEnv env) {
MappingParameter mappingParam = createMappingParam ? ExpressionsFactory.eINSTANCE.createMappingParameter() : null;
VarParameter varResult = createMappingParam ? mappingParam : ExpressionsFactory.eINSTANCE.createVarParameter();
varResult.setStartPosition(paramCS.getStartOffset());
varResult.setEndPosition(paramCS.getEndOffset());
if(paramCS.getSimpleNameCS() != null) {
varResult.setName(paramCS.getSimpleNameCS().getValue());
}
if(varResult.getName() == null){
varResult.setName(""); //$NON-NLS-1$
}
varResult.setEType(typeSpec.myType);
varResult.setKind(DirectionKind.OUT);
if(mappingParam != null) {
mappingParam.setExtent(typeSpec.myExtent);
if (mappingParam.getExtent() == null) {
QvtOperationalModuleEnv moduleEnv = getModuleContextEnv(env);
mappingParam.setExtent(moduleEnv.resolveModelParameter(typeSpec.myType, varResult.getKind()));
}
}
if(getCompilerOptions().isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(paramCS, varResult);
}
varResult.setRepresentedParameter(varResult);
return varResult;
}
private OCLExpression<EClassifier> visitAssignStatementCS(AssignStatementCS expressionCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
OCLExpressionCS lValueCS = expressionCS.getLValueCS();
OCLExpression<EClassifier> lValue = oclExpressionCS(lValueCS, env);
PathNameCS pathNameCS = extractQualifiedName(lValueCS);
if (pathNameCS == null) {
QvtOperationalUtil.reportError(env, ValidationMessages.notAnLValueError, lValueCS);
return null;
}
EList<String> qualifiedName = pathNameCS.getSequenceOfNames();
if (qualifiedName.size() > 2) {
QvtOperationalUtil.reportError(env, ValidationMessages.cannotModifyNestedPropertiesError, lValueCS);
return null;
}
String lvalueName = qualifiedName.get(0);
if (qualifiedName.size() == 1 && Environment.SELF_VARIABLE_NAME.equals(lvalueName)) {
QvtOperationalUtil.reportError(env, ValidationMessages.CantAssignToSelf, lValueCS);
return null;
}
if (qualifiedName.size() == 1 && QvtOperationalEnv.THIS.equals(lvalueName)) {
QvtOperationalUtil.reportError(env, ValidationMessages.CantAssignToThis, lValueCS);
return null;
}
OCLExpression<EClassifier> rightExpr = visitOclExpressionCS(expressionCS.getOclExpressionCS(), env);
if (rightExpr == null) {
return null;
}
if (lValue instanceof VariableExp) {
Variable<EClassifier, EParameter> variable = env.lookup(lvalueName);
if (variable == null) { // We mustn't be here. Must have been detected by OCL
QvtOperationalUtil.reportError(env, NLS.bind(ValidationMessages.unresolvedNameError, new Object[] { lvalueName }),
lValueCS);
return null;
}
QvtOperationalParserUtil.validateVariableModification(variable, pathNameCS, null, env, true);
QvtOperationalParserUtil.validateAssignment(variable.getName(), variable.getType(), rightExpr, expressionCS.isIncremental(),
pathNameCS, env);
} else if (lValue instanceof PropertyCallExp) {
@SuppressWarnings("unchecked")
PropertyCallExp<EClassifier, EStructuralFeature> propertyCallExp = (PropertyCallExp<EClassifier, EStructuralFeature>) lValue;
EStructuralFeature property = propertyCallExp.getReferredProperty();
if (property == null) { // We mustn't be here. This case is to be handled below
String fullName = QvtOperationalParserUtil.getStringRepresentation(pathNameCS, "."); //$NON-NLS-1$
QvtOperationalUtil.reportError(env, NLS.bind(ValidationMessages.invalidPropertyReferenceError,
new Object[] { fullName }), lValueCS);
return null;
} else {
if (!property.isChangeable()) {
QvtOperationalUtil.reportError(env, NLS.bind(ValidationMessages.ReadOnlyProperty, property.getName()), lValueCS);
} else {
OCLExpression<EClassifier> source = propertyCallExp.getSource();
if (source instanceof VariableExp) {
@SuppressWarnings("unchecked")
VariableExp<EClassifier, EParameter> sourceExp = (VariableExp<EClassifier, EParameter>) source;
Variable<EClassifier, EParameter> sourceVariable = sourceExp.getReferredVariable();
QvtOperationalParserUtil.validateVariableModification(sourceVariable, pathNameCS, property, env, false);
}
QvtOperationalParserUtil.validateAssignment(property.getName(),
env.getUMLReflection().getOCLType(property), rightExpr, expressionCS.isIncremental(),
lValueCS, env);
}
}
} else {
EStructuralFeature leftProp = null;
if (qualifiedName.size() > 1) {
Variable<EClassifier, EParameter> variable = env.lookup(lvalueName);
if (variable == null) {
QvtOperationalUtil.reportError(env, NLS.bind(ValidationMessages.unresolvedNameError, new Object[] { lvalueName }),
lValueCS);
return null;
}
leftProp = env.lookupProperty(variable.getType(), qualifiedName.get(qualifiedName.size() - 1));
if (leftProp == null) {
String fullName = QvtOperationalParserUtil.getStringRepresentation(pathNameCS, "."); //$NON-NLS-1$
QvtOperationalUtil.reportError(env, NLS.bind(ValidationMessages.invalidPropertyReferenceError,
new Object[] { fullName }), lValueCS);
return null;
}
}
// TODO: This code is to be transferred to the AST validator
if ((lValue != null) && !(lValue instanceof InvalidLiteralExp)) { // to avoid induced errors on unresolved variables
QvtOperationalUtil.reportError(env, ValidationMessages.notAnLValueError, lValueCS);
return null;
}
}
AssignExp result = ExpressionsFactory.eINSTANCE.createAssignExp();
result.setStartPosition(expressionCS.getStartOffset());
result.setEndPosition(expressionCS.getEndOffset());
result.getValue().add(rightExpr);
result.setIsReset(!expressionCS.isIncremental());
result.setLeft(lValue);
return result;
}
private PathNameCS extractQualifiedName(OCLExpressionCS qualified) {
if (qualified instanceof PathNameCS) {
return (PathNameCS) qualified;
}
else if (qualified instanceof VariableExpCS) {
PathNameCS result = CSTFactory.eINSTANCE.createPathNameCS();
result.getSequenceOfNames().add(((VariableExpCS) qualified).getSimpleNameCS().getValue());
result.setStartOffset(qualified.getStartOffset());
result.setEndOffset(qualified.getEndOffset());
return result;
}
else if (qualified instanceof FeatureCallExpCS) {
FeatureCallExpCS callExp = (FeatureCallExpCS) qualified;
if (callExp.getSource() == null) {
return null;
}
PathNameCS prefix = extractQualifiedName(callExp.getSource());
if (prefix == null) {
return null;
}
PathNameCS result = CSTFactory.eINSTANCE.createPathNameCS();
result.getSequenceOfNames().addAll(prefix.getSequenceOfNames());
result.getSequenceOfNames().add(callExp.getSimpleNameCS().getValue());
result.setStartOffset(qualified.getStartOffset());
result.setEndOffset(qualified.getEndOffset());
return result;
}
return null;
}
private VarParameter visitParameterDeclarationCS(ParameterDeclarationCS paramCS, boolean createMappingParam,
QvtOperationalModuleEnv env, boolean isOutAllowed) throws SemanticException {
DirectionKindEnum directionKindEnum = paramCS.getDirectionKind();
if (directionKindEnum == DirectionKindEnum.DEFAULT) {
directionKindEnum = DirectionKindEnum.IN;
}
DirectionKind directionKind = (DirectionKind) ExpressionsFactory.eINSTANCE.createFromString(
ExpressionsPackage.eINSTANCE.getDirectionKind(), directionKindEnum.getLiteral());
TypeSpecPair typeSpec = visitTypeSpecCS(paramCS.getTypeSpecCS(), directionKind, env);
if (typeSpec.myType == null) {
typeSpec.myType = env.getOCLStandardLibrary().getOclVoid();
}
MappingParameter mappingParam = createMappingParam ? ExpressionsFactory.eINSTANCE.createMappingParameter() : null;
VarParameter varParam = createMappingParam ? mappingParam : ExpressionsFactory.eINSTANCE.createVarParameter();
varParam.setRepresentedParameter(varParam);
varParam.setStartPosition(paramCS.getStartOffset());
varParam.setEndPosition(paramCS.getEndOffset());
if(paramCS.getSimpleNameCS() != null) {
varParam.setName(paramCS.getSimpleNameCS().getValue());
} else {
varParam.setName(""); //$NON-NLS-1$
}
varParam.setEType(typeSpec.myType);
varParam.setKind(directionKind);
if(mappingParam != null) {
mappingParam.setExtent(typeSpec.myExtent);
if (mappingParam.getExtent() == null) {
mappingParam.setExtent(env.resolveModelParameter(typeSpec.myType, directionKind));
if (mappingParam.getExtent() == null && directionKind == DirectionKind.OUT) {
env.reportError(ValidationMessages.OutParamWithoutExtent, paramCS);
}
}
}
if (!isOutAllowed && varParam.getKind() == DirectionKind.OUT) {
env.reportError(ValidationMessages.OutParamsNotSupported, paramCS);
}
// AST binding
if(myCompilerOptions.isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(paramCS, varParam);
}
//
return varParam;
}
private OCLExpression<EClassifier> visitVariableInitializationCS(VariableInitializationCS varInitCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
MappingMethodCS mappingMethod = null;
EObject tempContainer = varInitCS;
do {
tempContainer = tempContainer.eContainer();
if (tempContainer instanceof MappingMethodCS) {
mappingMethod = (MappingMethodCS) tempContainer;
break;
}
} while (tempContainer != null);
VariableInitExp result = ExpressionsFactory.eINSTANCE.createVariableInitExp();
result.setStartPosition(varInitCS.getStartOffset());
result.setEndPosition(varInitCS.getEndOffset());
if (validateInitializedValueCS(varInitCS, result, env)) {
if (QvtOperationalParserUtil.validateInitVariable(result, env)) {
addInitVariable(env, result);
}
}
// AST binding
if(myCompilerOptions.isGenerateCompletionData()) {
if(result.getName() != null) {
Variable<EClassifier, EParameter> envVar = env.lookupLocal(result.getName());
if(envVar != null) {
ASTBindingHelper.createCST2ASTBinding(varInitCS, envVar);
}
}
}
//
return result;
}
private ReturnExp visitReturnExpCS(ReturnExpCS returnExpCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
ReturnExp result = ExpressionsFactory.eINSTANCE.createReturnExp();
initStartEndPositions(result, returnExpCS);
if(returnExpCS.getValue() != null) {
OCLExpression<EClassifier> value = oclExpressionCS(returnExpCS.getValue(), env);
result.setValue(value);
if(value != null) {
result.setType(value.getType());
}
}
if(result.getType() == null) {
result.setType(env.getOCLStandardLibrary().getOclVoid());
}
return result;
}
private MappingBody visitMappingBodyCS(MappingBodyCS mappingBodyCS, QvtOperationalEnv env, MappingMethodCS mappingRuleCS)
throws SemanticException {
MappingBody body = ExpressionsFactory.eINSTANCE.createMappingBody();
body.setStartPosition(mappingBodyCS.getStartOffset());
body.setEndPosition(mappingBodyCS.getEndOffset());
//Spec 07-07-07: 8.2.1.19 MappingBody
//The rule for interpreting a body in which there is no population keyword is as follows:
//(1) If the mapping operation defines a unique result, the list of expressions in the body is the list of expressions of the -
//unique - implicit object expression (see ObjectExp) contained by the population section.
//(2) If the mapping operation defines more than one result, the list of expressions in the body is the list of expressions of
//the population section.
if (!mappingBodyCS.isHasPopulationKeyword()) {
MappingDeclarationCS mappingDeclarationCS = mappingRuleCS.getMappingDeclarationCS();
if (mappingDeclarationCS != null) {
boolean isUniqueResult = mappingDeclarationCS.getResult().size() == 1;
boolean isImplicitContext = mappingDeclarationCS.getResult().isEmpty()
&& (mappingDeclarationCS.getContextType() != null)
&& (mappingDeclarationCS.getDirectionKindCS() != null)
&& (mappingDeclarationCS.getDirectionKindCS().getDirectionKind() == DirectionKindEnum.INOUT);
if (isUniqueResult || isImplicitContext) {
OutExpCS implicitObjectExpCS = org.eclipse.m2m.internal.qvt.oml.cst.CSTFactory.eINSTANCE.createOutExpCS();
implicitObjectExpCS.setIsImplicit(true);
SimpleNameCS resultVar = CSTFactory.eINSTANCE.createSimpleNameCS();
String implicitVarName = isUniqueResult ? Environment.RESULT_VARIABLE_NAME : Environment.SELF_VARIABLE_NAME;
resultVar.setValue(implicitVarName);
implicitObjectExpCS.setSimpleNameCS(resultVar);
implicitObjectExpCS.setStartOffset(mappingBodyCS.getStartOffset());
implicitObjectExpCS.setEndOffset(mappingBodyCS.getEndOffset());
implicitObjectExpCS.getExpressions().addAll(mappingBodyCS.getStatements());
mappingBodyCS.getStatements().add(implicitObjectExpCS);
ObjectExp objectExp = visitOutExpCS(implicitObjectExpCS, env, false);
body.getContent().add(objectExp);
return body;
}
}
}
List<OCLExpression<EClassifier>> expressions = visitMappingSectionCS(mappingBodyCS, env);
body.getContent().addAll(expressions);
return body;
}
private int getStartOffset(ASTNode astNode, CSTNode cstNodeOpt) {
if(cstNodeOpt != null) {
return cstNodeOpt.getStartOffset();
}
return astNode.getStartPosition();
}
private int getEndOffset(ASTNode astNode, CSTNode cstNodeOpt) {
if(cstNodeOpt != null) {
return cstNodeOpt.getEndOffset();
}
return astNode.getEndPosition();
}
private void validateObjectExp(ObjectExp objectExp, OutExpCS objectExpCS, QvtOperationalEnv env) {
EClass derivedInstantiatedClass = objectExp.getInstantiatedClass();
Variable<EClassifier, EParameter> referredObject = objectExp.getReferredObject();
if(derivedInstantiatedClass == null && (referredObject != null && QVTUMLReflection.isUserModelElement(referredObject.getType()))) {
derivedInstantiatedClass = (EClass)referredObject.getType();
}
if((derivedInstantiatedClass == null) || !QVTUMLReflection.isUserModelElement(derivedInstantiatedClass)) {
CSTNode problemCS = null;
if(objectExpCS != null) {
problemCS = objectExpCS.getTypeSpecCS();
if(problemCS == null) {
problemCS = objectExpCS.getSimpleNameCS();
}
if(problemCS == null) {
problemCS = objectExpCS;
}
}
int startOffs = getStartOffset(objectExp, problemCS);
int endOffs = getEndOffset(objectExp, problemCS);
if(referredObject != null) {
if(referredObject.getType() != null && (referredObject.getType() instanceof CollectionType == false)) {
// we failed to figure out the class but type is available, let's report it's classifier only
env.reportError(NLS.bind(ValidationMessages.nonModelTypeError,
QvtOperationalParserUtil.safeGetQualifiedName(env, referredObject.getType())), startOffs, endOffs);
}
}
}
// check for the type conformance only if instantiatedClass class was explicitly set
if(referredObject != null) {
if(objectExp.getType() != null) {
CSTNode problemCS = null;
if(objectExpCS != null) {
problemCS = objectExpCS.getSimpleNameCS();
if(problemCS == null) {
problemCS = objectExpCS.getTypeSpecCS() != null ? objectExpCS.getTypeSpecCS() : objectExpCS;
}
}
EClassifier referredType = referredObject.getType();
EClassifier actualType = objectExp.getType();
// Note : invalid AST might have type node missing, so just check, a problem would be reported by variable validation
if(referredType != null && (TypeUtil.getRelationship(env, actualType, referredType) & UMLReflection.SAME_TYPE) == 0) {
String actualTypeName = QvtOperationalParserUtil.safeGetQualifiedName(env, actualType);
String referredTypeName = QvtOperationalParserUtil.safeGetQualifiedName(env, referredType);
String errorMessage = NLS.bind(ValidationMessages.QvtOperationalVisitorCS_instatiatedTypeDoesNotConformToReferredType,
actualTypeName, referredTypeName);
env.reportError(errorMessage, getStartOffset(objectExp, problemCS), getEndOffset(objectExp, problemCS));
}
if(referredObject.getRepresentedParameter() instanceof MappingParameter) {
MappingParameter mappingPar = (MappingParameter) referredObject.getRepresentedParameter();
if(mappingPar.getKind() == DirectionKind.IN) {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_canNotModifyINParameter, referredObject.getName()), problemCS);
}
}
}
} else if(derivedInstantiatedClass != null && (derivedInstantiatedClass.isAbstract() || derivedInstantiatedClass.isInterface())) {
// always creates a new instance, ensure non-abstract type.
String typeName = QvtOperationalParserUtil.safeGetQualifiedName(env, derivedInstantiatedClass);
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_canNotInstantiateAbstractType, typeName), objectExpCS);
}
}
private OCLExpression<EClassifier> visitExpressionStatementCS(ExpressionStatementCS expressionCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
return visitOclExpressionCS(expressionCS.getOclExpressionCS(), env);
}
private static EStructuralFeature createESFeature(EClassifier type) {
if(type instanceof EClass) {
return org.eclipse.emf.ecore.EcoreFactory.eINSTANCE.createEReference();
}
return org.eclipse.emf.ecore.EcoreFactory.eINSTANCE.createEAttribute();
}
private EStructuralFeature visitConfigPropertyCS(ConfigPropertyCS propCS, QvtOperationalFileEnv env) {
SimpleNameCS simpleNameCS = propCS.getSimpleNameCS();
String name = simpleNameCS != null ? simpleNameCS.getValue() : ""; //$NON-NLS-1$
EClassifier type = null;
if (propCS.getTypeCS() != null) {
type = visitTypeCS(propCS.getTypeCS(), null, env);
if (type != null) {
if (!QvtOperationalUtil.isCreateFromStringSupported(type)) {
env.reportError(NLS.bind(ValidationMessages.ConfigPropertyTypeUnsupported, new Object[] { type
.getName() }), propCS.getTypeCS());
}
}
} else {
env.reportError(NLS.bind(ValidationMessages.ConfigPropertyMustHaveType,
new Object[] { name }), simpleNameCS != null ? simpleNameCS : propCS);
}
EStructuralFeature feature = createESFeature(type);
feature.setName(name);
feature.setEType(type);
ASTSyntheticNode astNode = ASTSyntheticNodeAccess.createASTNode(feature);
astNode.setStartPosition(propCS.getStartOffset());
astNode.setEndPosition(propCS.getEndOffset());
return feature;
}
private EStructuralFeature visitLocalPropertyCS(LocalPropertyCS propCS, QvtOperationalEnv env) {
EClassifier type = null;
if (propCS.getTypeCS() != null) {
type = visitTypeCS(propCS.getTypeCS(), null, env);
}
EStructuralFeature prop = createESFeature(type);
SimpleNameCS simpleNameCS = propCS.getSimpleNameCS();
prop.setName(simpleNameCS.getValue());
prop.setEType(type);
ASTSyntheticNode astNode = ASTSyntheticNodeAccess.createASTNode(prop);
astNode.setStartPosition(propCS.getStartOffset());
astNode.setEndPosition(propCS.getEndOffset());
OCLExpression<EClassifier> exp = null;
if (propCS.getOclExpressionCS() != null) {
exp = visitOclExpressionCS(propCS.getOclExpressionCS(), env);
QvtOperationalParserUtil.setInitExpression(prop, exp);
}
if (prop.getEType() == null && exp != null) {
prop.setEType(exp.getType());
}
if(exp != null) {
EClassifier realType = exp.getType();
EClassifier declaredType = prop.getEType();
if (!QvtOperationalParserUtil.isAssignableToFrom(env, declaredType, realType)) {
env.reportError(NLS.bind(ValidationMessages.SemanticUtil_17,
new Object[] { QvtOperationalTypesUtil.getTypeFullName(declaredType), QvtOperationalTypesUtil.getTypeFullName(realType) }),
astNode.getStartPosition(), astNode.getEndPosition());
}
}
return prop;
}
private ContextualProperty visitContextualPropertyCS(ContextualPropertyCS propCS, QvtOperationalFileEnv env) {
ContextualProperty prop = ExpressionsFactory.eINSTANCE.createContextualProperty();
prop.setStartPosition(propCS.getStartOffset());
prop.setEndPosition(propCS.getEndOffset());
prop.setName(propCS.getScopedNameCS().getName());
EClassifier type = null;
if (propCS.getTypeCS() != null) {
type = visitTypeCS(propCS.getTypeCS(), null, env);
if (type == null) {
return null;
}
}
OCLExpression<EClassifier> exp = null;
if (propCS.getOclExpressionCS() != null) {
env.reportWarning(NLS.bind(ValidationMessages.IntermediatePropertiesInitNotSupported,
new Object[] { }), propCS.getOclExpressionCS());
exp = visitOclExpressionCS(propCS.getOclExpressionCS(), env);
}
if (type == null && exp != null) {
type = exp.getType();
}
if (type == null) {
return null;
}
prop.setEType(type);
prop.setInitExpression(exp);
if (exp != null) {
EClassifier realType = exp.getType();
EClassifier declaredType = prop.getEType();
if (!QvtOperationalParserUtil.isAssignableToFrom(env, declaredType, realType)) {
env.reportError(NLS.bind(ValidationMessages.SemanticUtil_17,
new Object[] { QvtOperationalTypesUtil.getTypeFullName(declaredType), QvtOperationalTypesUtil.getTypeFullName(realType) }),
prop.getStartPosition(), prop.getEndPosition());
}
}
EClassifier contextType = visitTypeCS(propCS.getScopedNameCS().getTypeCS(), null, env);
if (contextType != null) {
if(contextType instanceof EClass) {
prop.setContext((EClass)contextType);
} else {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_ContextualPropertyTypeIsNotClass,
new Object[] { prop.getName() }), propCS.getScopedNameCS().getTypeCS());
}
}
return prop;
}
protected EStructuralFeature visitModulePropertyCS(ModulePropertyCS propCS, QvtOperationalFileEnv env) {
EStructuralFeature result = null;
if (propCS instanceof ConfigPropertyCS) {
result = visitConfigPropertyCS((ConfigPropertyCS) propCS, env);
}
else if (propCS instanceof LocalPropertyCS) {
result = visitLocalPropertyCS((LocalPropertyCS) propCS, env);
}
else if (propCS instanceof ContextualPropertyCS) {
result = visitContextualPropertyCS((ContextualPropertyCS) propCS, env);
}
else {
assert false : "Unexpected CS class: " + propCS;
}
// AST binding
if (myCompilerOptions.isGenerateCompletionData()) {
propCS.setAst(result);
if(result instanceof ASTNode) {
ASTBindingHelper.createCST2ASTBinding(propCS, (ASTNode)result, env);
} else {
ASTSyntheticNode astNode = ASTSyntheticNodeAccess.getASTNode(result);
ASTSyntheticNodeAccess.setCST(astNode, propCS);
}
}
//
return result;
}
private OCLExpression<EClassifier> visitResolveExpCS(ResolveExpCS resolveExpCS, QvtOperationalEnv env) {
ResolveExp resolveExp = populateResolveExp(resolveExpCS, env, ExpressionsFactory.eINSTANCE.createResolveExp());
if (resolveExp.getSource() == null) {
env.reportError(NLS.bind(ValidationMessages.ResolveExpMustHaveASource, new Object[] { }), resolveExpCS);
}
DeprecatedImplicitSourceCallHelper.validateCallExp(resolveExpCS, resolveExp, env);
return resolveExp;
}
private void validateResolveExp(ResolveExp resolveExp,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
if(resolveExp.isIsDeferred()) {
if(!QvtResolveUtil.isSuppportedAsDeferredAssigned(resolveExp)) {
int startPos = (resolveExp.getSource() != null) ? resolveExp.getSource().getEndPosition() : resolveExp.getStartPosition();
QvtOperationalUtil.reportWarning(env, ValidationMessages.lateResolveNotUsedInDeferredAssignment, startPos, resolveExp.getEndPosition());
}
}
}
private OCLExpression<EClassifier> visitResolveInExpCS(ResolveInExpCS resolveInExpCS, QvtOperationalEnv env) {
ResolveInExp resolveInExp = ExpressionsFactory.eINSTANCE.createResolveInExp();
TypeCS contextTypeCS = resolveInExpCS.getInMappingType();
EClassifier eClassifier = (contextTypeCS == null) ? null : visitTypeCS(contextTypeCS, null, env); // mapping context type
eClassifier = eClassifier != null ? eClassifier : env.getModuleContextType();
String mappingName = resolveInExpCS.getInMappingName().getValue();
List<EOperation> rawMappingOperations = env.lookupMappingOperations(eClassifier, mappingName);
List<EOperation> mappingOperations = new ArrayList<EOperation>();
for (EOperation operation : rawMappingOperations) {
EClassifier owner = env.getUMLReflection().getOwningClassifier(operation);
if (((contextTypeCS == null) && (owner == null))
|| (TypeUtil.resolveType(env, owner) == eClassifier)) {
mappingOperations.add(operation);
}
}
if (mappingOperations.size() == 1) {
env.registerResolveInExp(resolveInExp, eClassifier, mappingName);
} else {
String mappingFQName = (eClassifier == null) ? "" : eClassifier.getName() + QvtOperationalTypesUtil.TYPE_NAME_SEPARATOR; //$NON-NLS-1$
mappingFQName += mappingName;
if (mappingOperations.size() == 0) {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_ResolveInMappingNotFound, new Object[] {
mappingFQName}), resolveInExpCS.getInMappingName() != null ? resolveInExpCS.getInMappingName() : resolveInExpCS);
} else if (mappingOperations.size() > 1) {
env.reportWarning(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_ResolveInSeveralMappingsFound, new Object[] {
mappingFQName}), resolveInExpCS);
env.registerResolveInExp(resolveInExp, eClassifier, mappingName);
}
}
ResolveExp result = populateResolveExp(resolveInExpCS, env, resolveInExp);
// DeprecatedImplicitSourceCallHelper.validateCallExp(resolveInExpCS, result, env);
return result;
}
private ResolveExp populateResolveExp(ResolveExpCS resolveExpCS, QvtOperationalEnv env, ResolveExp resolveExp) {
// AST binding
if(myCompilerOptions.isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(resolveExpCS, resolveExp, env);
}
//
if (resolveExpCS.getSource() != null) {
OCLExpression<EClassifier> sourceExp = visitOclExpressionCS(resolveExpCS.getSource(), env);
resolveExp.setSource(sourceExp);
} else {
// // lookup for implicit source
// Variable<EClassifier,EParameter> implicitSource = env.lookupImplicitSourceForResolveExp();
// if (implicitSource != null) {
// VariableExp<EClassifier,EParameter> vexp = org.eclipse.ocl.expressions.ExpressionsFactory.eINSTANCE.createVariableExp();
//
// vexp.setType(implicitSource.getType());
// vexp.setReferredVariable(implicitSource);
// vexp.setName(implicitSource.getName());
//
// resolveExp.setSource(vexp);
// }
}
resolveExp.setOne(resolveExpCS.isOne());
resolveExp.setIsInverse(resolveExpCS.isIsInverse());
resolveExp.setIsDeferred(resolveExpCS.isIsDeferred());
if (resolveExpCS.getTarget() != null) { // at least type is defined
Variable<EClassifier, EParameter> variable = EcoreFactory.eINSTANCE.createVariable();
EClassifier type = visitTypeCS(resolveExpCS.getTarget().getTypeCS(), null, env);
variable.setType(type);
boolean isTargetVarClashing = false;
String targetVarName = resolveExpCS.getTarget().getName();
if (targetVarName != null) {
if (env.lookupLocal(targetVarName) != null) {
isTargetVarClashing = true;
env.reportError(NLS.bind(ValidationMessages.SemanticUtil_15, new Object[] { targetVarName }),
resolveExpCS.getTarget().getStartOffset(), resolveExpCS.getTarget().getEndOffset());
}
variable.setName(targetVarName);
}
resolveExp.setTarget(variable);
// AST binding
if(myCompilerOptions.isGenerateCompletionData()) {
ASTBindingHelper.createCST2ASTBinding(resolveExpCS.getTarget(), variable, env);
}
//
if (resolveExp.isOne()) {
resolveExp.setType(type);
} else {
EClassifier resolveType = (EClassifier) env.getOCLFactory().createSequenceType(type);
resolveExp.setType(TypeUtil.resolveType(env, resolveType));
}
if (resolveExpCS.getCondition() != null) {
if (!isTargetVarClashing && variable.getName() != null) {
env.addElement(variable.getName(), variable, true);
}
OCLExpression<EClassifier> condExp = visitOclExpressionCS(resolveExpCS.getCondition(), env);
resolveExp.setCondition(condExp);
if (!isTargetVarClashing && variable.getName() != null) {
env.deleteElement(variable.getName());
// ensure to bind back to the ResolveExp container
resolveExp.setTarget(variable);
}
}
} else {
if (resolveExp.isOne()) {
resolveExp.setType(env.getOCLStandardLibrary().getOclAny());
} else {
EClassifier resolveType = (EClassifier) env.getOCLFactory().createSequenceType(env.getOCLStandardLibrary().getOclAny());
resolveExp.setType(TypeUtil.resolveType(env, resolveType));
}
}
resolveExp.setStartPosition(resolveExpCS.getStartOffset());
resolveExp.setEndPosition(resolveExpCS.getEndOffset());
if(resolveExpCS.isIsDeferred()) {
addLateResolve(resolveExp);
}
OCLExpression<EClassifier> condition = resolveExp.getCondition();
if(condition != null) {
EClassifier condType = condition.getType();
if(env.getOCLStandardLibrary().getBoolean() != condType) {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_booleanTypeExpressionExpected,
env.getUMLReflection().getName(condType)), condition.getStartPosition(), condition.getEndPosition());
}
}
return resolveExp;
}
private OCLExpression<EClassifier> visitForExp(ForExpCS forExpCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
OCLExpression<EClassifier> source =
getCollectionSourceExpression(forExpCS.getSource(), env);
if (!(source.getType() instanceof CollectionType)) {
return createDummyInvalidLiteralExp();
}
String name = forExpCS.getSimpleNameCS().getValue();
ForExp astNode = ExpressionsFactory.eINSTANCE.createForExp();
initASTMapping(env, astNode, forExpCS);
astNode.setName(name);
astNode.setStartPosition(forExpCS.getStartOffset());
astNode.setEndPosition(forExpCS.getEndOffset());
astNode.setType(env.getOCLStandardLibrary().getOclVoid());
EList<Variable<EClassifier, EParameter>> iterators = astNode.getIterator();
@SuppressWarnings("unchecked")
CollectionType<EClassifier, EOperation> sourceCollectionType = (CollectionType<EClassifier, EOperation>) source.getType();
Variable<EClassifier, EParameter> vdcl = null;
if (forExpCS.getVariable1() != null) {
vdcl = variableDeclarationCS(forExpCS.getVariable1(), env, true);
vdcl.setType(sourceCollectionType.getElementType());
iterators.add(vdcl);
}
Variable<EClassifier, EParameter> vdcl1 = null;
if (forExpCS.getVariable2() != null) {
vdcl1 = variableDeclarationCS(forExpCS.getVariable2(), env, true);
vdcl1.setType(sourceCollectionType.getElementType());
iterators.add(vdcl1);
}
if (forExpCS.getCondition() != null) {
OCLExpression<EClassifier> conditionExp = oclExpressionCS(forExpCS.getCondition(), env);
astNode.setCondition(conditionExp);
}
if (forExpCS.getBody() != null) {
OCLExpression<EClassifier> bodyExp = oclExpressionCS(forExpCS.getBody(), env);
astNode.setBody(bodyExp);
}
astNode.setSource(source);
if (vdcl != null) {
env.deleteElement(vdcl.getName());
}
if (vdcl1 != null) {
env.deleteElement(vdcl1.getName());
}
return astNode;
}
private OCLExpression<EClassifier> visitImperativeIterateExp(ImperativeIterateExpCS imperativeIterateExpCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
OCLExpression<EClassifier> source =
getCollectionSourceExpression(imperativeIterateExpCS.getSource(), env);
if (!(source.getType() instanceof CollectionType)) {
return createDummyInvalidLiteralExp();
}
String name = imperativeIterateExpCS.getSimpleNameCS().getValue();
Variable<EClassifier, EParameter> vdcl = null;
Variable<EClassifier, EParameter> vdcl1 = null;
List<Variable<EClassifier, EParameter>> iterators = null;
ImperativeIterateExp astNode;
@SuppressWarnings("unchecked")
CollectionType<EClassifier, EOperation> sourceCollectionType = (CollectionType<EClassifier, EOperation>) source.getType();
if (imperativeIterateExpCS.getVariable1() != null) {
vdcl = variableDeclarationCS(imperativeIterateExpCS.getVariable1(), env, true);
astNode = ExpressionsFactory.eINSTANCE.createImperativeIterateExp();
initASTMapping(env, astNode, imperativeIterateExpCS);
astNode.setName(name);
iterators = astNode.getIterator();
if (vdcl.getType() == null) {
vdcl.setType(sourceCollectionType.getElementType());
}
iterators.add(vdcl);
if (imperativeIterateExpCS.getVariable2() != null) {
vdcl1 = variableDeclarationCS(imperativeIterateExpCS.getVariable2(), env, true);
if (vdcl1.getType() == null) {
vdcl1.setType(sourceCollectionType.getElementType());
}
iterators.add(vdcl1);
}
} else {
astNode = ExpressionsFactory.eINSTANCE.createImperativeIterateExp();
initASTMapping(env, astNode, imperativeIterateExpCS);
astNode.setName(name);
iterators = astNode.getIterator();
// Synthesize the iterator expression.
vdcl = genVariableDeclaration(imperativeIterateExpCS, "visitImperativeIterateExp", env, null, //$NON-NLS-1$
sourceCollectionType.getElementType(), null, false, true, false);
iterators.add(vdcl);
}
TRACE("visitImperativeIterateExp: ", name);//$NON-NLS-1$
EClassifier resultElementType = null;
if (name.equals("xselect") || name.equals("selectOne")) {//$NON-NLS-1$ //$NON-NLS-2$
resultElementType = sourceCollectionType.getElementType();
} else {
// Body may be defined explicitly - then it is the collectselect(One) shorthand or xcollect/collectOne.
// It may be contained it the target variable - then it is the full notation of collectselect(One).
if (imperativeIterateExpCS.getBody() != null) {
OCLExpression<EClassifier> bodyExp = oclExpressionCS(imperativeIterateExpCS.getBody(), env);
astNode.setBody(bodyExp);
if (((imperativeIterateExpCS.getTarget() == null) || (imperativeIterateExpCS.getTarget().getInitExpression() == null))
&& (name.equals("collectselect") || name.equals("collectselectOne"))) { //$NON-NLS-1$ //$NON-NLS-2$
// This is the case with collectselect(One) shorthand
// list->prop[res| res.startswith("_")];
// equivalent to
// list->collectselect(i;res = i.prop | res.startswith("_"))
if (!isInnermostIteratorRelated(vdcl, bodyExp)) {
QvtOperationalUtil.reportError(env, NLS.bind(ValidationMessages.QvtOperationalVisitorCS_FeatureNotFoundForType,
new Object[] {QvtOperationalTypesUtil.getTypeFullName(vdcl.getType())}),
imperativeIterateExpCS.getBody());
}
if (imperativeIterateExpCS.getTarget() == null) {
Variable<EClassifier, EParameter> targetVdcl = genVariableDeclaration(imperativeIterateExpCS, "visitImperativeIterateExp", env, null, //$NON-NLS-1$
bodyExp.getType(), null, false, true, false);
astNode.setTarget(targetVdcl);
}
}
}
if (imperativeIterateExpCS.getTarget() != null) {
Variable<EClassifier, EParameter> targetVdcl = variableDeclarationCS(imperativeIterateExpCS.getTarget(), env, true);
if (targetVdcl.getInitExpression() != null) {
astNode.setBody(targetVdcl.getInitExpression()); // the body is transferred from the target variable due to containment
}
astNode.setTarget(targetVdcl);
}
if (astNode.getBody() != null) {
resultElementType = astNode.getBody().getType();
if ((astNode.getTarget() != null) && (astNode.getTarget().getType() == null)) {
astNode.getTarget().setType(resultElementType);
}
}
}
if (imperativeIterateExpCS.getCondition() != null) {
OCLExpression<EClassifier> conditionExp = oclExpressionCS(imperativeIterateExpCS.getCondition(), env);
astNode.setCondition(conditionExp);
if (conditionExp instanceof TypeExp<?>) {
TypeExp<EClassifier> typedCondition = (TypeExp<EClassifier>) conditionExp;
EClassifier rawTypeType = TypeUtil.resolveType(env, typedCondition.getType());
if (rawTypeType instanceof TypeType) {
@SuppressWarnings("unchecked")
TypeType<EClassifier, EOperation> typeType = (TypeType<EClassifier, EOperation>) rawTypeType;
resultElementType = typeType.getReferredType();
}
} else if ((conditionExp != null) && (conditionExp.getType() != getBoolean())) {
QvtOperationalUtil.reportError(env, ValidationMessages.QvtOperationalVisitorCS_WrongImperativeIteratorConditionType,
conditionExp.getStartPosition(), conditionExp.getEndPosition());
}
}
if (astNode.getTarget() != null) {
env.deleteElement(astNode.getTarget().getName());
}
if (name.equals("selectOne") || name.equals("collectOne") || name.equals("collectselectOne")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
astNode.setType(resultElementType);
} else if (name.equals("xselect")) { //$NON-NLS-1$
EClassifier resultCollectionType = getCollectionType(env, sourceCollectionType.getKind(), resultElementType);
astNode.setType(resultCollectionType);
} else { // xcollect and collectselect
EClassifier resultCollectionType = ((sourceCollectionType instanceof SetType) || (sourceCollectionType instanceof BagType)) ?
getCollectionType(env, CollectionKind.BAG_LITERAL, resultElementType)
: getCollectionType(env, CollectionKind.SEQUENCE_LITERAL, resultElementType);
astNode.setType(resultCollectionType);
}
astNode.setSource(source);
env.deleteElement(vdcl.getName());
if (vdcl1 != null) {
env.deleteElement(vdcl1.getName());
}
// ensure AST containment tree
astNode.getIterator().addAll(iterators);
return astNode;
}
private boolean isInnermostIteratorRelated(Variable<EClassifier, EParameter> vdcl, OCLExpression<EClassifier> bodyExp) {
if (bodyExp instanceof CallExp) {
CallExp bodyCallExp = (CallExp) bodyExp;
if (bodyCallExp.getSource() instanceof VariableExp) {
VariableExp<EClassifier, EParameter> sourceExp = (VariableExp<EClassifier, EParameter>) bodyCallExp.getSource();
return sourceExp.getReferredVariable() == vdcl;
}
return false;
}
return true; // might be switch exp, for example
}
private MappingCallExp createMappingCallExp(MappingCallExpCS expressionCS, OCLExpression<EClassifier> result) {
if (result instanceof OperationCallExp) {
OperationCallExp<EClassifier, EOperation> operationCallExp = (OperationCallExp<EClassifier, EOperation>) result;
EOperation operation = operationCallExp.getReferredOperation();
if (QvtOperationalUtil.isMappingOperation(operation)) {
MappingCallExp mappingCallExp = ExpressionsFactory.eINSTANCE.createMappingCallExp();
mappingCallExp.setStartPosition(operationCallExp.getStartPosition());
mappingCallExp.setEndPosition(operationCallExp.getEndPosition());
mappingCallExp.getArgument().addAll(operationCallExp.getArgument());
mappingCallExp.setReferredOperation(operation);
mappingCallExp.setSource(operationCallExp.getSource());
mappingCallExp.setType(operationCallExp.getType());
mappingCallExp.setIsStrict(expressionCS.isStrict());
mappingCallExp.setPropertyStartPosition(operationCallExp.getPropertyStartPosition());
mappingCallExp.setPropertyEndPosition(operationCallExp.getPropertyEndPosition());
return mappingCallExp;
}
}
return null;
}
private void validateOperationCall(OperationCallExpCS opCallCS, OperationCallExp<EClassifier, EOperation> operationCallExp,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
if (QvtOperationalParserUtil.isTypeCast(operationCallExp.getReferredOperation())) {
if (operationCallExp.getSource() != null && operationCallExp.getArgument().size() == 1) {
EClassifier sourceType = operationCallExp.getSource().getType();
EClassifier argumentType = ((OCLExpression<EClassifier>) operationCallExp.getArgument().get(0))
.getType();
if (argumentType instanceof TypeType
&& QvtOperationalParserUtil.isIncorrectCast(sourceType,
((TypeType<EClassifier, EOperation>) argumentType).getReferredType())) {
QvtOperationalUtil.reportWarning(env, ValidationMessages.incorrectCastWarning, opCallCS);
}
}
}
if (QvtOperationalUtil.isMappingOperation(operationCallExp.getReferredOperation())) {
if (false == opCallCS instanceof MappingCallExpCS) {
QvtOperationalUtil.reportWarning(env, NLS.bind(ValidationMessages.QvtOperationalVisitorCS_mapKeywordNotUsed,
operationCallExp.getReferredOperation().getName()), opCallCS);
}
}
}
private void validateImportedSignature(QvtOperationalEnv env, OperationalTransformation module, OperationalTransformation importedModule, ASTNode astNode) {
Set<ModelParameter> processedParams = new HashSet<ModelParameter>();
Set<ModelParameter> consideredParams = new HashSet<ModelParameter>();
for (ModelParameter importedParam : importedModule.getModelParameter()) {
for (ModelParameter param : module.getModelParameter()) {
if (consideredParams.contains(param)) {
continue;
}
if (QvtOperationalUtil.isModelParamEqual(param, importedParam, true)) {
consideredParams.add(param);
processedParams.add(importedParam);
break;
}
}
}
for (ModelParameter importedParam : importedModule.getModelParameter()) {
if (processedParams.contains(importedParam)) {
continue;
}
boolean isCorrespondanceFound = false;
for (ModelParameter param : module.getModelParameter()) {
if (consideredParams.contains(param)) {
continue;
}
if (QvtOperationalUtil.isModelParamEqual(param, importedParam, false)) {
consideredParams.add(param);
isCorrespondanceFound = true;
break;
}
}
if (!isCorrespondanceFound) {
env.reportWarning(
NLS.bind(ValidationMessages.QvtOperationalVisitorCS_incompatibleTransfSignature, importedModule.getName()),
astNode.getStartPosition(), astNode.getEndPosition());
return;
}
}
}
private void checkMainMappingConformance(QvtOperationalEnv env, ImperativeOperation operation) {
Set<ModelParameter> usedExtent = new HashSet<ModelParameter>(operation.getEParameters().size());
for (EParameter param : operation.getEParameters()) {
MappingParameter varParam = (MappingParameter) param;
if (usedExtent.contains(varParam.getExtent())) {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_extentDuplicateUse, null),
varParam.getStartPosition(), varParam.getEndPosition());
}
if (varParam.getKind() != DirectionKind.OUT) {
usedExtent.add(varParam.getExtent());
}
if (varParam.getExtent() == null) {
if(varParam.getKind() != DirectionKind.IN) {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_extentFailToInfer,
QvtOperationalTypesUtil.getTypeFullName(varParam.getEType())),
varParam.getStartPosition(), varParam.getEndPosition());
}
}
else if (varParam.getExtent().getKind() == DirectionKind.IN) {
if (varParam.getKind() != DirectionKind.IN) {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_extentDirectionMismatch, null),
varParam.getStartPosition(), varParam.getEndPosition());
}
}
else if (varParam.getExtent().getKind() == DirectionKind.OUT) {
if (varParam.getKind() != DirectionKind.OUT) {
env.reportError(NLS.bind(ValidationMessages.QvtOperationalVisitorCS_extentDirectionMismatch, null),
varParam.getStartPosition(), varParam.getEndPosition());
}
}
}
}
private void checkAbstractOutParamsInitialized(EList<VarParameter> result, MappingRuleCS methodCS, QvtOperationalEnv env) {
for (VarParameter varParameter : result) {
EClassifier type = varParameter.getEType();
if (type instanceof EClass) {
EClass eClass = (EClass) type;
if (!QvtOperationalUtil.isInstantiable(eClass)) {
MappingInitCS init = (methodCS.getMappingBody() == null) ? null : methodCS.getMappingBody().getMappingInitCS();
if (init != null) {
// TODO: The check could be more accurate
return;
}
if((methodCS.getMappingDeclarationCS() != null) && !(methodCS.getMappingDeclarationCS().getQualifiers().contains(QualifierKindCS.ABSTRACT))) {
boolean hasDisjunct = false;
for (MappingExtensionCS extensionCS : methodCS.getMappingDeclarationCS().getMappingExtension()) {
if(extensionCS.getKind() == MappingExtensionKindCS.DISJUNCTS) {
hasDisjunct = true;
break;
}
}
if(!hasDisjunct) {
env.reportError(ValidationMessages.QvtOperationalVisitorCS_AbstractTypesNotInitialized, methodCS);
}
}
}
}
}
}
private boolean validateInitializedValueCS(VariableInitializationCS varInitCS, VariableInitExp result,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
result.setName(varInitCS.getSimpleNameCS().getValue());
EClassifier type;
if (varInitCS.getTypeCS() != null) {
type = visitTypeCS(varInitCS.getTypeCS(), null, env);
if (type == null) {
return false;
}
} else {
type = null;
}
if (varInitCS.getOclExpressionCS() == null) {
if (type == null) {
return false;
} else {
OCLExpression<EClassifier> defaultInitializationValue = createDefaultInitializationValue(type, env);
if (defaultInitializationValue == null) {
NullLiteralExp<EClassifier> nullLiteralExp = oclFactory.createNullLiteralExp();
nullLiteralExp.setType(getOclVoid());
defaultInitializationValue = nullLiteralExp;
}
result.setValue(defaultInitializationValue);
}
} else {
OCLExpression<EClassifier> exp = visitOclExpressionCS(varInitCS.getOclExpressionCS(), env);
if (exp == null) {
return false;
}
result.setValue(exp);
}
result.setType(type);
return true;
}
private OCLExpression<EClassifier> createDefaultInitializationValue(EClassifier type,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
// 8.2.2.10 VariableInitExp
// A variable may not declare an initialization value. In this case a default value is assumed (an empty collection for a collection,
// zero for any numeric type, the empty string for a string and null for all other elements.
// A. Igdalov: Spec says nothing about Booleans and OclInvalid. Abstract collections (Collection, opposed to Bags, OrderedSets, etc.) are also neglected.
// Thus, this implementation assigns false to Booleans, Invalid to OclInvalids and nulls to abstract collections.
if (type instanceof org.eclipse.ocl.ecore.CollectionType) {
org.eclipse.ocl.ecore.CollectionType collectionType = (org.eclipse.ocl.ecore.CollectionType) type;
CollectionKind kind = collectionType.getKind();
if (CollectionKind.COLLECTION_LITERAL == kind) {
return null;
}
CollectionLiteralExp<EClassifier> collectionLiteralExp = oclFactory.createCollectionLiteralExp();
collectionLiteralExp.setKind(kind);
EClassifier resultType = getCollectionType(env, kind, collectionType.getElementType());
collectionLiteralExp.setType(resultType);
return collectionLiteralExp;
} else {
EClassifier resolvedType = env.getTypeResolver().resolve(type);
OCLStandardLibrary<EClassifier> oclStdLib = getStandardLibrary();
if (resolvedType == oclStdLib.getBoolean()) {
BooleanLiteralExp<EClassifier> booleanLiteralExp = oclFactory.createBooleanLiteralExp();
booleanLiteralExp.setBooleanSymbol(Boolean.FALSE);
booleanLiteralExp.setType(oclStdLib.getBoolean());
return booleanLiteralExp;
} else if (resolvedType == oclStdLib.getInteger()) {
IntegerLiteralExp<EClassifier> integerLiteralExp = oclFactory.createIntegerLiteralExp();
integerLiteralExp.setIntegerSymbol(0);
integerLiteralExp.setType(oclStdLib.getInteger());
return integerLiteralExp;
} else if (resolvedType == oclStdLib.getReal()) {
RealLiteralExp<EClassifier> realLiteralExp = oclFactory.createRealLiteralExp();
realLiteralExp.setRealSymbol(0.0);
realLiteralExp.setType(oclStdLib.getReal());
return realLiteralExp;
} else if (resolvedType == oclStdLib.getUnlimitedNatural()) {
UnlimitedNaturalLiteralExp<EClassifier> unlimitedNaturalLiteralExp = oclFactory.createUnlimitedNaturalLiteralExp();
unlimitedNaturalLiteralExp.setIntegerSymbol(0);
unlimitedNaturalLiteralExp.setType(oclStdLib.getUnlimitedNatural());
return unlimitedNaturalLiteralExp;
} else if (resolvedType == oclStdLib.getInvalid()) {
InvalidLiteralExp<EClassifier> invalidLiteralExp = oclFactory.createInvalidLiteralExp();
invalidLiteralExp.setType(oclStdLib.getInvalid());
return invalidLiteralExp;
} else if (resolvedType == oclStdLib.getString()) {
org.eclipse.ocl.expressions.StringLiteralExp<EClassifier> stringLiteralExp = oclFactory.createStringLiteralExp();
stringLiteralExp.setStringSymbol(""); //$NON-NLS-1$
stringLiteralExp.setType(oclStdLib.getString());
return stringLiteralExp;
}
}
return null;
}
private void addLateResolve(ResolveExp resolve) {
assert resolve.isIsDeferred();
if(myLateResolveExps == null) {
myLateResolveExps = new LinkedList<ResolveExp>();
}
myLateResolveExps.add(resolve);
}
private List<ResolveExp> getAllLateResolves() {
return myLateResolveExps != null ? myLateResolveExps : Collections.<ResolveExp>emptyList();
}
private void validate(Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
for (ResolveExp lateResolve : getAllLateResolves()) {
validateResolveExp(lateResolve, env);
}
}
/**
* SimpleNameCS
* @param simpleNameCS the <code>SimpleNameCS</code> <code>CSTNode</code>
* @param fEnv the OCL environment
* @param source the source of the <code>SimpleNameCS</code>
* @return the parsed <code>OCLExpression</code>
*/
private OCLExpression<EClassifier> customSimpleNameCS(
SimpleNameCS simpleNameCS,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env,
OCLExpression<EClassifier> source) {
if ((source != null) && isErrorNode(source)) {
// don't attempt to parse navigation from an unparseable source
return source; // return the same unparseable token
}
String simpleName = null;
EClassifier classifier = null;
/* A name can be a variable defined by a Variable declaration, the special
variable "self", an attribute or a reference to another object.
If the source is not null, then the last token was a "." or "->"
The source is used to establish the navigation.
If no type is provided, then either the name is a the use of a variable,
or there is an implicit variable declaration (self or an iterator)
that is the source.
*/
switch (simpleNameCS.getType().getValue()) {
case SimpleTypeEnum.SELF:
case SimpleTypeEnum.KEYWORD:
case SimpleTypeEnum.IDENTIFIER:
simpleName = simpleNameCS.getValue();
break;
case SimpleTypeEnum.INTEGER:
case SimpleTypeEnum.STRING:
case SimpleTypeEnum.REAL:
case SimpleTypeEnum.BOOLEAN:
case SimpleTypeEnum.OCL_ANY:
case SimpleTypeEnum.OCL_VOID:
case SimpleTypeEnum.INVALID:
case SimpleTypeEnum.OCL_MESSAGE:
// if we have a source, then this is a feature call
if (source == null) {
classifier = primitiveTypeCS(simpleNameCS.getType(), env);
simpleName = uml.getName(classifier);
}
break;
}
/*
* The source may be a collection type (for example, in self.children.name, children
* may be a set.)_ In this case, we have to get the element type of children, so
* that the attribute name can be found.
* The source type can also be a tuple type. In this case, we need to get the
* EClass of the tuple.
*
*/
EClassifier sourceElementType = null;
if (source != null) {
sourceElementType = source.getType();
if (sourceElementType instanceof CollectionType) {
@SuppressWarnings("unchecked")
CollectionType<EClassifier, EOperation> ct = (CollectionType<EClassifier, EOperation>) sourceElementType;
sourceElementType = ct.getElementType();
}
}
// cascaded alternatives for a simpleNameCS
OCLExpression<EClassifier> astNode = simpleTypeName(simpleNameCS, env, source,
classifier, simpleName);
if (astNode == null) {
astNode = simpleVariableName(simpleNameCS, env, source, simpleName);
}
if (astNode == null) {
astNode = simplePropertyName(simpleNameCS, env, source,
sourceElementType, simpleName);
}
if (astNode == null) {
astNode = simpleAssociationClassName(simpleNameCS, env, source,
sourceElementType, simpleName);
}
if (astNode == null) {
astNode = simpleUndefinedName(simpleNameCS, env, source, simpleName);
}
// FIXME - we should ask MDT OCL for a support to handle this in a better way
/*
* If the source type is a collection, then need there is an implicit COLLECT
* or imperative COLLECT operator.
*/
if ((source != null) && (source.getType() instanceof CollectionType)
&& (astNode instanceof FeatureCallExp)) {
CallExpCS callExpCS = (CallExpCS) simpleNameCS.eContainer();
FeatureCallExp<EClassifier> featureCallExp = (FeatureCallExp<EClassifier>) astNode;
astNode = isArrowAccessToCollection(callExpCS, source) ?
createImplicitXCollect(source, featureCallExp, env, simpleNameCS)
: createImplicitCollect(source, featureCallExp, env, simpleNameCS);
}
return astNode;
}
private static void createPropertyCallASTBinding(
CallExpCS propertyCallExpCS,
OCLExpression<EClassifier> result,
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) {
ASTNode boundAST = result;
CSTNode boundCST = propertyCallExpCS;
if(result instanceof IteratorExp) {
IteratorExp<EClassifier, EParameter> itExpAST = (IteratorExp<EClassifier, EParameter>) result;
if(propertyCallExpCS instanceof IteratorExpCS) {
IteratorExpCS itExpCST = (IteratorExpCS) propertyCallExpCS;
if(itExpCST.getBody() != null) {
boundCST = itExpCST.getBody();
}
}
if(itExpAST.getBody() instanceof FeatureCallExp) {
boundAST = (FeatureCallExp<EClassifier>) itExpAST.getBody();
}
} else if(result instanceof ImperativeIterateExp) {
ImperativeIterateExp impIterExpAST = (ImperativeIterateExp) result;
if(propertyCallExpCS instanceof ImperativeIterateExpCS) {
ImperativeIterateExpCS itExpCST = (ImperativeIterateExpCS) propertyCallExpCS;
if(itExpCST.getBody() != null) {
boundCST = itExpCST.getBody();
}
}
if(impIterExpAST.getBody() instanceof FeatureCallExp) {
boundAST = (FeatureCallExp<EClassifier>) impIterExpAST.getBody();
}
}
ASTBindingHelper.createCST2ASTBinding(boundCST, boundAST, env);
}
private static List<ModelParameter> getModelParameter(Module module) {
if(module instanceof OperationalTransformation) {
OperationalTransformation operationalTransformation = (OperationalTransformation) module;
return operationalTransformation.getModelParameter();
}
return Collections.emptyList();
}
private static void addInitVariable(
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter,
EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env,
VariableInitExp varInit) {
if (varInit.getName() != null) {
Variable<EClassifier, EParameter> var = EcoreFactory.eINSTANCE.createVariable();
var.setName(varInit.getName());
var.setType(varInit.getType());
env.addElement(varInit.getName(), var, true);
}
}
private static QvtOperationalModuleEnv getModuleContextEnv(QvtOperationalEnv env) {
Internal<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject>
nextParent = env;
while(nextParent != null) {
if(nextParent instanceof QvtOperationalModuleEnv) {
return (QvtOperationalModuleEnv) nextParent;
}
nextParent = nextParent.getInternalParent();
}
return null;
}
private static String wrappInSeeErrorLogMessage(String message) {
return NLS.bind(ValidationMessages.QvtOperationalVisitorCS_SeeErrorLogForDetails, message);
}
private static QvtOperationalEnv toQVTOperationalEnv(Environment<EPackage, EClassifier,
EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject,
CallOperationAction, SendSignalAction, Constraint, EClass, EObject> env) throws IllegalArgumentException {
QvtOperationalEnv adapter = OCLUtil.getAdapter(env, QvtOperationalEnv.class);
if(adapter == null) {
throw new IllegalArgumentException("QVTOperationalEnv is required"); //$NON-NLS-1$
}
return adapter;
}
}