package hu.bme.mit.incquery.cep.api.runtime; import hu.bme.mit.incquery.cep.api.CepJobs; import hu.bme.mit.incquery.cep.api.EventPatternAutomatonOptions; import hu.bme.mit.incquery.cep.api.ICepRule; import hu.bme.mit.incquery.cep.api.eventprocessingstrategy.EventProcessingStrategyFactory; import hu.bme.mit.incquery.cep.api.eventprocessingstrategy.IEventProcessingStrategy; import hu.bme.mit.incquery.cep.api.evm.CepActivationStates; import hu.bme.mit.incquery.cep.api.evm.CepEventSourceSpecification; import hu.bme.mit.incquery.cep.api.evm.CepEventType; import hu.bme.mit.incquery.cep.api.evm.CepRealm; import hu.bme.mit.incquery.cep.api.evm.IObservableComplexEventPattern; import hu.bme.mit.incquery.cep.logging.LoggerUtils; import hu.bme.mit.incquery.cep.metamodels.cep.Event; import hu.bme.mit.incquery.cep.metamodels.cep.EventPattern; import hu.bme.mit.incquery.cep.metamodels.internalsm.EventProcessingContext; import hu.bme.mit.incquery.cep.metamodels.internalsm.EventToken; import hu.bme.mit.incquery.cep.metamodels.internalsm.FinalState; import hu.bme.mit.incquery.cep.metamodels.internalsm.InitState; import hu.bme.mit.incquery.cep.metamodels.internalsm.InternalExecutionModel; import hu.bme.mit.incquery.cep.metamodels.internalsm.InternalsmFactory; import hu.bme.mit.incquery.cep.metamodels.internalsm.State; import hu.bme.mit.incquery.cep.metamodels.internalsm.StateMachine; import hu.bme.mit.incquery.cep.metamodels.internalsm.Transition; import hu.bme.mit.incquery.cep.runtime.evaluation.ModelHandlingWithViatraApi2; import hu.bme.mit.incquery.cep.runtime.evaluation.SMUtils; import hu.bme.mit.incquery.cep.runtime.evaluation.StateMachineBuilder; import hu.bme.mit.incquery.cep.streams.DefaultStreamManager; import hu.bme.mit.incquery.cep.streams.EventStream; import hu.bme.mit.incquery.cep.streams.IStreamManager; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.impl.AdapterImpl; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; import org.eclipse.incquery.runtime.evm.api.ActivationLifeCycle; import org.eclipse.incquery.runtime.evm.api.EventDrivenVM; import org.eclipse.incquery.runtime.evm.api.ExecutionSchema; import org.eclipse.incquery.runtime.evm.api.Job; import org.eclipse.incquery.runtime.evm.api.RuleSpecification; import org.eclipse.incquery.runtime.evm.api.event.EventType.RuleEngineEventType; import org.eclipse.incquery.runtime.evm.specific.scheduler.UpdateCompleteBasedScheduler; import org.eclipse.incquery.runtime.evm.specific.scheduler.UpdateCompleteBasedScheduler.UpdateCompleteBasedSchedulerFactory; import org.eclipse.incquery.runtime.evm.update.UpdateCompleteProvider; import com.google.common.base.Preconditions; import com.google.common.collect.Sets; public class EventModelManager { private final InternalsmFactory SM_FACTORY = InternalsmFactory.eINSTANCE; private final Logger logger = LoggerUtils.getInstance().getLogger(); private InternalExecutionModel model; private Resource smModelResource; private ResourceSet resourceSet; private IEventProcessingStrategy strategy; private ExecutionSchema topLevelExecutionSchema; private UpdateCompleteProviderExtension updateCompleteProvider; private Map<StateMachine, Boolean> wasEnabledForTheLatestEvent = new LinkedHashMap<StateMachine, Boolean>(); private CepRealm realm; private IStreamManager streamManager; private Adapter eventAdapter; // cache private Map<StateMachine, FinalState> finalStatesForStatemachines = new LinkedHashMap<StateMachine, FinalState>(); private Map<StateMachine, InitState> initStatesForStatemachines = new LinkedHashMap<StateMachine, InitState>(); private final class UpdateCompleteProviderExtension extends UpdateCompleteProvider { protected void latestEventHandled() { updateCompleted(); } } public EventModelManager() { prepareModel(); eventAdapter = new AdapterImpl() { @Override public void notifyChanged(Notification notification) { if (notification.getEventType() != Notification.ADD) { return; } Object newValue = notification.getNewValue(); if (newValue instanceof Event) { Event event = (Event) newValue; logger.debug("EventModelManager: Event " + event.getClass().getName() + " captured..."); refreshModel(event); } } }; // EventQueue.getInstance().eAdapters().add(eventAdapter); streamManager = DefaultStreamManager.getInstance(this); this.strategy = EventProcessingStrategyFactory.getStrategy(EventProcessingContext.CHRONICLE, this); this.realm = new CepRealm(); initializeSchema(); initializeLowLevelModelHandling(); } private void prepareModel() { model = SM_FACTORY.createInternalExecutionModel(); Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE; Map<String, Object> m = reg.getExtensionToFactoryMap(); m.put("cep", new XMIResourceFactoryImpl()); resourceSet = new ResourceSetImpl(); smModelResource = resourceSet.createResource(URI.createURI("cep/sm.cep")); smModelResource.getContents().add(model); } private void initializeSchema() { updateCompleteProvider = new UpdateCompleteProviderExtension(); UpdateCompleteBasedSchedulerFactory schedulerFactory = new UpdateCompleteBasedScheduler.UpdateCompleteBasedSchedulerFactory( updateCompleteProvider); topLevelExecutionSchema = EventDrivenVM.createExecutionSchema(realm, schedulerFactory, Collections.<RuleSpecification<?>> emptySet()); } private void initializeLowLevelModelHandling() { ModelHandlingWithViatraApi2 mhrViatraApi2 = new ModelHandlingWithViatraApi2(this); mhrViatraApi2.registerRulesWithCustomPriorities(); } public void addRules(List<ICepRule> rules) { Preconditions.checkArgument(!rules.isEmpty()); for (ICepRule rule : rules) { addSingleRule(rule); } initializeStateMachines(); } public void addRule(ICepRule rule) { addSingleRule(rule); initializeStateMachines(); } public void addSingleRule(ICepRule rule) { Preconditions.checkArgument(!rule.getEventPatterns().isEmpty()); for (EventPattern eventPattern : rule.getEventPatterns()) { EventPatternAutomatonOptions options = new EventPatternAutomatonOptions(this.strategy.getContext(), eventPattern.getPriority()); StateMachine stateMachine = getStateMachine(eventPattern, options); wasEnabledForTheLatestEvent.put(stateMachine, true); CepEventSourceSpecification sourceSpec = new CepEventSourceSpecification(stateMachine); Job<IObservableComplexEventPattern> job = rule.getJob(); if (job == null) { job = CepJobs.getDefaultJob(); } @SuppressWarnings("unchecked") RuleSpecification<IObservableComplexEventPattern> ruleSpec = new RuleSpecification<IObservableComplexEventPattern>( sourceSpec, getDefaultLifeCycle(), Sets.newHashSet(job)); topLevelExecutionSchema.addRule(ruleSpec); } } private ActivationLifeCycle getDefaultLifeCycle() { ActivationLifeCycle lifeCycle = ActivationLifeCycle.create(CepActivationStates.INACTIVE); lifeCycle.addStateTransition(CepActivationStates.INACTIVE, CepEventType.APPEARED, CepActivationStates.ACTIVE); lifeCycle .addStateTransition(CepActivationStates.ACTIVE, RuleEngineEventType.FIRE, CepActivationStates.INACTIVE); return lifeCycle; } private void initializeStateMachines() { for (InitState is : initStatesForStatemachines.values()) { if (is.getEventTokens().isEmpty()) { EventToken cv = SM_FACTORY.createEventToken(); cv.setCurrentState(is); model.getEventTokens().add(cv); } } } public StateMachine getStateMachine(EventPattern eventPattern, EventPatternAutomatonOptions options) { StateMachine stateMachine = new StateMachineBuilder(model, eventPattern, options).buildStateMachine(); FinalState finalState = null; InitState initState = null; for (State state : stateMachine.getStates()) { if (SMUtils.isFinal(state)) { finalState = (FinalState) state; break; } } if (finalState != null) { finalStatesForStatemachines.put(stateMachine, finalState); } for (State state : stateMachine.getStates()) { if (state instanceof InitState) { initState = (InitState) state; break; } } if (initState != null) { initStatesForStatemachines.put(stateMachine, initState); } return stateMachine; } private void refreshModel(Event event) { model.setLatestEvent(null); wasEnabledForTheLatestEvent.clear(); strategy.handleInitTokenCreation(model, SM_FACTORY, null); model.setLatestEvent(event); updateCompleteProvider.latestEventHandled(); strategy.handleSmResets(model, SM_FACTORY); } public InternalExecutionModel getModel() { return model; } public Resource getSmModelResource() { return smModelResource; } public IEventProcessingStrategy getStrategy() { return strategy; } public CepRealm getRealm() { return realm; } public Map<StateMachine, FinalState> getFinalStatesForStatemachines() { return finalStatesForStatemachines; } public void callbackOnFiredToken(Transition t, EventToken eventTokenToMove) { EObject state = t.eContainer(); if (!(state instanceof State)) { return; } EObject sm = ((State) state).eContainer(); if (!(sm instanceof StateMachine)) { return; } wasEnabledForTheLatestEvent.put(((StateMachine) sm), true); } public void callbackOnPatternRecognition(IObservableComplexEventPattern observedPattern) { strategy.handleInitTokenCreation(model, SM_FACTORY, observedPattern); } public Map<StateMachine, InitState> getInitStatesForStatemachines() { return initStatesForStatemachines; } public Map<StateMachine, Boolean> getWasEnabledForTheLatestEvent() { return wasEnabledForTheLatestEvent; } public ResourceSet getResourceSet() { return resourceSet; } public void setEventProcessingContext(EventProcessingContext context) { this.strategy = EventProcessingStrategyFactory.getStrategy(context, this); } public void setDebuggingLevel(Level level) { topLevelExecutionSchema.getLogger().setLevel(level); } public void setCepDebugLevel(Level level) { LoggerUtils.getInstance().getLogger().setLevel(level); } public IStreamManager getStreamManager() { return streamManager; } public void setStreamManager(IStreamManager streamManager) { this.streamManager = streamManager; } public void registerNewEventStream(EventStream newEventStream) { newEventStream.eAdapters().add(eventAdapter); } }