본문 바로가기

Lucene

[lucene] SynonymFilter

package lia.analysis.synonym;

import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.TokenFilter;
import org.apache.lucene.analysis.Token;
import java.io.IOException;
import java.util.Stack;

public class SynonymFilter extends TokenFilter {
  public static final String TOKEN_TYPE_SYNONYM = "SYNONYM";

  private Stack synonymStack;
  private SynonymEngine engine;

  public SynonymFilter(TokenStream in, SynonymEngine engine) {
    super(in);
    synonymStack = new Stack();
    this.engine = engine;
  }

  public Token next() throws IOException {
    if (synonymStack.size() > 0) { // 유의어 스택에 토큰이 있다면 리턴
      return (Token) synonymStack.pop();
    }

    Token token = input.next(); // 토큰 스트림에서 다음 토큰 가져오기..
    if (token == null) {
      return null;
    }

    addAliasesToStack(token); //유의어를 찾아서 스택에 쌓는다.

    return token; // 원래 토큰을 우선 리턴
  }

  private void addAliasesToStack(Token token) throws IOException {
    String[] synonyms = engine.getSynonyms(token.termText());

    if (synonyms == null) return;

    for (int i = 0; i < synonyms.length; i++) {
      Token synToken = new Token(synonyms[i],
                                 token.startOffset(),
                                 token.endOffset(),
                                 TOKEN_TYPE_SYNONYM);
      synToken.setPositionIncrement(0);

      synonymStack.push(synToken);
    }
  }
}

방식이 우선 원래 토큰을 리턴해주고
원래 토큰에 대한 유의어를 스택에 쌓아둔 다음에
next호출때 그 유의어들을 차례대로 리턴해준다.

유의어를 리턴해줄때는 원래 단어와 같은 위치에 존재함을 알려주기 위해
위치 증가값을 0으로 지정한다.

(원래 토큰의 위치가 1이면, 이 유의어들도 1..)