![JAR search and dependency download from the Maven repository](/logo.png)
net.sf.nakeduml.javageneration.bpm.AbstractEventHandlerInserter Maven / Gradle / Ivy
package net.sf.nakeduml.javageneration.bpm;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import net.sf.nakeduml.javageneration.NakedClassifierMap;
import net.sf.nakeduml.javageneration.NakedStructuralFeatureMap;
import net.sf.nakeduml.javageneration.oclexpressions.ValueSpecificationUtil;
import net.sf.nakeduml.javageneration.util.OJUtil;
import net.sf.nakeduml.javametamodel.OJBlock;
import net.sf.nakeduml.javametamodel.OJClass;
import net.sf.nakeduml.javametamodel.OJIfStatement;
import net.sf.nakeduml.javametamodel.OJOperation;
import net.sf.nakeduml.javametamodel.OJParameter;
import net.sf.nakeduml.javametamodel.OJPathName;
import net.sf.nakeduml.javametamodel.OJSimpleStatement;
import net.sf.nakeduml.javametamodel.OJStatement;
import net.sf.nakeduml.javametamodel.OJWhileStatement;
import net.sf.nakeduml.javametamodel.annotation.OJAnnotatedClass;
import net.sf.nakeduml.javametamodel.annotation.OJAnnotatedField;
import net.sf.nakeduml.javametamodel.annotation.OJAnnotatedOperation;
import net.sf.nakeduml.metamodel.commonbehaviors.GuardedFlow;
import net.sf.nakeduml.metamodel.commonbehaviors.INakedBehavior;
import net.sf.nakeduml.metamodel.commonbehaviors.INakedSignal;
import net.sf.nakeduml.metamodel.commonbehaviors.INakedTimeEvent;
import net.sf.nakeduml.metamodel.commonbehaviors.INakedTriggerContainer;
import net.sf.nakeduml.metamodel.core.INakedElement;
import net.sf.nakeduml.metamodel.core.INakedOperation;
import net.sf.nakeduml.metamodel.core.INakedProperty;
import net.sf.nakeduml.metamodel.core.INakedTypedElement;
import nl.klasse.octopus.codegen.umlToJava.maps.ClassifierMap;
import nl.klasse.octopus.model.IClassifier;
import nl.klasse.octopus.stdlib.IOclLibrary;
import org.jbpm.graph.exe.ExecutionContext;
public abstract class AbstractEventHandlerInserter extends AbstractBehaviorVisitor {
protected abstract void implementEventConsumption(FromNode node, OJIfStatement ifNotNull);
protected void maybeContinueFlow(OJOperation operationContext, OJBlock block, GuardedFlow flow) {
block.addToStatements("waitingToken.signal(\"" + flow.getMappingInfo().getPersistentName().getWithoutId() + "\")");
}
/**
* Inserts a call to the eventListener as the last line of code in the body
* of the triggering operation
*/
private void insertEventListenerCall(INakedBehavior behavior, INakedOperation nakedOperation) {
OJPathName path = OJUtil.classifierPathname(nakedOperation.getOwner());
OJClass myOwner = (OJClass) this.javaModel.findIntfOrCls(path);
OJOperation ojOperation = myOwner.findOperation(nakedOperation.getMappingInfo().getJavaName().toString(),
toOJPathNames(nakedOperation.getParamTypes()));
if (ojOperation != null) {
StringBuilder statement = new StringBuilder("");
if (behavior.isClassifierBehavior() && behavior.getContext().equals(nakedOperation.getOwner())) {
statement.append("getClassifierBehavior().");
} else {
// TODO broadcast to all running istances?
}
statement.append("on");
statement.append(nakedOperation.getMappingInfo().getJavaName().getCapped());
statement.append("(");
Iterator parms = ojOperation.getParameters().iterator();
while (parms.hasNext()) {
OJParameter parm = (OJParameter) parms.next();
statement.append(parm.getName());
if (parms.hasNext()) {
statement.append(",");
}
}
statement.append(")");
List statements = ojOperation.getBody().getStatements();
if (nakedOperation.hasReturnParameter()) {
statements.add(statements.size() - 2, new OJSimpleStatement(statement.toString()));
} else {
statements.add(new OJSimpleStatement(statement.toString()));
}
}
}
/**
* Implements the processSignal method for signals and injects the event
* listening code for operations
*
* @param behaviorClass
* @param behavior
*/
private void implementSignalProcessing(OJAnnotatedClass behaviorClass, INakedTriggerContainer behavior) {
for (INakedElement element : behavior.getAllMessageTriggers()) {
if (element instanceof INakedSignal) {
INakedSignal signal = (INakedSignal) element;
insertSignalListenerCall(behavior, signal);
} else if (element instanceof INakedOperation) {
INakedOperation no = (INakedOperation) element;
insertEventListenerCall(behavior, no);
}
}
}
private void insertSignalListenerCall(INakedTriggerContainer behavior, INakedSignal signal) {
// TODO this assumes that the Behavior is always nested inside the
// classifier it is behavior for
OJPathName path = OJUtil.classifierPathname(behavior.getContext() == null ? behavior : behavior.getContext());
OJClass myOwner = (OJClass) this.javaModel.findIntfOrCls(path);
String signalReception = "on" + signal.getMappingInfo().getJavaName().getCapped();
OJOperation ojOperation = OJUtil.findOperation(myOwner, signalReception);
if (ojOperation == null) {
ojOperation = new OJAnnotatedOperation();
ojOperation.setName(signalReception);
myOwner.addToOperations(ojOperation);
for (INakedProperty p : signal.getOwnedAttributes()) {
if (!OJUtil.isBuiltIn(p)) {
NakedStructuralFeatureMap map = OJUtil.buildStructuralFeatureMap(p);
ojOperation.addParam(map.umlName(), map.javaTypePath());
}
}
ojOperation.setReturnType(new OJPathName("boolean"));
ojOperation.getBody().addToStatements("return false");
}
StringBuilder statement = new StringBuilder("");
if (behavior.isClassifierBehavior()) {
statement.append("getClassifierBehavior().");
} else {
// TODO broadcast to all running istances?
}
statement.append(signalReception);
statement.append("(");
Iterator parms = ojOperation.getParameters().iterator();
while (parms.hasNext()) {
OJParameter parm = (OJParameter) parms.next();
statement.append(parm.getName());
if (parms.hasNext()) {
statement.append(",");
}
}
statement.append(")");
List statements = ojOperation.getBody().getStatements();
statements.add(statements.size() - 1, new OJSimpleStatement(statement.toString()));
}
/**
* Implements a method that is to be called when significant events occur.
* By convention it starts with the word "on" and returns a boolean
* indicating whether the event was executed or not
*/
private void implementEventListener(OJClass activityClass, WaitForEventElements eventActions) {
INakedElement event = eventActions.getEvent();
String methodName = null;
if (event instanceof INakedTimeEvent) {
// apply persistent name semantics - a revision may occur after the
// original event was logged
methodName = "on_" + event.getMappingInfo().getPersistentName().getWithoutId();
} else {
methodName = "on" + event.getMappingInfo().getJavaName().getCapped();
}
OJOperation listener = new OJAnnotatedOperation();
listener.setName(methodName);
listener.setReturnType(new OJPathName("boolean"));
activityClass.addToOperations(listener);
List params = eventActions.getArguments();
Iterator paramIterator = params.iterator();
while (paramIterator.hasNext()) {
INakedTypedElement param = (INakedTypedElement) paramIterator.next();
ClassifierMap map = new NakedClassifierMap(param.getType());
listener.addParam(param.getMappingInfo().getJavaName().toString(), map.javaTypePath());
}
OJAnnotatedField processed = new OJAnnotatedField();
processed.setName("consumed");
processed.setType(new OJPathName("boolean"));
processed.setInitExp("false");
listener.getBody().addToLocals(processed);
OJAnnotatedField nodes = new OJAnnotatedField();
nodes.setName("waitingToken");
nodes.setType(new OJPathName("org.jbpm.graph.exe.Token"));
listener.getBody().addToLocals(nodes);
for (FromNode node : eventActions.getWaitingNodes()) {
addLeavingLogic(listener, node, listener.getBody());
}
listener.setReturnType(new OJPathName("boolean"));
listener.getBody().addToStatements("return consumed");
}
protected void implementEventHandling(OJAnnotatedClass ojBehavior, INakedTriggerContainer behavior, Collection ea) {
addFindWaitingToken(ojBehavior);
for (WaitForEventElements eventActions : ea) {
implementEventListener(ojBehavior, eventActions);
}
implementSignalProcessing(ojBehavior, behavior);
}
public OJIfStatement implementConditionalFlows(OJOperation operationContext, FromNode node, OJIfStatement ifTokenFound) {
OJIfStatement ifGuard = null;
IClassifier booleanType = workspace.getOclEngine().getOclLibrary().lookupStandardType(IOclLibrary.BooleanTypeName);
for (GuardedFlow flow : node.getConditionalTransitions()) {
OJIfStatement newIf = new OJIfStatement();
newIf.setCondition(ValueSpecificationUtil.expressValue(operationContext, flow.getGuard(), flow.getContext(), booleanType));
newIf.getThenPart().addToStatements("consumed=true");
maybeContinueFlow(operationContext, newIf.getThenPart(), flow);
OJBlock block = null;
if (ifGuard == null) {
block = ifTokenFound.getThenPart();
} else {
block = new OJBlock();
ifGuard.setElsePart(block);
}
block.addToStatements(newIf);
ifGuard = newIf;
}
return ifGuard;
}
private void addFindWaitingToken(OJClass activityClass) {
OJPathName tokenPathName = new OJPathName("org.jbpm.graph.exe.Token");
activityClass.addToImports(tokenPathName);
OJOperation findWaitingToken = new OJAnnotatedOperation();
activityClass.addToOperations(findWaitingToken);
findWaitingToken.setName("findWaitingToken");
OJPathName stepPathName = new OJPathName(activityClass.getName() + "State");
findWaitingToken.addParam("step", stepPathName);
findWaitingToken.setReturnType(tokenPathName);
OJAnnotatedField iter = new OJAnnotatedField();
iter.setName("iter");
iter.setType(new OJPathName(Iterator.class.getName()));
activityClass.addToImports(Iterator.class.getName());
iter.setInitExp("processInstance.findAllTokens().iterator()");
findWaitingToken.getBody().addToLocals(iter);
// Iterate through the active tokens
OJWhileStatement whileNext = new OJWhileStatement();
findWaitingToken.getBody().addToStatements(whileNext);
whileNext.setCondition("iter.hasNext()");
OJAnnotatedField t = new OJAnnotatedField();
t.setName("t");
t.setType(tokenPathName);
t.setInitExp("(Token)iter.next()");
whileNext.getBody().addToLocals(t);
OJAnnotatedField currentGraphElement = new OJAnnotatedField();
currentGraphElement.setName("currentGraphElement");
OJPathName graphElementPathName = new OJPathName("org.jbpm.graph.def.GraphElement");
currentGraphElement.setType(graphElementPathName);
currentGraphElement.setInitExp("t.getNode()");
activityClass.addToImports(graphElementPathName);
activityClass.addToImports("org.jbpm.graph.def.Node");
whileNext.getBody().addToLocals(currentGraphElement);
// Iterate through the parent axis
OJWhileStatement whileParent = new OJWhileStatement();
whileParent.setCondition("currentGraphElement instanceof Node");
OJPathName nodePathName = new OJPathName("org.jbpm.graph.def.Node");
OJAnnotatedField currentNode = new OJAnnotatedField();
currentNode.setName("currentNode");
currentNode.setType(nodePathName);
currentNode.setInitExp("((Node)currentGraphElement)");
whileParent.getBody().addToLocals(currentNode);
OJIfStatement ifNameEquals = new OJIfStatement("currentNode.getFullyQualifiedName().equals(step.getQualifiedName())", "return t");
ifNameEquals.setElsePart(new OJBlock());
ifNameEquals.getElsePart().addToStatements("currentGraphElement=currentNode.getParent()");
whileParent.getBody().addToStatements(ifNameEquals);
whileNext.getBody().addToStatements(whileParent);
findWaitingToken.getBody().addToStatements("return null");
}
private void addLeavingLogic(OJOperation operationContext, FromNode node, OJBlock body) {
OJIfStatement ifTokenFound = new OJIfStatement();
body.addToStatements(ifTokenFound);
String literalExpression = operationContext.getOwner().getName() + "State." + BpmUtil.stepLiteralName(node.getWaitingElement());
if (node.isRestingNode()) {
ifTokenFound.setCondition("consumed==false && (waitingToken=findWaitingToken(" + literalExpression + "))" + "!=null");
} else {
operationContext.getOwner().addToImports(new OJPathName(ExecutionContext.class.getName()));
ifTokenFound.setCondition("consumed==false && (waitingToken=ExecutionContext.currentExecutionContext().getToken())!=null");
}
implementEventConsumption(node, ifTokenFound);
OJIfStatement ifGuard = implementConditionalFlows(operationContext, node, ifTokenFound);
GuardedFlow flow = node.getDefaultTransition();
if (flow != null) {
// default flow/transition
OJBlock block = null;
if (ifGuard == null) {
block = ifTokenFound.getThenPart();
} else {
block = new OJBlock();
ifGuard.setElsePart(block);
}
block.addToStatements("consumed=true");
maybeContinueFlow(operationContext, block, flow);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy