package sushi.correlation; import java.io.Serializable; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import sushi.event.SushiEvent; import sushi.event.SushiEventType; import sushi.event.attribute.SushiAttribute; import sushi.event.attribute.SushiAttributeTypeEnum; import sushi.event.collection.SushiMapTree; import sushi.process.SushiProcess; import sushi.process.SushiProcessInstance; /** * Provides methods to correlate existing and incoming events to process instances using single event type attributes. */ public class AttributeCorrelator { /** * Defines the correlation for a process using single event type attributes and correlates existing events for the process. * One definition of a correlation per process only. * * @param selectedEventTypes events of the given event types will be correlated - event types must be related to the process * @param correlationAttributes single event type attributes defining the correlation of the given process - * all the event types must contain this attribute (i.e. if an attribute with attribute expression 'A' is given and the event types * are E1, E2, and E3, the correlation is E1.A=E2.A, E1.A=E3.A and E2.A=E3.A * @param process the process from which the process instances are derived and created * @param timeCondition (optional) rule for advanced time correlation related to the process */ public static void correlate(List<SushiEventType> selectedEventTypes, List<SushiAttribute> correlationAttributes, SushiProcess process, TimeCondition timeCondition) { process.addCorrelationAttributes(correlationAttributes); if (timeCondition != null) { timeCondition.save(); process.setTimeCondition(timeCondition); } process.merge(); Set<SushiEvent> eventsToCorrelate = new HashSet<SushiEvent>(); for (SushiEventType actualEventType : selectedEventTypes) { eventsToCorrelate.addAll(SushiEvent.findByEventType(actualEventType)); } Iterator<SushiEvent> eventIterator = eventsToCorrelate.iterator(); while (eventIterator.hasNext()) { SushiEvent actualEvent = eventIterator.next(); correlateEventToProcessInstance(actualEvent, correlationAttributes, process, timeCondition); } } /** * Correlates an event to a process instance using single event type attributes. * If no matching process instance is found, a new process instance is created and the event is be correlated to this instance. * * @param actualEvent the event to be correlated to a process instance * @param correlationAttributes single event type attributes defining the correlation of the given process - * all the event types must contain this attribute (i.e. if an attribute with attribute expression 'A' is given and the event types * are E1, E2, and E3, the correlation is E1.A=E2.A, E1.A=E3.A and E2.A=E3.A * @param process the process from which the process instances are derived and created * @param timeCondition (optional) rule for advanced time correlation related to the process */ static void correlateEventToProcessInstance(SushiEvent actualEvent, List<SushiAttribute> correlationAttributes, SushiProcess process, TimeCondition timeCondition) { boolean insertedInExistingProcessInstance = false; List<SushiProcessInstance> processInstances = SushiProcessInstance.findByProcess(process); /* * Looking for a match from existing process instances. * The event is related to a process instance if their values of all correlation attributes are equal. * If a rule for advanced time correlation is provided, the event must additionally belong to the time period defined in the rule for advanced time correlation. * The event is finally added to the process instance. */ for (SushiProcessInstance actualProcessInstance : processInstances) { boolean processInstanceAndEventMatch = true; for (SushiAttribute actualCorrelationAttribute : correlationAttributes) { String nameOfactualAttribute = actualCorrelationAttribute.getAttributeExpression(); SushiMapTree<String, Serializable> valueTreeOfProcessInstance = actualProcessInstance.getCorrelationAttributesAndValues(); SushiMapTree<String, Serializable> valueTreeOfEvent = actualEvent.getValues(); if (!valueTreeOfProcessInstance.get(nameOfactualAttribute).toString().equals(valueTreeOfEvent.get(nameOfactualAttribute).toString())) { processInstanceAndEventMatch = false; break; } } if (processInstanceAndEventMatch && timeCondition != null) { processInstanceAndEventMatch = timeCondition.belongsEventToTimerEvent(actualEvent, actualProcessInstance.getTimerEvent()); } if (processInstanceAndEventMatch) { actualProcessInstance.addEvent(actualEvent); actualProcessInstance.merge(); actualEvent.addProcessInstance(actualProcessInstance); actualEvent.merge(); insertedInExistingProcessInstance = true; break; } } /* * If no process instance is matched and no rule for advanced time correlation is defined, * a new process instance is created here, the correlation values are taken from the event and * stored in the process instance. The event is finally added to the new process instance. * If no process instance is matched and a rule for advanced time correlation is defined, * a new process instance is created here only if a timer event serving as the benchmark * to which the advanced time correlation can be related exists and is not already * related to a process instance. */ if (!insertedInExistingProcessInstance) { SushiProcessInstance newProcessInstance = new SushiProcessInstance(); if (timeCondition != null) { SushiEvent timerEvent = timeCondition.getTimerEventForEvent(actualEvent, correlationAttributes); if (timerEvent == null) { return; } else { newProcessInstance.setTimerEvent(timerEvent); } } for (SushiAttribute actualCorrelationAttribute : correlationAttributes) { String correlationAttribute = actualCorrelationAttribute.getAttributeExpression(); Serializable correlationValue = actualEvent.getValues().get(actualCorrelationAttribute.getAttributeExpression()); newProcessInstance.getCorrelationAttributesAndValues().put(correlationAttribute, correlationValue); } newProcessInstance.addEvent(actualEvent); newProcessInstance.save(); actualEvent.addProcessInstance(newProcessInstance); actualEvent.merge(); process.addProcessInstance(newProcessInstance); process.save(); System.out.println("New process instance added!"); } } }