}
try
{
// Initialize the next executable socket to the initial socket.
NodeSocket currentSocket = context.getCurrentSocket();
if (currentSocket == null)
// There is no executable socket; the process has stopped
return;
Node currentNode = currentSocket.getNode();
NodeSocket entrySocket = currentSocket;
boolean isEntrySocket = currentSocket.isEntrySocket();
if (isEntrySocket)
{
// We have an entry socket; Regular node execution
// Evaluate any input parameter expressions or scripts and
// ensure that any required parameters are present.
prepareSocket(entrySocket);
// By default, we copy the parameters of the entry socket to parameters
// of the same name at the exit sockets
EngineUtil.copySocketParameters(entrySocket, null, context);
if (engine.hasActiveObservers(EngineTraceEvent.NODE_ENTRY, context))
{
engine.fireEngineEvent(new EngineTraceEvent(EngineTraceEvent.NODE_ENTRY, context, entrySocket, engine));
}
// Reassign the entry socket if the process has been updated while waiting for a debugger command ("hot code replace")
entrySocket = context.getCurrentSocket();
currentNode = entrySocket.getNode();
/////////////////////////////////////////////////
// Execute the node connected to the socket
/////////////////////////////////////////////////
if (LogUtil.isTraceEnabled(getClass()))
{
String nodeType = currentNode.getModelObjectSymbolName();
LogUtil.trace(getClass(), "Executing {0}Node $1. [{2}]", nodeType, currentNode.getQualifier(), context);
}
// Execute the NodeEntry handler, if any
HandlerContext hc = engine.executeHandler(currentNode.getEventHandlerDefinition(), HandlerTypes.NODE_ENTRY, context, entrySocket,
currentNode.getDefaultExitSocket());
if (hc != null && hc.hasNextSocketChanged())
{
// Handler changed the flow of control...
if (hc.getNextSocket() == null)
throw new EngineException("MissingNextSocket", "Handler of node '" + currentNode.getQualifier()
+ "' has set a null next socket.\nThe process cannot be continued.");
context.setCurrentSocket(hc.getNextSocket());
return;
}
// *** Execute the node ***
ModelObjectExecutor executor = engine.getModelObjectExecutorMgr().getExecutor(currentNode);
executor.executeModelObject(currentNode, this);
}
else
{
// We have an exit socket; Node has been executed already, process is being continued now.
}
// *** Handle any lifecycle state requests and perform the transaction handling ***
handleLifecycleRequest();
if (context.getLifecycleState() == LifecycleState.RUNNING)
{
NodeSocket nextSocket = context.getCurrentSocket();
if (nextSocket != null)
{
// Execute the node exit handler, if any and if not executing an error socket
if (! nextSocket.getName().equals(CoreConstants.ERROR_SOCKET_NAME))
{
HandlerContext hc2 = engine.executeHandler(currentNode.getEventHandlerDefinition(), HandlerTypes.NODE_EXIT, context, entrySocket, nextSocket);
if (hc2 != null && hc2.hasNextSocketChanged())
{
// Handler changed the flow of control...
nextSocket = hc2.getNextSocket();
context.setCurrentSocket(nextSocket);
}
}
if (nextSocket != null)
{
// Evaluate any output parameter expressions or scripts
postProcessSocket(nextSocket);
}
if (isEntrySocket)
{
// Clear the entry socket data from the context
EngineUtil.removeSocketData(entrySocket, context);
}
}
if (nextSocket != null)
{
if (engine.hasActiveObservers(EngineTraceEvent.NODE_EXIT, context))
{
engine.fireEngineEvent(new EngineTraceEvent(EngineTraceEvent.NODE_EXIT, context, nextSocket, engine));
}
// Reassign the entry socket if the process has been updated while waiting for a debugger command ("hot code replace")
nextSocket = context.getCurrentSocket();
// If we ended up with an entry socket for the next socket, the flow of control was diverted by the node handler directly.
// Otherwise, we need to perform the regular control link processing.
if (nextSocket.isExitSocket())
{
// *** Follow the control links to determine the new node. ***
// Note that the control link may perform transaction handling here.
advanceToNextSocket(nextSocket);
nextSocket = context.getCurrentSocket();
}
}
if (nextSocket == null || nextSocket.getNode() != currentNode)
{
// Remove local node data if we changed nodes
EngineUtil.removeNodeData(currentNode, context);
}
}