package com.sap.emf.ocl.trigger.impl; import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.ocl.ecore.OCLExpression; import org.eclipse.ocl.ecore.opposites.DefaultOppositeEndFinder; import org.eclipse.ocl.ecore.opposites.OppositeEndFinder; import org.eclipse.ocl.examples.eventmanager.EventFilter; import org.eclipse.ocl.examples.eventmanager.EventManager; import org.eclipse.ocl.examples.eventmanager.EventManagerFactory; import org.eclipse.ocl.examples.impactanalyzer.ImpactAnalyzer; import org.eclipse.ocl.examples.impactanalyzer.configuration.ActivationOption; import org.eclipse.ocl.examples.impactanalyzer.configuration.OptimizationActivation; import com.sap.emf.ocl.trigger.ExpressionWithContext; import com.sap.emf.ocl.trigger.TriggerManager; import com.sap.emf.ocl.trigger.Triggerable; public class TriggerManagerImpl implements TriggerManager { private final EventManager eventManager; private final OppositeEndFinder oppositeEndFinder; private final ActivationOption impactAnalysisConfiguration; private final Collection<AdapterForExpression> strongAdapterReferences; TriggerManagerImpl() { this(DefaultOppositeEndFinder.getInstance()); } public TriggerManagerImpl(OppositeEndFinder oppositeEndFinder) { this(oppositeEndFinder, OptimizationActivation.getOption()); } public TriggerManagerImpl(ActivationOption impactAnalysisConfiguration) { this(DefaultOppositeEndFinder.getInstance(), impactAnalysisConfiguration); } public TriggerManagerImpl(OppositeEndFinder oppositeEndFinder, ActivationOption impactAnalysisConfiguration) { this(oppositeEndFinder, impactAnalysisConfiguration, EventManagerFactory.eINSTANCE.createEventManager()); } public TriggerManagerImpl(OppositeEndFinder oppositeEndFinder, EventManager eventManager) { this(oppositeEndFinder, OptimizationActivation.getOption(), eventManager); } public TriggerManagerImpl(OppositeEndFinder oppositeEndFinder, ActivationOption impactAnalysisConfiguration, EventManager eventManager) { this.eventManager = eventManager; this.oppositeEndFinder = oppositeEndFinder; this.impactAnalysisConfiguration = impactAnalysisConfiguration; this.strongAdapterReferences = new HashSet<AdapterForExpression>(); } @Override public void register(Triggerable triggerable) { for (AdapterForExpression adapter : getAdapters(triggerable, oppositeEndFinder, impactAnalysisConfiguration)) { strongAdapterReferences.add(adapter); // ensure the adapter won't get GC'ed EventFilter filter = adapter.getEventFilter(); eventManager.subscribe(filter, adapter); } } /** * Creates one adapter for each expression returned from {@link #getTriggerExpressionsWithContext()} and * {@link #getTriggerExpressionsWithoutContext()}. For the former, the context element is used during * the creation of the {@link ImpactAnalyzer} which is useful for expressions where the type of "self" * can't be determined, e.g., because "self" doesn't occur in the expression. */ private Collection<AdapterForExpression> getAdapters(Triggerable triggerable, OppositeEndFinder oppositeEndFinder, ActivationOption impactAnalysisConfiguration) { Collection<AdapterForExpression> result = new LinkedList<AdapterForExpression>(); for (ExpressionWithContext expWithContext : triggerable.getTriggerExpressionsWithContext()) { result.add(new AdapterForExpression(triggerable, expWithContext.getExpression(), expWithContext .getContext(), triggerable.notifyOnNewContextElements(), oppositeEndFinder, impactAnalysisConfiguration)); } for (OCLExpression expWithoutContext : triggerable.getTriggerExpressionsWithoutContext()) { result.add(new AdapterForExpression(triggerable, expWithoutContext, /* notifyNewContextElements */false, oppositeEndFinder, impactAnalysisConfiguration)); } return result; } @Override public void addToObservedResourceSets(ResourceSet resourceSet) { eventManager.addToObservedResourceSets(resourceSet); } /** * TODO consider changing behavior so that an interim instance manages the association between * event managers and trigger managers, and the event manager only stops receiving events only * if all trigger managers have been removed */ @Override public void removeFromObservedResourceSets(ResourceSet resourceSet) { eventManager.removeFromObservedResourceSets(resourceSet); } }