package lux.index.analysis;
import java.io.IOException;
import java.io.Reader;
import java.util.Iterator;
import lux.xml.Offsets;
import net.sf.saxon.s9api.Axis;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.XdmNode;
import net.sf.saxon.s9api.XdmSequenceIterator;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
/**
* A TokenStream that extracts words from attributes in a Saxon Document model (XdmNode)
*/
public final class AttributeTokenStream extends TextOffsetTokenStream {
public AttributeTokenStream(String fieldName, Analyzer analyzer, TokenStream wrapped, XdmNode doc, Offsets offsets, Processor processor) {
super(fieldName, analyzer, wrapped, doc, offsets, processor);
contentIter = new AttributeIterator(doc);
}
@Override
public void reset (Reader reader) throws IOException {
super.reset(reader);
qnameTokenFilter.reset(getWrappedTokenStream());
setWrappedTokenStream (qnameTokenFilter);
}
@Override
protected boolean updateNodeAtts() {
// TODO: hide attribute content of hidden elements by returning false?
getAttributeQName();
return true;
}
private void getAttributeQName() {
qnameAtt.clearQNames();
QName qname = curNode.getNodeName();
qnameAtt.addQName(new lux.xml.QName(qname.getNamespaceURI(), qname.getLocalName(), qname.getPrefix()));
}
/**
* Iterates over /descendant::element()/@*); all descendant elements'
* attributes
*/
private static class AttributeIterator implements Iterator<XdmNode> {
private XdmSequenceIterator descendants;
private XdmSequenceIterator attributes;
private XdmNode next = null; // storage for lookahead
protected AttributeIterator(XdmNode node) {
descendants = node.axisIterator(Axis.DESCENDANT_OR_SELF);
attributes = EMPTY;
next = null;
}
@Override
public boolean hasNext() {
if (next != null) {
return true;
}
next = getNext();
return next != null;
}
private XdmNode getNext() {
for (;;) {
if (attributes.hasNext()) {
next = (XdmNode) attributes.next();
return next;
} else if (descendants.hasNext()) {
XdmNode node = (XdmNode) descendants.next();
attributes = node.axisIterator(Axis.ATTRIBUTE);
} else {
return null;
}
}
}
@Override
public XdmNode next() {
if (hasNext()) {
XdmNode node = next;
next = null;
return node;
}
return null;
}
@Override
public void remove() {
}
}
}
/*
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/.
*/