/***************************************************************************** * Copyright (c) 2010 CEA LIST. * * * 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: * CEA LIST - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.uml.textedit.property.xtext.validation; import org.eclipse.emf.ecore.EObject; import org.eclipse.papyrus.uml.textedit.property.xtext.umlProperty.MultiplicityRule; import org.eclipse.papyrus.uml.textedit.property.xtext.umlProperty.PropertyRule; import org.eclipse.papyrus.uml.textedit.property.xtext.umlProperty.RedefinesRule; import org.eclipse.papyrus.uml.textedit.property.xtext.umlProperty.SubsetsRule; import org.eclipse.papyrus.uml.textedit.property.xtext.umlProperty.UmlPropertyPackage; import org.eclipse.papyrus.uml.textedit.property.xtext.validation.AbstractUmlPropertyJavaValidator; import org.eclipse.uml2.uml.Classifier; import org.eclipse.uml2.uml.Element; import org.eclipse.uml2.uml.Namespace; import org.eclipse.uml2.uml.Package; import org.eclipse.uml2.uml.Property; import org.eclipse.xtext.validation.Check; /** * Class for customized java validation * */ public class UmlPropertyJavaValidator extends AbstractUmlPropertyJavaValidator { private static Namespace model ; private static Element contextElement ; // private variables for semantic error management (See IXtextSemanticValidator from org.eclipse.xtext.gmf.glue) private static boolean valid_MultiplicityRule = true ; private static boolean valid_RedefinesRule = true ; private static boolean valid_SubsetsRule = true ; public static void init(Element _contextElement) { contextElement = _contextElement ; if (contextElement != null) { Element elem = contextElement.getOwner() ; while (elem.getOwner() != null) { elem = elem.getOwner() ; } model = (Namespace)elem ; } } public static Namespace getModel() { return model ; } public static Element getContextElement() { return contextElement ; } public static boolean validate() { return valid_MultiplicityRule && valid_RedefinesRule && valid_SubsetsRule ; } /** * Custom validation for multiplicities. Raises an error in the case where the lower bound is upper than the upper bound. * */ @Check public void checkMultiplicityRule (MultiplicityRule rule) { int lowerValue = 0 ; int upperValue = 0 ; String errorMessage = "The upper bound of a multiplicity cannot be lower than the lower bound." ; try { if (rule.getBounds().size() == 2) { lowerValue = rule.getBounds().get(0).getValue().equals("*") ? -1 : Integer.valueOf(rule.getBounds().get(0).getValue()) ; upperValue = rule.getBounds().get(1).getValue().equals("*") ? -1 : Integer.valueOf(rule.getBounds().get(1).getValue()) ; if ((lowerValue == -1 && upperValue != -1) || (lowerValue > upperValue && upperValue != -1)) { error(errorMessage, UmlPropertyPackage.eINSTANCE.getBoundSpecification_Value()) ; //error(errorMessage, rule, UmlPropertyPackage.BOUND_SPECIFICATION__VALUE) ; valid_MultiplicityRule = false ; } else { valid_MultiplicityRule = true ; } } } catch (Exception e) { // An exception may be raised only in the case where the syntax for multiplicities is not respected. // No error needs to be generated (the syntax error is automatically handled by XText) } } @Check public void checkRedefinesRule (RedefinesRule rule) { try { Property redefinedProperty = rule.getProperty() ; String typeErrorMessage = "The type of the redefining property must conform to the type of the redefined property" ; String multiplicityErrorMessage = "The multiplicity of the redefining property must be contained in the multiplicity of the redefined property" ; String isDerivedErrorMessage = "Since the redefined property is derived, the redefining property must be derived" ; EObject container = rule.eContainer() ; while (container != null && !(container instanceof PropertyRule)) { container = container.eContainer() ; } if (container == null) return ; PropertyRule propertyRule = (PropertyRule)container ; Classifier typeOfRedefiningProperty = propertyRule.getType().getType() ; boolean isRedefiningPropertyDerived = propertyRule.getIsDerived() != null && propertyRule.getIsDerived().equals("/") ; valid_RedefinesRule = typeOfRedefiningProperty.conformsTo(redefinedProperty.getType()) ; if (! valid_RedefinesRule) { error(typeErrorMessage, UmlPropertyPackage.eINSTANCE.getRedefinesRule_Property()) ; //error(typeErrorMessage, rule, UmlPropertyPackage.REDEFINES_RULE__PROPERTY) ; return ; } int lowerBoundOfRedefinedProperty = redefinedProperty.getLower() ; int upperBoundOfRedefinedProperty = redefinedProperty.getUpper() ; int lowerBound = 1 ; int upperBound = 1 ; if (propertyRule.getMultiplicity() != null) { if (propertyRule.getMultiplicity().getBounds().size() == 1) { lowerBound = propertyRule.getMultiplicity().getBounds().get(0).getValue().equals("*") ? -1 : Integer.valueOf(propertyRule.getMultiplicity().getBounds().get(0).getValue()) ; upperBound = lowerBound ; } else if (propertyRule.getMultiplicity().getBounds().size() == 2) { lowerBound = propertyRule.getMultiplicity().getBounds().get(0).getValue().equals("*") ? -1 : Integer.valueOf(propertyRule.getMultiplicity().getBounds().get(0).getValue()) ; upperBound = propertyRule.getMultiplicity().getBounds().get(1).getValue().equals("*") ? -1 : Integer.valueOf(propertyRule.getMultiplicity().getBounds().get(1).getValue()) ; } } valid_RedefinesRule = lowerBound >= lowerBoundOfRedefinedProperty ; switch (upperBoundOfRedefinedProperty) { case -1: break ; default: valid_RedefinesRule = valid_RedefinesRule && upperBound <= upperBoundOfRedefinedProperty; break; } if (! valid_RedefinesRule) { error(multiplicityErrorMessage, UmlPropertyPackage.eINSTANCE.getRedefinesRule_Property()) ; //error(multiplicityErrorMessage, rule, UmlPropertyPackage.REDEFINES_RULE__PROPERTY) ; return ; } if (redefinedProperty.isDerived() && !isRedefiningPropertyDerived) valid_RedefinesRule = false ; if (! valid_RedefinesRule) { error(multiplicityErrorMessage, UmlPropertyPackage.eINSTANCE.getRedefinesRule_Property()) ; //error(isDerivedErrorMessage, rule, UmlPropertyPackage.REDEFINES_RULE__PROPERTY) ; return ; } } catch (Exception e) { // An exception may be raised only in the case where the syntax for subsets is not respected. // No error needs to be generated (the syntax error is automatically handled by XText) } } @Check public void checkSubsetsRule (SubsetsRule rule) { try { Property subsettedProperty = rule.getProperty() ; String typeErrorMessage = "The type of the subsetting property must conform to the type of the subsetted property" ; String multiplicityErrorMessage = "The multiplicity of the subsetting property must be contained in the multiplicity of the subsetted property" ; EObject container = rule.eContainer() ; while (container != null && !(container instanceof PropertyRule)) { container = container.eContainer() ; } if (container == null) return ; PropertyRule propertyRule = (PropertyRule)container ; Classifier typeOfSubsettingProperty = propertyRule.getType().getType() ; valid_SubsetsRule = typeOfSubsettingProperty.conformsTo(subsettedProperty.getType()) ; if (! valid_SubsetsRule) { error(multiplicityErrorMessage, UmlPropertyPackage.eINSTANCE.getSubsetsRule_Property()) ; //error(typeErrorMessage, rule, UmlPropertyPackage.SUBSETS_RULE__PROPERTY) ; return ; } int lowerBoundOfRedefinedProperty = subsettedProperty.getLower() ; int upperBoundOfRedefinedProperty = subsettedProperty.getUpper() ; int lowerBound = 1 ; int upperBound = 1 ; if (propertyRule.getMultiplicity() != null) { if (propertyRule.getMultiplicity().getBounds().size() == 1) { lowerBound = propertyRule.getMultiplicity().getBounds().get(0).getValue().equals("*") ? -1 : Integer.valueOf(propertyRule.getMultiplicity().getBounds().get(0).getValue()) ; upperBound = lowerBound ; } else if (propertyRule.getMultiplicity().getBounds().size() == 2) { lowerBound = propertyRule.getMultiplicity().getBounds().get(0).getValue().equals("*") ? -1 : Integer.valueOf(propertyRule.getMultiplicity().getBounds().get(0).getValue()) ; upperBound = propertyRule.getMultiplicity().getBounds().get(1).getValue().equals("*") ? -1 : Integer.valueOf(propertyRule.getMultiplicity().getBounds().get(1).getValue()) ; } } valid_SubsetsRule = lowerBound >= lowerBoundOfRedefinedProperty ; switch (upperBoundOfRedefinedProperty) { case -1: break ; default: valid_SubsetsRule = valid_SubsetsRule && upperBound <= upperBoundOfRedefinedProperty; break; } if (! valid_SubsetsRule) { error(multiplicityErrorMessage, UmlPropertyPackage.eINSTANCE.getSubsetsRule_Property()) ; //error(multiplicityErrorMessage, rule, UmlPropertyPackage.SUBSETS_RULE__PROPERTY) ; return ; } } catch (Exception e) { // An exception may be raised only in the case where the syntax for subsets is not respected. // No error needs to be generated (the syntax error is automatically handled by XText) } } }