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

📄 pythoninterp.java

📁 drools 一个开放源码的规则引擎
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package org.drools.semantics.python;

/*
 * Copyright 2002-2004 (C) The Werken Company. All Rights Reserved.
 *
 * Redistribution and use of this software and associated documentation
 * ("Software"), with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * 1. Redistributions of source code must retain copyright statements and
 * notices. Redistributions must also contain a copy of this document.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. The name "drools" must not be used to endorse or promote products derived
 * from this Software without prior written permission of The Werken Company.
 * For written permission, please contact bob@werken.com.
 *
 * 4. Products derived from this Software may not be called "drools" nor may
 * "drools" appear in their names without prior written permission of The Werken
 * Company. "drools" is a registered trademark of The Werken Company.
 *
 * 5. Due credit should be given to The Werken Company.
 * (http://drools.werken.com/).
 *
 * THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE WERKEN COMPANY OR ITS CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.util.Iterator;
import java.util.Map;

import org.drools.WorkingMemory;
import org.drools.rule.Declaration;
import org.drools.rule.Rule;
import org.drools.semantics.base.ClassObjectType;
import org.drools.spi.DefaultKnowledgeHelper;
import org.drools.spi.Functions;
import org.drools.spi.ObjectType;
import org.drools.spi.RuleBaseContext;
import org.drools.spi.Tuple;
import org.python.core.Py;
import org.python.core.PyCode;
import org.python.core.PyDictionary;
import org.python.core.PyModule;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PySystemState;
import org.python.core.parser;
import org.python.parser.ast.modType;

/**
 * Base class for Jython interpreter-based Python semantic components.
 * 
 * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter </a>
 */
public class PythonInterp implements Serializable
{
    /** The line separator system property ("\n" on UNIX). */
    private static final String LINE_SEPARATOR = System.getProperty( "line.separator" );

    // ------------------------------------------------------------
    // Class Initialization
    // ------------------------------------------------------------

    // ------------------------------------------------------------
    // Instance members
    // ------------------------------------------------------------

    /** The rule. */
    private final Rule          rule;

    /** Text. */
    private transient String        text;

    /** Original Text */
    private final String        origininalText;

    private final String            type;        

    /** The code. */
    private transient PyCode        code;

    /** The AST node. */
    private transient modType       node;

    private transient PyDictionary  globals;    

    /**
     * Initialise Jython's PySystemState
     */
    static
    {
        PySystemState.initialize( );

        PySystemState systemState = Py.getSystemState( );
        
        if ( systemState == null )
        {
            systemState = new PySystemState( );
        }
        
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        if (classLoader ==null) 
        {
            classLoader = PythonInterp.class.getClassLoader();
        }
        systemState.setClassLoader(classLoader);
        
        Py.setSystemState( systemState );
    }

    // ------------------------------------------------------------
    // Constructors
    // ------------------------------------------------------------

    /**
     * Construct.
     */
    protected PythonInterp(String text,
                           Rule rule,
                           String type)
    {
        this.rule = rule;
        this.origininalText = text;
        this.type = type;
        
        compile( );

    }
    
    private void compile()
    {
        StringBuffer globalText = new StringBuffer( );
        
        Iterator it = rule.getImporter( ).getImports( ).iterator( );

        while ( it.hasNext( ) )
        {
            globalText.append( convertToPythonImport( ( String ) it.next( ) ) );
            globalText.append( LINE_SEPARATOR );
        }

        globalText.append( "def q(cond,on_true,on_false):\n" );
        globalText.append( "  if cond:\n" );
        globalText.append( "    return on_true\n" );
        globalText.append( "  else:\n" );
        globalText.append( "    return on_false\n" );
        
        Functions functions = rule.getRuleSet( ).getFunctions( "python" );
        if ( functions != null )
        {
            globalText.append( stripOuterIndention( functions.getText( ) ) );
        }       
        
        if ( this.globals == null )
        {
            this.globals = getGlobals( globalText.toString( ) );
        }

        this.text = stripOuterIndention( this.origininalText );

        try
        {
            this.node = (modType) parser.parse( this.text,
                                                type );
            this.code = Py.compile( this.node,
                                    "<jython>" );
        }
        catch ( Exception e )
        {
            throw new RuntimeException( e.getLocalizedMessage( ) );
        }        
    }

    private String convertToPythonImport(String importEntry)
    {
        int lastDot = importEntry.lastIndexOf( '.' );
        String packageText = importEntry.substring( 0, lastDot );
        String className = importEntry.substring( lastDot + 1, importEntry.length( ) );
        return "from " + packageText + " import " + className;         
    }    

    /**
     * Parses a python script and returns the globals It is used to be able to
     * inject imports and functions into code when being executed by
     * Py.runCode(...)
     * 
     * @param text
     * @return PyDictionary globals
     */
    public PyDictionary getGlobals(String text)
    {
        PyModule module = new PyModule( "main",
                                        new PyDictionary( ) );

        PyObject locals = module.__dict__;       

        Py.exec( Py.compile_flags( text,
                                   "<string>",
                                   "exec",
                                   null ),
                 locals,
                 locals );

        return (PyDictionary) locals;
    }

    /**
     * Trims leading indention from the block of text. Since Python relies on
     * indention as part of its syntax, any XML indention introduced needs to be
     * stripped out. For example, this:
     * 
     * <pre>
     * 
     *  
     *  
     *    |   &lt;python:consequence&gt;
     *    |       if hello == 'Hello':
     *    |           print &quot;Hi&quot;
     *    |       else:
     *    |           print &quot;Bye&quot;
     *    |   &lt;/python:consequence&gt;
     *  
     *   
     *  
     * </pre>
     * 
     * is transformed into:
     * 
     * <pre>
     * 
     *  
     *  
     *    |   &lt;python:consequence&gt;
     *    |if hello == 'Hello':
     *    |    print &quot;Hi&quot;
     *    |else:
     *    |    print &quot;Bye&quot;
     *    |   &lt;/python:consequence&gt;
     *  
     *   
     *  
     * </pre>
     * 
     * @param text
     *            the block of text to be stripped
     * @return the block of text stripped of its leading indention
     */
    protected static String stripOuterIndention(String text)
    {
        try
        {

⌨️ 快捷键说明

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