Search in sources :

Example 1 with RuleImpl

use of org.drools.core.definitions.rule.impl.RuleImpl in project drools by kiegroup.

the class RuleExecutor method fire.

private int fire(InternalWorkingMemory wm, InternalAgenda agenda, AgendaFilter filter, int fireCount, int fireLimit) {
    int localFireCount = 0;
    if (!tupleList.isEmpty()) {
        if (!fireExitedEarly && isDeclarativeAgendaEnabled()) {
            // Network Evaluation can notify meta rules, which should be given a chance to fire first
            RuleAgendaItem nextRule = agenda.peekNextRule();
            if (!isHigherSalience(nextRule)) {
                fireExitedEarly = true;
                return localFireCount;
            }
        }
        RuleTerminalNode rtn = (RuleTerminalNode) pmem.getPathEndNode();
        RuleImpl rule = rtn.getRule();
        Tuple tuple = getNextTuple();
        if (rule.isAllMatches()) {
            fireConsequenceEvent(wm, agenda, (AgendaItem) tuple, DefaultAgenda.ON_BEFORE_ALL_FIRES_CONSEQUENCE_NAME);
        }
        Tuple lastTuple = null;
        for (; tuple != null; lastTuple = tuple, tuple = getNextTuple()) {
            // if the current Rule is no-loop and the origin rule is the same then return
            if (cancelAndContinue(wm, rtn, rule, tuple, filter)) {
                continue;
            }
            AgendaItem item = (AgendaItem) tuple;
            if (agenda.getActivationsFilter() != null && !agenda.getActivationsFilter().accept(item, wm, rtn)) {
                // only relevant for seralization, to not refire Matches already fired
                continue;
            }
            fireActivation(wm, agenda, item);
            localFireCount++;
            if (rtn.getLeftTupleSource() == null) {
                // The activation firing removed this rule from the rule base
                break;
            }
            agenda.flushPropagations();
            // dyanmic salience may have updated it, so get again.
            int salience = ruleAgendaItem.getSalience();
            if (queue != null && !queue.isEmpty() && salience != queue.peek().getSalience()) {
                ruleAgendaItem.dequeue();
                ruleAgendaItem.setSalience(queue.peek().getSalience());
                ruleAgendaItem.getAgendaGroup().add(ruleAgendaItem);
            }
            if (!rule.isAllMatches()) {
                // if firing rule is @All don't give way to other rules
                if (haltRuleFiring(fireCount, fireLimit, localFireCount, agenda)) {
                    // another rule has high priority and is on the agenda, so evaluate it first
                    break;
                }
                if (!wm.isSequential()) {
                    reEvaluateNetwork(agenda);
                }
            }
        }
        if (rule.isAllMatches()) {
            fireConsequenceEvent(wm, agenda, (AgendaItem) lastTuple, DefaultAgenda.ON_AFTER_ALL_FIRES_CONSEQUENCE_NAME);
        }
    }
    removeRuleAgendaItemWhenEmpty(wm);
    fireExitedEarly = false;
    return localFireCount;
}
Also used : RuleImpl(org.drools.core.definitions.rule.impl.RuleImpl) Tuple(org.drools.core.spi.Tuple) RuleTerminalNodeLeftTuple(org.drools.core.reteoo.RuleTerminalNodeLeftTuple) AgendaItem(org.drools.core.common.AgendaItem) RuleTerminalNode(org.drools.core.reteoo.RuleTerminalNode)

Example 2 with RuleImpl

use of org.drools.core.definitions.rule.impl.RuleImpl in project drools by kiegroup.

the class AddRemoveRule method removeRule.

/**
 * This method is called before the rule nodes are removed from the network.
 * For remove tuples are processed before the segments and pmems have been adjusted
 */
