77
88import ai .timefold .solver .core .api .function .QuadFunction ;
99import ai .timefold .solver .core .api .score .stream .uni .UniConstraintCollector ;
10+ import ai .timefold .solver .core .api .score .stream .uni .UniConstraintCollectorAccumulatedValue ;
11+ import ai .timefold .solver .core .api .score .stream .uni .UniConstraintCollectorAccumulator ;
1012import ai .timefold .solver .core .impl .util .Quadruple ;
1113
12- import org .jspecify .annotations .NonNull ;
14+ import org .jspecify .annotations .NullMarked ;
1315import org .jspecify .annotations .Nullable ;
1416
17+ @ NullMarked
1518final class ComposeFourUniCollector <A , ResultHolder1_ , ResultHolder2_ , ResultHolder3_ , ResultHolder4_ , Result1_ , Result2_ , Result3_ , Result4_ , Result_ >
1619 implements
1720 UniConstraintCollector <A , Quadruple <ResultHolder1_ , ResultHolder2_ , ResultHolder3_ , ResultHolder4_ >, Result_ > {
1821 private final UniConstraintCollector <A , ResultHolder1_ , Result1_ > first ;
1922 private final UniConstraintCollector <A , ResultHolder2_ , Result2_ > second ;
2023 private final UniConstraintCollector <A , ResultHolder3_ , Result3_ > third ;
2124 private final UniConstraintCollector <A , ResultHolder4_ , Result4_ > fourth ;
22- private final QuadFunction <Result1_ , Result2_ , Result3_ , Result4_ , Result_ > composeFunction ;
25+ private final QuadFunction <@ Nullable Result1_ , @ Nullable Result2_ , @ Nullable Result3_ , @ Nullable Result4_ , @ Nullable Result_ > composeFunction ;
2326
2427 private final Supplier <ResultHolder1_ > firstSupplier ;
2528 private final Supplier <ResultHolder2_ > secondSupplier ;
2629 private final Supplier <ResultHolder3_ > thirdSupplier ;
2730 private final Supplier <ResultHolder4_ > fourthSupplier ;
2831
29- private final BiFunction <ResultHolder1_ , A , Runnable > firstAccumulator ;
30- private final BiFunction <ResultHolder2_ , A , Runnable > secondAccumulator ;
31- private final BiFunction <ResultHolder3_ , A , Runnable > thirdAccumulator ;
32- private final BiFunction <ResultHolder4_ , A , Runnable > fourthAccumulator ;
32+ private final UniConstraintCollectorAccumulator <ResultHolder1_ , A > firstIncremental ;
33+ private final UniConstraintCollectorAccumulator <ResultHolder2_ , A > secondIncremental ;
34+ private final UniConstraintCollectorAccumulator <ResultHolder3_ , A > thirdIncremental ;
35+ private final UniConstraintCollectorAccumulator <ResultHolder4_ , A > fourthIncremental ;
3336
34- private final Function <ResultHolder1_ , Result1_ > firstFinisher ;
35- private final Function <ResultHolder2_ , Result2_ > secondFinisher ;
36- private final Function <ResultHolder3_ , Result3_ > thirdFinisher ;
37- private final Function <ResultHolder4_ , Result4_ > fourthFinisher ;
37+ private final Function <ResultHolder1_ , @ Nullable Result1_ > firstFinisher ;
38+ private final Function <ResultHolder2_ , @ Nullable Result2_ > secondFinisher ;
39+ private final Function <ResultHolder3_ , @ Nullable Result3_ > thirdFinisher ;
40+ private final Function <ResultHolder4_ , @ Nullable Result4_ > fourthFinisher ;
3841
3942 ComposeFourUniCollector (UniConstraintCollector <A , ResultHolder1_ , Result1_ > first ,
4043 UniConstraintCollector <A , ResultHolder2_ , Result2_ > second ,
@@ -52,10 +55,12 @@ final class ComposeFourUniCollector<A, ResultHolder1_, ResultHolder2_, ResultHol
5255 this .thirdSupplier = third .supplier ();
5356 this .fourthSupplier = fourth .supplier ();
5457
55- this .firstAccumulator = first .accumulator ();
56- this .secondAccumulator = second .accumulator ();
57- this .thirdAccumulator = third .accumulator ();
58- this .fourthAccumulator = fourth .accumulator ();
58+ this .firstIncremental = first .isIncremental () ? first .incrementalAccumulator () : toIncremental (first .accumulator ());
59+ this .secondIncremental =
60+ second .isIncremental () ? second .incrementalAccumulator () : toIncremental (second .accumulator ());
61+ this .thirdIncremental = third .isIncremental () ? third .incrementalAccumulator () : toIncremental (third .accumulator ());
62+ this .fourthIncremental =
63+ fourth .isIncremental () ? fourth .incrementalAccumulator () : toIncremental (fourth .accumulator ());
5964
6065 this .firstFinisher = first .finisher ();
6166 this .secondFinisher = second .finisher ();
@@ -64,44 +69,53 @@ final class ComposeFourUniCollector<A, ResultHolder1_, ResultHolder2_, ResultHol
6469 }
6570
6671 @ Override
67- public @ NonNull Supplier <Quadruple <ResultHolder1_ , ResultHolder2_ , ResultHolder3_ , ResultHolder4_ >> supplier () {
72+ public Supplier <Quadruple <ResultHolder1_ , ResultHolder2_ , ResultHolder3_ , ResultHolder4_ >> supplier () {
6873 return () -> {
69- ResultHolder1_ a = firstSupplier .get ();
70- ResultHolder2_ b = secondSupplier .get ();
71- ResultHolder3_ c = thirdSupplier .get ();
74+ var a = firstSupplier .get ();
75+ var b = secondSupplier .get ();
76+ var c = thirdSupplier .get ();
7277 return new Quadruple <>(a , b , c , fourthSupplier .get ());
7378 };
7479 }
7580
7681 @ Override
77- public @ NonNull BiFunction <Quadruple <ResultHolder1_ , ResultHolder2_ , ResultHolder3_ , ResultHolder4_ >, A , Runnable >
82+ public BiFunction <Quadruple <ResultHolder1_ , ResultHolder2_ , ResultHolder3_ , ResultHolder4_ >, A , Runnable >
7883 accumulator () {
79- return (resultHolder , a ) -> composeUndo (firstAccumulator .apply (resultHolder .a (), a ),
80- secondAccumulator .apply (resultHolder .b (), a ),
81- thirdAccumulator .apply (resultHolder .c (), a ),
82- fourthAccumulator .apply (resultHolder .d (), a ));
84+ throw new UnsupportedOperationException ();
8385 }
8486
85- private static Runnable composeUndo (Runnable first , Runnable second , Runnable third ,
86- Runnable fourth ) {
87- return () -> {
88- first .run ();
89- second .run ();
90- third .run ();
91- fourth .run ();
87+ @ Override
88+ public boolean isIncremental () {
89+ return true ;
90+ }
91+
92+ @ Override
93+ public UniConstraintCollectorAccumulator <Quadruple <ResultHolder1_ , ResultHolder2_ , ResultHolder3_ , ResultHolder4_ >, A >
94+ incrementalAccumulator () {
95+ return container -> {
96+ var v1 = firstIncremental .intoGroup (container .a ());
97+ var v2 = secondIncremental .intoGroup (container .b ());
98+ var v3 = thirdIncremental .intoGroup (container .c ());
99+ var v4 = fourthIncremental .intoGroup (container .d ());
100+ return new ComposingAccumulatedValue <>(v1 , v2 , v3 , v4 );
92101 };
93102 }
94103
95104 @ Override
96- public @ Nullable Function <Quadruple <ResultHolder1_ , ResultHolder2_ , ResultHolder3_ , ResultHolder4_ >, Result_ > finisher () {
105+ public Function <Quadruple <ResultHolder1_ , ResultHolder2_ , ResultHolder3_ , ResultHolder4_ >, @ Nullable Result_ > finisher () {
97106 return resultHolder -> composeFunction .apply (firstFinisher .apply (resultHolder .a ()),
98107 secondFinisher .apply (resultHolder .b ()),
99108 thirdFinisher .apply (resultHolder .c ()),
100109 fourthFinisher .apply (resultHolder .d ()));
101110 }
102111
112+ static <ResultContainer_ , A > UniConstraintCollectorAccumulator <ResultContainer_ , A >
113+ toIncremental (BiFunction <ResultContainer_ , A , Runnable > accumulator ) {
114+ return container -> new AdaptedIncrementalAccumulatedValue <>(accumulator , container );
115+ }
116+
103117 @ Override
104- public boolean equals (Object object ) {
118+ public boolean equals (@ Nullable Object object ) {
105119 if (this == object )
106120 return true ;
107121 if (object == null || getClass () != object .getClass ())
@@ -118,4 +132,62 @@ public boolean equals(Object object) {
118132 public int hashCode () {
119133 return Objects .hash (first , second , third , fourth , composeFunction );
120134 }
135+
136+ private static final class AdaptedIncrementalAccumulatedValue <ResultContainer_ , A >
137+ implements UniConstraintCollectorAccumulatedValue <A > {
138+
139+ private final BiFunction <ResultContainer_ , @ Nullable A , Runnable > accumulator ;
140+ private final ResultContainer_ container ;
141+ private @ Nullable Runnable runningUndo ;
142+
143+ public AdaptedIncrementalAccumulatedValue (BiFunction <ResultContainer_ , @ Nullable A , Runnable > accumulator ,
144+ ResultContainer_ container ) {
145+ this .accumulator = accumulator ;
146+ this .container = container ;
147+ }
148+
149+ @ Override
150+ public boolean add (@ Nullable A a ) {
151+ runningUndo = accumulator .apply (container , a );
152+ return true ;
153+ }
154+
155+ @ Override
156+ public boolean update (@ Nullable A a ) {
157+ runningUndo .run ();
158+ runningUndo = accumulator .apply (container , a );
159+ return true ;
160+ }
161+
162+ @ Override
163+ public boolean remove () {
164+ runningUndo .run ();
165+ runningUndo = null ;
166+ return true ;
167+ }
168+
169+ }
170+
171+ private record ComposingAccumulatedValue <A >(UniConstraintCollectorAccumulatedValue <A > v1 ,
172+ UniConstraintCollectorAccumulatedValue <A > v2 ,
173+ UniConstraintCollectorAccumulatedValue <A > v3 ,
174+ UniConstraintCollectorAccumulatedValue <A > v4 )
175+ implements
176+ UniConstraintCollectorAccumulatedValue <A > {
177+
178+ @ Override
179+ public boolean add (@ Nullable A a ) {
180+ return v1 .add (a ) | v2 .add (a ) | v3 .add (a ) | v4 .add (a );
181+ }
182+
183+ @ Override
184+ public boolean update (@ Nullable A a ) {
185+ return v1 .update (a ) | v2 .update (a ) | v3 .update (a ) | v4 .update (a );
186+ }
187+
188+ @ Override
189+ public boolean remove () {
190+ return v1 .remove () | v2 .remove () | v3 .remove () | v4 .remove ();
191+ }
192+ }
121193}
0 commit comments