bug #I7KY2N 逻辑运算增加短路效果,避免多余计算

This commit is contained in:
luoyi 2023-07-19 11:19:08 +08:00
parent 67e9616bd8
commit d9ebc78754
3 changed files with 40 additions and 15 deletions

View File

@ -1,7 +1,6 @@
package com.yomahub.liteflow.flow.element.condition; package com.yomahub.liteflow.flow.element.condition;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.enums.ConditionTypeEnum; import com.yomahub.liteflow.enums.ConditionTypeEnum;
import com.yomahub.liteflow.exception.AndOrConditionException; import com.yomahub.liteflow.exception.AndOrConditionException;
@ -11,7 +10,9 @@ import com.yomahub.liteflow.log.LFLog;
import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.log.LFLoggerManager;
import com.yomahub.liteflow.slot.DataBus; import com.yomahub.liteflow.slot.DataBus;
import com.yomahub.liteflow.slot.Slot; import com.yomahub.liteflow.slot.Slot;
import java.util.List; import java.util.List;
import java.util.function.Predicate;
public class AndOrCondition extends Condition { public class AndOrCondition extends Condition {
@ -23,21 +24,10 @@ public class AndOrCondition extends Condition {
public void executeCondition(Integer slotIndex) throws Exception { public void executeCondition(Integer slotIndex) throws Exception {
List<Executable> itemList = this.getItem(); List<Executable> itemList = this.getItem();
if (CollUtil.isEmpty(itemList)){ if (CollUtil.isEmpty(itemList)){
throw new AndOrConditionException("boolean item list is null"); throw new AndOrConditionException("boolean item list is null");
} }
boolean[] booleanArray = new boolean[itemList.size()];
for (int i = 0; i < itemList.size(); i++) {
Executable item = itemList.get(i);
item.setCurrChainId(this.getCurrChainId());
item.execute(slotIndex);
booleanArray[i] = item.getItemResultMetaValue(slotIndex);
LOG.info("the result of boolean component [{}] is [{}]", item.getId(), booleanArray[i]);
}
BooleanConditionTypeEnum booleanConditionType = this.getBooleanConditionType(); BooleanConditionTypeEnum booleanConditionType = this.getBooleanConditionType();
Slot slot = DataBus.getSlot(slotIndex); Slot slot = DataBus.getSlot(slotIndex);
@ -45,16 +35,37 @@ public class AndOrCondition extends Condition {
String resultKey = StrUtil.format("{}_{}",this.getClass().getName(),this.hashCode()); String resultKey = StrUtil.format("{}_{}",this.getClass().getName(),this.hashCode());
switch (booleanConditionType) { switch (booleanConditionType) {
case AND: case AND:
slot.setAndOrResult(resultKey, BooleanUtil.and(booleanArray)); slot.setAndOrResult(resultKey, itemList.stream().allMatch(new AndOrConditionPredicate(slotIndex)));
break; break;
case OR: case OR:
slot.setAndOrResult(resultKey, BooleanUtil.or(booleanArray)); slot.setAndOrResult(resultKey, itemList.stream().anyMatch(new AndOrConditionPredicate(slotIndex)));
break; break;
default: default:
throw new AndOrConditionException("condition type must be 'AND' or 'OR'"); throw new AndOrConditionException("condition type must be 'AND' or 'OR'");
} }
} }
private class AndOrConditionPredicate implements Predicate<Executable> {
private final Integer slotIndex;
public AndOrConditionPredicate(Integer slotIndex) {
this.slotIndex = slotIndex;
}
@Override
public boolean test(Executable condition) {
try {
condition.setCurrChainId(getCurrChainId());
condition.execute(slotIndex);
return condition.getItemResultMetaValue(slotIndex);
} catch (Exception e) {
throw new AndOrConditionException(e.getMessage());
}
}
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -39,7 +39,7 @@ public class BooleanOptELSpringbootTest extends BaseTest {
public void testBooleanOpt2() throws Exception { public void testBooleanOpt2() throws Exception {
LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg"); LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
Assertions.assertTrue(response.isSuccess()); Assertions.assertTrue(response.isSuccess());
Assertions.assertEquals("x1==>x2==>x3==>a", response.getExecuteStepStr()); Assertions.assertEquals("x1==>a", response.getExecuteStepStr());
} }
// IF情况下AND+NOT // IF情况下AND+NOT
@ -64,4 +64,13 @@ public class BooleanOptELSpringbootTest extends BaseTest {
Assertions.assertTrue(response.isSuccess()); Assertions.assertTrue(response.isSuccess());
Assertions.assertEquals("w1==>w2==>a==>bk==>w1==>w2==>a==>bk==>w1==>w2==>a==>bk==>w1==>w2==>a==>bk", response.getExecuteStepStr()); Assertions.assertEquals("w1==>w2==>a==>bk==>w1==>w2==>a==>bk==>w1==>w2==>a==>bk==>w1==>w2==>a==>bk", response.getExecuteStepStr());
} }
// AND + NOT 实现短路效果
@Test
public void testBooleanOpt6() throws Exception {
LiteflowResponse response = flowExecutor.execute2Resp("chain6", "arg");
Assertions.assertTrue(response.isSuccess());
Assertions.assertEquals("x1==>b", response.getExecuteStepStr());
}
} }

View File

@ -25,4 +25,9 @@
<chain name="chain5"> <chain name="chain5">
WHILE(AND(w1, NOT(w2))).DO(a).BREAK(bk); WHILE(AND(w1, NOT(w2))).DO(a).BREAK(bk);
</chain> </chain>
<chain name="chain6">
IF(AND(NOT(x1), x2, x3), a, b);
</chain>
</flow> </flow>