github.com/unirita/cuto@v0.9.8-0.20160830082821-aa6652f877b7/flowgen/converter/bpmn.go (about) 1 package converter 2 3 import "encoding/xml" 4 5 // Definitions element in BPMN. 6 type Definitions struct { 7 XMLName xml.Name `xml:"definitions"` 8 Process *Process `xml:"process"` 9 } 10 11 // NewDefinitions create empty Definitions object. 12 func NewDefinitions() *Definitions { 13 d := new(Definitions) 14 d.Process = NewProcess() 15 return d 16 } 17 18 // AppendServiceTask appends ServiceTask object to Definitions#Process. 19 func (d *Definitions) AppendServiceTask(task *ServiceTask) { 20 d.Process.Tasks = append(d.Process.Tasks, task) 21 } 22 23 // AppendParallelGateway appends ParallelGateway object to Definitions#Process. 24 func (d *Definitions) AppendParallelGateway(gateway *ParallelGateway) { 25 d.Process.Gateways = append(d.Process.Gateways, gateway) 26 } 27 28 // AppendSequenceFlow appends SequenceFlow object to Definitions#Process. 29 func (d *Definitions) AppendSequenceFlow(flow *SequenceFlow) { 30 d.Process.Flows = append(d.Process.Flows, flow) 31 } 32 33 // AppendJob appends job element to Definitions object. 34 // This function returns job ID to create connection with next element. 35 func (d *Definitions) AppendJob(job *Job, pre string) string { 36 s := NewServiceTask(job) 37 d.AppendServiceTask(s) 38 d.AppendSequenceFlow(NewSequenceFlow(pre, s.ID)) 39 return s.ID 40 } 41 42 // AppendGateway appends gateway element to Definitions object. 43 // This function returns close gateway ID to create connection with next element. 44 func (d *Definitions) AppendGateway(gw *Gateway, pre string) string { 45 openGW, closeGW := NewParallelGatewayPair(gw) 46 d.AppendParallelGateway(openGW) 47 d.AppendParallelGateway(closeGW) 48 d.AppendSequenceFlow(NewSequenceFlow(pre, openGW.ID)) 49 50 // Append inner paths. 51 for _, pathHead := range gw.PathHeads { 52 preInPath := openGW.ID 53 current := pathHead 54 for { 55 d.AppendJob(current, preInPath) 56 preInPath = current.ID() 57 var ok bool 58 59 next := current.Next() 60 if next == nil { 61 break 62 } 63 64 current, ok = next.(*Job) 65 if !ok { 66 panic("Nest of gateway detected.") 67 } 68 } 69 d.AppendSequenceFlow(NewSequenceFlow(preInPath, closeGW.ID)) 70 } 71 return closeGW.ID 72 } 73 74 // Process element in BPMN. 75 type Process struct { 76 Start *StartEvent `xml:"startEvent"` 77 End *EndEvent `xml:"endEvent"` 78 Tasks []*ServiceTask `xml:"serviceTask"` 79 Gateways []*ParallelGateway `xml:"parallelGateway"` 80 Flows []*SequenceFlow `xml:"sequenceFlow"` 81 } 82 83 // Create empty Process object. 84 func NewProcess() *Process { 85 p := new(Process) 86 p.Start = NewStartEvent() 87 p.End = NewEndEvent() 88 p.Tasks = make([]*ServiceTask, 0) 89 p.Gateways = make([]*ParallelGateway, 0) 90 p.Flows = make([]*SequenceFlow, 0) 91 return p 92 } 93 94 // StartEvent element in BPMN. 95 type StartEvent struct { 96 ID string `xml:"id,attr"` 97 } 98 99 // Create StartEvent object with unique ID. 100 func NewStartEvent() *StartEvent { 101 s := new(StartEvent) 102 s.ID = ":start" 103 return s 104 } 105 106 // EndEvent element in BPMN. 107 type EndEvent struct { 108 ID string `xml:"id,attr"` 109 } 110 111 // Create EndEvent object with unique ID. 112 func NewEndEvent() *EndEvent { 113 e := new(EndEvent) 114 e.ID = ":end" 115 return e 116 } 117 118 // ServiceTask element in BPMN. 119 type ServiceTask struct { 120 ID string `xml:"id,attr"` 121 Name string `xml:"name,attr"` 122 } 123 124 // Create ServiceTask object from job element. 125 func NewServiceTask(job *Job) *ServiceTask { 126 s := new(ServiceTask) 127 s.ID = job.ID() 128 s.Name = job.Name() 129 return s 130 } 131 132 // ParallelGateway element in BPMN. 133 type ParallelGateway struct { 134 ID string `xml:"id,attr"` 135 } 136 137 // Create pair of ParallelGateway to open and close parallel paths. 138 // This function has two return values. 139 // First one is gateway for open, second one is gateway for close. 140 func NewParallelGatewayPair(gw *Gateway) (*ParallelGateway, *ParallelGateway) { 141 const ( 142 openSuffix = "_open" 143 closeSuffix = "_close" 144 ) 145 146 openGW := new(ParallelGateway) 147 openGW.ID = gw.ID() + openSuffix 148 closeGW := new(ParallelGateway) 149 closeGW.ID = gw.ID() + closeSuffix 150 return openGW, closeGW 151 } 152 153 // SequenceFlow element in BPMN. 154 type SequenceFlow struct { 155 From string `xml:"sourceRef,attr"` 156 To string `xml:"targetRef,attr"` 157 } 158 159 // Create SequenceFlow 160 func NewSequenceFlow(from, to string) *SequenceFlow { 161 s := new(SequenceFlow) 162 s.From = from 163 s.To = to 164 return s 165 }