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

📄 packagebuilder.java

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

/*
 * 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.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.jci.compilers.CompilationResult;
import org.apache.commons.jci.compilers.EclipseJavaCompiler;
import org.apache.commons.jci.compilers.EclipseJavaCompilerSettings;
import org.apache.commons.jci.compilers.JavaCompiler;
import org.apache.commons.jci.compilers.JavaCompilerFactory;
import org.apache.commons.jci.problems.CompilationProblem;
import org.apache.commons.jci.readers.MemoryResourceReader;
import org.apache.commons.jci.readers.ResourceReader;
import org.drools.RuntimeDroolsException;
import org.drools.base.ClassFieldExtractorCache;
import org.drools.lang.descr.FunctionDescr;
import org.drools.lang.descr.PackageDescr;
import org.drools.lang.descr.PatternDescr;
import org.drools.lang.descr.RuleDescr;
import org.drools.rule.Package;
import org.drools.rule.Rule;
import org.drools.semantics.java.ClassTypeResolver;
import org.drools.semantics.java.FunctionBuilder;
import org.drools.semantics.java.PackageStore;
import org.drools.semantics.java.RuleBuilder;
import org.drools.spi.TypeResolver;
import org.drools.xml.XmlPackageReader;
import org.xml.sax.SAXException;

/**
 * This is the main compiler class for parsing and compiling rules and assembling or merging them into a
 * binary Package instance.
 * This can be done by merging into existing binary packages, or totally from source.
 */
public class PackageBuilder {

    private JavaCompiler                compiler;
    private Package                     pkg;
    private List                        results;
    private PackageStore                packageStoreWrapper;
    private MemoryResourceReader        src;
    private PackageBuilderConfiguration configuration;
    private Map                         errorHandlers;
    private List                        generatedClassList;
    private ClassTypeResolver           typeResolver;
    private ClassFieldExtractorCache    classFieldExtractorCache;

    /**
     * Use this when package is starting from scratch. 
     */
    public PackageBuilder() {
        this( null,
              null );
    }

    /**
     * This will allow you to merge rules into this pre existing package.
     */
    public PackageBuilder(final Package pkg) {
        this( pkg,
              null );
    }

    public PackageBuilder(PackageBuilderConfiguration configuration) {
        this( null,
              configuration );
    }

    /**
     * This allows you to pass in a pre existing package, and a configuration (for instance to set the classloader).
     * @param pkg A pre existing package (can be null if none exists)
     * @param configuration Optional configuration for this builder.
     */
    public PackageBuilder(final Package pkg,
                          PackageBuilderConfiguration configuration) {
        if ( configuration == null ) {
            configuration = new PackageBuilderConfiguration();
        }

        this.configuration = configuration;
        loadCompiler();
        this.src = new MemoryResourceReader();
        this.results = new ArrayList();
        this.errorHandlers = new HashMap();
        this.pkg = pkg;
        this.generatedClassList = new ArrayList();
        this.classFieldExtractorCache = new ClassFieldExtractorCache();

        if ( pkg != null ) {
            this.packageStoreWrapper = new PackageStore( pkg.getPackageCompilationData() );
        }
    }

    /**
     * Load a rule package from DRL source.
     * @param reader
     * @throws DroolsParserException
     * @throws IOException
     */
    public void addPackageFromDrl(final Reader reader) throws DroolsParserException,
                                                      IOException {
        final DrlParser parser = new DrlParser();
        final PackageDescr pkg = parser.parse( reader );
        this.results.addAll( parser.getErrors() );
        addPackage( pkg );
    }

    /**
     * Load a rule package from XML source.
     * @param reader
     * @throws DroolsParserException
     * @throws IOException
     */
    public void addPackageFromXml(final Reader reader) throws DroolsParserException,
                                                      IOException {
        final XmlPackageReader xmlReader = new XmlPackageReader();

        try {
            xmlReader.read( reader );
        } catch ( final SAXException e ) {
            throw new DroolsParserException( e.getCause() );
        }

        addPackage( xmlReader.getPackageDescr() );
    }

    /**
     * Load a rule package from DRL source using the supplied DSL configuration.
     * @param source The source of the rules.
     * @param dsl The source of the domain specific language configuration.
     * @throws DroolsParserException
     * @throws IOException
     */
    public void addPackageFromDrl(final Reader source,
                                  final Reader dsl) throws DroolsParserException,
                                                   IOException {
        final DrlParser parser = new DrlParser();
        final PackageDescr pkg = parser.parse( source,
                                               dsl );
        this.results.addAll( parser.getErrors() );
        addPackage( pkg );
    }

