package com.simonstl.namespace.elements;

import com.simonstl.namespace.*;
import org.xml.sax.*;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.XMLFilter;
import org.xml.sax.helpers.XMLFilterImpl;
import java.util.*;

/*
The contents of this file are subject to the Mozilla Public License  Version 1.1 (the "License"); you may not use this file except in  compliance with the License. You may obtain a copy of the License at 
http://www.mozilla.org/MPL/ 

Software distributed under the License is distributed on an "AS IS"  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the  License for the specific language governing rights and limitations under  the License. 

The Original Code is available at  http://simonstl.com/projects/fragment/original. 

The Initial Developer of the Original Code is Simon St.Laurent. Portions  created by Simon St.Laurent are Copyright (C) 2001. All Rights Reserved. 

Contributor(s): 
*/

/**
*
* <p>A filter which adds context namespace information to unqualified elements according to a set of inclusion or exclusion rules. If no rules are set, all namespaces are annotated.</p>
<p>Context will be indicated in the form of an attribute:</p>
<pre>&lt;unqual an:lastNSContext="http://www.example.com xmlns:anlc="http://simonstl.com/ns/namespaces/elements/lastContext/"&gt;
*
* @version 0.01  2 August 2001
* @author Simon St.Laurent
*/

public class ElementAnnotNamespaceFilter extends XMLFilterImpl { 

    private NamespaceRules rules=null;   //set of rules
    private ContextStack context =new ContextStack();

/**
* An empty constructor that requires the use of setParent before starting
* I don't think this works.
*/
public ElementAnnotNamespaceFilter () {

 } 

/**
* A constructor that takes the parser which will feed it SAX events
*/

public ElementAnnotNamespaceFilter (XMLReader parent) {
    super(parent); 
} 

/**
* sets up the rules, read in from a config file by RulesLoader or
* otherwise concocted in Java using the {@link com.simonstl.namespace.NamespaceRules NamespaceRules} class.
*
* @param newRules  the set of rules the NamespaceFilter will apply to content
*/
public void setRules (NamespaceRules newRules) {
  rules=newRules;
//rules.print();
}

/**
* in case you ever need to get the rules out of NamespaceFilter 
*/
public NamespaceRules getRules () {
  return rules;
}

/** 
* Check at startElement for names which should be qualified. 
* if the context namespace URI matches a rule, 
* the namespace will be forcibly applied to unqualifed elements.
*/ 

public void startElement (String uri, String localName, String qName, Attributes atts) throws SAXException {
//System.out.println("Starting "+uri+" "+"localName"+" "+qName);
  if (!(uri.equals(""))) {
    context.push(uri);
//System.out.println("Pushing: "+context.peek() +" at " +localName);
  }

  if ((uri.equals("")) && (!(context.peek().equals("")))){
    atts=addAtt(atts);
  }
//System.out.println("Finished "+uri+" "+"localName"+" "+qName);
  super.startElement(uri, localName, qName, atts); 
}

public void endElement (String uri, String localName, String qName) throws SAXException {
//test for end of qualification first
  if ((uri.equals(context.peek())) && (!(uri.equals("")))) {
//System.out.println("Popping: "+context.peek() +" at " +localName);
    context.pop();
  }

  super.endElement(uri, localName, qName); 

}

public Attributes addAtt(Attributes atts) {
//used to use new AttributesImpl(atts), but that hangs
   AttributesImpl attsWork=new AttributesImpl();
   
  String contextURI="";
    if (rules!=null) {
//System.out.println(context.peek());
       if (rules.isRule(context.peek())) {
         contextURI=context.peek();
//System.out.println("Matched!");
       }
    } else {//no rules
       contextURI=context.peek();
//System.out.println("No rules!");
    }
    if (!(contextURI.equals("")) ) {
//System.out.println("Match");
//System.out.println("Adding context: "+contextURI);
      attsWork.addAttribute("http://simonstl.com/ns/namespaces/elements/lastContext/", "lastNSContext", "an:lastNSContext", "CDATA", contextURI);
    }
//add the other attributes
    int numAtts=atts.getLength();
    for (int i=0; i<numAtts; i++) {
      attsWork.addAttribute( atts.getURI(i), atts.getLocalName(i), atts.getQName(i), atts.getType(i), atts.getValue(i) );
    }
 
return (Attributes) attsWork;
}


} 