public static void removeRule(TerminalNode tn, InternalWorkingMemory[] wms, InternalKnowledgeBase kBase) {
    if (log.isTraceEnabled()) {
        log.trace("Removing Rule {}", tn.getRule().getName());
    }
    boolean hasProtos = kBase.hasSegmentPrototypes();
    boolean hasWms = wms.length > 0;
    if (!hasProtos && !hasWms) {
        return;
    }
    RuleImpl rule = tn.getRule();
    LeftTupleNode firstSplit = getNetworkSplitPoint(tn);
    PathEndNodes pathEndNodes = getPathEndNodes(kBase, firstSplit, tn, rule, hasProtos, hasWms);
    for (InternalWorkingMemory wm : wms) {
        wm.flushPropagations();
        PathEndNodeMemories tnms = getPathEndMemories(wm, pathEndNodes);
        if (!tnms.subjectPmems.isEmpty()) {
            if (NodeTypeEnums.LeftInputAdapterNode == firstSplit.getType() && firstSplit.getAssociationsSize() == 1) {
                if (tnms.subjectPmem != null) {
                    flushStagedTuples(firstSplit, tnms.subjectPmem, wm);
                }
                processLeftTuples(firstSplit, wm, false, tn.getRule());
                removeNewPaths(wm, tnms.subjectPmems);
            } else {
                flushStagedTuples(tn, tnms.subjectPmem, pathEndNodes, wm);
                processLeftTuples(firstSplit, wm, false, tn.getRule());
                removeNewPaths(wm, tnms.subjectPmems);
                Map<PathMemory, SegmentMemory[]> prevSmemsLookup = reInitPathMemories(tnms.otherPmems, tn);
                // must collect all visited SegmentMemories, for link notification
                Set<SegmentMemory> smemsToNotify = handleExistingPaths(tn, prevSmemsLookup, tnms.otherPmems, wm, ExistingPathStrategy.REMOVE_STRATEGY);
                notifySegments(smemsToNotify, wm);
            }
        }
        if (tnms.subjectPmem != null && tnms.subjectPmem.isInitialized() && tnms.subjectPmem.getRuleAgendaItem().isQueued()) {
            // SubjectPmem can be null, if it was never initialized
            tnms.subjectPmem.getRuleAgendaItem().dequeue();
        }
    }
}
Also used : InternalWorkingMemory(org.drools.core.common.InternalWorkingMemory) SegmentMemory(org.drools.core.reteoo.SegmentMemory) LeftTupleNode(org.drools.core.reteoo.LeftTupleNode) RuleImpl(org.drools.core.definitions.rule.impl.RuleImpl) PathMemory(org.drools.core.reteoo.PathMemory)

Example 3 with RuleImpl

use of org.drools.core.definitions.rule.impl.RuleImpl in project drools by kiegroup.

the class AddRemoveRule method addRule.

/**
 * This method is called after the rule nodes have been added to the network
 * For add tuples are processed after the segments and pmems have been adjusted
 */
public static void addRule(TerminalNode tn, InternalWorkingMemory[] wms, InternalKnowledgeBase kBase) {
    if (log.isTraceEnabled()) {
        log.trace("Adding Rule {}", tn.getRule().getName());
    }
    boolean hasProtos = kBase.hasSegmentPrototypes();
    boolean hasWms = wms.length > 0;
    if (!hasProtos && !hasWms) {
        return;
    }
    RuleImpl rule = tn.getRule();
    LeftTupleNode firstSplit = getNetworkSplitPoint(tn);
    PathEndNodes pathEndNodes = getPathEndNodes(kBase, firstSplit, tn, rule, hasProtos, hasWms);
    for (InternalWorkingMemory wm : wms) {
        wm.flushPropagations();
        if (NodeTypeEnums.LeftInputAdapterNode == firstSplit.getType() && firstSplit.getAssociationsSize() == 1) {
            // rule added with no sharing
            insertLiaFacts(firstSplit, wm);
        } else {
            PathEndNodeMemories tnms = getPathEndMemories(wm, pathEndNodes);
            if (tnms.subjectPmem == null) {
                // If the existing PathMemories are not yet initialized there are no Segments or tuples to process
                continue;
            }
            Map<PathMemory, SegmentMemory[]> prevSmemsLookup = reInitPathMemories(tnms.otherPmems, null);
            // must collect all visited SegmentMemories, for link notification
            Set<SegmentMemory> smemsToNotify = handleExistingPaths(tn, prevSmemsLookup, tnms.otherPmems, wm, ExistingPathStrategy.ADD_STRATEGY);
            addNewPaths(wm, smemsToNotify, tnms.subjectPmems);
            processLeftTuples(firstSplit, wm, true, rule);
            notifySegments(smemsToNotify, wm);
        }
    }
    if (hasWms) {
        insertFacts(pathEndNodes, wms);
    } else {
        for (PathEndNode node : pathEndNodes.otherEndNodes) {
            node.resetPathMemSpec(null);
        }
    }
}
Also used : InternalWorkingMemory(org.drools.core.common.InternalWorkingMemory) SegmentMemory(org.drools.core.reteoo.SegmentMemory) LeftTupleNode(org.drools.core.reteoo.LeftTupleNode) PathEndNode(org.drools.core.reteoo.PathEndNode) RuleImpl(org.drools.core.definitions.rule.impl.RuleImpl) PathMemory(org.drools.core.reteoo.PathMemory)

