/** The Location Filter class is a SAX parser
* filter.  This class should be used between a SAX parser and the application, and may be
* 'layered' on top of or underneath other SAX parser filters.
*
* LocationFilter requires the use of a SAX parser and the ParserFilter parent class.
*
* @version 0.10, 12/4/98
* Copyright 1998 Simon St.Laurent 
* Information at: http://www.simonstl.com/projects/xlinkfilter/
* This code is licensed by Simon St.Laurent under the Mozilla Public License.
* See http://www.mozilla.org/MPL/ for details.
* No warranty provided - use at your own risk */

/* Modification history
*12/4/98 - Began development - Simon St.Laurent
*/


package com.simonstl.sax.location;

import org.ccil.cowan.sax.*;
import org.xml.sax.*;
import java.io.IOException;
import java.util.Stack;
import java.net.URL;

public class LocationFilter extends ParserFilter 
   {
    protected Stack locationStack;
    protected boolean returnAsAttribute=false;

   /**zero-argument constructor */
   public LocationFilter()
      throws IllegalAccessException, InstantiationException,
      ClassNotFoundException 
      {
      super();
      locationStack=new Stack();
      }

   /**one-argument constructor
   * @param parser - the SAX parser to be used underneath the filter. */
   public LocationFilter(Parser parser) 
      {
      super(parser);

      locationStack=new Stack();
      }
/**
* The setReturnAttribute tells the LocationFilter whether to include Location info as an attribute.
* This is not currently implemented.
*/
  public void setReturnAttribute(boolean returnAttribute) {
      this.returnAsAttribute=returnAttribute;
      }
/** The getLocation() method returns the Stack currently in use, identifying the location of the current
* element.  This direct access provides applications
*  with a ready means of addressing this element through a DOM tree.  For the most part, getLocationAsXPtr is
* more useful with XLinkFilter, but I left this access here so that people who need to identify element
* locations for other purposes can do so.
*/
  public Stack getLocation() {
		
	return locationStack;
      }

 /** The getLocationAsXPtr() method returns the location of the current element as an XPointer, suitable for use
 * in XLink applications, such as XLinkFilter.
 */

  public String getLocationAsXPtr() {
	String location;
	int count;
	Integer tempInt;

       
       location=new String();
       
       count=locationStack.size();
       for (int i=1; i<count-1; i++) {
	   if (i>1) {location=location+".";}
           location=location + "child(" + ((locationStack.elementAt(i)).toString()) +")";
       }

	
	return location;
      }
   // DocumentHandler implementation


/** 
* The startElement method provides most of the functionality of Location Filter, building a stack to keep
* track of where in the hierarchy the current element is.
*/
   public void startElement(String element, AttributeList atts)
      throws SAXException 
      { 
	int parentValue;
	Integer parentValueObject;

		if (!(locationStack.empty())) {
		parentValueObject=(Integer)locationStack.pop(); //get the parent element's counter
		parentValue=parentValueObject.intValue();
		parentValue++;
		locationStack.push(new Integer(parentValue));
	        } else {
		locationStack.push(new Integer(0));
		}
		
	locationStack.push(new Integer(0));
//for debug:
//System.out.println("Element: " + element + " Loc: "+this.getLocationAsXPtr());
         super.startElement(element, atts);
     
      }

   
   public void endElement(String element)
      throws SAXException 
      { 

	locationStack.pop(); //remove this element's counter

       //pass on to application's SAX handler
            super.endElement(element);
      }
    public String toString() {
       int count;
       String tempString;
       
       tempString=new String();
       
       count=locationStack.size();
       for (int i=0; i<count-1; i++) {
	   if (i>0) {tempString=tempString+"-";}
           tempString=tempString + ((locationStack.elementAt(i)).toString());
       }
       return tempString;
    }

}