註冊Drools的6運營商定製我有這樣的下列對象的幾個連鎖店,我想使用Drools的6.4.0處理:如何以編程方式KieServices與Java
@Value
public final class Node {
private final String code;
private final Node prev;
}
一個例子規則來使用,例如,如下:
rule "Initial repetition"
when
$n1: Node(prev == null, $c: code)
$n2: Node(prev == $n1, code == $c)
then
System.out.println($c + ": " + $n1 + ":" + $n2);
end
的Drools被初始化,並與下面的代碼運行:
private KieBase base;
public void process(List<Node> nodes) {
initialise();
KieSession session = base.newKieSession();
nodes.forEach(session::insert);
session.fireAllRules();
session.dispose();
}
private void initialise() {
if (base == null) {
// Get the KIE services
KieServices services = KieServices.Factory.get();
// Get a virtual file system
KieFileSystem fileSystem = services.newKieFileSystem();
// Add a DRL file to the virtual file system
String location = "/drools/Repetitions.drl";
InputStream stream = getClass().getResourceAsStream(location);
Resource resource = ResourceFactory.newInputStreamResource(stream);
fileSystem.write("src/main/resources" + location, resource);
// Build the virtual file system into a repository's container
KieBuilder builder = services.newKieBuilder(fileSystem).buildAll();
Results results = builder.getResults();
if (results.hasMessages(ERROR)) {
throw new RuntimeException(join("\n", results.getMessages()));
}
KieRepository repository = services.getRepository();
KieContainer container = services.newKieContainer(repository.getDefaultReleaseId());
// Get the knowledge base
base = container.newKieBase();
}
}
由於我必須識別每個鏈中的第一Node
的任何重複,我雖然來定義自定義操作符「之前」,以簡化的規則起草並能夠例如寫:
rule "Any repetition of first nodes"
when
$n1: Node(prev == null, $c: code)
$n2: Node($n1 precedes this, code == $c)
then
System.out.println($n2);
end
我已經創建PrecedesEvaluator
和PrecedesEvaluatorDefinition
如下:
public class PrecedesEvaluator extends BaseEvaluator {
private static final long serialVersionUID = ...L;
private final boolean isNegated;
public PrecedesEvaluator(ValueType type, boolean isNegated) {
super(type, isNegated ?
PrecedesEvaluatorDefinition.NOT_PRECEDES :
PrecedesEvaluatorDefinition.PRECEDES);
this.isNegated = isNegated;
}
@Override
public boolean evaluate(InternalWorkingMemory workingMemory, InternalReadAccessor extractor, InternalFactHandle factHandle, FieldValue value) {
Object nodeLeft = extractor.getValue(workingMemory, factHandle.getObject());
return isNegated^evaluateUnsafe(nodeLeft, value.getValue());
}
@Override
public boolean evaluate(InternalWorkingMemory workingMemory, InternalReadAccessor leftExtractor, InternalFactHandle left, InternalReadAccessor rightExtractor, InternalFactHandle right) {
Object nodeLeft = leftExtractor.getValue(workingMemory, left.getObject());
Object nodeRight = rightExtractor.getBigDecimalValue(workingMemory, right.getObject());
return isNegated^evaluateUnsafe(nodeLeft, nodeRight);
}
@Override
public boolean evaluateCachedLeft(InternalWorkingMemory workingMemory, VariableContextEntry context, InternalFactHandle right) {
Object nodeLeft = context.getFieldExtractor().getValue(workingMemory, right.getObject());
Object nodeRight = right.getObject();
return isNegated^evaluateUnsafe(nodeLeft, nodeRight);
}
@Override
public boolean evaluateCachedRight(InternalWorkingMemory workingMemory, VariableContextEntry context, InternalFactHandle left) {
Object nodeLeft = ((ObjectVariableContextEntry) context).right;
Object nodeRight = context.getFieldExtractor().getValue(workingMemory, left.getObject());
return isNegated^evaluateUnsafe(nodeLeft, nodeRight);
}
private boolean evaluateUnsafe(Object nodeLeft, Object nodeRight) {
if (!(nodeLeft instanceof Node)) {
throw new IllegalArgumentException("'nodeLeft' can't be casted to Node: " + nodeLeft.getClass());
}
if (!(nodeRight instanceof Node)) {
throw new IllegalArgumentException("'nodeRight' can't be casted to Node: " + nodeRight.getClass());
}
return evaluate((Node) nodeLeft, (Node) nodeRight);
}
private boolean evaluate(node nodeLeft, node nodeRight) {
Node current = nodeRight;
while (current != null) {
if (current == null) {
return false;
}
if (current == nodeLeft) {
return true;
}
current = current.getPrev();
}
return false;
}
}
public class PrecedesEvaluatorDefinition implements EvaluatorDefinition {
private static final long serialVersionUID = ...L;
protected static final String precedesOp = "precedes";
public static Operator PRECEDES;
public static Operator NOT_PRECEDES;
private static String[] SUPPORTED_IDS;
private PrecedesEvaluator evaluator;
private PrecedesEvaluator negatedEvaluator;
@Override
public String[] getEvaluatorIds() {
return new String[] {precedesOp};
}
@Override
public boolean isNegatable() {
return true;
}
@Override
public Evaluator getEvaluator(ValueType type, String operatorId, boolean isNegated, String parameterText, Target leftTarget, Target rightTarget) {
return isNegated ?
(negatedEvaluator == null ? new PrecedesEvaluator(type, true) : negatedEvaluator) :
(evaluator == null ? new PrecedesEvaluator(type, false) : evaluator);
}
@Override
public Evaluator getEvaluator(ValueType type, String operatorId, boolean isNegated, String parameterText) {
return getEvaluator(type, operatorId, isNegated, parameterText, Target.BOTH, Target.BOTH);
}
@Override
public Evaluator getEvaluator(ValueType type, Operator operator, String parameterText) {
return getEvaluator(type, operator.getOperatorString(), operator.isNegated(), parameterText);
}
@Override
public Evaluator getEvaluator(ValueType type, Operator operator) {
return getEvaluator(type, operator.getOperatorString(), operator.isNegated(), null);
}
@Override
public boolean supportsType(ValueType type) {
return true;
}
@Override
public Target getTarget() {
return Target.BOTH;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
throw new UnsupportedOperationException("writeExternal not usable");
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
throw new UnsupportedOperationException("readExternal not usable");
}
static {
if (SUPPORTED_IDS == null) {
PRECEDES = Operator.addOperatorToRegistry(precedesOp, false);
NOT_PRECEDES = Operator.addOperatorToRegistry(precedesOp, true);
SUPPORTED_IDS = new String[] {precedesOp};
}
}
}
我看了一些導遊網上,我試圖註冊程序的新操作如下:
private void initialise() {
if (base == null) {
...
KieBaseConfiguration configuration = services.newKieBaseConfiguration();
KieBaseOption option = EvaluatorOption.get(precedesOp, new PrecedesEvaluatorDefinition());
configuration.setOption(option); // Wrong type
...
base = container.newKieBase(configuration);
}
}
或
private void initialise() {
if (base == null) {
KnowledgeBuilderConfiguration configuration = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration();
EvaluatorOption option = EvaluatorOption.get(precedesOp, new PrecedesEvaluatorDefinition());
configuration.setOption(option);
...
base = container.newKieBase(configuration); // Wrong type!
}
}
在這兩種情況下,但是,一個類型不匹配發生,並且編譯失敗。
所以我的問題是:我該如何註冊我的操作符才能在規則中使用(請注意,如果可能,我不希望使用XML文件)?
酷!我不知道這可能通過'KieServices'! :+1: –