-
Notifications
You must be signed in to change notification settings - Fork 0
Home
gobpmnModels is a library in the Go language for classes and elements in the Business Process Model Notation.
Note
This library makes no claim to the exact application of the specification or the definition of all elements. The aim is a step-by-step adaptation to the OMG specification.
All Elements for Business Process Model Notation are defined in the folder /pkg/Name_Of_Element.go. All declared packages containing the elements to build the model from scratch. It doesn't contain the elements, like BPMNDI (for diagrams), to build a fully diagram out of it.
The following packages are declared:
- artifacts
- attributes
- collaboration
- conditional
- core
- data
- events
- flow
- gateways
- impl
- loop
- marker
- pool
- process
- subprocesses
- tasks
- time
go get https://github.com/deemount/gobpmnTypes
go get https://github.com/deemount/gobpmnModels
Example how to import a package
import github.com/deemount/gobpmnModels/pkg/tasks
Before you create an element or package for gobpmnModels, please enquire about the specifications of the OMG.
Link to the OMG Specification in PDF
A package in gobpmnModels can consist of one element or a group of elements. The name of a package is therefore derived either from the name of the element (provided there is no name conflict with structs or interfaces), the group name or an assigned context.
The name of the package must not conflict with the names already assigned to other packages in the respective repositories.
A package usually consists of the following files:
- Delegates.go
- Interfaces.go
- Structs.go
- Types.go
In addition, there are the file names for the respective element that is defined in this package.
An element in a package is first defined in a struct in the Structs.go file with the name of the element. I do not use (or try not to use) any abbreviations or other abstractions, but write the name of the element in the so-called "SnakeCase" variant. By capitalising the name, I ensure that the defined structure can be reused globally in other packages.
An example to illustrate this
type ElementStructur struct {}
Note
Each element is assigned to the @Elementary section
Many elements consist of the same attributes. Some packages therefore already contain further structure definitions based on existing attributes from other elements or included elements, which can simply be copied and pasted. If several elements have been defined in a package and these have redundant fields, it is advisable to define these in separate structure definitions.
type ElementAttributes struct {
ID string
}
/*
* @Elementary
*/
type ElementStructur struct {
ElementsAttributes
}
This ensures that repetitive attributes only have to be edited in one specific place.
Now the defined struct or element must be assigned to the dependent element by copying the name and type to it. Here too, you must have knowledge of the structure of a BPMN model.
Most elements in gobpmnModels have a copy of their structure labelled with a T prefix. This decision was made because otherwise no unmarshal would be possible when reading the XML file with the BPMN specification. The first call of the T-structures takes place in the directory /repository in the file BpmnEngine.go under the method LoadFromBytes.
The implementation of the T-structures is far from complete and so far contains only a few copied elements. And here too, not all fields have been copied from the original structure, but only to the extent necessary for initial operable test executions.
These structures could be eliminated with an additional XSD interpreter. However, I am not yet aware of any tool that I could easily implement for use.
Note:
In future, no T-structures should be defined or used.
Example of Definitions Struct with copy in T
// Definitions represents the root element
Definitions struct {
XMLName xml.Name `xml:"bpmn:definitions" json:"-"`
Bpmn string `xml:"xmlns:bpmn,attr" json:"-"`
Xsd string `xml:"xmlns:xsd,attr,omitempty" json:"-"`
Xsi string `xml:"xmlns:xsi,omitempty" json:"-"`
XsiSchemaLocation string `xml:"xsi:schemaLocation,attr,omitempty" json:"-"`
DC string `xml:"xmlns:dc,attr,omitempty" json:"-"`
OmgDC string `xml:"xmlns:omgdc,attr,omitempty" json:"-"`
ID string `xml:"id,attr" json:"id"`
TargetNamespace string `xml:"targetNamespace,attr" json:"-"`
DefinitionsBaseElements
}
// TDefinitions ...
TDefinitions struct {
XMLName xml.Name `xml:"definitions" json:"-"`
ID string `xml:"id,attr" json:"id"`
TDefinitionsBaseElements
}
)
There are so-called getter and setter methods for each element or field. The setter methods have a pointer receiver and the prefix "Set" in front of them. The getter methods have a value receiver and (contrary to the recommendation) a prefix named "Get" in front. The decision in favour of a prefix with "Get" was made because some fields would otherwise have collided with the name of the method.
Note:
In future, however, there should be fewer getter and setter methods available, but instead all-encompassing methods that lead more quickly to a dependent link between the elements and fields through the correct parameter selection.
Example of SetID for the element collaboration
func (collaboration *Collaboration) SetID(typ string, suffix interface{}) {
switch typ {
case "collaboration":
collaboration.ID = fmt.Sprintf("Collaboration_%v", suffix)
}
}
Example of GetID for the element collaboration
func (collaboration Collaboration) GetID() *Collaboration {
return &collaboration.ID
}