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))
24 , attributeRegistry(limexHandle)
30 std::vector<std::reference_wrapper<XML::bpmnos::tAttribute>>
attributes;
42 std::vector<std::reference_wrapper<XML::bpmnos::tAttribute>>
attributes;
62 return std::make_unique<LookupTable>(lookupName,source,
folders);
71 if ( extensionElements.has_value() ) {
73 if ( tables.has_value() ) {
81 [lookupTable](
const std::vector<double>& args)
83 return lookupTable->at(args);
93 collaboration.has_value()
106 auto extensionElements = std::make_unique<BPMNOS::Model::ExtensionElements>(process,
attributeRegistry,
nullptr,
getData(process) );
123 for (
auto& messageDefinition : extensionElements->messageDefinitions ) {
124 for (
auto& [_,content] : messageDefinition->contentMap ) {
125 auto attribute = content->attribute;
127 throw std::runtime_error(
"Model: Message received by task '" + baseElement->id +
"' attempts to modify global attribute '" + attribute->id +
"'");
130 throw std::runtime_error(
"Model: Message received by task '" + baseElement->id +
"' attempts to modify data attribute '" + attribute->id +
"'");
132 attribute->isImmutable =
false;
138 adHocSubProcess && adHocSubProcess->
performer == adHocSubProcess
152 std::make_unique<Gatekeeper>(sequenceFlow,scope)
157 return std::make_unique<SequentialAdHocSubProcess>(adHocSubProcess,parent);
162 type.has_value() && type->get().xmlns ==
"https://bpmnos.telematique.eu"
164 if ( type->get().value.value ==
"Decision" ) {
166 return std::make_unique<DecisionTask>(task,parent);
169 throw std::runtime_error(
"Model: Illegal type '" + (std::string)type->get().value +
"'");
180 std::make_unique<Timer>(startEvent,parent)
188 std::make_unique<Timer>(boundaryEvent,parent)
196 std::make_unique<Timer>(catchEvent,parent)
204 std::make_unique<Signal>(startEvent,parent)
212 std::make_unique<Signal>(boundaryEvent,parent)
220 std::make_unique<Signal>(catchEvent,parent)
228 std::make_unique<Signal>(throwEvent,parent)
236 std::make_unique<Conditions>(startEvent,parent)
244 std::make_unique<Conditions>(boundaryEvent,parent)
252 std::make_unique<Conditions>(catchEvent,parent)
261 auto contains = [](
const std::vector<std::unique_ptr<Attribute>>&
attributes,
Attribute* attribute) {
262 return std::any_of(
attributes.begin(),
attributes.end(),[attribute](
const std::unique_ptr<Attribute>& ptr) {
263 return ptr.get() == attribute;
267 for (
auto& messageDefinition : extensionElements->messageDefinitions ) {
268 for (
auto& [_,content] : messageDefinition->contentMap ) {
269 Attribute* attribute = content->attribute;
272 throw std::runtime_error(
"Model: Message start event '" + baseElement->id +
"' attempts to modify global attribute '" + attribute->
id +
"'");
275 if ( !contains(parentExtension->data,attribute) ) {
276 throw std::runtime_error(
"Model: Message start event '" + baseElement->id +
"' attempts to modify data attribute '" + attribute->
id +
"' which is not owned by event-subprocess");
282 if ( !contains(parentExtension->attributes,attribute) ) {
296 for (
auto& messageDefinition : extensionElements->messageDefinitions ) {
297 for (
auto& [_,content] : messageDefinition->contentMap ) {
298 Attribute* attribute = content->attribute;
300 throw std::runtime_error(
"Model: Message boundary event '" + baseElement->id +
"' attempts to modify global attribute '" + attribute->
id +
"'");
303 throw std::runtime_error(
"Model: Message boundary event '" + baseElement->id +
"' attempts to modify data attribute '" + attribute->
id +
"'");
316 for (
auto& messageDefinition : extensionElements->messageDefinitions ) {
317 for (
auto& [_,content] : messageDefinition->contentMap ) {
318 Attribute* attribute = content->attribute;
320 throw std::runtime_error(
"Model: Message catch event '" + baseElement->id +
"' attempts to modify global attribute '" + attribute->
id +
"'");
323 throw std::runtime_error(
"Model: Message catch event '" + baseElement->id +
"' attempts to modify data attribute '" + attribute->
id +
"'");
346 for (
auto& sendingProcess :
processes ) {
348 auto throwingMessageEvents = sendingProcess->find_all(
352 for (
auto& receivingProcess :
processes ) {
354 if ( sendingProcess.get() != receivingProcess.get() ) {
356 auto catchingMessageEvents = receivingProcess->find_all(
360 for (
auto throwingMessageEvent : throwingMessageEvents ) {
361 for (
auto catchingMessageEvent : catchingMessageEvents ) {
373 auto& relevantFlows = getMessageFlows(messageEvent);
374 if ( relevantFlows.empty() ) {
382 node = eventSubProcess;
383 scope = eventSubProcess->parent;
386 relevantFlows = getMessageFlows(scope);
389 }
while ( relevantFlows.empty() && node);
391 return relevantFlows;
396 throwingMessageEvent,
397 [](
BPMN::Node* node) -> std::vector<BPMN::MessageFlow*>& {
402 if ( outgoingMessageFlows.empty() ) {
409 for (
auto messageFlow : outgoingMessageFlows ) {
410 auto& [process,flowNode] = messageFlow->target;
411 if ( process == receivingProcess ) {
412 if ( flowNode == catchingMessageEvent ) {
417 found = flowNode->find_all(
418 [catchingMessageEvent](
const BPMN::Node* node) {
return node == catchingMessageEvent;}
422 found = process->find_all(
423 [catchingMessageEvent](
const BPMN::Node* node) {
return node == catchingMessageEvent;}
438 catchingMessageEvent,
439 [](
BPMN::Node* node) -> std::vector<BPMN::MessageFlow*>& {
444 if ( incomingMessageFlows.empty() ) {
451 for (
auto messageFlow : incomingMessageFlows ) {
452 auto& [process,flowNode] = messageFlow->source;
453 if ( process == sendingProcess ) {
454 if ( flowNode == throwingMessageEvent ) {
459 found = flowNode->find_all(
460 [throwingMessageEvent](
const BPMN::Node* node) {
return node == throwingMessageEvent;}
464 found = process->find_all(
465 [throwingMessageEvent](
const BPMN::Node* node) {
return node == throwingMessageEvent;}
479 for (
auto& outgoingMessageDefinition : senderExtension->messageDefinitions ) {
481 for (
auto& incomingMessageDefinition : recipientExtension->messageDefinitions) {
483 assert( outgoingMessageDefinition.get() );
484 assert( incomingMessageDefinition.get() );
486 if ( outgoingMessageDefinition->name != incomingMessageDefinition->name ) {
489 if ( outgoingMessageDefinition->header != incomingMessageDefinition->header ) {
493 if (
messageMayBeCaught(sendingProcess, throwingMessageEvent, receivingProcess, catchingMessageEvent) &&
494 messageMayBeThrown(sendingProcess, throwingMessageEvent, receivingProcess, catchingMessageEvent)
498 senderExtension->messageCandidates.begin(),
499 senderExtension->messageCandidates.end(),
501 ) == senderExtension->messageCandidates.end()
504 senderExtension->messageCandidates.push_back(catchingMessageEvent->
as<
BPMN::FlowNode>());
508 recipientExtension->messageCandidates.begin(),
509 recipientExtension->messageCandidates.end(),
511 ) == recipientExtension->messageCandidates.end()
514 recipientExtension->messageCandidates.push_back(throwingMessageEvent->
as<
BPMN::FlowNode>());
522 for (
auto& resource : resources ) {
524 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
LIMEX::Handle< double > limexHandle
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)
std::unique_ptr< XML::XMLObject > root
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< T > > getOptionalChild()
Get an optional child of type T.
std::optional< std::reference_wrapper< Attribute > > getOptionalAttributeByName(const AttributeName &name)
Get an optional attribute with the specified attribute name.
Attribute & getRequiredAttributeByName(const AttributeName &name)
Get a required 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.
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