    /** 
     * This adds a package from a Descr/AST 
     * This will also trigger a compile, if there are any generated classes to compile
     * of course.
     */
    public void addPackage(final PackageDescr packageDescr) {

        validatePackageName( packageDescr );
        validateUniqueRuleNames( packageDescr );

        if ( this.pkg != null ) {
            //mergePackage( packageDescr ) ;
            mergePackage( this.pkg,
                          packageDescr );
        } else {
            this.pkg = newPackage( packageDescr );
        }

        //only try to compile if there are no parse errors
        if ( !hasErrors() ) {
            //iterate and compile
            for ( final Iterator it = packageDescr.getFunctions().iterator(); it.hasNext(); ) {
                addFunction( (FunctionDescr) it.next() );
            }

            //iterate and compile
            for ( final Iterator it = packageDescr.getRules().iterator(); it.hasNext(); ) {
                addRule( (RuleDescr) it.next() );
            }
        }

        if ( this.generatedClassList.size() > 0 ) {
            this.compileAll();
        }
    }

    private void validatePackageName(final PackageDescr packageDescr) {
        if ( packageDescr.getName() == null || "".equals( packageDescr.getName() ) ) {

            throw new MissingPackageNameException( "Missing package name for rule package." );
        }
    }

    private void validateUniqueRuleNames(final PackageDescr packageDescr) {
        Set names = new HashSet();
        for ( Iterator iter = packageDescr.getRules().iterator(); iter.hasNext(); ) {
            RuleDescr rule = (RuleDescr) iter.next();
            String name = rule.getName();
            if ( names.contains( name ) ) {
                this.results.add( new ParserError( "Duplicate rule name: " + name,
                                                   rule.getLine(),
                                                   rule.getColumn() ) );
            }
            names.add( name );
        }
    }

    private Package newPackage(final PackageDescr packageDescr) {
        final Package pkg = new Package( packageDescr.getName(),
                                         this.configuration.getClassLoader() );

        this.packageStoreWrapper = new PackageStore( pkg.getPackageCompilationData() );

        mergePackage( pkg,
                      packageDescr );

        return pkg;
    }

    private void mergePackage(final Package pkg,
                              final PackageDescr packageDescr) {
        final List imports = packageDescr.getImports();
        for ( final Iterator it = imports.iterator(); it.hasNext(); ) {
            pkg.addImport( (String) it.next() );
        }

        final TypeResolver typeResolver = new ClassTypeResolver( imports,
                                                                 pkg.getPackageCompilationData().getClassLoader() );

        final Map globals = packageDescr.getGlobals();
        for ( final Iterator it = globals.keySet().iterator(); it.hasNext(); ) {
            final String identifier = (String) it.next();
            final String className = (String) globals.get( identifier );

            Class clazz;
            try {
                clazz = typeResolver.resolveType( className );
                pkg.addGlobal( identifier,
                               clazz );
            } catch ( final ClassNotFoundException e ) {
                new GlobalError( identifier );
            }
        }
    }

    /** 
     * This adds a compile "task" for when the compiler of 
     * semantics (JCI) is called later on with compileAll()\
     * which actually does the compiling.
     * The ErrorHandler is required to map the errors back to the 
     * element that caused it.
     */
    private void addClassCompileTask(final String className,
                                     final String text,
                                     final MemoryResourceReader src,
                                     ErrorHandler handler) {

        String fileName = className.replace( '.',
                                             '/' ) + ".java";
        src.add( fileName,
                 text.getBytes() );

        this.errorHandlers.put( fileName,
                                handler );
        this.generatedClassList.add( className );
    }

    private void addFunction(final FunctionDescr functionDescr) {
        final FunctionBuilder buidler = new FunctionBuilder();
        addClassCompileTask( this.pkg.getName() + "." + ucFirst( functionDescr.getName() ),
                             buidler.build( this.pkg,
                                            functionDescr ),
                             this.src,
                             new FunctionErrorHandler( functionDescr,
                                                       "Function Compilation error" ) );

    }

    private void addRule(final RuleDescr ruleDescr) {

        final String ruleClassName = getUniqueLegalName( this.pkg.getName(),
                                                         ruleDescr.getName(),
                                                         "java",
                                                         this.src );
        ruleDescr.SetClassName( ucFirst( ruleClassName ) );

        final RuleBuilder builder = new RuleBuilder( getTypeResolver(),
                                                     classFieldExtractorCache );

        builder.build( this.pkg,
                       ruleDescr );

        this.results.addAll( builder.getErrors() );

        final Rule rule = builder.getRule();

        // Check if there is any code to compile. If so compile it.       
        if ( builder.getRuleClass() != null ) {
            addRuleSemantics( builder,
                              rule,
                              ruleDescr );
        }

        this.pkg.addRule( rule );
    }

    /**
     * @return a Type resolver, lazily. 
     * If one does not exist yet, it will be initialised.
     */

⌨️ 快捷键说明

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