package sushi.query.bpmn; import java.util.Arrays; import java.util.List; import sushi.bpmn.element.AbstractBPMNElement; import sushi.bpmn.monitoringpoint.MonitoringPoint; import sushi.bpmn.monitoringpoint.MonitoringPointStateTransition; import sushi.query.PatternQueryType; import sushi.query.SushiPatternQuery; import sushi.query.SushiQueryTypeEnum; /** * This query factory creates queries for concrete BPMN elements, * which represents the monitorable state transitions of the current element. * @author micha */ public class StateTransitionQueryFactory extends AbstractPatternQueryFactory { public StateTransitionQueryFactory(PatternQueryGenerator patternQueryGenerator) { super(patternQueryGenerator); } /** * This method should generate a query for a single BPMN element, this query makes it possible to monitor the life cycle of a BPMN element. * It is possible to observe the single state transitions of an activity when it is executed with multiple monitoring points. * @param element * @param catchingMonitorableElement * @param resendElement * @return */ @Override protected SushiPatternQuery generateQuery(AbstractBPMNElement element, AbstractBPMNElement catchingMonitorableElement, SushiPatternQuery parentQuery) { SushiPatternQuery query = null; String queryString = generateQueryString(element, catchingMonitorableElement); //Falls eine PatternQuery für dieses Element schon angelegt ist, dann wird die Query nur upgedated if(patternQueryGenerator.getQueryForElement(element) != null){ query = patternQueryGenerator.getQueryForElement(element); addQueryRelationship(parentQuery, query); updateQuery(query); System.out.println(query.getTitle() + ": " + queryString); if(query != null && query.getListener() != null){ query.getListener().setCatchingElement(catchingMonitorableElement); } } else { query = new SushiPatternQuery(generateQueryName("StateTransition"), queryString, SushiQueryTypeEnum.LIVE, PatternQueryType.STATETRANSITION, Arrays.asList(element)); addQueryRelationship(parentQuery, query); registerQuery(query); System.out.println(query.getTitle() + ": " + queryString); if(query != null && query.getListener() != null){ query.getListener().setCatchingElement(catchingMonitorableElement); } } return query; } /** * @param element * @param catchingMonitorableElement * @return */ private String generateQueryString(AbstractBPMNElement element, AbstractBPMNElement catchingMonitorableElement) { //Nicht alle Monitoring Points eines Elements müssen vorhanden sein //Genereller Query-Ablauf: (Enable->Begin->Terminate) OR Skip MonitoringPoint enableMonitoringPoint = element.getMonitoringPointByStateTransitionType(MonitoringPointStateTransition.enable); MonitoringPoint beginMonitoringPoint = element.getMonitoringPointByStateTransitionType(MonitoringPointStateTransition.begin); MonitoringPoint terminateMonitoringPoint = element.getMonitoringPointByStateTransitionType(MonitoringPointStateTransition.terminate); MonitoringPoint skipMonitoringPoint = element.getMonitoringPointByStateTransitionType(MonitoringPointStateTransition.skip); List<MonitoringPoint> regularMonitoringPoints = Arrays.asList(enableMonitoringPoint, beginMonitoringPoint, terminateMonitoringPoint); int elementsWithMonitoringPoints = 0; StringBuilder sequencePatternQueryString = new StringBuilder(); sequencePatternQueryString.append("SELECT * FROM PATTERN [("); for(MonitoringPoint monitoringPoint : regularMonitoringPoints){ if(monitoringPoint != null && monitoringPoint.getEventType() != null){ if(elementsWithMonitoringPoints > 0){ sequencePatternQueryString.append(" " + EsperPatternOperators.SEQUENCE.operator + " "); } sequencePatternQueryString.append("EVERY S" + elementsWithMonitoringPoints + "="); sequencePatternQueryString.append(monitoringPoint.getEventType().getTypeName()); elementsWithMonitoringPoints++; } } sequencePatternQueryString.append(") "); boolean elementHasSkipMonitoringPoint = skipMonitoringPoint != null && skipMonitoringPoint.getEventType() != null; if(elementHasSkipMonitoringPoint){ if(elementsWithMonitoringPoints > 0){ sequencePatternQueryString.append(" " + EsperPatternOperators.XOR.operator + " "); } sequencePatternQueryString.append("EVERY S" + elementsWithMonitoringPoints + "="); sequencePatternQueryString.append(skipMonitoringPoint.getEventType().getTypeName()); elementsWithMonitoringPoints++; } if(catchingMonitorableElement == null){ sequencePatternQueryString.append("]"); } else { sequencePatternQueryString.append(" " + EsperPatternOperators.XOR.operator + " EVERY C1="); sequencePatternQueryString.append(catchingMonitorableElement.getMonitoringPoints().get(0).getEventType().getTypeName()); sequencePatternQueryString.append("]"); } if(!elementHasSkipMonitoringPoint){ //gleiche ProcessInstanceID-Bedingung anhängen, falls Skip-Monitoring-Point nicht hinzugefügt, //bei OR-Operator in Pattern ist die Bedingung nicht möglich sequencePatternQueryString.append(" WHERE sushi.esper.SushiUtils.isIntersectionNotEmpty({"); for(int j = 0; j < elementsWithMonitoringPoints; j++){ if(j == elementsWithMonitoringPoints - 1){ //letztes Element --> kein Komma sequencePatternQueryString.append("S" + j + ".ProcessInstances"); } else { sequencePatternQueryString.append("S" + j + ".ProcessInstances,"); } } sequencePatternQueryString.append("})"); } String queryString = sequencePatternQueryString.toString(); return queryString; } }