-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreflect.go
160 lines (131 loc) · 4.42 KB
/
reflect.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package gobpmn_reflection
import (
"reflect"
"strings"
)
// Reflect ...
type Reflect struct {
Anonym map[int]string
Config map[int]string
Rflct map[int]string
IF interface{}
Temporary reflect.Value
Element reflect.Value
}
// New initialize interface {} p
func New(p interface{}) *Reflect {
return &Reflect{IF: p}
}
// Interface where Element is the interface {}
func (ref *Reflect) Interface() *Reflect {
ref.Element = reflect.ValueOf(&ref.IF).Elem()
return ref
}
// Allocate allocates a temporary variable with type of the struct.
// ref.Element.Elem() is the value contained in the interface
func (ref *Reflect) Allocate() *Reflect {
ref.Temporary = reflect.New(ref.Element.Elem().Type()).Elem()
ref.Temporary.Set(ref.Element.Elem())
return ref
}
/*
Maps initializes maps to analyze then later
- anonym: all anonymous fields
- config: all boolean fields
- rflct: all reflection fields
*/
func (ref *Reflect) Maps() *Reflect {
ref.Anonym = make(map[int]string)
ref.Config = make(map[int]string)
ref.Rflct = make(map[int]string)
return ref
}
// Assign holds the methods to reflect fields of interface {}
func (ref *Reflect) Assign() {
ref.anonymousFields()
ref.reflectionType()
ref.boolType()
}
// Set temporary variable values to interface {}
// This method is set inside at the end of a build method, where
// fields of a struct got reflected by names
func (ref *Reflect) Set() any {
ref.Element.Set(ref.Temporary)
return ref.Element.Interface()
}
// Defaults receives the definitions repository by the app in p argument
// and calls the main elements to set the maps, including process parameters
// n of process. The method contains the reflected process definition (p interface{})
// and calls it by the reflected method name.
// Note: This method hides specific setters (SetProcess, SetCollaboration, SetDiagram).
func (ref *Reflect) Defaults(p interface{}, opts ...Option) {
// el is the interface {} of a given definition
el := reflect.ValueOf(&p).Elem()
//counter := reflect.ValueOf(&c).Elem()
// Get the number of processes
//numParticipants := counter.Elem().FieldByName("Participant").Int()
//numProcess := counter.Elem().FieldByName("Process").Int()
// Allocate a temporary variable with type of the struct.
// el.Elem() is the value contained in the interface
definitions := reflect.New(el.Elem().Type()).Elem() // *core.Definitions
definitions.Set(el.Elem()) // reflected process definitions el will be assigned to the core definitions
//if numParticipants > 0 {
collaboration := definitions.MethodByName("SetCollaboration")
collaboration.Call([]reflect.Value{})
//}
//if numProcess > 0 {
process := definitions.MethodByName("SetProcess")
process.Call([]reflect.Value{reflect.ValueOf(1)}) // int(numProcess)
//}
/*
Actually, diagram is decoupled. So, no func needs to be called here ...
diagram := definitions.MethodByName("SetDiagram")
diagram.Call([]reflect.Value{reflect.ValueOf(1)}) // 1 represents number of diagrams
*/
}
/*
* @private
*/
// anonymousFields takes all compounds which are anonymous
func (ref *Reflect) anonymousFields() {
fields := reflect.VisibleFields(reflect.TypeOf(ref.IF))
index := 0
for _, field := range fields {
if field.Anonymous {
ref.Anonym[index] = field.Name
index++
}
}
}
// reflectionType with three static filter options
func (ref Reflect) reflectionType() {
fields := reflect.VisibleFields(reflect.TypeOf(ref.IF))
index := 0
for _, field := range fields {
if !field.Anonymous && ref.isNotDefinitions(field) && field.Type.Name() == "Injection" {
ref.Rflct[index] = field.Name
index++
}
}
}
// boolType with one static filter option, which must be kind of reflect.Bool
// The bool type of a field in a struct describes mostly configuration settings
// The field must contain a sibling in title case, e.g. IsExecutable
func (ref Reflect) boolType() {
fields := reflect.VisibleFields(reflect.TypeOf(ref.IF))
index := 0
for _, field := range fields {
if field.Type.Kind() == reflect.Bool {
ref.Config[index] = field.Name
index++
}
}
}
// isDefinitions ...
func (ref *Reflect) isDefinitions(field reflect.StructField) bool {
return strings.ToLower(field.Name) == "def" || strings.ToLower(field.Name) == "definitions"
}
// isNotDefinitions ...
func (ref *Reflect) isNotDefinitions(field reflect.StructField) bool {
return strings.ToLower(field.Name) != "def" || strings.ToLower(field.Name) != "definitions"
}