⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rulebuilder.java

📁 jboss规则引擎
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
package org.drools.semantics.java;

/*
 * Copyright 2005 JBoss Inc
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.language.AngleBracketTemplateLexer;
import org.drools.RuntimeDroolsException;
import org.drools.base.ClassFieldExtractor;
import org.drools.base.ClassFieldExtractorCache;
import org.drools.base.ClassObjectType;
import org.drools.base.EvaluatorFactory;
import org.drools.base.FieldFactory;
import org.drools.base.FieldImpl;
import org.drools.compiler.RuleError;
import org.drools.lang.descr.AndDescr;
import org.drools.lang.descr.AttributeDescr;
import org.drools.lang.descr.BoundVariableDescr;
import org.drools.lang.descr.ColumnDescr;
import org.drools.lang.descr.ConditionalElementDescr;
import org.drools.lang.descr.EvalDescr;
import org.drools.lang.descr.ExistsDescr;
import org.drools.lang.descr.FieldBindingDescr;
import org.drools.lang.descr.LiteralDescr;
import org.drools.lang.descr.NotDescr;
import org.drools.lang.descr.OrDescr;
import org.drools.lang.descr.PatternDescr;
import org.drools.lang.descr.PredicateDescr;
import org.drools.lang.descr.QueryDescr;
import org.drools.lang.descr.ReturnValueDescr;
import org.drools.lang.descr.RuleDescr;
import org.drools.rule.And;
import org.drools.rule.BoundVariableConstraint;
import org.drools.rule.Column;
import org.drools.rule.Declaration;
import org.drools.rule.EvalCondition;
import org.drools.rule.Exists;
import org.drools.rule.GroupElement;
import org.drools.rule.LiteralConstraint;
import org.drools.rule.Not;
import org.drools.rule.Or;
import org.drools.rule.Package;
import org.drools.rule.PredicateConstraint;
import org.drools.rule.Query;
import org.drools.rule.ReturnValueConstraint;
import org.drools.rule.Rule;
import org.drools.spi.Evaluator;
import org.drools.spi.FieldExtractor;
import org.drools.spi.FieldValue;
import org.drools.spi.TypeResolver;

/**
 * This builds the rule structure from an AST.
 * Generates semantic code where necessary if semantics are used.
 * This is an internal API.
 */
public class RuleBuilder {
    private Package                           pkg;
    private Rule                              rule;
    private RuleDescr                         ruleDescr;

    public String                             ruleClass;
    public List                               methods;
    public Map                                invokers;

    private Map                               invokerLookups;

    private Map                               descrLookups;

    private Map                               declarations;

    private int                               counter;

    private ColumnCounter                     columnCounter;

    private int                               columnOffset;

    private List                              errors;

    private final TypeResolver                      typeResolver;

    private Map                               notDeclarations;

    private static final StringTemplateGroup  ruleGroup            = new StringTemplateGroup( new InputStreamReader( RuleBuilder.class.getResourceAsStream( "javaRule.stg" ) ),
                                                                                              AngleBracketTemplateLexer.class );

    private static final StringTemplateGroup  invokerGroup         = new StringTemplateGroup( new InputStreamReader( RuleBuilder.class.getResourceAsStream( "javaInvokers.stg" ) ),
                                                                                              AngleBracketTemplateLexer.class );

    private static final KnowledgeHelperFixer knowledgeHelperFixer = new KnowledgeHelperFixer();
    private static final FunctionFixer        functionFixer        = new FunctionFixer();

    // @todo move to an interface so it can work as a decorator
    private final JavaExprAnalyzer            analyzer             = new JavaExprAnalyzer();
    private ClassFieldExtractorCache classFieldExtractorCache;


    public RuleBuilder(TypeResolver resolver, ClassFieldExtractorCache cache) {
        this.classFieldExtractorCache = cache;
        this.typeResolver = resolver;
        this.errors = new ArrayList();
    }

    public Map getInvokers() {
        return this.invokers;
    }

    public Map getDescrLookups() {
        return this.descrLookups;
    }

    public String getRuleClass() {
        return this.ruleClass;
    }

    public Map getInvokerLookups() {
        return this.invokerLookups;
    }

    public List getErrors() {
        return this.errors;
    }

    public Rule getRule() {
        if ( !this.errors.isEmpty() ) {
            this.rule.setSemanticallyValid( false );
        }
        return this.rule;
    }

    public Package getPackage() {
        return this.pkg;
    }

    public synchronized Rule build(final Package pkg,
                                   final RuleDescr ruleDescr) {
        this.pkg = pkg;
        this.methods = new ArrayList();
        this.invokers = new HashMap();
        this.invokerLookups = new HashMap();
        this.declarations = new HashMap();
        this.descrLookups = new HashMap();
        this.columnCounter = new ColumnCounter();


        this.ruleDescr = ruleDescr;

        if ( ruleDescr instanceof QueryDescr ) {
            this.rule = new Query( ruleDescr.getName() );
        } else {
            this.rule = new Rule( ruleDescr.getName() );
        }

        // Assign attributes
        setAttributes( this.rule,
                       ruleDescr.getAttributes() );

        // Build the left hand side
        // generate invoker, methods
        build( ruleDescr );

        return this.rule;
    }

