package com.sap.ide.refactoring.core.constraints;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.omg.ocl.attaching.ClassifierInvariant;
import org.omg.ocl.attaching.OclConstraint;
import org.omg.ocl.attaching.__impl.OclConstraintImpl;
import org.omg.ocl.expressions.__impl.OclExpressionInternal;
import com.sap.tc.moin.ocl.ia.ClassScopeAnalyzer;
import com.sap.tc.moin.ocl.ia.instancescope.AnnotatedRefObjectImpl;
import com.sap.tc.moin.ocl.ia.instancescope.InstanceScopeAnalysis;
import com.sap.tc.moin.ocl.ia.instancescope.NavigationStep;
import com.sap.tc.moin.ocl.ia.instancescope.PathCache;
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.OclMetaModelConstraintRegistrationWrapper;
import com.sap.tc.moin.repository.core.jmi.reflect.RefObjectImpl;
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.events.type.ModelChangeEvent;
import com.sap.tc.moin.repository.mmi.model.Classifier;
import com.sap.tc.moin.repository.mmi.model.__impl.MofClassImpl;
import com.sap.tc.moin.repository.mmi.model.__impl.MofClassWrapper;
import com.sap.tc.moin.repository.ocl.metamodel.OclMetaModelConstraintRegistration;
import com.sap.tc.moin.repository.shared.util.Tuple.Pair;
/**
* Thin adapter that allows to register moin metamodel constraints in the impact analysis.
*
* @author Stephan Erb (d049157)
*
*/
public class ConstraintSpecificImpactAnalysisFacade {
private final OclMetaModelConstraintRegistration constraintRegistration;
private final OclConstraintImpl constraint;
/**
* Used for the instance scope impact analysis so as to not having to
* re-analyze the same expressions over and over again.
*/
private final PathCache instanceScopeAnalysisPathCache;
private EventFilter eventFilter;
private InstanceScopeAnalysis analyzer;
private ClassScopeAnalyzer classScopeAnalyzer;
public ConstraintSpecificImpactAnalysisFacade(OclMetaModelConstraintRegistration constraintRegistration, OclConstraintImpl constraint) {
this.constraintRegistration = constraintRegistration;
this.constraint = constraint;
this.instanceScopeAnalysisPathCache = new PathCache();
}
public EventFilter getEventFilter(Connection connection, boolean notifyNewContextElement) {
if (eventFilter == null) {
eventFilter = getClassScopeAnalyzer(connection, notifyNewContextElement).getEventFilter();
}
return eventFilter;
}
private ClassScopeAnalyzer getClassScopeAnalyzer(Connection connection, boolean notifyNewContextElement) {
if (classScopeAnalyzer == null) {
classScopeAnalyzer = new ClassScopeAnalyzer(((ConnectionWrapper) connection).unwrap(), (OclExpressionInternal) constraint.getOclExpression(), notifyNewContextElement);
}
return classScopeAnalyzer;
}
public Set<MRI> getAffectedModelElements(Connection connection, ModelChangeEvent mce) {
Map<Pair<NavigationStep, RefObjectImpl>, Set<AnnotatedRefObjectImpl>> cache = new HashMap<Pair<NavigationStep, RefObjectImpl>, Set<AnnotatedRefObjectImpl>>();
return getImpactAnalyzer(connection).getAffectedElements(getContext(connection), mce, cache);
}
private InstanceScopeAnalysis getImpactAnalyzer(Connection connection) {
if (analyzer == null) {
analyzer = new InstanceScopeAnalysis(constraintRegistration, constraint.getOclExpression(), ((ConnectionWrapper) connection).unwrap(),
instanceScopeAnalysisPathCache, getClassScopeAnalyzer(connection, /* notifyNewContextElement */false));
}
return analyzer;
}
private MofClassImpl getContext(Connection connection) {
MetaModelConstraintInfoImpl infoImpl = (MetaModelConstraintInfoImpl) ((OclMetaModelConstraintRegistrationWrapper) constraintRegistration).unwrap();
Collection<Classifier> classifiers = connection.getAssociation(ClassifierInvariant.ASSOCIATION_DESCRIPTOR).getInvariantOf((OclConstraint) ((ConnectionWrapper) connection).unwrap().getElement(infoImpl.getConstraintMRI()));
assert classifiers.size() == 1; // TODO: We currently assume that there is always just one.
return ((MofClassWrapper) classifiers.iterator().next()).unwrap();
}
}