Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions mdl/executor/cmd_microflows_format_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,24 @@ func (e *Executor) formatListOperation(op microflows.ListOperation, outputVar st
return fmt.Sprintf("$%s = CONTAINS($%s, $%s);", outputVar, o.ListVariable, o.ObjectVariable)
case *microflows.EqualsOperation:
return fmt.Sprintf("$%s = EQUALS($%s, $%s);", outputVar, o.ListVariable1, o.ListVariable2)
case *microflows.FindByAttributeOperation:
ref := o.Attribute
if ref == "" {
ref = o.Association
}
parts := strings.Split(ref, ".")
fieldName := parts[len(parts)-1]
return fmt.Sprintf("$%s = FIND($%s, $currentObject/%s = %s);", outputVar, o.ListVariable, fieldName, o.Expression)
case *microflows.FilterByAttributeOperation:
ref := o.Attribute
if ref == "" {
ref = o.Association
}
parts := strings.Split(ref, ".")
fieldName := parts[len(parts)-1]
return fmt.Sprintf("$%s = FILTER($%s, $currentObject/%s = %s);", outputVar, o.ListVariable, fieldName, o.Expression)
case *microflows.RangeOperation:
return fmt.Sprintf("$%s = RANGE($%s, %s, %s);", outputVar, o.ListVariable, o.OffsetExpression, o.LimitExpression)
default:
return fmt.Sprintf("$%s = LIST OPERATION %T;", outputVar, op)
}
Expand Down
48 changes: 48 additions & 0 deletions mdl/executor/cmd_microflows_format_listop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,51 @@ func TestFormatListOperation_Nil(t *testing.T) {
t.Errorf("got %q", got)
}
}

func TestFormatListOperation_FindByAttribute(t *testing.T) {
e := newTestExecutor()
got := e.formatListOperation(&microflows.FindByAttributeOperation{
ListVariable: "Orders",
Attribute: "MyModule.Order.Status",
Expression: "'Active'",
}, "Found")
if got != "$Found = FIND($Orders, $currentObject/Status = 'Active');" {
t.Errorf("got %q", got)
}
}

func TestFormatListOperation_FindByAssociation(t *testing.T) {
e := newTestExecutor()
got := e.formatListOperation(&microflows.FindByAttributeOperation{
ListVariable: "Orders",
Association: "MyModule.Order_Customer",
Expression: "$Customer",
}, "Found")
if got != "$Found = FIND($Orders, $currentObject/Order_Customer = $Customer);" {
t.Errorf("got %q", got)
}
}

func TestFormatListOperation_FilterByAttribute(t *testing.T) {
e := newTestExecutor()
got := e.formatListOperation(&microflows.FilterByAttributeOperation{
ListVariable: "Orders",
Attribute: "MyModule.Order.IsActive",
Expression: "true",
}, "Filtered")
if got != "$Filtered = FILTER($Orders, $currentObject/IsActive = true);" {
t.Errorf("got %q", got)
}
}