Example 4 with RuleImpl

use of org.drools.core.definitions.rule.impl.RuleImpl in project drools by kiegroup.

the class KnowledgeBaseImpl method removeRule.

public void removeRule(final String packageName, final String ruleName) {
    enqueueModification(() -> {
        final InternalKnowledgePackage pkg = pkgs.get(packageName);
        if (pkg == null) {
            throw new IllegalArgumentException("Package name '" + packageName + "' does not exist for this Rule Base.");
        }
        RuleImpl rule = pkg.getRule(ruleName);
        if (rule == null) {
            throw new IllegalArgumentException("Rule name '" + ruleName + "' does not exist in the Package '" + packageName + "'.");
        }
        this.eventSupport.fireBeforeRuleRemoved(rule);
        this.reteooBuilder.removeRules(Collections.singletonList(rule));
        this.eventSupport.fireAfterRuleRemoved(rule);
        pkg.removeRule(rule);
        addReloadDialectDatas(pkg.getDialectRuntimeRegistry());
    });
}
Also used : RuleImpl(org.drools.core.definitions.rule.impl.RuleImpl) InternalKnowledgePackage(org.drools.core.definitions.InternalKnowledgePackage)

Example 5 with RuleImpl

use of org.drools.core.definitions.rule.impl.RuleImpl in project drools by kiegroup.

the class KnowledgeBaseImpl method mergePackage.

/**
 * Merge a new package with an existing package.
 * Most of the work is done by the concrete implementations,
 * but this class does some work (including combining imports, compilation data, globals,
 * and the actual Rule objects into the package).
 */
