For a rule, I need to increase the cardinality to 5. I am unsure how to add the .map
function and downstream the data. Also, after downstream how to extract the data.
Please see the following code what I am trying to develop. The commented section inside the code I am trying to fill out the .map
and .penalizeConfigurable
section I am trying to extract it.
return constraintFactory.forEach(RuleSetting.class)
.filter(ruleSetting -> ruleSetting.getRuleName().equals("E015")&& ruleSetting.getIsActive() == true)
.join(Shift.class)
.join(ForeignerType.class)
.filter((ruleSetting, shift, foreignerType) -> shift.getEmployee().getForeignerType() != null
&& foreignerType.getForeignerType().equals(shift.getEmployee().getForeignerType())
&& shift.getWeekNo() != null
)
.groupBy((ruleSetting, shift, foreignerType)->ruleSetting,
(ruleSetting, shift, foreignerType)->shift.getEmployee(),
(ruleSetting, shift, foreignerType)->shift.getWeekNo(),
ConstraintCollectors.sumLong((ruleSetting, shift, foreignerType)->shift.getWorkMinutes()))
.filter((ruleSetting, employee, weekNo, totalDuration) -> totalDuration > employee.getContracts().getMaxMinutesPerWeek())
.map(//How to fill the map function??
)
.join(ForeignerType.class)
.penalizeConfigurable((first, foreigner)->{
//How to extract the data here.
Double result = Math.abs(((double)totalDuration / (double) employee.getContracts().getMaxMinutesPerWeek()));
result = result * Math.abs(ruleSetting.getWeight());
return result.intValue();
})
.indictWith((ruleSetting, employee, weekNo, totalDuration) ->{
EmployeeScoreKeyItems res = new EmployeeScoreKeyItems(EmployeeScoreKeyItems.KeyType.BY_WEEK,
ruleSetting.getRuleName(),
employee.getEmployeeId(),
null, null, weekNo, null);
return List.of(res);
})
.asConstraint("E015")
map(...)
allows you to change between cardinalities arbitrarily, up to the maximum cardinality of 4. If you need to go above 4, there is a trick - you can pack several of the arguments into another type.
Consider a Java record like this:
record QuadTuple<A, B, C, D>(A a, B b, C c, D d) {
}
We can pack a Quad
stream to a Uni
stream like so:
.map((a, b, c, d) -> new QuadTuple<>(a, b, c, d))
Or, to use a method reference:
.map(QuadTuple::new)
In a subsequent filter, for example, you'd do:
.filter(quadTuple -> quadTuple.a() > 0)
Once you have a Uni
stream like this, you can treat it like any other stream, and start join
ing on it.