blob: acaeac8d2e5d45d39bc2bb037cc8086fa2c44e16 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2018 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Axel Uhl - Initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.ecore.parser;
import java.util.Iterator;
import java.util.List;
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.EStructuralFeature;
import org.eclipse.ocl.Environment;
import org.eclipse.ocl.ecore.CallOperationAction;
import org.eclipse.ocl.ecore.Constraint;
import org.eclipse.ocl.ecore.OppositePropertyCallExp;
import org.eclipse.ocl.ecore.SendSignalAction;
import org.eclipse.ocl.ecore.utilities.VisitorExtension;
import org.eclipse.ocl.expressions.OCLExpression;
import org.eclipse.ocl.internal.l10n.OCLMessages;
import org.eclipse.ocl.types.CollectionType;
import org.eclipse.ocl.util.TypeUtil;
import org.eclipse.ocl.utilities.UMLReflection;
/**
* @since 3.1
*/
public class ValidationVisitor
extends
org.eclipse.ocl.parser.ValidationVisitor<
EPackage, EClassifier, EOperation, EStructuralFeature,
EEnumLiteral, EParameter, EObject,
CallOperationAction, SendSignalAction, Constraint,
EClass, EObject>
implements VisitorExtension<Boolean> {
public ValidationVisitor(
Environment<EPackage, EClassifier, EOperation, EStructuralFeature, EEnumLiteral, EParameter, EObject, CallOperationAction, SendSignalAction, Constraint, EClass, EObject> environment) {
super(environment);
}
/**
* Callback for an PropertyCallExp visit. Well-formedness rule: The
* type of the PropertyCallExp is the type of the referred
* EStructuralFeature.
*
* @param pc the property call expression
* @return Boolean -- true if validated
* @since 3.1
*/
public Boolean visitOppositePropertyCallExp(OppositePropertyCallExp pc) {
EStructuralFeature property = pc.getReferredOppositeProperty();
OCLExpression<EClassifier> source = pc.getSource();
EClassifier type = pc.getType();
if (property == null) {
String message = OCLMessages.bind(
OCLMessages.NullProperty_ERROR_,
pc.toString());
return validatorError(pc, message, "visitOppositePropertyCallExp");//$NON-NLS-1$
}
if (source == null) {
String message = OCLMessages.bind(
OCLMessages.NullNavigationSource_ERROR_,
pc.toString());
return validatorError(pc, message, "visitOppositePropertyCallExp");//$NON-NLS-1$
}
if (type == null) {
String message = OCLMessages.bind(
OCLMessages.NullNavigationType_ERROR_,
pc.toString());
return validatorError(pc, message, "visitOppositePropertyCallExp");//$NON-NLS-1$
}
List<OCLExpression<EClassifier>> qualifiers = pc.getQualifier();
if (!qualifiers.isEmpty()) {
// navigation qualifiers must conform to expected qualifier types
List<EStructuralFeature> expectedQualifierTypes = uml.getQualifiers(property);
if (expectedQualifierTypes.size() != qualifiers.size()) {
String message = OCLMessages.bind(
OCLMessages.MismatchedQualifiers_ERROR_,
pc.toString());
return validatorError(pc, message, "visitOppositePropertyCallExp");//$NON-NLS-1$
} else {
Iterator<EStructuralFeature> eiter = expectedQualifierTypes.iterator();
Iterator<OCLExpression<EClassifier>> qiter = qualifiers.iterator();
while (eiter.hasNext()) {
EClassifier expectedType = getOCLType(eiter.next());
OCLExpression<EClassifier> qualifier = qiter.next();
EClassifier qualifierType = qualifier.getType();
if ((TypeUtil.getRelationship(env, qualifierType, expectedType)
& UMLReflection.SUBTYPE) == 0) {
String message = OCLMessages.bind(
OCLMessages.MismatchedQualifiers_ERROR_,
pc.toString());
return validatorError(pc, message, "visitPropertyCallExp");//$NON-NLS-1$
}
}
}
}
if (visitFeatureCallExp(pc)) {
return Boolean.TRUE;
}
source.accept(this);
EClassifier refType = TypeUtil.getPropertyType(env, source.getType(), property);
if (!pc.getQualifier().isEmpty() && (refType instanceof CollectionType<?, ?>)) {
// qualifying the navigation results in a non-collection
// type
@SuppressWarnings("unchecked")
CollectionType<EClassifier, EOperation> ct = (CollectionType<EClassifier, EOperation>) refType;
refType = ct.getElementType();
}
return Boolean.valueOf(TypeUtil.exactTypeMatch(env, refType, type));
}
}