private void mergePackage(InternalKnowledgePackage pkg, InternalKnowledgePackage newPkg) {
    // Merge imports
    final Map<String, ImportDeclaration> imports = pkg.getImports();
    imports.putAll(newPkg.getImports());
    // Merge static imports
    for (String staticImport : newPkg.getStaticImports()) {
        pkg.addStaticImport(staticImport);
    }
    String lastIdent = null;
    String lastType = null;
    try {
        // merge globals
        if (newPkg.getGlobals() != null && newPkg.getGlobals() != Collections.EMPTY_MAP) {
            Map<String, String> globals = pkg.getGlobals();
            // Add globals
            for (final Map.Entry<String, String> entry : newPkg.getGlobals().entrySet()) {
                final String identifier = entry.getKey();
                final String type = entry.getValue();
                lastIdent = identifier;
                lastType = type;
                if (globals.containsKey(identifier) && !globals.get(identifier).equals(type)) {
                    throw new RuntimeException(pkg.getName() + " cannot be integrated");
                } else {
                    pkg.addGlobal(identifier, this.rootClassLoader.loadClass(type));
                    // this isn't a package merge, it's adding to the rulebase, but I've put it here for convienience
                    addGlobal(identifier, this.rootClassLoader.loadClass(type));
                }
            }
        }
    } catch (ClassNotFoundException e) {
        throw new RuntimeException("Unable to resolve class '" + lastType + "' for global '" + lastIdent + "'");
    }
    // merge entry point declarations
    if (newPkg.getEntryPointIds() != null) {
        for (String ep : newPkg.getEntryPointIds()) {
            pkg.addEntryPointId(ep);
        }
    }
    // merge the type declarations
    if (newPkg.getTypeDeclarations() != null) {
        // add type declarations
        for (TypeDeclaration type : newPkg.getTypeDeclarations().values()) {
            // @TODO should we allow overrides? only if the class is not in use.
            if (!pkg.getTypeDeclarations().containsKey(type.getTypeName())) {
                // add to package list of type declarations
                pkg.addTypeDeclaration(type);
            }
        }
    }
    // merge window declarations
    if (newPkg.getWindowDeclarations() != null) {
        // add window declarations
        for (WindowDeclaration window : newPkg.getWindowDeclarations().values()) {
            if (!pkg.getWindowDeclarations().containsKey(window.getName()) || pkg.getWindowDeclarations().get(window.getName()).equals(window)) {
                pkg.addWindowDeclaration(window);
            } else {
                throw new RuntimeException("Unable to merge two conflicting window declarations for window named: " + window.getName());
            }
        }
    }
    // Merge rules into the RuleBase package
    // as this is needed for individual rule removal later on
    List<RuleImpl> rulesToBeRemoved = new ArrayList<RuleImpl>();
    for (Rule newRule : newPkg.getRules()) {
        // remove the rule if it already exists
        RuleImpl oldRule = pkg.getRule(newRule.getName());
        if (oldRule != null) {
            rulesToBeRemoved.add(oldRule);
        }
    }
    if (!rulesToBeRemoved.isEmpty()) {
        removeRules(rulesToBeRemoved);
    }
    for (Rule newRule : newPkg.getRules()) {
        pkg.addRule((RuleImpl) newRule);
    }
    // Merge The Rule Flows
    if (newPkg.getRuleFlows() != null) {
        for (Process flow : newPkg.getRuleFlows().values()) {
            pkg.addProcess(flow);
        }
    }
    if (!newPkg.getResourceTypePackages().isEmpty()) {
        for (ResourceTypePackage rtkKpg : newPkg.getResourceTypePackages().values()) {
            ResourceType rt = rtkKpg.getResourceType();
            KieWeavers weavers = ServiceRegistry.getInstance().get(KieWeavers.class);
            KieWeaverService weaver = weavers.getWeavers().get(rt);
            weaver.merge(this, pkg, rtkKpg);
        }
    }
}
Also used : KieWeaverService(org.kie.api.internal.weaver.KieWeaverService) ArrayList(java.util.ArrayList) RuleImpl(org.drools.core.definitions.rule.impl.RuleImpl) Process(org.kie.api.definition.process.Process) ResourceType(org.kie.api.io.ResourceType) KieWeavers(org.kie.api.internal.weaver.KieWeavers) WindowDeclaration(org.drools.core.rule.WindowDeclaration) ImportDeclaration(org.drools.core.rule.ImportDeclaration) Rule(org.kie.api.definition.rule.Rule) ResourceTypePackage(org.kie.api.internal.io.ResourceTypePackage) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) TypeDeclaration(org.drools.core.rule.TypeDeclaration)

Aggregations

RuleImpl (org.drools.core.definitions.rule.impl.RuleImpl)107 Test (org.junit.Test)51 Pattern (org.drools.core.rule.Pattern)30 InternalKnowledgePackage (org.drools.core.definitions.InternalKnowledgePackage)28 RuleDescr (org.drools.compiler.lang.descr.RuleDescr)21 WorkingMemory (org.drools.core.WorkingMemory)21 KnowledgePackageImpl (org.drools.core.definitions.impl.KnowledgePackageImpl)18 BuildContext (org.drools.core.reteoo.builder.BuildContext)16 KnowledgeHelper (org.drools.core.spi.KnowledgeHelper)16 Consequence (org.drools.core.spi.Consequence)15 GroupElement (org.drools.core.rule.GroupElement)14 ClassObjectType (org.drools.core.base.ClassObjectType)13 InternalWorkingMemory (org.drools.core.common.InternalWorkingMemory)13 IOException (java.io.IOException)12 ObjectInput (java.io.ObjectInput)12 ObjectOutput (java.io.ObjectOutput)12 PackageDescr (org.drools.compiler.lang.descr.PackageDescr)12 RuleTerminalNode (org.drools.core.reteoo.RuleTerminalNode)12 KnowledgeBuilderImpl (org.drools.compiler.builder.impl.KnowledgeBuilderImpl)11 KnowledgeBaseImpl (org.drools.core.impl.KnowledgeBaseImpl)11