package org.xbib.elasticsearch.index.analysis.concat; import org.apache.lucene.analysis.TokenFilter; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import java.io.IOException; import java.util.ArrayDeque; import java.util.Deque; import java.util.LinkedList; import java.util.Map; import java.util.Queue; /** * */ public final class PairTokenFilter extends TokenFilter { private final CharTermAttribute termAttr; private final Map<String, String> pairs; private final Queue<String> queue; protected PairTokenFilter(TokenStream input, Map<String, String> pairs) { super(input); this.termAttr = addAttribute(CharTermAttribute.class); this.pairs = pairs; this.queue = new LinkedList<>(); } @Override public boolean incrementToken() throws IOException { if (!queue.isEmpty()) { termAttr.append(queue.poll()); return true; } if (!input.incrementToken()) { return false; } Deque<String> stack = new ArrayDeque<>(); while (pairs.containsKey(termAttr.toString())) { String term = termAttr.toString(); stack.push(term); if (!input.incrementToken()) { break; } String next = termAttr.toString(); if (pairs.get(term).equals(next)) { stack.pop(); stack.push(term + " " + next); break; } else if (!pairs.containsKey(next)) { stack.push(next); } } for (String term : stack) { queue.add(term); } if (!queue.isEmpty()) { termAttr.setEmpty().append(queue.poll()); } return true; } @Override public boolean equals(Object object) { return object instanceof PairTokenFilter && pairs.equals( ((PairTokenFilter)object).pairs); } @Override public int hashCode() { return pairs.hashCode(); } }