Skip to content

Commit 1a7bf6f

Browse files
authored
[TASK] TRK-4879 Move package set from trk-publisher-api (#39)
1 parent 0a45326 commit 1a7bf6f

6 files changed

Lines changed: 1144 additions & 1 deletion

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
.idea
1+
.idea
2+
.DS_Store

gofp/setx/product.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package setx
2+
3+
import (
4+
"cmp"
5+
"fmt"
6+
7+
"github.com/msales/gox/gofp"
8+
)
9+
10+
type Product[Value cmp.Ordered] struct {
11+
Result[Value]
12+
immutable bool
13+
}
14+
15+
func NewProduct[Value cmp.Ordered]() Product[Value] {
16+
return Product[Value]{
17+
Result: Result[Value]{
18+
Operator: All,
19+
Values: []Value{},
20+
},
21+
}
22+
}
23+
24+
// Merge merges a condition to existing result - check package description for algorithm description
25+
func (r *Product[Value]) Merge(operator Operator, values ...Value) (MergeResult, error) {
26+
if r.immutable {
27+
return Immutable, nil
28+
}
29+
30+
switch operator {
31+
case All:
32+
return r.mergeAll(values)
33+
case None:
34+
return r.mergeNone(values)
35+
case In:
36+
return r.mergeIn(values)
37+
case NotIn:
38+
return r.mergeNotIn(values)
39+
default:
40+
return Error, fmt.Errorf("unknown operator")
41+
}
42+
}
43+
44+
func (r *Product[Value]) mergeNone(values []Value) (MergeResult, error) {
45+
if len(values) > 0 {
46+
return Error, fmt.Errorf("cannot merge any values when using none operator")
47+
}
48+
return r.makeImmutable()
49+
}
50+
51+
func (r *Product[Value]) mergeAll(values []Value) (MergeResult, error) {
52+
if len(values) > 0 {
53+
return Error, fmt.Errorf("cannot merge any values when using all operator")
54+
}
55+
// ToDo: implement when needed - the case we have will never use this
56+
return r.makeImmutable()
57+
}
58+
59+
func (r *Product[Value]) mergeIn(values []Value) (MergeResult, error) {
60+
switch r.Operator {
61+
case In:
62+
// operator was IN and merging IN => IN
63+
// so the resulting list is just an intersection of both
64+
r.Result.intersect(values...)
65+
if len(r.Values) == 0 {
66+
return r.makeImmutable()
67+
}
68+
return Continue, nil
69+
case NotIn:
70+
// operator was NOT_IN and merging IN => IN
71+
r.Values = r.mergeInNotIn(r.Values, values)
72+
r.Operator = In
73+
if len(r.Values) == 0 {
74+
// If resulting set is empty (IN is completely contained in NOT IN condition)
75+
// then this pair of conditions makes the result always false, so NONE and immutable.
76+
return r.makeImmutable()
77+
}
78+
return Continue, nil
79+
case All:
80+
// if the result is mutable and operator is ALL, this means it was not used yet
81+
// with first usage, operator and values are set
82+
r.Operator = In
83+
r.Values = values
84+
return Continue, nil
85+
default:
86+
return Error, fmt.Errorf("unknown operator in result")
87+
}
88+
}
89+
90+
func (r *Product[Value]) mergeNotIn(values []Value) (MergeResult, error) {
91+
switch r.Operator {
92+
case In:
93+
// operator was IN and merging NOT IN => IN
94+
r.Values = r.mergeInNotIn(values, r.Values)
95+
// the operator was already IN
96+
if len(r.Values) == 0 {
97+
// If resulting set is empty (IN is completely contained in NOT IN condition)
98+
// then this pair of conditions makes the result always false, so NONE and immutable.
99+
return r.makeImmutable()
100+
}
101+
return Continue, nil
102+
case NotIn:
103+
// operator was NOT IN and merging NOT IN => NOT IN
104+
// Result is a sum of both sets.
105+
r.Result.merge(values...)
106+
return Continue, nil
107+
case All:
108+
// if the result is mutable and operator is ALL, this means it was not used yet
109+
// with first usage, operator and values are set
110+
r.Operator = NotIn
111+
r.Values = values
112+
return Continue, nil
113+
default:
114+
return Error, fmt.Errorf("unknown operator in result")
115+
}
116+
}
117+
118+
// makeImmutable changes the result to immutable with all possible values.
119+
// Once this state is reached it can't be changed.
120+
// If conditions so far make the result completely open, no other condition can narrow it anymore
121+
// because all conditions are connected with OR. ANY OR SOMETHING => ANY.
122+
func (r *Product[Value]) makeImmutable() (MergeResult, error) {
123+
r.Values = []Value{}
124+
r.immutable = true
125+
r.Operator = None
126+
return Immutable, nil
127+
}
128+
129+
func (r *Product[Value]) mergeInNotIn(inValues, notInValues []Value) []Value {
130+
diff := gofp.DiffRight(inValues, notInValues)
131+
return diff
132+
}

0 commit comments

Comments
 (0)