package gov.nasa.jpl.mbee.mdk.docgen.validation; import com.nomagic.magicdraw.annotation.Annotation; import com.nomagic.magicdraw.core.Project; import com.nomagic.magicdraw.uml.BaseElement; import com.nomagic.magicdraw.validation.ElementValidationRuleImpl; import com.nomagic.magicdraw.validation.SmartListenerConfigurationProvider; import com.nomagic.uml2.ext.jmi.helpers.StereotypesHelper; import com.nomagic.uml2.ext.jmi.smartlistener.SmartListenerConfig; import com.nomagic.uml2.ext.magicdraw.classes.mdinterfaces.Interface; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.*; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Package; import gov.nasa.jpl.mbee.mdk.constraint.BasicConstraint; import gov.nasa.jpl.mbee.mdk.constraint.BasicConstraint.Type; import gov.nasa.jpl.mbee.mdk.docgen.DocGenProfile; import gov.nasa.jpl.mbee.mdk.generator.DocumentValidator; import gov.nasa.jpl.mbee.mdk.util.CompareUtils; import gov.nasa.jpl.mbee.mdk.util.Debug; import gov.nasa.jpl.mbee.mdk.util.Utils; import gov.nasa.jpl.mbee.mdk.util.Utils2; import gov.nasa.jpl.mbee.mdk.ocl.OclEvaluator; import gov.nasa.jpl.mbee.mdk.validation.ValidationRule; import gov.nasa.jpl.mbee.mdk.validation.ValidationRuleViolation; import gov.nasa.jpl.mbee.mdk.validation.ViolationSeverity; import java.lang.Class; import java.util.*; /** * A constraint in some context of the model, whose violation will be posted in * the MD validation results window. */ public class ConstraintValidationRule extends ValidationRule implements ElementValidationRuleImpl, SmartListenerConfigurationProvider { protected Element constraintElement = null; // protected List<Element> context = new ArrayList<Element>(); protected Element context = null; protected Constraint constraint = null; protected Set<BaseElement> elementsWithConstraints = new LinkedHashSet<BaseElement>(); protected Map<BaseElement, Set<gov.nasa.jpl.mbee.mdk.constraint.Constraint>> elementToConstraintMap = new TreeMap<BaseElement, Set<gov.nasa.jpl.mbee.mdk.constraint.Constraint>>( CompareUtils.GenericComparator .instance()); protected Map<gov.nasa.jpl.mbee.mdk.constraint.Constraint, Set<BaseElement>> constraintToElementMap = new TreeMap<gov.nasa.jpl.mbee.mdk.constraint.Constraint, Set<BaseElement>>( CompareUtils.GenericComparator .instance()); protected Map<BaseElement, Set<ValidationRuleViolation>> constraintElementToViolationMap = new TreeMap<BaseElement, Set<ValidationRuleViolation>>( CompareUtils.GenericComparator .instance()); protected Set<Annotation> annotations = null; public BasicConstraint.Type constraintType = Type.ANY; public boolean loggingResults = true; public ConstraintValidationRule() { super("Constraint", "Model constraint violation", ViolationSeverity.WARNING); Debug.outln("ConstraintValidationRule()"); } // public ConstraintValidationRule( Element constraintElement, Element // context, Constraint constraint ) { // this.constraintElement = constraintElement; // this.context = context; // this.constraint = constraint; // } // // public ConstraintValidationRule( Element constraint, // Collection<Element> context ) { // // this.constraint = constraint; // // this.context.addAll( context ); // // } @Override public ValidationRuleViolation addViolation(ValidationRuleViolation v) { if (v == null) { return null; } Utils2.addToSet(constraintElementToViolationMap, v.getElement(), v); return super.addViolation(v); } @Override public ValidationRuleViolation addViolation(Element e, String comment) { ValidationRuleViolation v = super.addViolation(e, comment); Utils2.addToSet(constraintElementToViolationMap, v.getElement(), v); return v; } @Override public ValidationRuleViolation addViolation(Element e, String comment, boolean reported) { ValidationRuleViolation v = super.addViolation(e, comment, reported); Utils2.addToSet(constraintElementToViolationMap, v.getElement(), v); return v; } public Set<ValidationRuleViolation> getViolations(Element constraintElement) { return constraintElementToViolationMap.get(constraintElement); } /* * (non-Javadoc) * * @see * com.nomagic.magicdraw.validation.ElementValidationRuleImpl#init(com.nomagic * .magicdraw.core.Project, * com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Constraint) */ @Override public void init(Project paramProject, Constraint paramConstraint) { Debug.outln("init(Project=" + paramProject + ", Constraint=" + paramConstraint + ")"); if (constraintElement == null) { constraintElement = paramConstraint; } } protected void initConstraintMaps(Project paramProject, Collection<? extends Element> paramCollection) { elementToConstraintMap.clear(); constraintToElementMap.clear(); elementsWithConstraints.clear(); constraintElementToViolationMap.clear(); if (Utils2.isNullOrEmpty(paramCollection)) { paramCollection = Utils2.newList(Utils.getRootElement(paramProject)); } // // collect all constraints and the objects they constrain // Collection< String > ids = paramProject.getAllIDS(); // // for ( String id : ids ) { // BaseElement elem = Converters.getIdToElementConverter() // .apply(id, paramProject); for (Element elemt : paramCollection) { if (elemt == null) { continue; } // Get all constraints on this element since it was specifically // selected. List<gov.nasa.jpl.mbee.mdk.constraint.Constraint> constraints = BasicConstraint.getConstraints(elemt, constraintType); if (!Utils2.isNullOrEmpty(constraints)) { elementsWithConstraints.add(elemt); } Utils2.addAllToSet(elementToConstraintMap, elemt, constraints); for (gov.nasa.jpl.mbee.mdk.constraint.Constraint constr : constraints) { Utils2.addToSet(constraintToElementMap, constr, elemt); } // Now look to see if it or its children are constraints List<Element> subElems = Utils2.newList(elemt); if (elemt instanceof Package) { subElems.addAll(Utils.collectOwnedElements(elemt, 0)); } for (Element elem : subElems) { // Make a Constraint if elem is a constraint element and add it // with its constrained elements. if (BasicConstraint.constraintIsType(elem, constraintType)) { // elementIsConstraint( // elem // ) // ) // { List<Object> constrained = BasicConstraint .getConstrainedObjectsFromConstraintElement(elem); gov.nasa.jpl.mbee.mdk.constraint.Constraint constr = new BasicConstraint(elem, constrained); for (Object o : constrained) { if (o instanceof BaseElement) { BaseElement baseElem = (BaseElement) o; elementsWithConstraints.add(baseElem); Utils2.addToSet(constraintToElementMap, constr, baseElem); Utils2.addToSet(elementToConstraintMap, baseElem, constr); } } } } } } public Collection<gov.nasa.jpl.mbee.mdk.constraint.Constraint> getAffectedConstraints( Collection<BaseElement> elements) { Set<gov.nasa.jpl.mbee.mdk.constraint.Constraint> constraints = new TreeSet<gov.nasa.jpl.mbee.mdk.constraint.Constraint>( CompareUtils.GenericComparator.instance()); for (BaseElement elem : elements) { constraints.addAll(elementToConstraintMap.get(elem)); } return constraints; } public static Element getConstraintObject(gov.nasa.jpl.mbee.mdk.constraint.Constraint constraint) { if (constraint == null || Utils2.isNullOrEmpty(constraint.getConstrainingElements())) { return null; } return constraint.getConstrainingElements().iterator().next(); } public static boolean isUml(gov.nasa.jpl.mbee.mdk.constraint.Constraint constraint) { Element constrObj = getConstraintObject(constraint); return (constrObj != null && constrObj instanceof Constraint); } public static boolean isDocGenConstraint(gov.nasa.jpl.mbee.mdk.constraint.Constraint constraint) { Element constrObj = getConstraintObject(constraint); return (constrObj != null && StereotypesHelper.hasStereotypeOrDerived(constrObj, DocGenProfile.constraintStereotype)); } private static boolean isLanguageOcl(gov.nasa.jpl.mbee.mdk.constraint.Constraint constraint) { if (isDocGenConstraint(constraint)) { return true; } if (!isUml(constraint)) { return false; // complain?? } ValueSpecification spec = ((Constraint) getConstraintObject(constraint)).getSpecification(); if (!(spec instanceof OpaqueExpression)) { return false; } OpaqueExpression expr = (OpaqueExpression) spec; List<String> languages = expr.getLanguage(); for (String lang : languages) { if (lang.trim().equalsIgnoreCase("ocl")) { return true; } } return false; } /* * (non-Javadoc) * * @see * com.nomagic.magicdraw.validation.ElementValidationRuleImpl#run(com.nomagic * .magicdraw.core.Project, * com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Constraint, * java.util.Collection) */ @Override public Set<Annotation> run(Project paramProject, Constraint paramConstraint, Collection<? extends Element> paramCollection) { Set<Annotation> result = new HashSet<Annotation>(); System.out.println("*** Starting MDK Validate Constraints: " + constraintType + " ***"); // boolean wasOn = Debug.isOn(); // Debug.turnOn(); // Debug.outln( "run(Project, " + paramConstraint + " , " // + paramCollection + ")" ); initConstraintMaps(paramProject, paramCollection); // Set< BaseElement > elements = elementToConstraintMap.keySet(); @SuppressWarnings("unchecked") Collection<gov.nasa.jpl.mbee.mdk.constraint.Constraint> constraints = (Collection<gov.nasa.jpl.mbee.mdk.constraint.Constraint>) (Utils2 .isNullOrEmpty(elementsWithConstraints) ? (constraintToElementMap == null ? Utils2.newList() : constraintToElementMap.keySet()) : getAffectedConstraints(elementsWithConstraints)); for (gov.nasa.jpl.mbee.mdk.constraint.Constraint constraint : constraints) { try { Boolean satisfied = DocumentValidator.evaluateConstraint(constraint, this, isLanguageOcl(constraint)); if (loggingResults) { logResults(satisfied, constraint); } // Boolean satisfied = constraint.evaluate(); // if ( satisfied != null && satisfied.equals( Boolean.FALSE ) ) // { // //List<NMAction> actionList = new ArrayList<NMAction>(); // //actionList.add(styleAdd); // Annotation annotation = // new Annotation( constraint.getViolatedConstraintElement(), // paramConstraint ); // result.add(annotation); // } } catch (Throwable e) { Debug.error(true, false, "ConstraintValidationRule: " + e.getLocalizedMessage()); e.printStackTrace(); } } Constraint cons = Utils.getWarningConstraint(paramProject); result = Utils.getAnnotations(this, paramProject, cons); annotations = result; System.out.println("*** Finished MDK Validate Constraints: " + constraintType + " ***"); // if ( !wasOn ) Debug.turnOff(); return result; } public static void logResults(Boolean satisfied, gov.nasa.jpl.mbee.mdk.constraint.Constraint constraint) { if (satisfied == null) { String errorMsg = ""; OclEvaluator e = OclEvaluator.instance; if (e != null) { errorMsg = e.errorMessage; } System.out.println(" Not OCL parsable: " + constraint + "; " + errorMsg); } else if (satisfied) { System.out.println(" Passed: " + constraint); } else { System.out.println(" Failed: " + constraint); } } /* * (non-Javadoc) * * @see com.nomagic.magicdraw.validation.ElementValidationRuleImpl#dispose() */ @Override public void dispose() { } @Override public Map<Class<? extends Element>, Collection<SmartListenerConfig>> getListenerConfigurations() { Map<Class<? extends Element>, Collection<SmartListenerConfig>> configMap = new HashMap<Class<? extends Element>, Collection<SmartListenerConfig>>(); SmartListenerConfig config = new SmartListenerConfig(); // SmartListenerConfig nested = // config.listenToNested(PropertyNames.ELEMENT); SmartListenerConfig nested = config.listenToNested("ownedOperation"); nested.listenTo("name"); nested.listenTo("ownedParameter"); Collection<SmartListenerConfig> configs = Collections.singletonList(config); configMap.put(Element.class, configs); configMap.put(Interface.class, configs); return configMap; } }