Beispiel #1
0
        /// <summary> Here is a description of the compilation algorithm.
        /// 1. iterate over the conditional elements
        /// i. generate the alpha nodes
        /// a. literal constraints generate alpha node
        /// b. predicate constaints that compare against a literal generate alpha node
        /// ii. calculate the bindings
        /// a. each binding has a rowId
        /// b. NOT and EXIST CE do not increment the rowId
        /// 2. iterate over the conditional elements
        /// i. generate the beta nodes
        /// ii. attach the Left Input adapater nodes
        /// iii. attach the join nodes to the alpha nodes
        /// 3. create the terminal node and attach to the last
        /// join node.
        /// 
        /// This means the rule compiler takes a 2 pass approach to
        /// compiling rules. At the start of the method, it sets 3
        /// attributes to null: prevCE, prevJoinNode, joinNode.
        /// Those attributes are used by the compile join methods,
        /// so it's important to set it to null at the start. If
        /// we don't the Current rule won't compile correctly.
        /// </summary>
        public virtual bool addRule(Rule.IRule rule)
        {
            rule.resolveTemplates(engine);
            if (!validate || (validate && tval.analyze(rule) == Analysis_Fields.VALIDATION_PASSED))
            {
                // we have to set the attributes to null, before we start compiling a rule.

                // we've set the attributes to null, so we can compile now!!

                if (rule.Conditions != null && rule.Conditions.Length > 0)
                {
                    // we check the name of the rule to see if it is for a specific
                    // module. if it is, we have to Add it to that module
                    Module = rule;
                    try
                    {
                        ICondition[] conds = rule.Conditions;
                        // first we create the constraints, before creating the Conditional
                        // elements which include joins
                        // we use a counter and only increment it to make sure the
                        // row index of the bindings are accurate. this makes it simpler
                        // for the rule compiler and compileJoins is cleaner and does
                        // less work.
                        int counter = 0;
                        for (int idx = 0; idx < conds.Length; idx++)
                        {
                            ICondition con = conds[idx];
                            // compile object conditions
                            //implement in the ObjectConditionCompiler.compile or ExistConditionCompiler.compile
                            con.getCompiler(this).compile(con, counter, rule, rule.RememberMatch);

                            if ((con is ObjectCondition) && (!((ObjectCondition) con).Negated))
                            {
                                counter++;
                            }
                        }
                        // now we compile the joins
                        compileJoins(rule);

                        BaseNode last = rule.LastNode;
                        TerminalNode tnode = createTerminalNode(rule);

                        attachTerminalNode(last, tnode);
                        // compile the actions
                        compileActions(rule, rule.Actions);
                        // now we pass the bindings to the rule, so that actiosn can
                        // resolve the bindings

                        // now we Add the rule to the module
                        currentMod.addRule(rule);
                        CompileMessageEventArgs ce = new CompileMessageEventArgs(rule, EventType.ADD_RULE_EVENT);
                        ce.Rule = rule;
                        notifyListener(ce);
                        return true;
                    }
                    catch (AssertException e)
                    {
                        CompileMessageEventArgs ce = new CompileMessageEventArgs(rule, EventType.INVALID_RULE);
                        ce.Message = Messages.getString("RuleCompiler.assert.error"); //$NON-NLS-1$
                        notifyListener(ce);
                        TraceLogger.Instance.Debug(e);
                        return false;
                    }
                }
                else if (rule.Conditions.Length == 0)
                {
                    Module = rule;
                    // the rule has no LHS, this means it only has actions
                    BaseNode last = (BaseNode) inputnodes.Get(engine.initFact);
                    TerminalNode tnode = createTerminalNode(rule);
                    compileActions(rule, rule.Actions);
                    attachTerminalNode(last, tnode);
                    // now we Add the rule to the module
                    currentMod.addRule(rule);
                    CompileMessageEventArgs ce = new CompileMessageEventArgs(rule, EventType.ADD_RULE_EVENT);
                    ce.Rule = rule;
                    notifyListener(ce);
                    return true;
                }
                return false;
            }
            else
            {
                // we need to print out a message saying the rule was not valid
                ISummary error = tval.Errors;
                engine.writeMessage("Rule " + rule.Name + " was not added. ", Constants.DEFAULT_OUTPUT); //$NON-NLS-1$ //$NON-NLS-2$
                engine.writeMessage(error.Message, Constants.DEFAULT_OUTPUT);
                ISummary warn = tval.Warnings;
                engine.writeMessage(warn.Message, Constants.DEFAULT_OUTPUT);
                return false;
            }
        }