FileDocCategorySizeDatePackage
SPathFilter.javaAPI DocGlassfish v2 API10086Sat May 05 19:17:16 BST 2007org.apache.taglibs.standard.extra.spath

SPathFilter

public class SPathFilter extends XMLFilterImpl

Filters a SAX stream based on a single supplied SPath expression.

author
Shawn Bayern

Fields Summary
protected List
steps
The steps in the SPath expression we use for filtering.
private int
depth
private Stack
acceptedDepths
private int
excludedDepth
private static final boolean
DEBUG
Constructors Summary
public SPathFilter(Path path)
Constructs a new SPathFilter, given a Path.


    //*********************************************************************
    // Main method (for testing)

           
/*
    public static void main(String args[])
	    throws ParseException, IOException, SAXException {
// temporary...
System.setProperty("org.xml.sax.driver", "org.apache.xerces.parsers.SAXParser");

	// retrieve and parse the expression
	String expr = args[0];
	SPathParser s = new SPathParser(expr);
	Path p = s.expression();

	// construct the appropriate SAX chain
	// (reader -> us -> serializer)
	XMLReader r = XMLReaderFactory.createXMLReader();
	XMLFilter f1 = new SPathFilter(p);
	XMLFilter f2 = new XMLFilterImpl();
	f1.setParent(r);
	f2.setParent(f1);
	Serializer sz = SerializerFactory.getSerializer
	    (OutputProperties.getDefaultMethodProperties("xml"));
	sz.setOutputStream(System.out);
	f2.setContentHandler(sz.asContentHandler());

	// go!
	f2.parse(new InputSource(System.in));
	System.out.println();
    }
*/

    //*********************************************************************
    // Constructor and initialization methods

            
       
	init();
	this.steps = path.getSteps();
    
Methods Summary
public voidcharacters(char[] ch, int start, int length)
Filter for characters().

	if (isAccepted())
	    getContentHandler().characters(ch, start, length);
    
public voidendElement(java.lang.String uri, java.lang.String localName, java.lang.String qName)
Filter for endElement().

	// reduce the depth
	depth--;

	if (isExcluded()) {
	    // determine if exclusion ends with us
	    if (excludedDepth == depth)
	        excludedDepth = -1;

	    // either way, we have been excluded, so pass nothing through
	    return;
	}

	// if we're excepted (for now), include ourselves...
	if (isAccepted())
	    getContentHandler().endElement(uri, localName, qName);

	    if (DEBUG) {
		System.err.println("***   Closing tag: " + localName);
		System.err.println("***   acceptedDepths.size(): " + acceptedDepths.size());
		System.err.println("***   last accepted depth: " + ((Integer)acceptedDepths.peek()).intValue());
		System.err.println("***   depth: " + depth);
	    }

	// now, back off if we correspond to a "successful" start tag
        if (acceptedDepths.size() > 0 &&
		(((Integer)acceptedDepths.peek()).intValue()) == depth)
	    acceptedDepths.pop();
    
public voidendPrefixMapping(java.lang.String prefix)
Filter for endPrefixMapping().

	if (isAccepted())
	    getContentHandler().endPrefixMapping(prefix);
    
public voidignorableWhitespace(char[] ch, int start, int length)
Filter for ignoreableWhitespace().

	if (isAccepted())
	    getContentHandler().ignorableWhitespace(ch, start, length);
    
private voidinit()
Initializes state used for filtering.

	depth = 0;
	excludedDepth = -1;
	acceptedDepths = new Stack();
    
private booleanisAccepted()
Returns true if events should be passed through, false otherwise.

	return (acceptedDepths.size() >= steps.size());
    
private booleanisExcluded()
Returns true if events should be blocked, false otherwise.

	return (excludedDepth != -1);
    
public static booleannodeMatchesStep(Step s, java.lang.String uri, java.lang.String localName, java.lang.String qName, org.xml.sax.Attributes a)

	// if the name doesn't match, then we've got a loser
	if (!s.isMatchingName(uri, localName))
	    return false;

	// it's still in the game; check the predicates
	List l = s.getPredicates();
	for (int i = 0; l != null && i < l.size(); i++) {
	    Predicate p = (Predicate) l.get(i);
	    if (!(p instanceof AttributePredicate))
		throw new UnsupportedOperationException
		    ("only attribute predicates are supported by filter");
	    if (!((AttributePredicate) p).isMatchingAttribute(a))
		return false;		// all predicates must match
	}

	// it's survived
	return true;
    
public voidprocessingInstruction(java.lang.String target, java.lang.String data)
Filter for processingInstruction().

	if (isAccepted())
	    getContentHandler().processingInstruction(target, data);
    
public voidskippedEntity(java.lang.String name)
Filter for skippedEntity().

	if (isAccepted())
	    getContentHandler().skippedEntity(name);
    
public voidstartDocument()
Resets state.

	init();
    
public voidstartElement(java.lang.String uri, java.lang.String localName, java.lang.String qName, org.xml.sax.Attributes a)
Filter for startElement().

	// always update the depth
	depth++;

	// if we're in an accepted section, simply pass through
	if (isAccepted()) {
	    getContentHandler().startElement(uri, localName, qName, a);
	    return;
	}

	// likewise, if we're excluded, then simply block and return
	if (isExcluded())
	    return;

	// now, not accepted or excluded, let's see if we've got a match.
	// we need to get the appropriate step based on the number of
	// steps we've previously accepted
	Step currentStep = (Step) steps.get(acceptedDepths.size());

	if (nodeMatchesStep(currentStep, uri, localName, qName, a)) {
	    if (DEBUG)
		System.err.println("*** Progressive match (" + acceptedDepths.size() + "): " + localName);
	    // new match (progressive)
	    acceptedDepths.push(Integer.valueOf(depth - 1));

	    // is it enough?  give acceptance another chance...
	    if (isAccepted())
	        getContentHandler().startElement(uri, localName, qName, a);
	} else if (!currentStep.isDepthUnlimited()) {
	    // if the step was preceded by '/' instead of '//', then
	    // we can't have a match at this node or beneath it
	    excludedDepth = depth - 1;
	}

	// nothing left to check; no reason to include node
        return;
    
public voidstartPrefixMapping(java.lang.String prefix, java.lang.String uri)
Filter for startPrefixMapping().

	if (isAccepted())
	    getContentHandler().startPrefixMapping(prefix, uri);