26 , sequenceFlow(nullptr)
27 , state(
State::CREATED)
30 , globals(const_cast<
SystemState*>(owner->systemState)->globals)
39 , sequenceFlow(nullptr)
41 , status(other->status)
43 , globals(const_cast<
SystemState*>(owner->systemState)->globals)
49 : owner(others.front()->owner)
51 , node(others.front()->node)
52 , sequenceFlow(nullptr)
53 , state(others.front()->state)
54 , status(mergeStatus(others))
56 , globals(const_cast<
SystemState*>(owner->systemState)->globals)
68 engine->commands.emplace_back(std::bind(&StateMachine::deleteTokensAwaitingBoundaryEvent,stateMachine,
this),
this);
72 systemState->tokenAssociatedToBoundaryEventToken.erase(
this);
80 systemState->tokenAwaitingCompensationActivity.erase(
this);
84 systemState->tokensAwaitingEvent.erase(
this);
87 systemState->tokenAtEventBasedGateway.erase(
this);
92 auto it = systemState->messageAwaitingDelivery.find(
this);
93 if ( it != systemState->messageAwaitingDelivery.end() ) {
94 auto message = it->second.lock();
101 systemState->messageAwaitingDelivery.erase(it);
108 if ( tokenAtSequentialPerformer && tokenAtSequentialPerformer->performing ==
this ) {
109 releaseSequentialPerformer();
113 if ( activity->loopCharacteristics.has_value() &&
114 !activity->isForCompensation
118 systemState->tokensAtActivityInstance.erase(
this);
119 systemState->exitStatusAtActivityInstance.erase(
this);
122 systemState->tokenAtMultiInstanceActivity.erase(
this);
124 systemState->tokenAwaitingMultiInstanceExit.erase(
this);
145 return extensionElements->attributeRegistry;
150 throw std::runtime_error(
"Token: cannot determine attribute registry");
161 nlohmann::ordered_json jsonObject;
165 jsonObject[
"nodeId"] =
node->
id;
171 jsonObject[
"status"] = nlohmann::ordered_json::object();
174 for (
auto attribute : attributeRegistry.statusAttributes ) {
175 if ( attribute->index >=
status.size() ) {
181 if ( !statusValue.has_value() ) {
182 jsonObject[
"status"][attribute->name] = nullptr ;
184 else if ( attribute->type ==
BOOLEAN) {
185 bool value = (bool)statusValue.value();
186 jsonObject[
"status"][attribute->name] = value ;
188 else if ( attribute->type ==
INTEGER) {
189 int value = (int)statusValue.value();
190 jsonObject[
"status"][attribute->name] = value ;
192 else if ( attribute->type ==
DECIMAL) {
193 double value = (double)statusValue.value();
194 jsonObject[
"status"][attribute->name] = value ;
196 else if ( attribute->type ==
STRING) {
198 jsonObject[
"status"][attribute->name] = value ;
202 jsonObject[
"status"][attribute->name] = value ;
208 if (
data->size() ) {
209 jsonObject[
"data"] = nlohmann::ordered_json::object();
211 for (
auto attribute : attributeRegistry.dataAttributes ) {
212 if ( attribute->index >=
data->size() ) {
218 if ( !dataValue.has_value() ) {
219 jsonObject[
"data"][attribute->name] = nullptr ;
221 else if ( attribute->type ==
BOOLEAN) {
222 bool value = (bool)dataValue.value();
223 jsonObject[
"data"][attribute->name] = value ;
225 else if ( attribute->type ==
INTEGER) {
226 int value = (int)dataValue.value();
227 jsonObject[
"data"][attribute->name] = value ;
229 else if ( attribute->type ==
DECIMAL) {
230 double value = (double)dataValue.value();
231 jsonObject[
"data"][attribute->name] = value ;
233 else if ( attribute->type ==
STRING) {
235 jsonObject[
"data"][attribute->name] = value ;
239 jsonObject[
"data"][attribute->name] = value ;
245 jsonObject[
"globals"] = nlohmann::ordered_json::object();
247 for (
auto attribute : attributeRegistry.globalAttributes ) {
248 auto globalValue =
globals[attribute->index];
249 if ( !globalValue.has_value() ) {
250 jsonObject[
"globals"][attribute->name] = nullptr ;
252 else if ( attribute->type ==
BOOLEAN) {
253 bool value = (bool)globalValue.value();
254 jsonObject[
"globals"][attribute->name] = value ;
256 else if ( attribute->type ==
INTEGER) {
257 int value = (int)globalValue.value();
258 jsonObject[
"globals"][attribute->name] = value ;
260 else if ( attribute->type ==
DECIMAL) {
261 double value = (double)globalValue.value();
262 jsonObject[
"globals"][attribute->name] = value ;
264 else if ( attribute->type ==
STRING) {
266 jsonObject[
"globals"][attribute->name] = value ;
270 jsonObject[
"globals"][attribute->name] = value ;
279bool Token::entryIsFeasible()
const {
290bool Token::completionIsFeasible()
const {
301bool Token::exitIsFeasible()
const {
312void Token::advanceFromCreated() {
329void Token::advanceToReady() {
332 throw std::runtime_error(
"Token: ready timestamp at node '" +
node->
id +
"' is larger than current time");
350 engine->
commands.emplace_back(std::bind(&StateMachine::createMultiInstanceActivityTokens,stateMachine,
this),
this);
363void Token::advanceToEntered() {
368 throw std::runtime_error(
"Token: entry timestamp at node '" +
node->
id +
"' is larger than current time");
371 throw std::runtime_error(
"Token: entry timestamp for process '" +
owner->
process->
id +
"' is larger than current time");
378 assert( extensionElements );
380 computeInitialValues( extensionElements );
385 assert( extensionElements );
388 activity->loopCharacteristics.has_value() &&
393 if ( extensionElements->
loopIndex.has_value() && extensionElements->
loopIndex.value()->expression ) {
395 auto attribute = extensionElements->
loopIndex.value()->expression->isAttribute();
396 if (
auto index = attributeRegistry.getValue( attribute,
status, *
data,
globals); index.has_value() ) {
398 attributeRegistry.setValue(attribute,
status, *
data,
globals, (
unsigned int)index.value() + 1);
405 else if ( extensionElements->
loopMaximum.has_value() ) {
406 throw std::runtime_error(
"Token: no attribute provided for loop index parameter of standard loop activity '" +
node->
id +
"' with loop maximum" );
410 computeInitialValues( extensionElements );
426 owned->registerRecipient();
437 engine->commands.emplace_back(std::bind(&StateMachine::initiateEventSubprocesses,stateMachine,
this),
this);
446 if ( !entryIsFeasible() ) {
447 engine->commands.emplace_back(std::bind(&Token::advanceToFailed,
this),
this);
452 engine->commands.emplace_back(std::bind(&Token::advanceToBusy,
this),
this);
460 if ( activity->boundaryEvents.size() ) {
461 engine->commands.emplace_back(std::bind(&StateMachine::initiateBoundaryEvents,stateMachine,
this),
this);
466 if ( !entryIsFeasible() ) {
467 engine->commands.emplace_back(std::bind(&Token::advanceToFailed,
this),
this);
472 engine->commands.emplace_back(std::bind(&Token::advanceToBusy,
this),
this);
479 engine->commands.emplace_back(std::bind(&Token::advanceToBusy,
this),
this);
484 engine->commands.emplace_back(std::bind(&Token::advanceToBusy,
this),
this);
487 engine->commands.emplace_back(std::bind(&Token::advanceToFailed,
this),
this);
494 engine->commands.emplace_back(std::bind(&StateMachine::handleEscalation,
const_cast<StateMachine*
>(
owner),
this),
this);
513 auto it = std::find_if(
514 context->compensableSubProcesses.begin(),
515 context->compensableSubProcesses.end(),
516 [&eventSubProcess](
const std::shared_ptr<StateMachine>& stateMachine) ->
bool {
518 return ( stateMachine->scope->compensationEventSubProcess == eventSubProcess );
521 context = ( it != context->compensableSubProcesses.end() ? it->get() :
nullptr );
526 if (
auto compensations = context->getCompensationTokens(compensateThrowEvent->activity);
530 engine->commands.emplace_back(std::bind(&Token::update,
this,
State::BUSY),
this);
531 context->compensate( std::move(compensations),
this );
541 engine->commands.emplace_back(std::bind(&Token::advanceToDone,
this),
this);
544 advanceToDeparting();
548void Token::advanceToBusy() {
558 extensionElements && extensionElements->
operators.size()
565 throw std::runtime_error(
"Token: timestamp at node '" +
node->
id +
"' is deleted");
569 throw std::runtime_error(
"Token: Operators for task '" +
node->
id +
"' attempt to modify timestamp");
586 if ( scope->startNodes.empty() ) {
588 engine->
commands.emplace_back(std::bind(&Token::advanceToCompleted,
this),
this);
591 if ( scope->startNodes.size() == 1 ) {
599 throw std::runtime_error(
"Token: process '" + scope->id +
"' has multiple start nodes");
606 if ( scope->startNodes.empty() ) {
608 engine->
commands.emplace_back(std::bind(&Token::advanceToCompleted,
this),
this);
619 if ( scope->startNodes.empty() ) {
622 engine->
commands.emplace_back(std::bind(&Token::advanceToCompleted,
this),
this);
625 if ( scope->startNodes.size() == 1 ) {
633 throw std::runtime_error(
"Token: subprocess '" + scope->id +
"' has multiple start nodes");
641 engine->
commands.emplace_back(std::bind(&Token::advanceToDeparting,
this),
this);
646 if (!trigger->expression) {
647 throw std::runtime_error(
"Token: no trigger given for node '" +
node->
id +
"'");
656 engine->
commands.emplace_back(std::bind(&Token::advanceToCompleted,
this),
this);
673 engine->
commands.emplace_back(std::bind(&Token::advanceToCompleted,
this),
this);
677 awaitMessageDelivery();
689 if ( sendTask->loopCharacteristics.has_value() ) {
691 if ( !extensionElements->
loopIndex.has_value() || !extensionElements->
loopIndex->get()->expression ) {
692 throw std::runtime_error(
"Token: send task '" + sendTask->id +
"' requires status attribute holding loop index");
694 auto attribute = extensionElements->
loopIndex->get()->expression->isAttribute();
695 if ( !
status[attribute->index].has_value() ) {
696 throw std::runtime_error(
"Token: cannot find loop index for send task '" + sendTask->id +
"'");
698 assert(
status[attribute->index].value() >= 1 );
699 sendMessage( (
size_t)(
int)
status[attribute->index].value()-1 );
708 awaitTaskCompletionEvent();
713 engine->
commands.emplace_back(std::bind(&Token::advanceToCompleted,
this),
this);
724void Token::advanceToCompleted() {
727 throw std::runtime_error(
"Token: completion timestamp at node '" +
node->
id +
"' is larger than current time");
730 throw std::runtime_error(
"Token: completion timestamp for process '" +
owner->
process->
id +
"' is larger than current time");
744 throw std::runtime_error(
"Token: Operators for task '" +
node->
id +
"' attempt to modify timestamp");
759 if ( !eventSubProcess ) {
760 throw std::runtime_error(
"Token: typed start event must belong to event subprocess");
764 throw std::runtime_error(
"Token: Operators for event-subprocess '" + eventSubProcess->id +
"' attempt to modify timestamp");
790 if ( !completionIsFeasible() ) {
792 engine->commands.emplace_back(std::bind(&Token::advanceToFailed,
this),
this);
798 if ( activity->compensatedBy ) {
799 if ( activity->isForCompensation ) {
800 throw std::runtime_error(
"Token: compensation activity '" + activity->id +
"' must not be compensated");
806 if ( activity->isForCompensation ) {
808 if ( !completionIsFeasible() ) {
809 engine->commands.emplace_back(std::bind(&Token::advanceToFailed,
this),
this);
814 engine->commands.emplace_back(std::bind(&StateMachine::completeCompensationActivity,stateMachine,
this),
this);
821 if ( !completionIsFeasible() ) {
822 engine->commands.emplace_back(std::bind(&Token::advanceToFailed,
this),
this);
832 engine->commands.emplace_back(std::bind(&StateMachine::compensateActivity,
const_cast<StateMachine*
>(
owner),
this),
this);
840 if ( boundaryEvent->isInterrupting ) {
842 engine->commands.emplace_back(std::bind(&StateMachine::interruptActivity,stateMachine,tokenAtActivity), tokenAtActivity);
846 engine->commands.emplace_back(std::bind(&StateMachine::initiateBoundaryEvent,stateMachine,tokenAtActivity,
node), tokenAtActivity);
855 throw std::runtime_error(
"Token: typed start event must belong to event subprocess");
865 auto it = std::find_if(context->pendingEventSubProcesses.begin(), context->pendingEventSubProcesses.end(), [
this](std::shared_ptr<StateMachine>& eventSubProcess) {
866 auto pendingToken = eventSubProcess->tokens.front();
867 return pendingToken.get() == this;
870 assert( it != context->pendingEventSubProcesses.end() );
872 if ( startEvent->isInterrupting ) {
876 context->interruptingEventSubProcess = std::move(*it);
877 context->pendingEventSubProcesses.erase(it);
880 for (
auto eventSubProcess : context->pendingEventSubProcesses ) {
881 eventSubProcess->clearObsoleteTokens();
883 context->pendingEventSubProcesses.clear();
886 for (
auto eventSubProcess : context->nonInterruptingEventSubProcesses ) {
887 eventSubProcess->clearObsoleteTokens();
889 context->nonInterruptingEventSubProcesses.clear();
892 context->clearObsoleteTokens();
897 std::shared_ptr pendingEventSubProcess = std::make_shared<StateMachine>(it->get());
900 context->nonInterruptingEventSubProcesses.push_back(std::move(*it));
903 *it = pendingEventSubProcess;
908 auto eventSubProcess = context->pendingEventSubProcesses.back().get();
920 engine->commands.emplace_back(std::bind(&Token::advanceToFailed,
this),
this);
923 engine->commands.emplace_back(std::bind(&Token::advanceToDone,
this),
this);
926 advanceToDeparting();
935 engine->commands.emplace_back(std::bind(&StateMachine::handleEventBasedGatewayActivation,
const_cast<StateMachine*
>(
owner),
this),
this);
942 engine->commands.emplace_back(std::bind(&Token::advanceToDone,
this),
this);
946 advanceToDeparting();
949void Token::advanceToExiting() {
954 throw std::runtime_error(
"Token: exit timestamp at node '" +
node->
id +
"' is larger than current time");
960 if ( !exitIsFeasible() ) {
961 engine->commands.emplace_back(std::bind(&Token::advanceToFailed,
this),
this);
967 if ( extensionElements && ( extensionElements->
attributes.size() || extensionElements->
data.size() ) ) {
982 auto LOOP = [&]() ->
bool {
985 assert( value.has_value() );
986 if ( !value.value() ) {
994 assert( extensionElements->
loopIndex.value()->expression );
995 auto indexAttribute = extensionElements->
loopIndex.value()->expression->isAttribute();
996 assert( indexAttribute );
997 auto index = attributeRegistry.getValue( indexAttribute,
status, *
data,
globals).value();
999 if ( index >= maximum ) {
1013 if ( extensionElements && extensionElements->
attributes.size() ) {
1022 engine->commands.emplace_back(std::bind(&StateMachine::deleteMultiInstanceActivityToken,stateMachine,
this),
this);
1028 if ( !activity->boundaryEvents.empty() ) {
1030 engine->commands.emplace_back( std::bind(&StateMachine::deleteTokensAwaitingBoundaryEvent,stateMachine,
this), stateMachine );
1044 engine->commands.emplace_back(std::bind(&Token::advanceToDone,
this),
this);
1047 advanceToDeparting();
1050void Token::advanceToDone() {
1057 engine->commands.emplace_back(std::bind(&StateMachine::deleteAdHocSubProcessToken,stateMachine,
this),
this);
1063void Token::advanceToDeparting() {
1068 engine->
commands.emplace_back(std::bind(&Token::advanceToDeparted,
this,
node->
outgoing.front()),
this);
1073 throw std::runtime_error(
"Token: implicit split at node '" +
node->
id +
"'");
1088 throw std::logic_error(
"Token: no gatekeeper provided for sequence flow '" +
sequenceFlow->
id +
"'");
1094 if ( exclusiveGateway->defaultFlow ) {
1096 engine->
commands.emplace_back(std::bind(&Token::advanceToDeparted,
this,exclusiveGateway->defaultFlow),
this);
1100 engine->
commands.emplace_back(std::bind(&Token::advanceToFailed,
this),
this);
1106 engine->
commands.emplace_back(std::bind(&StateMachine::handleDivergingGateway,
const_cast<StateMachine*
>(
owner),
this),
this);
1115 engine->commands.emplace_back(std::bind(&Token::advanceToArrived,
this),
this);
1118void Token::advanceToArrived() {
1125 throw std::runtime_error(
"Token: implicit join at node '" +
node->
id +
"'");
1129 awaitGatewayActivation();
1142 engine->
commands.emplace_back(std::bind(&Token::advanceToEntered,
this),
this);
1146void Token::advanceToFailed() {
1166 engine->commands.emplace_back(std::bind(&Token::terminate,
this),
this);
1171 engine->commands.emplace_back(std::bind(&StateMachine::handleFailure,
const_cast<StateMachine*
>(
owner),
this),
this);
1174void Token::terminate() {
1180 owned->clearObsoleteTokens();
1194 engine->commands.emplace_back(std::bind(&StateMachine::handleFailure,
const_cast<StateMachine*
>(
owner),
this),
this);
1198void Token::awaitCompensation() {
1200 if (
auto compensationActivity = activity->compensatedBy->represents<
BPMN::Activity>();
1201 compensationActivity &&
1204 throw std::runtime_error(
"Token: compensation activities must have the same loop characteristics as the compensated activity '" +
node->
id +
"'");
1214 engine->commands.emplace_back( std::bind(&StateMachine::createCompensationEventSubProcess,stateMachine,subProcess->compensationEventSubProcess,
status), stateMachine );
1218 auto it = std::find_if(activity->boundaryEvents.begin(), activity->boundaryEvents.end(), [](
BPMN::FlowNode* boundaryEvent) {
1219 return ( boundaryEvent->represents<BPMN::CompensateBoundaryEvent>() );
1221 if ( it != activity->boundaryEvents.end() ) {
1223 engine->commands.emplace_back( std::bind(&StateMachine::createCompensationTokenForBoundaryEvent,stateMachine,*it,
status), stateMachine );
1228void Token::awaitReadyEvent() {
1234void Token::awaitEntryEvent() {
1241 tokenAtSequentialPerformer->pendingSequentialEntries.emplace_back(weak_from_this());
1243 if ( tokenAtSequentialPerformer->performing ) {
1251 systemState->pendingEntryDecisions.emplace_back( weak_from_this(),
decisionRequest );
1256void Token::awaitChoiceEvent() {
1260 systemState->pendingChoiceDecisions.emplace_back( weak_from_this(),
decisionRequest );
1264void Token::awaitTaskCompletionEvent() {
1267 systemState->tokensAwaitingCompletionEvent.emplace(time,weak_from_this());
1270void Token::awaitExitEvent() {
1275 systemState->pendingExitDecisions.emplace_back( weak_from_this(),
decisionRequest );
1279void Token::awaitMessageDelivery() {
1284 systemState->pendingMessageDeliveryDecisions.emplace_back( weak_from_this(),
decisionRequest );
1302void Token::awaitGatewayActivation() {
1307 auto gatewayIt = systemState->tokensAwaitingGatewayActivation[stateMachine].find(
node);
1308 if (gatewayIt == systemState->tokensAwaitingGatewayActivation[stateMachine].end()) {
1310 gatewayIt = systemState->tokensAwaitingGatewayActivation[stateMachine].insert({
node,{}}).first;
1313 auto& [key,tokens] = *gatewayIt;
1314 tokens.emplace_back(
this);
1317template<
typename DecisionType,
typename... Args>
1318std::shared_ptr<DecisionType> Token::createDecisionRequest(Args&&... args) {
1320 auto event = std::make_shared<DecisionType>(
this, std::forward<Args>(args)...);
1326void Token::withdraw() {
1333void Token::emitSignal() {
1338 auto& waitingTokens = systemState->tokensAwaitingSignal[signalDefinition->name];
1339 if ( !waitingTokens.empty() ) {
1341 VariedValueMap contentValueMap = getSignalContent(signalDefinition->contentMap);
1343 for (
auto& [token_ptr] : waitingTokens ) {
1344 auto token = token_ptr.lock();
1347 token->setSignalContent(contentValueMap);
1351 engine->
commands.emplace_back(std::bind(&Token::advanceToCompleted,token.get()), token.get());
1353 waitingTokens.clear();
1360 for (
auto& [key,contentDefinition] : contentMap) {
1361 if (
status[contentDefinition->attribute->index].has_value() ) {
1362 contentValueMap.emplace( key, attributeRegistry.getValue(contentDefinition->attribute,
status,*
data,
globals) );
1365 contentValueMap.emplace( key, std::nullopt );
1368 return contentValueMap;
1377 for (
auto& [key,contentValue] : sourceMap) {
1378 if (
auto it = signalDefinition->contentMap.find(key); it != signalDefinition->contentMap.end() ) {
1379 auto& [_,definition] = *it;
1380 auto attribute = definition->attribute;
1382 if ( std::holds_alternative< std::optional<number> >(contentValue) && std::get< std::optional<number> >(contentValue).has_value() ) {
1384 attributeRegistry.setValue(attribute,
status, *
data,
globals, std::get< std::optional<number> >(contentValue).value() );
1386 else if (std::holds_alternative<std::string>(contentValue)) {
1388 Value value = std::get< std::string >(contentValue);
1401 if ( signalDefinition->contentMap.size() > sourceMap.size() - counter ) {
1403 for (
auto& [key,definition] : signalDefinition->contentMap) {
1404 if ( !sourceMap.contains(key) ) {
1406 attributeRegistry.setValue(definition->attribute,
status, *
data,
globals, std::nullopt );
1416void Token::sendMessage(
size_t index) {
1418 systemState->
messages.emplace_back(std::make_shared<Message>(
this,index));
1419 auto& message = systemState->messages.back();
1421 if ( message->recipient.has_value() ) {
1423 auto it = systemState->archive.find((
long unsigned int)message->recipient.value());
1424 if ( it == systemState->archive.end() ) {
1427 systemState->unsent[(
long unsigned int)message->recipient.value()].emplace_back(message->weak_from_this());
1429 else if (
auto stateMachine = it->second.lock() ) {
1431 systemState->inbox[stateMachine.get()].emplace_back(message->weak_from_this());
1432 systemState->outbox[
node].emplace_back(message->weak_from_this());
1437 systemState->outbox[
node].emplace_back(message->weak_from_this());
1441 systemState->messageAwaitingDelivery[
this] = message->weak_from_this();
1451 assert( adHocSubProcess );
1454 while (sequentialPerfomerToken->
node && sequentialPerfomerToken->
node != adHocSubProcess->performer) {
1457 return sequentialPerfomerToken;
1460void Token::occupySequentialPerformer() {
1463 assert( !tokenAtSequentialPerformer->performing );
1464 tokenAtSequentialPerformer->pendingSequentialEntries.remove(
this);
1467 tokenAtSequentialPerformer->performing =
this;
1470 for (
auto& [ token_ptr ] : tokenAtSequentialPerformer->pendingSequentialEntries ) {
1471 if (
auto activityToken = token_ptr.lock() ) {
1474 assert( activityToken->decisionRequest );
1476 activityToken->decisionRequest.reset();
1481void Token::releaseSequentialPerformer() {
1485 assert( tokenAtSequentialPerformer->performing );
1488 tokenAtSequentialPerformer->performing =
nullptr;
1491 for (
auto& [ token_ptr ] : tokenAtSequentialPerformer->pendingSequentialEntries ) {
1492 if (
auto activityToken = token_ptr.lock() ) {
1495 assert( !activityToken->decisionRequest );
1498 systemState->pendingEntryDecisions.emplace_back(activityToken,activityToken->decisionRequest);
1505void Token::update(State newState) {
1506 assert(
status.size() >= 1 );
1507 assert(
data->size() >= 1 );
1526 throw std::runtime_error(
"Token: timestamp at node '" +
node->
id +
"' is larger than current time");
1531void Token::notify()
const {
std::list< Command > commands
List of commands to be executed.
void notify(const Observable *observable) const
Represents a state machine for BPMN execution of a scope in the model.
const BPMN::Scope * scope
Pointer to the current scope.
StateMachines pendingEventSubProcesses
Container with state machines of all inactive event subprocesses that may be triggered.
const SystemState * systemState
const BPMN::Process * process
Pointer to the top-level process.
StateMachines nonInterruptingEventSubProcesses
Container with state machines of all active event subprocesses that are not interrupting.
const StateMachine * root
Pointer to the root state machine.
std::shared_ptr< StateMachine > interruptingEventSubProcess
State machines representing an active event subprocess that is interrupting.
void run(Values status)
Create initial token and advance it.
std::optional< BPMNOS::number > instance
Numeric representation of instance id (TODO: can we const this?)
Tokens tokens
Container with all tokens within the scope of the state machine.
Tokens compensationTokens
Container with all tokens created for a compensation activity.
SharedValues data
Container holding references to all data attributes.
A class representing the state that the execution or simulation of a given scenario is in.
BPMNOS::number currentTime
Timestamp holding the point in time that the engine is in (this is usually representing now).
std::unordered_map< BPMNOS::number, auto_list< std::weak_ptr< Token > > > tokensAwaitingSignal
Map holding a container of all tokens at a signal event awaiting a signal with a given name.
BPMNOS::number getTime() const
Function returning the current time.
Messages messages
Container holding all messages created by a throwing message event.
std::unordered_map< Token *, std::vector< Token * > > tokensAwaitingBoundaryEvent
Map holding a container of all tokens at a boundary event awaiting to be triggered for each token at ...
auto_list< std::weak_ptr< Token > > tokensAwaitingReadyEvent
Container holding all tokens awaiting a ready event.
auto_set< BPMNOS::number, std::weak_ptr< Token > > tokensAwaitingTimer
Sorted container holding holding all tokens awaiting a timer event.
std::unordered_map< BPMNOS::number, auto_list< std::weak_ptr< Token > > > tokensAwaitingCondition
Map holding a container of all tokens at a conditional event belonginge to a process instance.
Represents a token running through a (sub)process.
BPMNOS::number getInstanceId() const
const BPMN::FlowNode * node
Token * performing
Pointer to the activity token currently performed (only applies if node is a performer referenced by ...
const BPMNOS::Model::AttributeRegistry & getAttributeRegistry() const
const StateMachine * owner
State machine owning the token.
std::shared_ptr< StateMachine > owned
State machine owned by the token.
SharedValues * data
Pointer to the data of the owner or owned state machine subprocesses)
std::shared_ptr< DecisionRequest > decisionRequest
const BPMN::SequenceFlow * sequenceFlow
static std::string stateName[]
Token * getSequentialPerformerToken() const
Returns token at sequential performer for tokens at activities within sequential adhoc subprocesses.
Token(const StateMachine *owner, const BPMN::FlowNode *node, const Values &status)
nlohmann::ordered_json jsonify() const
std::vector< Attribute * > statusAttributes
Class holding extension elements representing conditions for sequence flows and conditional events.
Class representing a task in which one or more choices have to be made.
Class holding extension elements representing execution data for nodes.
std::vector< std::unique_ptr< Operator > > operators
std::vector< std::unique_ptr< Attribute > > attributes
Vector containing new status attributes declared for the node.
void computeInitialValues(BPMNOS::number currentTime, BPMNOS::Values &status, DataType &data, BPMNOS::Values &globals) const
struct BPMNOS::Model::ExtensionElements::@0 dataUpdate
Struct containing data attributes that are modified through operators and a flag indicating whether a...
bool isInstantaneous
Boolean indicating whether operators may modify timestamp.
bool feasibleEntry(const BPMNOS::Values &status, const DataType &data, const BPMNOS::Values &globals) const
BPMNOS::number getContributionToObjective(const BPMNOS::Values &status, const DataType &data, const BPMNOS::Values &globals) const
Returns the contribution to the objective by the attributes declared for the node.
std::optional< std::unique_ptr< Parameter > > loopIndex
Attribute holding the automatically generated loop index.
std::optional< std::unique_ptr< Parameter > > loopCondition
Boolean attribute indicating whether an exit condition holds.
void applyOperators(BPMNOS::Values &status, DataType &data, BPMNOS::Values &globals) const
AttributeRegistry attributeRegistry
Registry allowing to look up all status and data attributes by their names.
std::vector< std::unique_ptr< Attribute > > data
Vector containing data attributes declared for data objects within the node's scope.
std::optional< std::unique_ptr< Parameter > > loopMaximum
Maximum number of iterations of a standard loop (requires loopIndex).
Class holding extension elements representing gatekeeper conditions for sequence flows.
Class representing adhoc subprocesses with sequential ordering.
Class holding extension elements representing the definition of signal events.
BPMNOS::number name
Signal name.
Class holding extension elements representing the trigger of timer events.
std::vector< BoundaryEvent * > boundaryEvents
std::optional< LoopCharacteristics > loopCharacteristics
@ MultiInstanceSequential
std::unique_ptr< ExtensionElements > extensionElements
std::string id
Id of element.
Base class for all boundary events attached to an Activity.
Scope * parent
Reference to the parent node.
T * as()
Casts the element to the specified type T.
T * represents()
Attempts to cast the element to the specified type T.
TypedStartEvent * startEvent
std::vector< std::reference_wrapper< T > > get()
Returns a vector of elements of type T embedded within a container of type T.
Base class for BPMN elements that may contain incoming and outgoing sequence flows.
std::vector< SequenceFlow * > incoming
Vector containing all incoming sequence flows of the node.
std::vector< SequenceFlow * > outgoing
Vector containing all outgoing sequence flows of the node.
Base class for BPMN elements that may contain a ChildNode elements.
EventSubProcess * compensationEventSubProcess
Pointer to compensation event subprocess of the scope.
The SequenceFlow class encapsulates the information and relationships associated with a sequence flow...
FlowNode * target
Reference to the target node of the sequence flow.
Base class for all start events with an event definition.
void erase_ptr(std::vector< std::unique_ptr< T > > &container, const T *elementPtr)
Erase a specific element from a vector of unique pointers.
std::unordered_map< std::string, std::unique_ptr< Content > > ContentMap
std::unordered_map< std::string, std::variant< std::optional< number >, std::string > > VariedValueMap
std::string to_string(number numericValue, const ValueType &type)
Converts a number to a string.
number to_number(const std::string &valueString, const ValueType &type)
Converts a string to a number.
BPMNOS_NUMBER_TYPE number
std::variant< bool, int, double, std::string > Value
@ SequentialPerformerUpdate
static constexpr size_t Instance
static constexpr size_t Timestamp