1#include <unordered_set>
21Model::Model(
const std::string filename,
const std::vector<std::string> folders)
22 : filename(
std::move(filename))
23 , folders(
std::move(folders))
25 LIMEX::Expression<double>::initialize();
31 LIMEX::Expression<double>::free();
35 std::vector<std::reference_wrapper<XML::bpmnos::tAttribute>>
attributes;
47 std::vector<std::reference_wrapper<XML::bpmnos::tAttribute>>
attributes;
67 return std::make_unique<LookupTable>(lookupName,source,
folders);
76 if ( extensionElements.has_value() ) {
78 if ( tables.has_value() ) {
83 auto callables = LIMEX::Expression<double>::getCallables();
84 if ( std::ranges::find(callables, lookupTable->name) == callables.end() ) {
87 LIMEX::Expression<double>::addCallable(
89 [lookupTable](
const std::vector<double>& args)
91 return lookupTable->at(args);
102 collaboration.has_value()
115 auto extensionElements = std::make_unique<BPMNOS::Model::ExtensionElements>(process,
attributeRegistry,
nullptr,
getData(process) );
132 for (
auto& messageDefinition : extensionElements->messageDefinitions ) {
133 for (
auto& [_,content] : messageDefinition->contentMap ) {
134 auto attribute = content->attribute;
136 throw std::runtime_error(
"Model: Message received by task '" + baseElement->id +
"' attempts to modify global attribute '" + attribute->id +
"'");
139 throw std::runtime_error(
"Model: Message received by task '" + baseElement->id +
"' attempts to modify data attribute '" + attribute->id +
"'");
141 attribute->isImmutable =
false;
147 adHocSubProcess && adHocSubProcess->
performer == adHocSubProcess
161 std::make_unique<Gatekeeper>(sequenceFlow,scope)
166 return std::make_unique<SequentialAdHocSubProcess>(adHocSubProcess,parent);
171 type.has_value() && type->get().xmlns ==
"https://bpmnos.telematique.eu"
173 if ( type->get().value.value ==
"Decision" ) {
175 return std::make_unique<DecisionTask>(task,parent);
178 throw std::runtime_error(
"Model: Illegal type '" + (std::string)type->get().value +
"'");
189 std::make_unique<Timer>(startEvent,parent)
197 std::make_unique<Timer>(boundaryEvent,parent)
205 std::make_unique<Timer>(catchEvent,parent)
213 std::make_unique<Signal>(startEvent,parent)
221 std::make_unique<Signal>(boundaryEvent,parent)
229 std::make_unique<Signal>(catchEvent,parent)
237 std::make_unique<Signal>(throwEvent,parent)
245 std::make_unique<Conditions>(startEvent,parent)
253 std::make_unique<Conditions>(boundaryEvent,parent)
261 std::make_unique<Conditions>(catchEvent,parent)
270 auto contains = [](
const std::vector<std::unique_ptr<Attribute>>&
attributes,
Attribute* attribute) {
271 return std::any_of(
attributes.begin(),
attributes.end(),[attribute](
const std::unique_ptr<Attribute>& ptr) {
272 return ptr.get() == attribute;
276 for (
auto& messageDefinition : extensionElements->messageDefinitions ) {
277 for (
auto& [_,content] : messageDefinition->contentMap ) {
278 Attribute* attribute = content->attribute;
281 throw std::runtime_error(
"Model: Message start event '" + baseElement->id +
"' attempts to modify global attribute '" + attribute->
id +
"'");
284 if ( !contains(parentExtension->data,attribute) ) {
285 throw std::runtime_error(
"Model: Message start event '" + baseElement->id +
"' attempts to modify data attribute '" + attribute->
id +
"' which is not owned by event-subprocess");
291 if ( !contains(parentExtension->attributes,attribute) ) {
305 for (
auto& messageDefinition : extensionElements->messageDefinitions ) {
306 for (
auto& [_,content] : messageDefinition->contentMap ) {
307 Attribute* attribute = content->attribute;
309 throw std::runtime_error(
"Model: Message boundary event '" + baseElement->id +
"' attempts to modify global attribute '" + attribute->
id +
"'");
312 throw std::runtime_error(
"Model: Message boundary event '" + baseElement->id +
"' attempts to modify data attribute '" + attribute->
id +
"'");
325 for (
auto& messageDefinition : extensionElements->messageDefinitions ) {
326 for (
auto& [_,content] : messageDefinition->contentMap ) {
327 Attribute* attribute = content->attribute;
329 throw std::runtime_error(
"Model: Message catch event '" + baseElement->id +
"' attempts to modify global attribute '" + attribute->
id +
"'");
332 throw std::runtime_error(
"Model: Message catch event '" + baseElement->id +
"' attempts to modify data attribute '" + attribute->
id +
"'");
355 for (
auto& sendingProcess :
processes ) {
357 auto throwingMessageEvents = sendingProcess->find_all(
361 for (
auto& receivingProcess :
processes ) {
363 if ( sendingProcess.get() != receivingProcess.get() ) {
365 auto catchingMessageEvents = receivingProcess->find_all(
369 for (
auto throwingMessageEvent : throwingMessageEvents ) {
370 for (
auto catchingMessageEvent : catchingMessageEvents ) {
382 auto& relevantFlows = getMessageFlows(messageEvent);
383 if ( relevantFlows.empty() ) {
391 node = eventSubProcess;
392 scope = eventSubProcess->parent;
395 relevantFlows = getMessageFlows(scope);
398 }
while ( relevantFlows.empty() && node);
400 return relevantFlows;
405 throwingMessageEvent,
406 [](
BPMN::Node* node) -> std::vector<BPMN::MessageFlow*>& {
411 if ( outgoingMessageFlows.empty() ) {
418 for (
auto messageFlow : outgoingMessageFlows ) {
419 auto& [process,flowNode] = messageFlow->target;
420 if ( process == receivingProcess ) {
421 if ( flowNode == catchingMessageEvent ) {
426 found = flowNode->find_all(
427 [catchingMessageEvent](
const BPMN::Node* node) {
return node == catchingMessageEvent;}
431 found = process->find_all(
432 [catchingMessageEvent](
const BPMN::Node* node) {
return node == catchingMessageEvent;}
447 catchingMessageEvent,
448 [](
BPMN::Node* node) -> std::vector<BPMN::MessageFlow*>& {
453 if ( incomingMessageFlows.empty() ) {
460 for (
auto messageFlow : incomingMessageFlows ) {
461 auto& [process,flowNode] = messageFlow->source;
462 if ( process == sendingProcess ) {
463 if ( flowNode == throwingMessageEvent ) {
468 found = flowNode->find_all(
469 [throwingMessageEvent](
const BPMN::Node* node) {
return node == throwingMessageEvent;}
473 found = process->find_all(
474 [throwingMessageEvent](
const BPMN::Node* node) {
return node == throwingMessageEvent;}
488 for (
auto& outgoingMessageDefinition : senderExtension->messageDefinitions ) {
490 for (
auto& incomingMessageDefinition : recipientExtension->messageDefinitions) {
492 assert( outgoingMessageDefinition.get() );
493 assert( incomingMessageDefinition.get() );
495 if ( outgoingMessageDefinition->name != incomingMessageDefinition->name ) {
498 if ( outgoingMessageDefinition->header != incomingMessageDefinition->header ) {
502 if (
messageMayBeCaught(sendingProcess, throwingMessageEvent, receivingProcess, catchingMessageEvent) &&
503 messageMayBeThrown(sendingProcess, throwingMessageEvent, receivingProcess, catchingMessageEvent)
507 senderExtension->messageCandidates.begin(),
508 senderExtension->messageCandidates.end(),
510 ) == senderExtension->messageCandidates.end()
513 senderExtension->messageCandidates.push_back(catchingMessageEvent->
as<
BPMN::FlowNode>());
517 recipientExtension->messageCandidates.begin(),
518 recipientExtension->messageCandidates.end(),
520 ) == recipientExtension->messageCandidates.end()
523 recipientExtension->messageCandidates.push_back(throwingMessageEvent->
as<
BPMN::FlowNode>());
531 for (
auto& resource : resources ) {
533 performer && performer->
name.has_value() && performer->name.value().get().value.value ==
"Sequential"
bool isImmutable
Flag indicating whether attribute value may be changed by operator, choice, or intermediate catch eve...
Class holding extension elements representing execution data for nodes.
AttributeRegistry attributeRegistry
Registry allowing to look up all status and data attributes by their names.
std::unique_ptr< BPMN::FlowNode > createTimerStartEvent(XML::bpmn::tStartEvent *startEvent, BPMN::Scope *parent) override
std::unique_ptr< BPMN::FlowNode > createSignalCatchEvent(XML::bpmn::tCatchEvent *catchEvent, BPMN::Scope *parent) override
void createMessageCandidates(BPMN::Process *sendingProcess, BPMN::FlowNode *throwingMessageEvent, BPMN::Process *receivingProcess, BPMN::FlowNode *catchingMessageEvent)
std::unique_ptr< BPMN::FlowNode > createSignalThrowEvent(XML::bpmn::tThrowEvent *throwEvent, BPMN::Scope *parent) override
std::unique_ptr< BPMN::FlowNode > createSignalBoundaryEvent(XML::bpmn::tBoundaryEvent *boundaryEvent, BPMN::Scope *parent) override
std::unique_ptr< LookupTable > createLookupTable(XML::bpmnos::tTable *table)
std::vector< std::reference_wrapper< XML::bpmnos::tAttribute > > getData(XML::bpmn::tBaseElement *element)
std::vector< std::reference_wrapper< XML::bpmnos::tAttribute > > getAttributes(XML::bpmn::tBaseElement *element)
std::vector< BPMN::MessageFlow * > & determineMessageFlows(BPMN::FlowNode *messageEvent, auto getMessageFlows)
Model(const std::string filename, const std::vector< std::string > folders={})
std::unique_ptr< BPMN::SequenceFlow > createSequenceFlow(XML::bpmn::tSequenceFlow *sequenceFlow, BPMN::Scope *scope) override
std::unique_ptr< BPMN::FlowNode > createMessageBoundaryEvent(XML::bpmn::tBoundaryEvent *boundaryEvent, BPMN::Scope *parent) override
std::unique_ptr< XML::XMLObject > createRoot(const std::string &filename) override
std::vector< std::unique_ptr< Attribute > > attributes
Vector containing new global attributes declared for the model.
void createMessageFlows() override
std::unique_ptr< BPMN::FlowNode > createMessageStartEvent(XML::bpmn::tStartEvent *startEvent, BPMN::Scope *parent) override
bool messageMayBeThrown(BPMN::Process *sendingProcess, BPMN::FlowNode *throwingMessageEvent, BPMN::Process *receivingProcess, BPMN::FlowNode *catchingMessageEvent)
std::unique_ptr< BPMN::Process > createProcess(XML::bpmn::tProcess *process) override
std::unique_ptr< BPMN::FlowNode > createConditionalCatchEvent(XML::bpmn::tCatchEvent *catchEvent, BPMN::Scope *parent) override
std::unique_ptr< BPMN::FlowNode > createAdHocSubProcess(XML::bpmn::tAdHocSubProcess *adHocSubProcess, BPMN::Scope *parent) override
const std::string filename
File name of the BPMN model.
bool messageMayBeCaught(BPMN::Process *sendingProcess, BPMN::FlowNode *throwingMessageEvent, BPMN::Process *receivingProcess, BPMN::FlowNode *catchingMessageEvent)
std::unique_ptr< BPMN::FlowNode > createMessageCatchEvent(XML::bpmn::tCatchEvent *catchEvent, BPMN::Scope *parent) override
const std::vector< std::string > folders
Folders containing lookup tables.
std::unique_ptr< BPMN::FlowNode > createTimerCatchEvent(XML::bpmn::tCatchEvent *catchEvent, BPMN::Scope *parent) override
std::unique_ptr< BPMN::FlowNode > createMessageThrowEvent(XML::bpmn::tThrowEvent *throwEvent, BPMN::Scope *parent) override
AttributeRegistry attributeRegistry
Registry allowing to look up all status and data attributes by their names.
std::unique_ptr< BPMN::FlowNode > createConditionalBoundaryEvent(XML::bpmn::tBoundaryEvent *boundaryEvent, BPMN::Scope *parent) override
std::unique_ptr< BPMN::FlowNode > createActivity(XML::bpmn::tActivity *activity, BPMN::Scope *parent) override
std::vector< std::unique_ptr< LookupTable > > lookupTables
Vector containing lookup tables declared in model.
std::unique_ptr< BPMN::FlowNode > createSignalStartEvent(XML::bpmn::tStartEvent *startEvent, BPMN::Scope *parent) override
std::unique_ptr< BPMN::FlowNode > createTask(XML::bpmn::tTask *task, BPMN::Scope *parent) override
std::unique_ptr< BPMN::FlowNode > createConditionalStartEvent(XML::bpmn::tStartEvent *startEvent, BPMN::Scope *parent) override
std::unique_ptr< BPMN::FlowNode > createTimerBoundaryEvent(XML::bpmn::tBoundaryEvent *boundaryEvent, BPMN::Scope *parent) override
std::unique_ptr< BPMN::EventSubProcess > createEventSubProcess(XML::bpmn::tSubProcess *subProcess, BPMN::Scope *parent) override
static bool hasSequentialPerformer(const std::vector< std::reference_wrapper< XML::bpmn::tResourceRole > > &resources)
Class representing adhoc subprocesses with sequential ordering.
std::unique_ptr< ExtensionElements > extensionElements
T * get()
Casts the element to the specified type T.
Base class for BPMN elements within a Scope.
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.
Base class for BPMN elements that may contain incoming and outgoing sequence flows.
virtual std::unique_ptr< FlowNode > createTimerStartEvent(XML::bpmn::tStartEvent *startEvent, Scope *parent)
virtual std::unique_ptr< FlowNode > createMessageThrowEvent(XML::bpmn::tThrowEvent *throwEvent, Scope *parent)
std::vector< std::unique_ptr< Process > > processes
virtual std::unique_ptr< FlowNode > createMessageBoundaryEvent(XML::bpmn::tBoundaryEvent *boundaryEvent, Scope *parent)
virtual std::unique_ptr< SequenceFlow > createSequenceFlow(XML::bpmn::tSequenceFlow *sequenceFlow, Scope *scope)
virtual std::unique_ptr< FlowNode > createSignalBoundaryEvent(XML::bpmn::tBoundaryEvent *boundaryEvent, Scope *parent)
virtual void readBPMNFile(const std::string &filename)
virtual std::unique_ptr< FlowNode > createTimerBoundaryEvent(XML::bpmn::tBoundaryEvent *boundaryEvent, Scope *parent)
virtual std::unique_ptr< FlowNode > createTimerCatchEvent(XML::bpmn::tCatchEvent *catchEvent, Scope *parent)
virtual std::unique_ptr< FlowNode > createMessageStartEvent(XML::bpmn::tStartEvent *startEvent, Scope *parent)
virtual std::unique_ptr< FlowNode > createConditionalBoundaryEvent(XML::bpmn::tBoundaryEvent *boundaryEvent, Scope *parent)
virtual std::unique_ptr< FlowNode > createActivity(XML::bpmn::tActivity *activity, Scope *parent)
virtual std::unique_ptr< XML::XMLObject > createRoot(const std::string &filename)
virtual std::unique_ptr< FlowNode > createConditionalStartEvent(XML::bpmn::tStartEvent *startEvent, Scope *parent)
virtual std::unique_ptr< FlowNode > createConditionalCatchEvent(XML::bpmn::tCatchEvent *catchEvent, Scope *parent)
virtual std::unique_ptr< EventSubProcess > createEventSubProcess(XML::bpmn::tSubProcess *subProcess, Scope *parent)
virtual void createMessageFlows()
virtual std::unique_ptr< FlowNode > createMessageCatchEvent(XML::bpmn::tCatchEvent *catchEvent, Scope *parent)
virtual std::unique_ptr< FlowNode > createSignalThrowEvent(XML::bpmn::tThrowEvent *throwEvent, Scope *parent)
virtual std::unique_ptr< FlowNode > createSignalCatchEvent(XML::bpmn::tCatchEvent *catchEvent, Scope *parent)
virtual std::unique_ptr< Process > createProcess(XML::bpmn::tProcess *process)
virtual std::unique_ptr< FlowNode > createTask(XML::bpmn::tTask *task, Scope *parent)
static std::unique_ptr< T > bind(std::unique_ptr< T > &&baseElement, std::unique_ptr< ExtensionElements > &&extensionElements)
Binds the extension elements to the given baseElement.
virtual std::unique_ptr< FlowNode > createSignalStartEvent(XML::bpmn::tStartEvent *startEvent, Scope *parent)
Base class for all nodes in a BPMN model.
std::vector< MessageFlow * > receiving
Vector containing all message flows going in to the node.
std::vector< MessageFlow * > sending
Vector containing all message flows going out of the node.
Base class for BPMN elements that may contain a ChildNode elements.
std::vector< std::reference_wrapper< T > > find()
Find all descendants of type T.
std::optional< std::reference_wrapper< Attribute > > getOptionalAttributeByName(const AttributeName &attributeName)
Get an optional attribute with the specified attribute name.
std::vector< std::reference_wrapper< T > > getChildren()
Get all children of type T.
T * get()
Attempt to cast the current instance to the specified type T.
Attribute & getRequiredAttributeByName(const AttributeName &attributeName)
Get a required attribute with the specified attribute name.
std::optional< std::reference_wrapper< tExtensionElements > > extensionElements
std::optional< std::reference_wrapper< Attribute > > name
Attribute value can be expected to be of type 'std::string'.
const std::string Instance