blob: be5453e35982061162e1ec0390f894258a688f73 [file] [log] [blame]
/*
-----------------------------------------------------------------------
-- CHESS Live/Batch Validator plugin --
-- --
-- Copyright (C) 2011-2012 --
-- University of Padova, ITALY --
-- --
-- Author: Stefano Puri --
-- --
-- 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 --
-----------------------------------------------------------------------
*/
package org.polarsys.chess.validator.constraints;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.uml2.uml.Component;
import org.eclipse.uml2.uml.Interface;
import org.eclipse.uml2.uml.InterfaceRealization;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.Parameter;
import org.eclipse.uml2.uml.ParameterDirectionKind;
import org.eclipse.uml2.uml.Realization;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.emf.validation.AbstractModelConstraint;
import org.eclipse.emf.validation.IValidationContext;
import org.polarsys.chess.chessmlprofile.util.Constants;
/**
* The Class FV_04.
* This class implements the following constraint (invoked by the EMF validation framework):
* The ComponentType must define the same operations as the Interface it realizes
*/
public class FV_04 extends AbstractModelConstraint {
/* (non-Javadoc)
* @see org.eclipse.emf.validation.AbstractModelConstraint#validate(org.eclipse.emf.validation.IValidationContext)
*/
@Override
public IStatus validate(IValidationContext ctx) {
EObject eObject = ctx.getTarget();
Component component = (Component)eObject;
IStatus success = ctx.createSuccessStatus();
Stereotype componentTypeStereo = component.getAppliedStereotype(Constants.COMPONENT_TYPE);
if (componentTypeStereo!=null) {
// This component is a ComponentType
// If it realizes an interface, then it has to define at least the same operations
for (Realization realization : component.getRealizations()) {
if (realization instanceof InterfaceRealization) {
// Skip realizations that are not InterfaceRealization
Boolean isClient = false;
for (NamedElement elem : realization.getClients()) {
if (elem.equals(component)) {
isClient = true;
}
}
if (isClient) {
// Check that the component defines the same operations as the Interface
for (NamedElement elem : realization.getSuppliers()) {
if (elem instanceof Interface) {
Interface rInt = (Interface) elem;
for (Operation op : rInt.getOwnedOperations()) {
// For each operation, the component type must define the same
Boolean opFound = false;
for (Operation compOp : component.getOwnedOperations()) {
// Compare operations
if (compareOperations(compOp, op)) {
opFound=true;
break;
}
}
if (!opFound) {
// Then it is an error
String errorMsg = "The <<ComponentType>> " + component.getName() + " does not define operation " + op.getName() + " from the interface " + rInt.getName() + " it realizes";
IStatus failure = ctx.createFailureStatus(
component,
errorMsg
);
return failure;
}
}
}
}
}
}
}
}
return success;
}
/**
* Compare operations.
*
* @param op1 the op1
* @param op2 the op2
* @return the boolean
*/
private Boolean compareOperations(Operation op1, Operation op2) {
Boolean result = true;
// Compare names
if (!op1.getName().equals(op2.getName())) {
result=false;
}
else {
// Compare return types
if (op1.getType() != op2.getType()) {
result=false;
}
else {
// Compare the number of parameters
Collection<Parameter> params1 = removeReturnParameter(op1.getOwnedParameters());
Collection<Parameter> params2 = removeReturnParameter(op2.getOwnedParameters());
if (params1.size() != params2.size() ) {
result=false;
}
else {
Iterator<Parameter> it1 = params1.iterator();
Iterator<Parameter> it2 = params2.iterator();
while (it1.hasNext()) {
Parameter p1 = it1.next();
Parameter p2 = it2.next();
if (p1.getType()!=p2.getType()) {
result=false;
break;
}
}
}
}
}
return result;
}
/**
* Removes the return parameter.
*
* @param ownedParameters the owned parameters
* @return the collection
*/
private Collection<Parameter> removeReturnParameter(
EList<Parameter> ownedParameters) {
Collection<Parameter> result = new ArrayList<Parameter>();
for (Parameter p : ownedParameters) {
if (!p.getDirection().equals(ParameterDirectionKind.get(ParameterDirectionKind.RETURN))) {
result.add(p);
}
}
return result;
}
}