blob: 4e8b00f729768d5cb3fd4208cb9f3310b830e046 [file] [log] [blame]
/**
* <copyright>
*
* Copyright (c) 2008 E.D.Willink and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* E.D.Willink - initial API and implementation
*
* </copyright>
*
* $Id: RelationOperations.java,v 1.3 2009/03/05 22:04:41 ewillink Exp $
*/
package org.eclipse.qvt.declarative.ecore.QVTRelation.operations;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.DiagnosticChain;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.ocl.ecore.OCLExpression;
import org.eclipse.ocl.ecore.Variable;
import org.eclipse.ocl.ecore.VariableExp;
import org.eclipse.qvt.declarative.ecore.QVTBase.Domain;
import org.eclipse.qvt.declarative.ecore.QVTBase.Pattern;
import org.eclipse.qvt.declarative.ecore.QVTBase.Predicate;
import org.eclipse.qvt.declarative.ecore.QVTBase.Rule;
import org.eclipse.qvt.declarative.ecore.QVTBase.TypedModel;
import org.eclipse.qvt.declarative.ecore.QVTRelation.Relation;
import org.eclipse.qvt.declarative.ecore.QVTRelation.RelationDomain;
import org.eclipse.qvt.declarative.ecore.QVTRelation.RelationImplementation;
import org.eclipse.qvt.declarative.ecore.operations.EPackageOperations;
public class RelationOperations extends AbstractQVTRelationOperations
{
public static RelationOperations INSTANCE = new RelationOperations();
/**
* Validates the EveryDomainIsARelationDomain constraint of '<em>Relation</em>'.
*/
public boolean checkEveryDomainIsARelationDomain(Relation relation, DiagnosticChain diagnostics, Map<Object, Object> context) {
boolean allOk = true;
for (Domain domain : relation.getDomain()) {
if (!(domain instanceof RelationDomain)) {
Object[] messageSubstitutions = new Object[] { getObjectLabel(domain, context) };
appendError(diagnostics, domain, QVTRelationMessages._UI_Relation_DomainIsNotARelationDomain, messageSubstitutions);
allOk = false;
}
}
return allOk;
}
/**
* Validates the AtLeastTwoDomains constraint of '<em>Relation</em>'.
*/
public boolean checkAtLeastTwoDomains(Relation relation, DiagnosticChain diagnostics, Map<Object, Object> context) {
if (relation.getDomain().size() < 2) {
Object[] messageSubstitutions = new Object[] { getObjectLabel(relation, context) };
appendError(diagnostics, relation, QVTRelationMessages._UI_Relation_LessThanTwoDomains, messageSubstitutions);
return false;
}
return true;
}
/**
* Validates the DomainTypedModelsMatchModelParameters constraint of '<em>Rule</em>'.
*/
public boolean checkDomainTypedModelsMatchModelParameters(Rule rule, DiagnosticChain diagnostics, Map<Object, Object> context) {
List<Domain> domains = rule.getDomain();
List<TypedModel> modelParameters = rule.getTransformation().getModelParameter();
int domainCount = domains.size();
int modelParameterCount = modelParameters.size();
if (domainCount < modelParameterCount) {
Object[] messageSubstitutions = new Object[] { domainCount, getObjectLabel(rule, context), modelParameterCount };
appendError(diagnostics, rule, QVTRelationMessages._UI_Relation_DomainTypedModelsDoNotMatchModelParameters, messageSubstitutions);
return false;
}
boolean allOk = true;
for (int i = 0; i < domainCount; i++)
{
Domain domain = domains.get(i);
TypedModel typedModel = domain.getTypedModel();
if (i < modelParameterCount) {
TypedModel modelParameter = modelParameters.get(i);
if (typedModel == null)
continue; // Multiplicity error
if (typedModel != modelParameter) {
if (!modelParameters.contains(typedModel))
continue; // Domain consistency error
Object[] messageSubstitutions = new Object[] { getObjectLabel(domain, context), getObjectLabel(modelParameter, context) };
appendError(diagnostics, rule, QVTRelationMessages._UI_Relation_DomainTypedModelIsNotModelParameter, messageSubstitutions);
allOk = false;
}
} else if (typedModel != null) {
Object[] messageSubstitutions = new Object[] { getObjectLabel(domain, context) };
appendError(diagnostics, rule, QVTRelationMessages._UI_Relation_DomainWithoutModelParameterMustBePrimitive, messageSubstitutions);
allOk = false;
}
}
return allOk;
}
/**
* Validates the NonTopLevelIsNotInvokedWarning constraint of '<em>Relation</em>'.
*/
public boolean checkNonTopLevelIsNotInvokedWarning(Relation relation, DiagnosticChain diagnostics, Map<Object, Object> context) {
// TODO implement the constraint
return true;
}
/**
* Validates the RelationImplsAreUniqueWarning constraint of '<em>Relation</em>'.
*/
public boolean checkRelationImplsAreUniqueWarning(Relation relation, DiagnosticChain diagnostics, Map<Object, Object> context) {
UniquenessChecker<EOperation, RelationImplementation> checker = new UniquenessChecker<EOperation, RelationImplementation>()
{
@Override
protected EOperation getKey(RelationImplementation value) {
return value.getImpl();
}
@Override
protected int getSeverity() {
return Diagnostic.WARNING;
}
};
return checker.check(relation.getOperationalImpl(), QVTRelationMessages._UI_Relation_ImplIsNotUnique, relation, diagnostics, context);
}
protected boolean checkTypesAreDeclaredByRelation(Relation relation, DiagnosticChain diagnostics, Map<Object, Object> context, Pattern pattern, String errorMessage) {
if (pattern == null)
return true;
boolean allOk = true;
for (OCLExpression expression : getPatternExpressions(pattern)) {
for (VariableExp variableReference : getAllVariableReferences(expression)) {
Variable variable = (Variable) variableReference.getReferredVariable();
EClassifier type = getTransitiveElementType(variable.getEType());
if (!declaresType(relation, type)) {
Object[] messageSubstitutions = new Object[] { getObjectLabel(type, context), getObjectLabel(variable, context), getObjectLabel(relation, context) };
appendError(diagnostics, variableReference, errorMessage, messageSubstitutions);
allOk = false;
}
}
for (Variable variable : getAllVariables(expression)) {
EClassifier type = getTransitiveElementType(variable.getEType());
if (!declaresType(relation, type)) {
Object[] messageSubstitutions = new Object[] { getObjectLabel(type, context), getObjectLabel(variable, context), getObjectLabel(relation, context) };
appendError(diagnostics, variable, errorMessage, messageSubstitutions);
allOk = false;
}
}
}
return allOk;
}
protected boolean checkVariablesAreDefinedByRelation(Relation relation,
DiagnosticChain diagnostics, Map<Object, Object> context, Pattern pattern, String errorMessage) {
if (pattern == null)
return true;
boolean allOk = true;
for (OCLExpression expression : getPatternExpressions(pattern)) {
for (VariableExp variableReference : getAllVariableReferences(expression)) {
Variable variable = (Variable) variableReference.getReferredVariable();
if (!definesVariable(relation, variable) && !locallyDefined(variableReference)) {
Object[] messageSubstitutions = new Object[] { getObjectLabel(variable, context), getObjectLabel(relation, context) };
appendError(diagnostics, variableReference, errorMessage, messageSubstitutions);
allOk = false;
}
}
}
return allOk;
}
/**
* Validates the VariablesAreUnique constraint of '<em>Relation</em>'.
*/
public boolean checkVariablesAreUnique(Relation relation, DiagnosticChain diagnostics, Map<Object, Object> context) {
return checkUniqueNames(relation, relation.getVariable(), QVTRelationMessages._UI_Relation_VariableNameIsNotUnique, diagnostics, context);
}
/**
* Validates the WhenTypesAreDeclaredByRelation constraint of '<em>Relation</em>'.
*/
public boolean checkWhenTypesAreDeclaredByRelation(Relation relation, DiagnosticChain diagnostics, Map<Object, Object> context) {
Pattern pattern = relation.getWhen();
String errorMessage = QVTRelationMessages._UI_Relation_WhenTypeIsNotDeclaredByRelation;
return checkTypesAreDeclaredByRelation(relation, diagnostics, context, pattern, errorMessage);
}
/**
* Validates the WhenVariablesAreDefinedByRelation constraint of '<em>Relation</em>'.
*/
public boolean checkWhenVariablesAreDefinedByRelation(Relation relation, DiagnosticChain diagnostics, Map<Object, Object> context) {
Pattern pattern = relation.getWhen();
String errorMessage = QVTRelationMessages._UI_Relation_WhenVariableIsNotDefinedByRelation;
return checkVariablesAreDefinedByRelation(relation, diagnostics, context, pattern, errorMessage);
}
/**
* Validates the WhereTypesAreDeclaredByRelation constraint of '<em>Relation</em>'.
*/
public boolean checkWhereTypesAreDeclaredByRelation(Relation relation, DiagnosticChain diagnostics, Map<Object, Object> context) {
String errorMessage = QVTRelationMessages._UI_Relation_WhereTypeIsNotDeclaredByRelation;
Pattern pattern = relation.getWhere();
return checkTypesAreDeclaredByRelation(relation, diagnostics, context, pattern, errorMessage);
}
/**
* Validates the WhereVariablesAreDefinedByRelation constraint of '<em>Relation</em>'.
*/
public boolean checkWhereVariablesAreDefinedByRelation(Relation relation, DiagnosticChain diagnostics, Map<Object, Object> context) {
String errorMessage = QVTRelationMessages._UI_Relation_WhereVariableIsNotDefinedByRelation;
Pattern pattern = relation.getWhere();
return checkVariablesAreDefinedByRelation(relation, diagnostics, context, pattern, errorMessage);
}
public boolean declaresType(Relation relation, EClassifier type) {
return isPredefinedType(type) || getDeclaredPackages(relation).contains(type.getEPackage());
}
public boolean definesVariable(Relation relation, Variable variable) {
return relation.getVariable().contains(variable);
}
public Set<Variable> getAllLocalVariables1(Collection<OCLExpression> expressions) {
Set<Variable> variables = new HashSet<Variable>();
for (OCLExpression expression : expressions) {
for (TreeIterator<EObject> i = expression.eAllContents(); i.hasNext(); ) {
EObject eObject = i.next();
if (eObject instanceof Variable)
variables.add((Variable) eObject);
}
}
return variables;
}
public Set<EPackage> getDeclaredPackages(Relation relation) {
Set<EPackage> declaredPackages = new HashSet<EPackage>();
for (Domain domain : relation.getDomain()) {
TypedModel typedModel = domain.getTypedModel();
if (typedModel != null) {
for (EPackage usedPackage : typedModel.getUsedPackage()) {
Set<EPackage> allUsedPackages = EPackageOperations.INSTANCE.getAllEPackages(usedPackage);
declaredPackages.addAll(allUsedPackages);
}
}
}
return declaredPackages;
}
public Collection<OCLExpression> getPatternExpressions(Pattern pattern) {
List<OCLExpression> expressions = new ArrayList<OCLExpression>();
for (Predicate predicate : pattern.getPredicate()) {
OCLExpression conditionExpression = predicate.getConditionExpression();
if (conditionExpression != null)
expressions.add(conditionExpression);
}
return expressions;
}
}