欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Lucene代码分析8

程序员文章站 2022-07-09 21:43:25
...

[email protected]

今天继续对Lucene中的Analysis进行分析

阅读的DotLucene版本是1.9.RC1

PyLucene基本工作原理
首先必须了解 PyLucene是如何实现的,其实 PyLucene 是在 Python 程序中嵌入了一个 JVM 来使用 Lucene,这个工作主要通过 JCC 来完成,JCC 编译 Lucene 源码为 C++,然后在 Python 中通过 JNI 进行调用。
现在我们希望在 Python 中扩展 Java 源码中的类,仍然要借助 JCC。

添加 Java 源码
假设我们要扩展 Lucene 中的类 A,首先要用 Java 写一个子类 PythonA 继承自 A,通常放在 org.apache.pylucene 里。示例代码如下:

package org.apache.pylucene.analysis;

import java.io.Reader;
import org.apache.lucene.analysis.Analyzer;

public class PythonAnalyzer extends Analyzer {

    private long pythonObject;

    public PythonAnalyzer()
    {
    }

    public void pythonExtension(long pythonObject)
    {
        this.pythonObject = pythonObject;
    }
    public long pythonExtension()
    {
        return this.pythonObject;
    }

    public void finalize()
        throws Throwable
    {
        pythonDecRef();
    }

    public native void pythonDecRef();

/*————————————————————分割线———————————————————————————*/

    @Override
    public native TokenStreamComponents createComponents(final String fieldName);

    @Override
    public native Reader initReader(String fieldName, Reader reader);
}

分割线以上除了构造函数以外不管扩展哪个类都必须这样写,分割线以下根据自己的需求来就好。方法最好用 public 来修饰,用 protected 可能会出错。
写好以后放到可以被 make 到的地方,当然最好放在 org.apache.pylucene 中,然后重新 make、make install。

在 Python 中扩展及遇到的问题

完成上面步骤后,在 Python 中直接继承 PythonA 就行,注意如果有 __init__() 的话,必须调用父类的构造方法。

遇到的问题:

1、Java 中 .class 的用法显然在 Python 中无法使用,而 getClass() 方法是通过对象来调用而不是类,可以考虑 Class.forName(),但是 Lucene 源码中的类使用 Class.forName() 可能找不到,最好使用 findClass() 方法。

>>> import lucene
>>> from lucene import findClass
>>> lucene.initVM(vmargs=['-Djava.awt.headless=true'])
>>> findClass('org/apache/lucene/document/Document')
    <Class: class org.apache.lucene.document.Document>
>>> Class.forName('org.apache.lucene.document.Document')
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    lucene.JavaError: java.lang.ClassNotFoundException: org/apache/lucene/document/Document
>>> Class.forName('java.lang.Object')
    <Class: class java.lang.Object>

2、Java源码中的父类 A 的变量在 Python 的子类中无法访问,可以在PythonA 的代码中添加 相应的 get 方法,提供访问接口。

3、关于处理 Java 中的数组,在 Python 中可以通过如下方式构造 Java 中的数组:

>>> array = JArray('int')(size)
    # the resulting Java int array is initialized with zeroes
>>> array = JArray('int')(sequence)
    # the sequence must only contain ints
    # the resulting Java int array contains the ints in the sequence

要把一个 Java 中的 char 数组转换为 Python 中的 str,只需要执行

''.join(array)
在 Python 中访问的话支持使用 [] 进行访问,可以修改元素内容,但无法改变数组大小。

4、Unicode 对象 s 转为 utf-8 :

s.encode('utf-8')