    private void setAttributes(final Rule rule,
                               final List attributes) {
        for ( final Iterator it = attributes.iterator(); it.hasNext(); ) {
            final AttributeDescr attributeDescr = (AttributeDescr) it.next();
            final String name = attributeDescr.getName();
            if ( name.equals( "salience" ) ) {
                rule.setSalience( Integer.parseInt( attributeDescr.getValue() ) );
            } else if ( name.equals( "no-loop" ) ) {
                if ( attributeDescr.getValue() == null ) {
                    rule.setNoLoop( true );
                } else {
                    rule.setNoLoop( Boolean.valueOf( attributeDescr.getValue() ).booleanValue() );
                }
            } else if ( name.equals( "auto-focus" ) ) {
                if ( attributeDescr.getValue() == null ) {
                    rule.setAutoFocus( true );
                } else {
                    rule.setAutoFocus( Boolean.valueOf( attributeDescr.getValue() ).booleanValue() );
                }
            } else if ( name.equals( "agenda-group" ) ) {
                rule.setAgendaGroup( attributeDescr.getValue() );
            } else if ( name.equals( "activation-group" ) ) {
                rule.setXorGroup( attributeDescr.getValue() );
            } else if ( name.equals( "duration" ) ) {
                rule.setDuration( Long.parseLong( attributeDescr.getValue() ) );
                rule.setAgendaGroup( "" );
            } else if ( name.equals( "language" ) ) {
                //@todo: we don't currently  support multiple languages
            }
        }
    }

    private void build(final RuleDescr ruleDescr) {

        for ( final Iterator it = ruleDescr.getLhs().getDescrs().iterator(); it.hasNext(); ) {
            final Object object = it.next();
            if ( object instanceof ConditionalElementDescr ) {
                if ( object instanceof AndDescr ) {
                    final And and = new And();
                    this.columnCounter.setParent( and );
                    build( this.rule,
                           (ConditionalElementDescr) object,
                           and,
                           false,   // do not decrement offset
                           false ); // do not decrement first offset
                    this.rule.addPattern( and );
                } else if ( object instanceof OrDescr ) {
                    final Or or = new Or();
                    this.columnCounter.setParent( or );
                    build( this.rule,
                           (ConditionalElementDescr) object,
                           or,
                           true,    // when OR is used, offset MUST be decremented
                           false ); // do not decrement first offset
                    this.rule.addPattern( or );
                } else if ( object instanceof NotDescr ) {
                    // We cannot have declarations created inside a not visible outside it, so track no declarations so they can be removed
                    this.notDeclarations = new HashMap();
                    final Not not = new Not();
                    this.columnCounter.setParent( not );
                    build( this.rule,
                           (ConditionalElementDescr) object,
                           not,
                           true,   // when NOT is used, offset MUST be decremented
                           true ); // when NOT is used, offset MUST be decremented for first column
                    this.rule.addPattern( not );

                    // remove declarations bound inside not node
                    for ( final Iterator notIt = this.notDeclarations.keySet().iterator(); notIt.hasNext(); ) {
                        this.declarations.remove( notIt.next() );
                    }

                    this.notDeclarations = null;
                } else if ( object instanceof ExistsDescr ) {
                    // We cannot have declarations created inside a not visible outside it, so track no declarations so they can be removed
                    this.notDeclarations = new HashMap();
                    final Exists exists = new Exists();
                    this.columnCounter.setParent( exists );
                    build( this.rule,
                           (ConditionalElementDescr) object,
                           exists,
                           true,   // when EXIST is used, offset MUST be decremented
                           true ); // when EXIST is used, offset MUST be decremented for first column
                    // remove declarations bound inside not node
                    for ( final Iterator notIt = this.notDeclarations.keySet().iterator(); notIt.hasNext(); ) {
                        this.declarations.remove( notIt.next() );
                    }

                    this.notDeclarations = null;
                    this.rule.addPattern( exists );
                } else if ( object instanceof EvalDescr ) {
                    final EvalCondition eval = build( (EvalDescr) object );
                    if ( eval != null ) {
                        this.rule.addPattern( eval );
                    }
                }
            } else if ( object instanceof ColumnDescr ) {
                final Column column = build( (ColumnDescr) object );
                if ( column != null ) {
                    this.rule.addPattern( column );
                }
            }
        }

        // Build the consequence and generate it's invoker/methods
        // generate the main rule from the previously generated methods.
        if ( !(ruleDescr instanceof QueryDescr) ) {
            // do not build the consequence if we have a query
            buildConsequence( ruleDescr );
        }
        buildRule( ruleDescr );
    }

    private void build(final Rule rule,
                       final ConditionalElementDescr descr,
                       final GroupElement ce,
                       final boolean decrementOffset,
                       boolean decrementFirst) {
        for ( final Iterator it = descr.getDescrs().iterator(); it.hasNext(); ) {
            final Object object = it.next();
            if ( object instanceof ConditionalElementDescr ) {
                if ( object instanceof AndDescr ) {
                    final And and = new And();
                    this.columnCounter.setParent( and );
                    build( rule,
                           (ConditionalElementDescr) object,
                           and,
                           false,   // do not decrement offset
                           false ); // do not decrement first offset
                    ce.addChild( and );
                } else if ( object instanceof OrDescr ) {
                    final Or or = new Or();
                    this.columnCounter.setParent( or );
                    build( rule,
                           (ConditionalElementDescr) object,
                           or,
                           true,    // when OR is used, offset MUST be decremented
                           false ); // do not decrement first offset
                    ce.addChild( or );
                } else if ( object instanceof NotDescr ) {
                    final Not not = new Not();
                    this.columnCounter.setParent( not );
                    build( rule,
                           (ConditionalElementDescr) object,
                           not,
                           true,   // when NOT is used, offset MUST be decremented
                           true ); // when NOT is used, offset MUST be decremented for first column

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -