@@ -2,6 +2,7 @@ package types
22
33import (
44 "fmt"
5+ "strings"
56)
67
78type SeclangActions struct {
@@ -110,6 +111,92 @@ func (a ActionWithParam) GetParam() string {
110111 return ""
111112}
112113
114+ type VarAssignment struct {
115+ Variable string `yaml:"variable"`
116+ Value string `yaml:"value"`
117+ }
118+
119+ type SetvarAction struct {
120+ Collection CollectionName `yaml:"collection,omitempty"`
121+ Operation string `yaml:"operation,omitempty"`
122+ Assignments []VarAssignment `yaml:"assignments,omitempty"`
123+ }
124+
125+ // GetKey returns the action name (it is always "setvar")
126+ func (a SetvarAction ) GetKey () string {
127+ return SetVar .String ()
128+ }
129+
130+ // ToString allows to implement the Action interface
131+ func (a SetvarAction ) ToString () string {
132+ if len (a .Assignments ) == 0 {
133+ return ""
134+ }
135+
136+ var result []string
137+ // Reconstruct the setvar actions
138+ for _ , asg := range a .Assignments {
139+ result = append (result , SetVar .String ()+ ":" + a .Collection .String ()+ "." + asg .Variable + a .Operation + asg .Value )
140+ }
141+ return strings .Join (result , ", " )
142+ }
143+
144+ func (a * SetvarAction ) AppendAssignment (variable , value string ) error {
145+ a .Assignments = append (a .Assignments , VarAssignment {Variable : variable , Value : value })
146+ return nil
147+ }
148+
149+ func (a SetvarAction ) GetAllParams () []string {
150+ if len (a .Assignments ) == 0 {
151+ return []string {}
152+ }
153+
154+ var result []string
155+ // Get all the variables
156+ for _ , asg := range a .Assignments {
157+ res := SetVar .String () + ":" + a .Collection .String () + "." + asg .Variable + a .Operation + asg .Value
158+ result = append (result , res )
159+ }
160+ return result
161+ }
162+
163+ func (s VarAssignment ) MarshalYAML () (interface {}, error ) {
164+ if s .Variable == "" || s .Value == "" {
165+ return nil , fmt .Errorf ("invalid variable assignment: missing variable name or value" )
166+ }
167+ return map [string ]string {s .Variable : s .Value }, nil
168+ }
169+
170+ func (s SetvarAction ) MarshalYAML () (interface {}, error ) {
171+ if s .Collection == UNKNOWN_COLLECTION || s .Operation == "" || len (s .Assignments ) == 0 {
172+ return nil , fmt .Errorf ("invalid setvar action: missing collection name, operation, or assignments" )
173+ }
174+ if s .Collection == TX && s .Operation == "=" {
175+ // Default case
176+ res := map [string ][]VarAssignment {}
177+ res ["setvar" ] = s .Assignments
178+ return res , nil
179+ } else {
180+ // Non-default case, collection is different to `TX` or operation is different to `=`.
181+ // Fields are re-mapped to a mirrored struct in order to preserve the order in the YAML
182+ res := map [string ]struct {
183+ Collection CollectionName
184+ Operation string
185+ Assignments []VarAssignment
186+ }{}
187+ res ["setvar" ] = struct {
188+ Collection CollectionName
189+ Operation string
190+ Assignments []VarAssignment
191+ }{
192+ Collection : s .Collection ,
193+ Operation : s .Operation ,
194+ Assignments : s .Assignments ,
195+ }
196+ return res , nil
197+ }
198+ }
199+
113200// ActionType is a constraint for all action types
114201type ActionType interface {
115202 DisruptiveAction | FlowAction | DataAction | NonDisruptiveAction
@@ -130,6 +217,14 @@ func NewActionWithParam[T ActionType](action T, param string) (ActionWithParam,
130217 return ActionWithParam {actionStr : param }, nil
131218}
132219
220+ // NewSetvarAction creates a new SetvarAction with the given collection name, operation, and variable assignments
221+ func NewSetvarAction (collection CollectionName , operation string , vars []VarAssignment ) (SetvarAction , error ) {
222+ if collection != GLOBAL && collection != IP && collection != RESOURCE && collection != SESSION && collection != TX && collection != USER {
223+ return SetvarAction {}, fmt .Errorf ("invalid setvar action: invalid collection name '%s'" , collection )
224+ }
225+ return SetvarAction {Collection : collection , Operation : operation , Assignments : vars }, nil
226+ }
227+
133228type DisruptiveAction int
134229
135230const (
@@ -431,6 +526,42 @@ func (s *SeclangActions) AddNonDisruptiveActionWithParam(action NonDisruptiveAct
431526 return nil
432527}
433528
529+ // AddSetvarAction adds a setvar action to the NonDisruptiveActions list
530+ func (s * SeclangActions ) AddSetvarAction (collection , variable , operation , value string ) error {
531+ colName := stringToCollectionName (strings .ToUpper (collection ))
532+ // Check if there is already a setvar action in the last position
533+ if len (s .NonDisruptiveActions ) > 0 {
534+ lastAction := s .NonDisruptiveActions [len (s .NonDisruptiveActions )- 1 ]
535+ if lastAction .GetKey () != SetVar .String () || lastAction .(SetvarAction ).Collection != colName || lastAction .(SetvarAction ).Operation != operation {
536+ // If the last action is not setvar, we need to create a new one
537+ newAction , err := NewSetvarAction (colName , operation , []VarAssignment {{Variable : variable , Value : value }})
538+ if err != nil {
539+ return err
540+ }
541+ s .NonDisruptiveActions = append (s .NonDisruptiveActions , newAction )
542+ } else {
543+ // If the last action is setvar, we need to append the param to it
544+ sv , ok := lastAction .(SetvarAction )
545+ if ! ok {
546+ return fmt .Errorf ("invalid action type: expected SetvarAction, got %T" , lastAction )
547+ }
548+ err := sv .AppendAssignment (variable , value )
549+ if err != nil {
550+ return err
551+ }
552+ s .NonDisruptiveActions [len (s .NonDisruptiveActions )- 1 ] = sv
553+ }
554+ } else {
555+ // If there are no actions yet, we need to create a new setvar action
556+ newAction , err := NewSetvarAction (colName , operation , []VarAssignment {{Variable : variable , Value : value }})
557+ if err != nil {
558+ return err
559+ }
560+ s .NonDisruptiveActions = append (s .NonDisruptiveActions , newAction )
561+ }
562+ return nil
563+ }
564+
434565func (s * SeclangActions ) AddNonDisruptiveActionOnly (action NonDisruptiveAction ) error {
435566 newAction , err := NewActionOnly (action )
436567 if err != nil {
@@ -518,35 +649,24 @@ func (s *SeclangActions) GetActionByKey(key string) Action {
518649 return ActionWithParam {}
519650}
520651
521- func (s * SeclangActions ) GetActionsByKey (key string ) []ActionWithParam {
522- actions := []ActionWithParam {}
523- // if s.DisruptiveAction != nil {
524- // if s.DisruptiveAction.ToString() == key {
525- // actions = append(actions, s.DisruptiveAction)
526- // }
527- // }
652+ func (s * SeclangActions ) GetActionsByKey (key string ) []Action {
653+ actions := []Action {}
654+ if s .DisruptiveAction != nil && s .DisruptiveAction .GetKey () == key {
655+ actions = append (actions , s .DisruptiveAction )
656+ }
528657 for _ , action := range s .NonDisruptiveActions {
529658 if action .GetKey () == key {
530- aP , ok := action .(ActionWithParam )
531- if ok {
532- actions = append (actions , aP )
533- }
659+ actions = append (actions , action )
534660 }
535661 }
536662 for _ , action := range s .FlowActions {
537663 if action .GetKey () == key {
538- aP , ok := action .(ActionWithParam )
539- if ok {
540- actions = append (actions , aP )
541- }
664+ actions = append (actions , action )
542665 }
543666 }
544667 for _ , action := range s .DataActions {
545668 if action .GetKey () == key {
546- aP , ok := action .(ActionWithParam )
547- if ok {
548- actions = append (actions , aP )
549- }
669+ actions = append (actions , action )
550670 }
551671 }
552672 return actions
0 commit comments