package com.sap.ide.refactoring.core.constraints; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; import org.eclipse.core.runtime.IProgressMonitor; import org.omg.ocl.attaching.__impl.OclConstraintImpl; import org.omg.ocl.attaching.__impl.OclConstraintWrapper; import org.omg.ocl.expressions.OclExpression; import com.sap.ide.refactoring.Activator; import com.sap.tc.moin.ocl.evaluator.EvaluatorException; import com.sap.tc.moin.ocl.evaluator.ExpressionUndefinedException; import com.sap.tc.moin.ocl.evaluator.OclConstraintEvaluator; import com.sap.tc.moin.repository.Connection; import com.sap.tc.moin.repository.MRI; import com.sap.tc.moin.repository.core.ConnectionWrapper; import com.sap.tc.moin.repository.core.CoreConnection; import com.sap.tc.moin.repository.core.OclMetaModelConstraintRegistrationWrapper; import com.sap.tc.moin.repository.core.ocl.service.impl.MetaModelConstraintInfoImpl; import com.sap.tc.moin.repository.events.filter.EventFilter; import com.sap.tc.moin.repository.mmi.reflect.RefObject; import com.sap.tc.moin.repository.ocl.OclRegistryService; import com.sap.tc.moin.repository.ocl.metamodel.OclMetaModelConstraintRegistration; import com.sap.tc.moin.repository.ocl.notification.OclConstraintManagerException; /** * A central manager for the registration, deregistration and evaluation of OCL * metamodel constraints. * * @author Stephan Erb (d049157) * */ public class MetaModelConstraintRegistry { private final Connection connection; private final HashMap<OclMetaModelConstraintRegistration, IAConstrantInvalidationListener> listenerPerRegistration = new HashMap<OclMetaModelConstraintRegistration, IAConstrantInvalidationListener>(); public MetaModelConstraintRegistry(Connection connection) { this.connection = connection; } public void registerAllMetaModelConstraintsForIncrementalEvaluation(IProgressMonitor pm) { OclRegistryService registry = connection.getOclRegistryService(); try { pm.beginTask("Preparing OCL MetaModel Constraints (IA Setup)", registry.getMetamodelConstraintRegistry().getAvailableMetamodelConstraints().size()); for (OclMetaModelConstraintRegistration registration : registry.getMetamodelConstraintRegistry().getAvailableMetamodelConstraints()) { IAConstrantInvalidationListener listener = new IAConstrantInvalidationListener(connection, createOrGetCachedAnalyzer(registration)); EventFilter filter = listener.getEventFilter(); connection.getSession().getEventRegistry().registerListener(listener, filter); listenerPerRegistration.put(registration, listener); pm.worked(1); } } catch (OclConstraintManagerException e) { throw new RuntimeException("Failed to setup OCL Constraint Impact Analyzers", e); } finally { pm.done(); } } private ConstraintSpecificImpactAnalysisFacade createOrGetCachedAnalyzer(OclMetaModelConstraintRegistration registration) { HashMap<List<String>, ConstraintSpecificImpactAnalysisFacade> cache = Activator.getDefault().getImpactAnalyzerConstraintCache(); if (!cache.containsKey(registration.getQualifiedName())) { cache.put(registration.getQualifiedName(), new ConstraintSpecificImpactAnalysisFacade(registration, unwrapConstraintOfConstraintRegistration(registration))); } return cache.get(registration.getQualifiedName()); } private OclConstraintImpl unwrapConstraintOfConstraintRegistration(OclMetaModelConstraintRegistration constraintRegistration) { MetaModelConstraintInfoImpl infoImpl = ((MetaModelConstraintInfoImpl) ((OclMetaModelConstraintRegistrationWrapper) constraintRegistration).unwrap()); return ((OclConstraintWrapper) connection.getElement(infoImpl.getConstraintMRI())).unwrap(); } public void deregisterRegisteredMetaModelConstraintListeners(IProgressMonitor pm) { pm.beginTask("Deregistering OCL MetaModel Impact Analyzers", listenerPerRegistration.size()); for (IAConstrantInvalidationListener listener : listenerPerRegistration.values()) { connection.getSession().getEventRegistry().deregister(listener); } listenerPerRegistration.clear(); pm.done(); } /** * Returns all currently broken constraints. * @return */ public Collection<ConstraintViolation> evaluateConstraints(IProgressMonitor pm) { pm.beginTask("Evaluating Impacted OCL constraints", listenerPerRegistration.size()); Collection<ConstraintViolation> violations = new LinkedList<ConstraintViolation>(); OclConstraintEvaluator evaluator = new OclConstraintEvaluator(); for (Entry<OclMetaModelConstraintRegistration, IAConstrantInvalidationListener> entry : listenerPerRegistration.entrySet()) { IAConstrantInvalidationListener listener = entry.getValue(); OclMetaModelConstraintRegistration registration = entry.getKey(); CoreConnection coreConn = ((ConnectionWrapper) connection).unwrap(); OclExpression expression = unwrapConstraintOfConstraintRegistration(registration).getOclExpression(); for (MRI impactedElementMRI : listener.getElementsImpactedByEvents()) { RefObject elementToCheck = (RefObject) connection.getElement(impactedElementMRI); try { boolean isValid = evaluator.evaluate(coreConn, expression, elementToCheck); if (!isValid) { ConstraintViolation violation = new ConstraintViolation(elementToCheck, registration); violations.add(violation); } } catch (ExpressionUndefinedException e) { Activator.logError(e, "Failed to evaluate metamodel constraint"); ConstraintViolation violation = new ConstraintViolation(elementToCheck, registration); violations.add(violation);; } catch (EvaluatorException e) { Activator.logError(e, "Failed to evaluate metamodel constraint"); ConstraintViolation violation = new ConstraintViolation(elementToCheck, registration); violations.add(violation);; } finally { pm.worked(1); } } } pm.done(); return violations; } }