func TestFormatListOperation_Range(t *testing.T) {
e := newTestExecutor()
got := e.formatListOperation(&microflows.RangeOperation{
ListVariable: "Orders",
OffsetExpression: "0",
LimitExpression: "10",
}, "Page")
if got != "$Page = RANGE($Orders, 0, 10);" {
t.Errorf("got %q", got)
}
}
32 changes: 32 additions & 0 deletions sdk/microflows/microflows_actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,38 @@ type FilterOperation struct {

func (FilterOperation) isListOperation() {}

// FindByAttributeOperation finds an element by attribute or association value.
type FindByAttributeOperation struct {
model.BaseElement
ListVariable string `json:"listVariable"`
Attribute string `json:"attribute,omitempty"`
Association string `json:"association,omitempty"`
Expression string `json:"expression"`
}

func (FindByAttributeOperation) isListOperation() {}

// FilterByAttributeOperation filters a list by attribute or association value.
type FilterByAttributeOperation struct {
model.BaseElement
ListVariable string `json:"listVariable"`
Attribute string `json:"attribute,omitempty"`
Association string `json:"association,omitempty"`
Expression string `json:"expression"`
}

func (FilterByAttributeOperation) isListOperation() {}

// RangeOperation takes a range slice from a list.
type RangeOperation struct {
model.BaseElement
ListVariable string `json:"listVariable"`
OffsetExpression string `json:"offsetExpression"`
LimitExpression string `json:"limitExpression"`
}

func (RangeOperation) isListOperation() {}

// SortOperation sorts a list.
type SortOperation struct {
model.BaseElement
Expand Down
99 changes: 99 additions & 0 deletions sdk/mpr/parser_listoperation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// SPDX-License-Identifier: Apache-2.0

package mpr

import (
"testing"

"github.com/mendixlabs/mxcli/sdk/microflows"
)

func TestParseListOperation_FindByAttribute(t *testing.T) {
raw := map[string]any{
"$Type": "Microflows$Find",
"$ID": nil,
"ListName": "Orders",
"Attribute": "MyModule.Order.Status",
"Expression": "'Active'",
}
op := parseListOperation(raw)
got, ok := op.(*microflows.FindByAttributeOperation)
if !ok {
t.Fatalf("expected *FindByAttributeOperation, got %T", op)
}
if got.ListVariable != "Orders" {
t.Errorf("ListVariable: got %q, want %q", got.ListVariable, "Orders")
}
if got.Attribute != "MyModule.Order.Status" {
t.Errorf("Attribute: got %q, want %q", got.Attribute, "MyModule.Order.Status")
}
if got.Expression != "'Active'" {
t.Errorf("Expression: got %q, want %q", got.Expression, "'Active'")
}
}

func TestParseListOperation_FindByAssociation(t *testing.T) {
raw := map[string]any{
"$Type": "Microflows$Find",
"$ID": nil,
"ListName": "Orders",
"Association": "MyModule.Order_Customer",
"Expression": "$Customer",
}
op := parseListOperation(raw)
got, ok := op.(*microflows.FindByAttributeOperation)
if !ok {
t.Fatalf("expected *FindByAttributeOperation, got %T", op)
}
if got.Association != "MyModule.Order_Customer" {
t.Errorf("Association: got %q, want %q", got.Association, "MyModule.Order_Customer")
}
}

func TestParseListOperation_FilterByAttribute(t *testing.T) {
raw := map[string]any{
"$Type": "Microflows$Filter",
"$ID": nil,
"ListName": "Orders",
"Attribute": "MyModule.Order.IsActive",
"Expression": "true",
}
op := parseListOperation(raw)
got, ok := op.(*microflows.FilterByAttributeOperation)
if !ok {
t.Fatalf("expected *FilterByAttributeOperation, got %T", op)
}
if got.ListVariable != "Orders" {
t.Errorf("ListVariable: got %q, want %q", got.ListVariable, "Orders")
}
if got.Attribute != "MyModule.Order.IsActive" {
t.Errorf("Attribute: got %q, want %q", got.Attribute, "MyModule.Order.IsActive")
}
}

func TestParseListOperation_Range(t *testing.T) {
raw := map[string]any{
"$Type": "Microflows$ListRange",
"$ID": nil,
"ListName": "Orders",
"CustomRange": map[string]any{
"$Type": "Microflows$CustomRange",
"OffsetExpression": "0",
"LimitExpression": "10",
},
}
op := parseListOperation(raw)
got, ok := op.(*microflows.RangeOperation)
if !ok {
t.Fatalf("expected *RangeOperation, got %T", op)
}
if got.ListVariable != "Orders" {
t.Errorf("ListVariable: got %q, want %q", got.ListVariable, "Orders")
}
if got.OffsetExpression != "0" {
t.Errorf("OffsetExpression: got %q, want %q", got.OffsetExpression, "0")
}
if got.LimitExpression != "10" {
t.Errorf("LimitExpression: got %q, want %q", got.LimitExpression, "10")
}
}
28 changes: 28 additions & 0 deletions sdk/mpr/parser_microflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,34 @@ func parseListOperation(raw map[string]any) microflows.ListOperation {
ListVariable1: listVar,
ListVariable2: extractString(raw["SecondListOrObjectName"]),
}
case "Microflows$Find":
return &microflows.FindByAttributeOperation{
BaseElement: model.BaseElement{ID: id},
ListVariable: listVar,
Attribute: extractString(raw["Attribute"]),
Association: extractString(raw["Association"]),
Expression: extractString(raw["Expression"]),
}
case "Microflows$Filter":
return &microflows.FilterByAttributeOperation{
BaseElement: model.BaseElement{ID: id},
ListVariable: listVar,
Attribute: extractString(raw["Attribute"]),
Association: extractString(raw["Association"]),
Expression: extractString(raw["Expression"]),
}
case "Microflows$ListRange":
offset, limit := "", ""
if cr, ok := raw["CustomRange"].(map[string]any); ok {
offset = extractString(cr["OffsetExpression"])
limit = extractString(cr["LimitExpression"])
}
return &microflows.RangeOperation{
BaseElement: model.BaseElement{ID: id},
ListVariable: listVar,
OffsetExpression: offset,
LimitExpression: limit,
}
default:
return nil
}
Expand Down