/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id$
 */

package org.apache.xml.serializer.dom3;

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;

import org.apache.xml.serializer.dom3.NamespaceSupport;
import org.apache.xml.serializer.OutputPropertiesFactory;
import org.apache.xml.serializer.SerializationHandler;
import org.apache.xml.serializer.utils.MsgKey;
import org.apache.xml.serializer.utils.Utils;
import org.apache.xml.serializer.utils.XML11Char;
import org.apache.xml.serializer.utils.XMLChar;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMError;
import org.w3c.dom.DOMErrorHandler;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Entity;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import org.w3c.dom.ls.LSSerializerFilter;
import org.w3c.dom.traversal.NodeFilter;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.LocatorImpl;

/**
 * Built on org.apache.xml.serializer.TreeWalker and adds functionality to
 * traverse and serialize a DOM Node (Level 2 or Level 3) as specified in 
 * the DOM Level 3 LS Recommedation by evaluating and applying DOMConfiguration 
 * parameters and filters if any during serialization.
 *   
 * @xsl.usage internal
 */
final class DOM3TreeWalker {

    /**
     * The SerializationHandler, it extends ContentHandler and when
     * this class is instantiated via the constructor provided, a
     * SerializationHandler object is passed to it.
     */
    private SerializationHandler fSerializer = null;

    /** We do not need DOM2Helper since DOM Level 3 LS applies to DOM Level 2 or newer */

    /** Locator object for this TreeWalker          */
    private LocatorImpl fLocator = new LocatorImpl();

    /** ErrorHandler */
    private DOMErrorHandler fErrorHandler = null;

    /** LSSerializerFilter */
    private LSSerializerFilter fFilter = null;

    /** If the serializer is an instance of a LexicalHandler */
    private LexicalHandler fLexicalHandler = null;

    private int fWhatToShowFilter;

    /** New Line character to use in serialization */
    private String fNewLine = null;

    /** DOMConfiguration Properties */
    private Properties fDOMConfigProperties = null;

    /** Keeps track if we are in an entity reference when entities=true */
    private boolean fInEntityRef = false;

    /** Stores the version of the XML document to be serialize */
    private String fXMLVersion = null;

    /** XML Version, default 1.0 */
    private boolean fIsXMLVersion11 = false;

    /** Is the Node a Level 3 DOM node */
    private boolean fIsLevel3DOM = false;

    /** DOM Configuration Parameters */
    private int fFeatures = 0;

    /** Flag indicating whether following text to be processed is raw text          */
    boolean fNextIsRaw = false;

    // 
    private static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";

    //
    private static final String XMLNS_PREFIX = "xmlns";

    // 
    private static final String XML_URI = "http://www.w3.org/XML/1998/namespace";

    // 
    private static final String XML_PREFIX = "xml";

    /** stores namespaces in scope */
    protected NamespaceSupport fNSBinder;

    /** stores all namespace bindings on the current element */
    protected NamespaceSupport fLocalNSBinder;
    
    /** stores the current element depth */
    private int fElementDepth = 0;

    // ***********************************************************************
    // DOMConfiguration paramter settings 
    // ***********************************************************************
    // Parameter canonical-form, true [optional] - NOT SUPPORTED 
    private final static int CANONICAL = 0x1 << 0;

    // Parameter cdata-sections, true [required] (default)
    private final static int CDATA = 0x1 << 1;

    // Parameter check-character-normalization, true [optional] - NOT SUPPORTED 
    private final static int CHARNORMALIZE = 0x1 << 2;

    // Parameter comments, true [required] (default)
    private final static int COMMENTS = 0x1 << 3;

    // Parameter datatype-normalization, true [optional] - NOT SUPPORTED
    private final static int DTNORMALIZE = 0x1 << 4;

    // Parameter element-content-whitespace, true [required] (default) - value - false [optional] NOT SUPPORTED
    private final static int ELEM_CONTENT_WHITESPACE = 0x1 << 5;

    // Parameter entities, true [required] (default)
    private final static int ENTITIES = 0x1 << 6;

    // Parameter infoset, true [required] (default), false has no effect --> True has no effect for the serializer
    private final static int INFOSET = 0x1 << 7;

    // Parameter namespaces, true [required] (default)
    private final static int NAMESPACES = 0x1 << 8;

    // Parameter namespace-declarations, true [required] (default)
    private final static int NAMESPACEDECLS = 0x1 << 9;

    // Parameter normalize-characters, true [optional] - NOT SUPPORTED
    private final static int NORMALIZECHARS = 0x1 << 10;

    // Parameter split-cdata-sections, true [required] (default)
    private final static int SPLITCDATA = 0x1 << 11;

    // Parameter validate, true [optional] - NOT SUPPORTED
    private final static int VALIDATE = 0x1 << 12;

    // Parameter validate-if-schema, true [optional] - NOT SUPPORTED
    private final static int SCHEMAVALIDATE = 0x1 << 13;

    // Parameter split-cdata-sections, true [required] (default)
    private final static int WELLFORMED = 0x1 << 14;

    // Parameter discard-default-content, true [required] (default)
    // Not sure how this will be used in level 2 Documents
    private final static int DISCARDDEFAULT = 0x1 << 15;

    // Parameter format-pretty-print, true [optional] 
    private final static int PRETTY_PRINT = 0x1 << 16;

    // Parameter ignore-unknown-character-denormalizations, true [required] (default)
    // We currently do not support XML 1.1 character normalization
    private final static int IGNORE_CHAR_DENORMALIZE = 0x1 << 17;

    // Parameter discard-default-content, true [required] (default)
    private final static int XMLDECL = 0x1 << 18;

    /**
     * Constructor.
     * @param   contentHandler serialHandler The implemention of the SerializationHandler interface
     */
    DOM3TreeWalker(
        SerializationHandler serialHandler,
        DOMErrorHandler errHandler,
        LSSerializerFilter filter,
        String newLine) {
        fSerializer = serialHandler;
        //fErrorHandler = errHandler == null ? new DOMErrorHandlerImpl() : errHandler; // Should we be using the default?
        fErrorHandler = errHandler;
        fFilter = filter;
        fLexicalHandler = null;
        fNewLine = newLine;

        fNSBinder = new NamespaceSupport();
        fLocalNSBinder = new NamespaceSupport();
        
        fDOMConfigProperties = fSerializer.getOutputFormat();
        fSerializer.setDocumentLocator(fLocator);
        initProperties(fDOMConfigProperties);
        
        try {
            // Bug see Bugzilla  26741
            fLocator.setSystemId(
                System.getProperty("user.dir") + File.separator + "dummy.xsl");
        } catch (SecurityException se) { // user.dir not accessible from applet

        }
    }

    /**
     * Perform a pre-order traversal non-recursive style.  
     *
     * Note that TreeWalker assumes that the subtree is intended to represent 
     * a complete (though not necessarily well-formed) document and, during a 
     * traversal, startDocument and endDocument will always be issued to the 
     * SAX listener.
     *  
     * @param pos Node in the tree where to start traversal
     *
     * @throws TransformerException
     */
    public void traverse(Node pos) throws org.xml.sax.SAXException {
        this.fSerializer.startDocument();

        // Determine if the Node is a DOM Level 3 Core Node.
        if (pos.getNodeType() != Node.DOCUMENT_NODE) {
            Document ownerDoc = pos.getOwnerDocument();
            if (ownerDoc != null
                && ownerDoc.getImplementation().hasFeature("Core", "3.0")) {
                fIsLevel3DOM = true;
            }
        } else {
            if (((Document) pos)
                .getImplementation()
                .hasFeature("Core", "3.0")) {
                fIsLevel3DOM = true;
            }
        }

        if (fSerializer instanceof LexicalHandler) {
            fLexicalHandler = ((LexicalHandler) this.fSerializer);
        }

        if (fFilter != null)
            fWhatToShowFilter = fFilter.getWhatToShow();

        Node top = pos;

        while (null != pos) {
            startNode(pos);

            Node nextNode = null;

            nextNode = pos.getFirstChild();

            while (null == nextNode) {
                endNode(pos);

                if (top.equals(pos))
                    break;

                nextNode = pos.getNextSibling();

                if (null == nextNode) {
                    pos = pos.getParentNode();

                    if ((null == pos) || (top.equals(pos))) {
                        if (null != pos)
                            endNode(pos);

                        nextNode = null;

                        break;
                    }
                }
            }

            pos = nextNode;
        }
        this.fSerializer.endDocument();
    }

    /**
     * Perform a pre-order traversal non-recursive style.
     
     * Note that TreeWalker assumes that the subtree is intended to represent 
     * a complete (though not necessarily well-formed) document and, during a 
     * traversal, startDocument and endDocument will always be issued to the 
     * SAX listener.
     *
     * @param pos Node in the tree where to start traversal
     * @param top Node in the tree where to end traversal
     *
     * @throws TransformerException
     */
    public void traverse(Node pos, Node top) throws org.xml.sax.SAXException {

        this.fSerializer.startDocument();

        // Determine if the Node is a DOM Level 3 Core Node.
        if (pos.getNodeType() != Node.DOCUMENT_NODE) {
            Document ownerDoc = pos.getOwnerDocument();
            if (ownerDoc != null
                && ownerDoc.getImplementation().hasFeature("Core", "3.0")) {
                fIsLevel3DOM = true;
            }
        } else {
            if (((Document) pos)
                .getImplementation()
                .hasFeature("Core", "3.0")) {
                fIsLevel3DOM = true;
            }
        }

        if (fSerializer instanceof LexicalHandler) {
            fLexicalHandler = ((LexicalHandler) this.fSerializer);
        }

        if (fFilter != null)
            fWhatToShowFilter = fFilter.getWhatToShow();

        while (null != pos) {
            startNode(pos);

            Node nextNode = null;

            nextNode = pos.getFirstChild();

            while (null == nextNode) {
                endNode(pos);

                if ((null != top) && top.equals(pos))
                    break;

                nextNode = pos.getNextSibling();

                if (null == nextNode) {
                    pos = pos.getParentNode();

                    if ((null == pos) || ((null != top) && top.equals(pos))) {
                        nextNode = null;

                        break;
                    }
                }
            }

            pos = nextNode;
        }
        this.fSerializer.endDocument();
    }

    /**
     * Optimized dispatch of characters.
     */
    private final void dispatachChars(Node node)
        throws org.xml.sax.SAXException {
        if (fSerializer != null) {
            this.fSerializer.characters(node);
        } else {
            String data = ((Text) node).getData();
            this.fSerializer.characters(data.toCharArray(), 0, data.length());
        }
    }

    /**
     * Start processing given node
     *
     * @param node Node to process
     *
     * @throws org.xml.sax.SAXException
     */
    protected void startNode(Node node) throws org.xml.sax.SAXException {
        if (node instanceof Locator) {
            Locator loc = (Locator) node;
            fLocator.setColumnNumber(loc.getColumnNumber());
            fLocator.setLineNumber(loc.getLineNumber());
            fLocator.setPublicId(loc.getPublicId());
            fLocator.setSystemId(loc.getSystemId());
        } else {
            fLocator.setColumnNumber(0);
            fLocator.setLineNumber(0);
        }

        switch (node.getNodeType()) {
            case Node.DOCUMENT_TYPE_NODE :
                serializeDocType((DocumentType) node, true);
                break;
            case Node.COMMENT_NODE :
                serializeComment((Comment) node);
                break;
            case Node.DOCUMENT_FRAGMENT_NODE :
                // Children are traversed
                break;
            case Node.DOCUMENT_NODE :
                break;
            case Node.ELEMENT_NODE :
                serializeElement((Element) node, true);
                break;
            case Node.PROCESSING_INSTRUCTION_NODE :
                serializePI((ProcessingInstruction) node);
                break;
            case Node.CDATA_SECTION_NODE :
                serializeCDATASection((CDATASection) node);
                break;
            case Node.TEXT_NODE :
                serializeText((Text) node);
                break;
            case Node.ENTITY_REFERENCE_NODE :
                serializeEntityReference((EntityReference) node, true);
                break;
            default :
                }
    }

    /**
     * End processing of given node 
     *
     *
     * @param node Node we just finished processing
     *
     * @throws org.xml.sax.SAXException
     */
    protected void endNode(Node node) throws org.xml.sax.SAXException {

        switch (node.getNodeType()) {
            case Node.DOCUMENT_NODE :
                break;
            case Node.DOCUMENT_TYPE_NODE :
                serializeDocType((DocumentType) node, false);
                break;
            case Node.ELEMENT_NODE :
                serializeElement((Element) node, false);
                break;
            case Node.CDATA_SECTION_NODE :
                break;
            case Node.ENTITY_REFERENCE_NODE :
                serializeEntityReference((EntityReference) node, false);
                break;
            default :
                }
    }

    // ***********************************************************************
    // Node serialization methods
    // ***********************************************************************
    /**
     * Applies a filter on the node to serialize
     * 
     * @param node The Node to serialize
     * @return True if the node is to be serialized else false if the node 
     *         is to be rejected or skipped. 
     */
    protected boolean applyFilter(Node node, int nodeType) {
        if (fFilter != null && (fWhatToShowFilter & nodeType) != 0) {

            short code = fFilter.acceptNode(node);
            switch (code) {
                case NodeFilter.FILTER_REJECT :
                case NodeFilter.FILTER_SKIP :
                    return false; // skip the node
                default : // fall through..
            }
        }
        return true;
    }

    /**
     * Serializes a Document Type Node.
     * 
     * @param node The Docuemnt Type Node to serialize
     * @param bStart Invoked at the start or end of node.  Default true. 
     */
    protected void serializeDocType(DocumentType node, boolean bStart)
        throws SAXException {
        // The DocType and internalSubset can not be modified in DOM and is
        // considered to be well-formed as the outcome of successful parsing.
        String docTypeName = node.getNodeName();
        String publicId = node.getPublicId();
        String systemId = node.getSystemId();
        String internalSubset = node.getInternalSubset();

        //DocumentType nodes are never passed to the filter
        
        if (internalSubset != null && !"".equals(internalSubset)) {

            if (bStart) {
                try {
                    // The Serializer does not provide a way to write out the
                    // DOCTYPE internal subset via an event call, so we write it
                    // out here.
                    Writer writer = fSerializer.getWriter();
                    StringBuffer dtd = new StringBuffer();

                    dtd.append("<!DOCTYPE ");
                    dtd.append(docTypeName);
                    if (null != publicId) {
                        dtd.append(" PUBLIC \"");
                        dtd.append(publicId);
                        dtd.append('\"');
                    }

                    if (null != systemId) {
                        if (null == publicId) {
                            dtd.append(" SYSTEM \"");
                        } else {
                            dtd.append(" \"");
                        }    
                        dtd.append(systemId);
                        dtd.append('\"');
                    }
                    
                    dtd.append(" [ ");
                    
                    dtd.append(fNewLine);
                    dtd.append(internalSubset);
                    dtd.append("]>");
                    dtd.append(new String(fNewLine));
                    
                    writer.write(dtd.toString());
                    writer.flush();
                    
                } catch (IOException e) {
                    throw new SAXException(Utils.messages.createMessage(
                            MsgKey.ER_WRITING_INTERNAL_SUBSET, null), e);
                }
            } // else if !bStart do nothing
            
        } else {
            
            if (bStart) {
                if (fLexicalHandler != null) {
                    fLexicalHandler.startDTD(docTypeName, publicId, systemId);
                }
            } else {
                if (fLexicalHandler != null) {
                    fLexicalHandler.endDTD();
                }
            }
        }
    }

    /**
     * Serializes a Comment Node.
     * 
     * @param node The Comment Node to serialize
     */
    protected void serializeComment(Comment node) throws SAXException {
        // comments=true
        if ((fFeatures & COMMENTS) != 0) {
            String data = node.getData();

            // well-formed=true
            if ((fFeatures & WELLFORMED) != 0) {
                isCommentWellFormed(data);
            }

            if (fLexicalHandler != null) {
                // apply the LSSerializer filter after the operations requested by the 
                // DOMConfiguration parameters have been applied 
                if (!applyFilter(node, NodeFilter.SHOW_COMMENT)) {
                    return;
                }

                fLexicalHandler.comment(data.toCharArray(), 0, data.length());
            }
        }
    }

    /**
     * Serializes an Element Node.
     * 
     * @param node The Element Node to serialize
     * @param bStart Invoked at the start or end of node.   
     */
    protected void serializeElement(Element node, boolean bStart)
        throws SAXException {
        if (bStart) {
            fElementDepth++;

            // We use the Xalan specific startElement and starPrefixMapping calls 
            // (and addAttribute and namespaceAfterStartElement) as opposed to
            // SAX specific, for performance reasons as they reduce the overhead
            // of creating an AttList object upfront.

            // well-formed=true
            if ((fFeatures & WELLFORMED) != 0) {
                isElementWellFormed(node);
            }

            // REVISIT: We apply the LSSerializer filter for elements before
            // namesapce fixup
            if (!applyFilter(node, NodeFilter.SHOW_ELEMENT)) {
                return;
            }

            // namespaces=true, record and fixup namspaced element
            if ((fFeatures & NAMESPACES) != 0) {
            	fNSBinder.pushContext();
            	fLocalNSBinder.reset();
            	
                recordLocalNSDecl(node);
                fixupElementNS(node);
            }

            // Namespace normalization
            fSerializer.startElement(
            		node.getNamespaceURI(),
                    node.getLocalName(),
                    node.getNodeName());

            serializeAttList(node);
            
        } else {
        	fElementDepth--;

            // apply the LSSerializer filter
            if (!applyFilter(node, NodeFilter.SHOW_ELEMENT)) {
                return;
            }

            this.fSerializer.endElement(
            	node.getNamespaceURI(),
                node.getLocalName(),
                node.getNodeName());
            // since endPrefixMapping was not used by SerializationHandler it was removed
            // for performance reasons.

            if ((fFeatures & NAMESPACES) != 0 ) {
                    fNSBinder.popContext();
            }
            
        }
    }

    /**
     * Serializes the Attr Nodes of an Element.
     * 
     * @param node The OwnerElement whose Attr Nodes are to be serialized.
     */
    protected void serializeAttList(Element node) throws SAXException {
        NamedNodeMap atts = node.getAttributes();
        int nAttrs = atts.getLength();

        for (int i = 0; i < nAttrs; i++) {
            Node attr = atts.item(i);

            String localName = attr.getLocalName();
            String attrName = attr.getNodeName();
            String attrPrefix = attr.getPrefix() == null ? "" : attr.getPrefix();
            String attrValue = attr.getNodeValue();

            // Determine the Attr's type.
            String type = null;
            if (fIsLevel3DOM) {
                type = ((Attr) attr).getSchemaTypeInfo().getTypeName();
            }
            type = type == null ? "CDATA" : type;

            String attrNS = attr.getNamespaceURI();
            if (attrNS !=null && attrNS.length() == 0) {
            	attrNS=null;
                // we must remove prefix for this attribute
            	attrName=attr.getLocalName();
            }

            boolean isSpecified = ((Attr) attr).getSpecified();
            boolean addAttr = true;
            boolean applyFilter = false;
            boolean xmlnsAttr =
                attrName.equals("xmlns") || attrName.startsWith("xmlns:");

            // well-formed=true
            if ((fFeatures & WELLFORMED) != 0) {
                isAttributeWellFormed(attr);
            }
            
            //-----------------------------------------------------------------
            // start Attribute namespace fixup
            //-----------------------------------------------------------------
            // namespaces=true, normalize all non-namespace attributes
            // Step 3. Attribute
            if ((fFeatures & NAMESPACES) != 0 && !xmlnsAttr) {
           	
        		// If the Attr has a namespace URI
        		if (attrNS != null) {
        			attrPrefix = attrPrefix == null ? "" : attrPrefix;

        			String declAttrPrefix = fNSBinder.getPrefix(attrNS);
        			String declAttrNS = fNSBinder.getURI(attrPrefix);
        			
        			// attribute has no prefix (default namespace decl does not apply to
        			// attributes)
        			// OR
        			// attribute prefix is not declared
        			// OR
        			// conflict: attribute has a prefix that conflicts with a binding
        			if ("".equals(attrPrefix) || "".equals(declAttrPrefix)
        					|| !attrPrefix.equals(declAttrPrefix)) {

        				// namespaceURI matches an in scope declaration of one or
        				// more prefixes
        				if (declAttrPrefix != null && !"".equals(declAttrPrefix)) {
        					// pick the prefix that was found and change attribute's
        					// prefix and nodeName.
        					attrPrefix = declAttrPrefix;
        					
        					if (declAttrPrefix.length() > 0 ) { 
        						attrName = declAttrPrefix + ":" + localName;
        					} else {
        						attrName = localName;
        					}	
        				} else {
        					// The current prefix is not null and it has no in scope
        					// declaration
        					if (attrPrefix != null && !"".equals(attrPrefix)
        							&& declAttrNS == null) {
        						// declare this prefix
        						if ((fFeatures & NAMESPACEDECLS) != 0) {
        							fSerializer.addAttribute(XMLNS_URI, attrPrefix,
        									XMLNS_PREFIX + ":" + attrPrefix, "CDATA",
        									attrNS);
        							fNSBinder.declarePrefix(attrPrefix, attrNS);
        							fLocalNSBinder.declarePrefix(attrPrefix, attrNS);
        						}
        					} else {
        						// find a prefix following the pattern "NS" +index
        						// (starting at 1)
        						// make sure this prefix is not declared in the current
        						// scope.
        						int counter = 1;
        						attrPrefix = "NS" + counter++;

        						while (fLocalNSBinder.getURI(attrPrefix) != null) {
        							attrPrefix = "NS" + counter++;
        						}
        						// change attribute's prefix and Name
        						attrName = attrPrefix + ":" + localName;
        						
        						// create a local namespace declaration attribute
        						// Add the xmlns declaration attribute
        						if ((fFeatures & NAMESPACEDECLS) != 0) {
                                       							
        							fSerializer.addAttribute(XMLNS_URI, attrPrefix,
        									XMLNS_PREFIX + ":" + attrPrefix, "CDATA",
        									attrNS);
            						fNSBinder.declarePrefix(attrPrefix, attrNS);
            						fLocalNSBinder.declarePrefix(attrPrefix, attrNS);
        						}
        					}
        				}
        			}

        		} else { // if the Attr has no namespace URI
        			// Attr has no localName
        			if (localName == null) {
        				// DOM Level 1 node!
        				String msg = Utils.messages.createMessage(
        						MsgKey.ER_NULL_LOCAL_ELEMENT_NAME,
        						new Object[] { attrName });

        				if (fErrorHandler != null) {
        					fErrorHandler
        							.handleError(new DOMErrorImpl(
        									DOMError.SEVERITY_ERROR, msg,
        									MsgKey.ER_NULL_LOCAL_ELEMENT_NAME, null,
        									null, null));
        				}

        			} else { // uri=null and no colon
        				// attr has no namespace URI and no prefix
        				// no action is required, since attrs don't use default
        			}
        		}

            }

            
            // discard-default-content=true
            // Default attr's are not passed to the filter and this contraint
            // is applied only when discard-default-content=true 
            // What about default xmlns attributes???? check for xmlnsAttr
            if ((((fFeatures & DISCARDDEFAULT) != 0) && isSpecified)
                || ((fFeatures & DISCARDDEFAULT) == 0)) {
                applyFilter = true;
            } else {
            	addAttr = false;
            }

            if (applyFilter) {
                // apply the filter for Attributes that are not default attributes
                // or namespace decl attributes
                if (fFilter != null
                    && (fFilter.getWhatToShow() & NodeFilter.SHOW_ATTRIBUTE)
                        != 0) {

                    if (!xmlnsAttr) {
                        short code = fFilter.acceptNode(attr);
                        switch (code) {
                            case NodeFilter.FILTER_REJECT :
                            case NodeFilter.FILTER_SKIP :
                                addAttr = false;
                                break;
                            default : //fall through..
                        }
                    }
                }
            }

            // if the node is a namespace node
            if (addAttr && xmlnsAttr) {
                // If namespace-declarations=true, add the node , else don't add it
                if ((fFeatures & NAMESPACEDECLS) != 0) {
               		// The namespace may have been fixed up, in that case don't add it.
                	if (localName != null && !"".equals(localName)) {
                		fSerializer.addAttribute(attrNS, localName, attrName, type, attrValue);
                	} 
                }
            } else if (
                addAttr && !xmlnsAttr) { // if the node is not a namespace node
                // If namespace-declarations=true, add the node with the Attr nodes namespaceURI
                // else add the node setting it's namespace to null or else the serializer will later
                // attempt to add a xmlns attr for the prefixed attribute
                if (((fFeatures & NAMESPACEDECLS) != 0) && (attrNS != null)) {
                    fSerializer.addAttribute(
                        attrNS,
                        localName,
                        attrName,
                        type,
                        attrValue);
                } else {
                    fSerializer.addAttribute(
                        "",
                        localName,
                        attrName,
                        type,
                        attrValue);
                }
            }

            // 
            if (xmlnsAttr && ((fFeatures & NAMESPACEDECLS) != 0)) {
                int index;
                // Use "" instead of null, as Xerces likes "" for the 
                // name of the default namespace.  Fix attributed 
                // to "Steven Murray" <smurray@ebt.com>.
                String prefix =
                    (index = attrName.indexOf(":")) < 0
                        ? ""
                        : attrName.substring(index + 1);

                if (!"".equals(prefix)) {
                    fSerializer.namespaceAfterStartElement(prefix, attrValue);
                }
            }
        }
        
    }
   
    /**
     * Serializes an ProcessingInstruction Node.
     * 
     * @param node The ProcessingInstruction Node to serialize
     */
    protected void serializePI(ProcessingInstruction node)
        throws SAXException {
        ProcessingInstruction pi = node;
        String name = pi.getNodeName();

        // well-formed=true
        if ((fFeatures & WELLFORMED) != 0) {
            isPIWellFormed(node);
        }

        // apply the LSSerializer filter
        if (!applyFilter(node, NodeFilter.SHOW_PROCESSING_INSTRUCTION)) {
            return;
        }

        // String data = pi.getData();
        if (name.equals("xslt-next-is-raw")) {
            fNextIsRaw = true;
        } else {
            this.fSerializer.processingInstruction(name, pi.getData());
        }
    }

    /**
     * Serializes an CDATASection Node.
     * 
     * @param node The CDATASection Node to serialize
     */
    protected void serializeCDATASection(CDATASection node)
        throws SAXException {
        // well-formed=true
        if ((fFeatures & WELLFORMED) != 0) {
            isCDATASectionWellFormed(node);
        }

        // cdata-sections = true
        if ((fFeatures & CDATA) != 0) {

            // split-cdata-sections = true
            // Assumption: This parameter has an effect only when
			// cdata-sections=true
            // ToStream, by default splits cdata-sections. Hence the check
			// below.
            String nodeValue = node.getNodeValue();
            int endIndex = nodeValue.indexOf("]]>");
            if ((fFeatures & SPLITCDATA) != 0) {
                if (endIndex >= 0) {
                    // The first node split will contain the ]] markers
                    String relatedData = nodeValue.substring(0, endIndex + 2);

                    String msg =
                        Utils.messages.createMessage(
                            MsgKey.ER_CDATA_SECTIONS_SPLIT,
                            null);

                    if (fErrorHandler != null) {
                        fErrorHandler.handleError(
                            new DOMErrorImpl(
                                DOMError.SEVERITY_WARNING,
                                msg,
                                MsgKey.ER_CDATA_SECTIONS_SPLIT,
                                null,
                                relatedData,
                                null));
                    }
                }
            } else {
                if (endIndex >= 0) {
                    // The first node split will contain the ]] markers 
                    String relatedData = nodeValue.substring(0, endIndex + 2);

                    String msg =
                        Utils.messages.createMessage(
                            MsgKey.ER_CDATA_SECTIONS_SPLIT,
                            null);

                    if (fErrorHandler != null) {
                        fErrorHandler.handleError(
                            new DOMErrorImpl(
                                DOMError.SEVERITY_ERROR,
                                msg,
                                MsgKey.ER_CDATA_SECTIONS_SPLIT));
                    }
                    // Report an error and return.  What error???
                    return;
                }
            }

            // apply the LSSerializer filter
            if (!applyFilter(node, NodeFilter.SHOW_CDATA_SECTION)) {
                return;
            }

            // splits the cdata-section
            if (fLexicalHandler != null) {
                fLexicalHandler.startCDATA();
            }
            dispatachChars(node);
            if (fLexicalHandler != null) {
                fLexicalHandler.endCDATA();
            }
        } else {
            dispatachChars(node);
        }
    }

    /**
     * Serializes an Text Node.
     * 
     * @param node The Text Node to serialize
     */
    protected void serializeText(Text node) throws SAXException {
        if (fNextIsRaw) {
            fNextIsRaw = false;
            fSerializer.processingInstruction(
                javax.xml.transform.Result.PI_DISABLE_OUTPUT_ESCAPING,
                "");
            dispatachChars(node);
            fSerializer.processingInstruction(
                javax.xml.transform.Result.PI_ENABLE_OUTPUT_ESCAPING,
                "");
        } else {
            // keep track of dispatch or not to avoid duplicaiton of filter code
            boolean bDispatch = false;

            // well-formed=true
            if ((fFeatures & WELLFORMED) != 0) {
                isTextWellFormed(node);
            }

            // if the node is whitespace
            // Determine the Attr's type.
            boolean isElementContentWhitespace = false;
            if (fIsLevel3DOM) {
                isElementContentWhitespace =
                       node.isElementContentWhitespace();
            }

            if (isElementContentWhitespace) {
                // element-content-whitespace=true
                if ((fFeatures & ELEM_CONTENT_WHITESPACE) != 0) {
                    bDispatch = true;
                }
            } else {
                bDispatch = true;
            }

            // apply the LSSerializer filter
            if (!applyFilter(node, NodeFilter.SHOW_TEXT)) {
                return;
            }

            if (bDispatch) {
                dispatachChars(node);
            }
        }
    }

    /**
     * Serializes an EntityReference Node.
     * 
     * @param node The EntityReference Node to serialize
     * @param bStart Inicates if called from start or endNode 
     */
    protected void serializeEntityReference(
        EntityReference node,
        boolean bStart)
        throws SAXException {
        if (bStart) {
            EntityReference eref = node;
            // entities=true
            if ((fFeatures & ENTITIES) != 0) {
                
                // perform well-formedness and other checking only if 
                // entities = true

                // well-formed=true
                if ((fFeatures & WELLFORMED) != 0) {
                    isEntityReferneceWellFormed(node);
                }

                // check "unbound-prefix-in-entity-reference" [fatal] 
                // Raised if the configuration parameter "namespaces" is set to true
                if ((fFeatures & NAMESPACES) != 0) {
                    checkUnboundPrefixInEntRef(node);
                }

                // The filter should not apply in this case, since the
                // EntityReference is not being expanded.
                // should we pass entity reference nodes to the filter???
            } 
            
            if (fLexicalHandler != null) {

                // startEntity outputs only Text but not Element, Attr, Comment 
                // and PI child nodes.  It does so by setting the m_inEntityRef 
                // in ToStream and using this to decide if a node is to be 
                // serialized or not.
                fLexicalHandler.startEntity(eref.getNodeName());
            } 

        } else {
            EntityReference eref = node;
            // entities=true or false, 
            if (fLexicalHandler != null) {
                fLexicalHandler.endEntity(eref.getNodeName());
            }
        }
    }

    
    // ***********************************************************************
    // Methods to check well-formedness
    // ***********************************************************************
    /**
     * Taken from org.apache.xerces.dom.CoreDocumentImpl
     * 
     * Check the string against XML's definition of acceptable names for
     * elements and attributes and so on using the XMLCharacterProperties
     * utility class
     */
    protected boolean isXMLName(String s, boolean xml11Version) {

        if (s == null) {
            return false;
        }
        if (!xml11Version)
            return XMLChar.isValidName(s);
        else
            return XML11Char.isXML11ValidName(s);
    }

    /**
     * Taken from org.apache.xerces.dom.CoreDocumentImpl
     *  
     * Checks if the given qualified name is legal with respect
     * to the version of XML to which this document must conform.
     *
     * @param prefix prefix of qualified name
     * @param local local part of qualified name
     */
    protected boolean isValidQName(
        String prefix,
        String local,
        boolean xml11Version) {

        // check that both prefix and local part match NCName
        if (local == null)
            return false;
        boolean validNCName = false;

        if (!xml11Version) {
            validNCName =
                (prefix == null || XMLChar.isValidNCName(prefix))
                    && XMLChar.isValidNCName(local);
        } else {
            validNCName =
                (prefix == null || XML11Char.isXML11ValidNCName(prefix))
                    && XML11Char.isXML11ValidNCName(local);
        }

        return validNCName;
    }

    /**
     * Checks if a XML character is well-formed
     * 
     * @param characters A String of characters to be checked for Well-Formedness
     * @param refInvalidChar A reference to the character to be returned that was determined invalid. 
     */
    protected boolean isWFXMLChar(String chardata, Character refInvalidChar) {
        if (chardata == null || (chardata.length() == 0)) {
            return true;
        }

        char[] dataarray = chardata.toCharArray();
        int datalength = dataarray.length;

        // version of the document is XML 1.1
        if (fIsXMLVersion11) {
            //we need to check all characters as per production rules of XML11
            int i = 0;
            while (i < datalength) {
                if (XML11Char.isXML11Invalid(dataarray[i++])) {
                    // check if this is a supplemental character
                    char ch = dataarray[i - 1];
                    if (XMLChar.isHighSurrogate(ch) && i < datalength) {
                        char ch2 = dataarray[i++];
                        if (XMLChar.isLowSurrogate(ch2)
                            && XMLChar.isSupplemental(
                                XMLChar.supplemental(ch, ch2))) {
                            continue;
                        }
                    }
                    // Reference to invalid character which is returned
                    refInvalidChar = new Character(ch);
                    return false;
                }
            }
        } // version of the document is XML 1.0
        else {
            // we need to check all characters as per production rules of XML 1.0
            int i = 0;
            while (i < datalength) {
                if (XMLChar.isInvalid(dataarray[i++])) {
                    // check if this is a supplemental character
                    char ch = dataarray[i - 1];
                    if (XMLChar.isHighSurrogate(ch) && i < datalength) {
                        char ch2 = dataarray[i++];
                        if (XMLChar.isLowSurrogate(ch2)
                            && XMLChar.isSupplemental(
                                XMLChar.supplemental(ch, ch2))) {
                            continue;
                        }
                    }
                    // Reference to invalid character which is returned                    
                    refInvalidChar = new Character(ch);
                    return false;
                }
            }
        } // end-else fDocument.isXMLVersion()

        return true;
    } // isXMLCharWF

    /**
     * Checks if a XML character is well-formed.  If there is a problem with
     * the character a non-null Character is returned else null is returned.
     * 
     * @param characters A String of characters to be checked for Well-Formedness
     * @return Character A reference to the character to be returned that was determined invalid. 
     */
    protected Character isWFXMLChar(String chardata) {
    	Character refInvalidChar;
        if (chardata == null || (chardata.length() == 0)) {
            return null;
        }

        char[] dataarray = chardata.toCharArray();
        int datalength = dataarray.length;

        // version of the document is XML 1.1
        if (fIsXMLVersion11) {
            //we need to check all characters as per production rules of XML11
            int i = 0;
            while (i < datalength) {
                if (XML11Char.isXML11Invalid(dataarray[i++])) {
                    // check if this is a supplemental character
                    char ch = dataarray[i - 1];
                    if (XMLChar.isHighSurrogate(ch) && i < datalength) {
                        char ch2 = dataarray[i++];
                        if (XMLChar.isLowSurrogate(ch2)
                            && XMLChar.isSupplemental(
                                XMLChar.supplemental(ch, ch2))) {
                            continue;
                        }
                    }
                    // Reference to invalid character which is returned
                    refInvalidChar = new Character(ch);
                    return refInvalidChar;
                }
            }
        } // version of the document is XML 1.0
        else {
            // we need to check all characters as per production rules of XML 1.0
            int i = 0;
            while (i < datalength) {
                if (XMLChar.isInvalid(dataarray[i++])) {
                    // check if this is a supplemental character
                    char ch = dataarray[i - 1];
                    if (XMLChar.isHighSurrogate(ch) && i < datalength) {
                        char ch2 = dataarray[i++];
                        if (XMLChar.isLowSurrogate(ch2)
                            && XMLChar.isSupplemental(
                                XMLChar.supplemental(ch, ch2))) {
                            continue;
                        }
                    }
                    // Reference to invalid character which is returned                    
                    refInvalidChar = new Character(ch);
                    return refInvalidChar;
                }
            }
        } // end-else fDocument.isXMLVersion()

        return null;
    } // isXMLCharWF

    /**
     * Checks if a comment node is well-formed
     * 
     * @param data The contents of the comment node
     * @return a boolean indiacating if the comment is well-formed or not.
     */
    protected void isCommentWellFormed(String data) {
        if (data == null || (data.length() == 0)) {
            return;
        }

        char[] dataarray = data.toCharArray();
        int datalength = dataarray.length;

        // version of the document is XML 1.1
        if (fIsXMLVersion11) {
            // we need to check all chracters as per production rules of XML11
            int i = 0;
            while (i < datalength) {
                char c = dataarray[i++];
                if (XML11Char.isXML11Invalid(c)) {
                    // check if this is a supplemental character
                    if (XMLChar.isHighSurrogate(c) && i < datalength) {
                        char c2 = dataarray[i++];
                        if (XMLChar.isLowSurrogate(c2)
                            && XMLChar.isSupplemental(
                                XMLChar.supplemental(c, c2))) {
                            continue;
                        }
                    }
                    String msg =
                        Utils.messages.createMessage(
                            MsgKey.ER_WF_INVALID_CHARACTER_IN_COMMENT,
                            new Object[] { new Character(c)});

                    if (fErrorHandler != null) {
                        fErrorHandler.handleError(
                            new DOMErrorImpl(
                                DOMError.SEVERITY_FATAL_ERROR,
                                msg,
                                MsgKey.ER_WF_INVALID_CHARACTER,
                                null,
                                null,
                                null));
                    }
                } else if (c == '-' && i < datalength && dataarray[i] == '-') {
                    String msg =
                        Utils.messages.createMessage(
                            MsgKey.ER_WF_DASH_IN_COMMENT,
                            null);

                    if (fErrorHandler != null) {
                        fErrorHandler.handleError(
                            new DOMErrorImpl(
                                DOMError.SEVERITY_FATAL_ERROR,
                                msg,
                                MsgKey.ER_WF_INVALID_CHARACTER,
                                null,
                                null,
                                null));
                    }
                }
            }
        } // version of the document is XML 1.0
        else {
            // we need to check all chracters as per production rules of XML 1.0
            int i = 0;
            while (i < datalength) {
                char c = dataarray[i++];
                if (XMLChar.isInvalid(c)) {
                    // check if this is a supplemental character
                    if (XMLChar.isHighSurrogate(c) && i < datalength) {
                        char c2 = dataarray[i++];
                        if (XMLChar.isLowSurrogate(c2)
                            && XMLChar.isSupplemental(
                                XMLChar.supplemental(c, c2))) {
                            continue;
                        }
                    }
                    String msg =
                        Utils.messages.createMessage(
                            MsgKey.ER_WF_INVALID_CHARACTER_IN_COMMENT,
                            new Object[] { new Character(c)});

                    if (fErrorHandler != null) {
                        fErrorHandler.handleError(
                            new DOMErrorImpl(
                                DOMError.SEVERITY_FATAL_ERROR,
                                msg,
                                MsgKey.ER_WF_INVALID_CHARACTER,
                                null,
                                null,
                                null));
                    }
                } else if (c == '-' && i < datalength && dataarray[i] == '-') {
                    String msg =
                        Utils.messages.createMessage(
                            MsgKey.ER_WF_DASH_IN_COMMENT,
                            null);

                    if (fErrorHandler != null) {
                        fErrorHandler.handleError(
                            new DOMErrorImpl(
                                DOMError.SEVERITY_FATAL_ERROR,
                                msg,
                                MsgKey.ER_WF_INVALID_CHARACTER,
                                null,
                                null,
                                null));
                    }
                }
            }
        }
        return;
    }

    /**
     * Checks if an element node is well-formed, by checking its Name for well-formedness.
     * 
     * @param data The contents of the comment node
     * @return a boolean indiacating if the comment is well-formed or not.
     */
    protected void isElementWellFormed(Node node) {
        boolean isNameWF = false;
        if ((fFeatures & NAMESPACES) != 0) {
            isNameWF =
                isValidQName(
                    node.getPrefix(),
                    node.getLocalName(),
                    fIsXMLVersion11);
        } else {
            isNameWF = isXMLName(node.getNodeName(), fIsXMLVersion11);
        }

        if (!isNameWF) {
            String msg =
                Utils.messages.createMessage(
                    MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME,
                    new Object[] { "Element", node.getNodeName()});

            if (fErrorHandler != null) {
                fErrorHandler.handleError(
                    new DOMErrorImpl(
                        DOMError.SEVERITY_FATAL_ERROR,
                        msg,
                        MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME,
                        null,
                        null,
                        null));
            }
        }
    }

    /**
     * Checks if an attr node is well-formed, by checking it's Name and value
     * for well-formedness.
     * 
     * @param data The contents of the comment node
     * @return a boolean indiacating if the comment is well-formed or not.
     */
    protected void isAttributeWellFormed(Node node) {
        boolean isNameWF = false;
        if ((fFeatures & NAMESPACES) != 0) {
            isNameWF =
                isValidQName(
                    node.getPrefix(),
                    node.getLocalName(),
                    fIsXMLVersion11);
        } else {
            isNameWF = isXMLName(node.getNodeName(), fIsXMLVersion11);
        }

        if (!isNameWF) {
            String msg =
                Utils.messages.createMessage(
                    MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME,
                    new Object[] { "Attr", node.getNodeName()});

            if (fErrorHandler != null) {
                fErrorHandler.handleError(
                    new DOMErrorImpl(
                        DOMError.SEVERITY_FATAL_ERROR,
                        msg,
                        MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME,
                        null,
                        null,
                        null));
            }
        }

        // Check the Attr's node value
        // WFC: No < in Attribute Values
        String value = node.getNodeValue();
        if (value.indexOf('<') >= 0) {
            String msg =
                Utils.messages.createMessage(
                    MsgKey.ER_WF_LT_IN_ATTVAL,
                    new Object[] {
                        ((Attr) node).getOwnerElement().getNodeName(),
                        node.getNodeName()});

            if (fErrorHandler != null) {
                fErrorHandler.handleError(
                    new DOMErrorImpl(
                        DOMError.SEVERITY_FATAL_ERROR,
                        msg,
                        MsgKey.ER_WF_LT_IN_ATTVAL,
                        null,
                        null,
                        null));
            }
        }

        // we need to loop through the children of attr nodes and check their values for
        // well-formedness  
        NodeList children = node.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            Node child = children.item(i);
            // An attribute node with no text or entity ref child for example
            // doc.createAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:ns");
            // followes by
            // element.setAttributeNodeNS(attribute);
            // can potentially lead to this situation.  If the attribute
            // was a prefix Namespace attribute declaration then then DOM Core 
            // should have some exception defined for this.
            if (child == null) {
                // we should probably report an error
                continue;
            }
            switch (child.getNodeType()) {
                case Node.TEXT_NODE :
                    isTextWellFormed((Text) child);
                    break;
                case Node.ENTITY_REFERENCE_NODE :
                    isEntityReferneceWellFormed((EntityReference) child);
                    break;
                default :
            }
        }

        // TODO:
        // WFC: Check if the attribute prefix is bound to 
        // http://www.w3.org/2000/xmlns/  

        // WFC: Unique Att Spec
        // Perhaps pass a seen boolean value to this method.  serializeAttList will determine
        // if the attr was seen before.
    }

    /**
     * Checks if a PI node is well-formed, by checking it's Name and data
     * for well-formedness.
     * 
     * @param data The contents of the comment node
     */
    protected void isPIWellFormed(ProcessingInstruction node) {
        // Is the PI Target a valid XML name
        if (!isXMLName(node.getNodeName(), fIsXMLVersion11)) {
            String msg =
                Utils.messages.createMessage(
                    MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME,
                    new Object[] { "ProcessingInstruction", node.getTarget()});

            if (fErrorHandler != null) {
                fErrorHandler.handleError(
                    new DOMErrorImpl(
                        DOMError.SEVERITY_FATAL_ERROR,
                        msg,
                        MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME,
                        null,
                        null,
                        null));
            }
        }

        // Does the PI Data carry valid XML characters

        // REVISIT: Should we check if the PI DATA contains a ?> ???
        Character invalidChar = isWFXMLChar(node.getData());
        if (invalidChar != null) {
            String msg =
                Utils.messages.createMessage(
                    MsgKey.ER_WF_INVALID_CHARACTER_IN_PI,
                    new Object[] { Integer.toHexString(Character.getNumericValue(invalidChar.charValue())) });

            if (fErrorHandler != null) {
                fErrorHandler.handleError(
                    new DOMErrorImpl(
                        DOMError.SEVERITY_FATAL_ERROR,
                        msg,
                        MsgKey.ER_WF_INVALID_CHARACTER,
                        null,
                        null,
                        null));
            }
        }
    }

    /**
     * Checks if an CDATASection node is well-formed, by checking it's data
     * for well-formedness.  Note that the presence of a CDATA termination mark
     * in the contents of a CDATASection is handled by the parameter 
     * spli-cdata-sections
     * 
     * @param data The contents of the comment node
     */
    protected void isCDATASectionWellFormed(CDATASection node) {
        // Does the data valid XML character data        
        Character invalidChar = isWFXMLChar(node.getData());
        //if (!isWFXMLChar(node.getData(), invalidChar)) {
        if (invalidChar != null) {
            String msg =
                Utils.messages.createMessage(
                    MsgKey.ER_WF_INVALID_CHARACTER_IN_CDATA,
                    new Object[] { Integer.toHexString(Character.getNumericValue(invalidChar.charValue())) });

            if (fErrorHandler != null) {
                fErrorHandler.handleError(
                    new DOMErrorImpl(
                        DOMError.SEVERITY_FATAL_ERROR,
                        msg,
                        MsgKey.ER_WF_INVALID_CHARACTER,
                        null,
                        null,
                        null));
            }
        }
    }

    /**
     * Checks if an Text node is well-formed, by checking if it contains invalid
     * XML characters.
     * 
     * @param data The contents of the comment node
     */
    protected void isTextWellFormed(Text node) {
        // Does the data valid XML character data        
    	Character invalidChar = isWFXMLChar(node.getData());
    	if (invalidChar != null) {
            String msg =
                Utils.messages.createMessage(
                    MsgKey.ER_WF_INVALID_CHARACTER_IN_TEXT,
                    new Object[] { Integer.toHexString(Character.getNumericValue(invalidChar.charValue())) });

            if (fErrorHandler != null) {
                fErrorHandler.handleError(
                    new DOMErrorImpl(
                        DOMError.SEVERITY_FATAL_ERROR,
                        msg,
                        MsgKey.ER_WF_INVALID_CHARACTER,
                        null,
                        null,
                        null));
            }
        }
    }

    /**
     * Checks if an EntityRefernece node is well-formed, by checking it's node name.  Then depending
     * on whether it is referenced in Element content or in an Attr Node, checks if the EntityReference
     * references an unparsed entity or a external entity and if so throws raises the 
     * appropriate well-formedness error.  
     * 
     * @param data The contents of the comment node
     * @parent The parent of the EntityReference Node
     */
    protected void isEntityReferneceWellFormed(EntityReference node) {
        // Is the EntityReference name a valid XML name
        if (!isXMLName(node.getNodeName(), fIsXMLVersion11)) {
            String msg =
                Utils.messages.createMessage(
                    MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME,
                    new Object[] { "EntityReference", node.getNodeName()});

            if (fErrorHandler != null) {
                fErrorHandler.handleError(
                    new DOMErrorImpl(
                        DOMError.SEVERITY_FATAL_ERROR,
                        msg,
                        MsgKey.ER_WF_INVALID_CHARACTER_IN_NODE_NAME,
                        null,
                        null,
                        null));
            }
        }

        // determine the parent node
        Node parent = node.getParentNode();

        // Traverse the declared entities and check if the nodeName and namespaceURI
        // of the EntityReference matches an Entity.  If so, check the if the notationName
        // is not null, if so, report an error.
        DocumentType docType = node.getOwnerDocument().getDoctype();
        if (docType != null) {
            NamedNodeMap entities = docType.getEntities();
            for (int i = 0; i < entities.getLength(); i++) {
                Entity ent = (Entity) entities.item(i);

                String nodeName =
                    node.getNodeName() == null ? "" : node.getNodeName();
                String nodeNamespaceURI =
                    node.getNamespaceURI() == null
                        ? ""
                        : node.getNamespaceURI();
                String entName =
                    ent.getNodeName() == null ? "" : ent.getNodeName();
                String entNamespaceURI =
                    ent.getNamespaceURI() == null ? "" : ent.getNamespaceURI();
                // If referenced in Element content
                // WFC: Parsed Entity
                if (parent.getNodeType() == Node.ELEMENT_NODE) {
                    if (entNamespaceURI.equals(nodeNamespaceURI)
                        && entName.equals(nodeName)) {

                        if (ent.getNotationName() != null) {
                            String msg =
                                Utils.messages.createMessage(
                                    MsgKey.ER_WF_REF_TO_UNPARSED_ENT,
                                    new Object[] { node.getNodeName()});

                            if (fErrorHandler != null) {
                                fErrorHandler.handleError(
                                    new DOMErrorImpl(
                                        DOMError.SEVERITY_FATAL_ERROR,
                                        msg,
                                        MsgKey.ER_WF_REF_TO_UNPARSED_ENT,
                                        null,
                                        null,
                                        null));
                            }
                        }
                    }
                } // end if WFC: Parsed Entity

                // If referenced in an Attr value
                // WFC: No External Entity References
                if (parent.getNodeType() == Node.ATTRIBUTE_NODE) {
                    if (entNamespaceURI.equals(nodeNamespaceURI)
                        && entName.equals(nodeName)) {

                        if (ent.getPublicId() != null
                            || ent.getSystemId() != null
                            || ent.getNotationName() != null) {
                            String msg =
                                Utils.messages.createMessage(
                                    MsgKey.ER_WF_REF_TO_EXTERNAL_ENT,
                                    new Object[] { node.getNodeName()});

                            if (fErrorHandler != null) {
                                fErrorHandler.handleError(
                                    new DOMErrorImpl(
                                        DOMError.SEVERITY_FATAL_ERROR,
                                        msg,
                                        MsgKey.ER_WF_REF_TO_EXTERNAL_ENT,
                                        null,
                                        null,
                                        null));
                            }
                        }
                    }
                } //end if WFC: No External Entity References
            }
        }
    } // isEntityReferneceWellFormed    

    /**
     * If the configuration parameter "namespaces" is set to true, this methods
     * checks if an entity whose replacement text contains unbound namespace 
     * prefixes is referenced in a location where there are no bindings for 
     * the namespace prefixes and if so raises a LSException with the error-type
     * "unbound-prefix-in-entity-reference"   
     * 
     * @param Node, The EntityReference nodes whose children are to be checked
     */
    protected void checkUnboundPrefixInEntRef(Node node) {
        Node child, next;
        for (child = node.getFirstChild(); child != null; child = next) {
            next = child.getNextSibling();

            if (child.getNodeType() == Node.ELEMENT_NODE) {

                //If a NamespaceURI is not declared for the current
                //node's prefix, raise a fatal error.
                String prefix = child.getPrefix();
                if (prefix != null
                		&& fNSBinder.getURI(prefix) == null) {
                    String msg =
                        Utils.messages.createMessage(
                            MsgKey.ER_ELEM_UNBOUND_PREFIX_IN_ENTREF,
                            new Object[] {
                                node.getNodeName(),
                                child.getNodeName(),
                                prefix });

                    if (fErrorHandler != null) {
                        fErrorHandler.handleError(
                            new DOMErrorImpl(
                                DOMError.SEVERITY_FATAL_ERROR,
                                msg,
                                MsgKey.ER_ELEM_UNBOUND_PREFIX_IN_ENTREF,
                                null,
                                null,
                                null));
                    }
                }

                NamedNodeMap attrs = child.getAttributes();

                for (int i = 0; i < attrs.getLength(); i++) {
                    String attrPrefix = attrs.item(i).getPrefix();
                    if (attrPrefix != null
                    		&& fNSBinder.getURI(attrPrefix) == null) {
                        String msg =
                            Utils.messages.createMessage(
                                MsgKey.ER_ATTR_UNBOUND_PREFIX_IN_ENTREF,
                                new Object[] {
                                    node.getNodeName(),
                                    child.getNodeName(),
                                    attrs.item(i)});

                        if (fErrorHandler != null) {
                            fErrorHandler.handleError(
                                new DOMErrorImpl(
                                    DOMError.SEVERITY_FATAL_ERROR,
                                    msg,
                                    MsgKey.ER_ATTR_UNBOUND_PREFIX_IN_ENTREF,
                                    null,
                                    null,
                                    null));
                        }
                    }
                }
            }

            if (child.hasChildNodes()) {
                checkUnboundPrefixInEntRef(child);
            }
        }
    }

    // ***********************************************************************
    // Namespace normalization
    // ***********************************************************************
    /**
     * Records local namespace declarations, to be used for normalization later
     * 
     * @param Node, The element node, whose namespace declarations are to be recorded
     */
    protected void recordLocalNSDecl(Node node) {
        NamedNodeMap atts = ((Element) node).getAttributes();
        int length = atts.getLength();

        for (int i = 0; i < length; i++) {
            Node attr = atts.item(i);

            String localName = attr.getLocalName();
            String attrPrefix = attr.getPrefix();
            String attrValue = attr.getNodeValue();
            String attrNS = attr.getNamespaceURI();

            localName =
                localName == null
                    || XMLNS_PREFIX.equals(localName) ? "" : localName;
            attrPrefix = attrPrefix == null ? "" : attrPrefix;
            attrValue = attrValue == null ? "" : attrValue;
            attrNS = attrNS == null ? "" : attrNS;

            // check if attribute is a namespace decl
            if (XMLNS_URI.equals(attrNS)) {

                // No prefix may be bound to http://www.w3.org/2000/xmlns/.
                if (XMLNS_URI.equals(attrValue)) {
                    String msg =
                        Utils.messages.createMessage(
                            MsgKey.ER_NS_PREFIX_CANNOT_BE_BOUND,
                            new Object[] { attrPrefix, XMLNS_URI });

                    if (fErrorHandler != null) {
                        fErrorHandler.handleError(
                            new DOMErrorImpl(
                                DOMError.SEVERITY_ERROR,
                                msg,
                                MsgKey.ER_NS_PREFIX_CANNOT_BE_BOUND,
                                null,
                                null,
                                null));
                    }
                } else {
                    // store the namespace-declaration
                	if (XMLNS_PREFIX.equals(attrPrefix) ) {
                        // record valid decl
                        if (attrValue.length() != 0) {
                            fNSBinder.declarePrefix(localName, attrValue);
                        } else {
                            // Error; xmlns:prefix=""
                        }
                    } else { // xmlns
                        // empty prefix is always bound ("" or some string)
                        fNSBinder.declarePrefix("", attrValue);
                    }
                }
                
            }
        }
    }

    /**
     * Fixes an element's namespace
     * 
     * @param Node, The element node, whose namespace is to be fixed
     */
    protected void fixupElementNS(Node node) throws SAXException {
        String namespaceURI = ((Element) node).getNamespaceURI();
        String prefix = ((Element) node).getPrefix();
        String localName = ((Element) node).getLocalName();

        if (namespaceURI != null) {
            //if ( Element's prefix/namespace pair (or default namespace,
            // if no prefix) are within the scope of a binding )
            prefix = prefix == null ? "" : prefix;
            String inScopeNamespaceURI = fNSBinder.getURI(prefix);

            if ((inScopeNamespaceURI != null
                && inScopeNamespaceURI.equals(namespaceURI))) {
                // do nothing, declaration in scope is inherited
                
            } else {
                // Create a local namespace declaration attr for this namespace,
                // with Element's current prefix (or a default namespace, if
                // no prefix). If there's a conflicting local declaration
                // already present, change its value to use this namespace.
                
                // Add the xmlns declaration attribute
            	//fNSBinder.pushNamespace(prefix, namespaceURI, fElementDepth);
                if ((fFeatures & NAMESPACEDECLS) != 0) {
                    if ("".equals(prefix) || "".equals(namespaceURI)) {
                    	((Element)node).setAttributeNS(XMLNS_URI, XMLNS_PREFIX, namespaceURI);
                    } else {
                    	((Element)node).setAttributeNS(XMLNS_URI, XMLNS_PREFIX + ":" + prefix, namespaceURI);
                    }
                }
                fLocalNSBinder.declarePrefix(prefix, namespaceURI);
                fNSBinder.declarePrefix(prefix, namespaceURI);

            } 
        } else {
            // Element has no namespace
            // DOM Level 1
            if (localName == null || "".equals(localName)) {
                //  DOM Level 1 node!
                String msg =
                    Utils.messages.createMessage(
                        MsgKey.ER_NULL_LOCAL_ELEMENT_NAME,
                        new Object[] { node.getNodeName()});

                if (fErrorHandler != null) {
                    fErrorHandler.handleError(
                        new DOMErrorImpl(
                            DOMError.SEVERITY_ERROR,
                            msg,
                            MsgKey.ER_NULL_LOCAL_ELEMENT_NAME,
                            null,
                            null,
                            null));
                }
            } else {
            	namespaceURI = fNSBinder.getURI("");
            	if (namespaceURI !=null && namespaceURI.length() > 0) {
            	    ((Element)node).setAttributeNS(XMLNS_URI, XMLNS_PREFIX, "");
            		fLocalNSBinder.declarePrefix("", "");
                    fNSBinder.declarePrefix("", "");
            	}
            }
        }
    }
    /** 
     * This table is a quick lookup of a property key (String) to the integer that
     * is the bit to flip in the fFeatures field, so the integers should have
     * values 1,2,4,8,16...
     * 
     */
    private static final Hashtable s_propKeys = new Hashtable();
    static {

        // Initialize the mappings of property keys to bit values (Integer objects)
        // or mappings to a String object "", which indicates we are interested
        // in the property, but it does not have a simple bit value to flip

        // cdata-sections
        int i = CDATA;
        Integer val = new Integer(i);
        s_propKeys.put(
            DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_CDATA_SECTIONS,
            val);

        // comments
        int i1 = COMMENTS;
        val = new Integer(i1);
        s_propKeys.put(
            DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_COMMENTS,
            val);

        // element-content-whitespace
        int i2 = ELEM_CONTENT_WHITESPACE;
        val = new Integer(i2);
        s_propKeys.put(
            DOMConstants.S_DOM3_PROPERTIES_NS
                + DOMConstants.DOM_ELEMENT_CONTENT_WHITESPACE,
            val);
        int i3 = ENTITIES;

        // entities
        val = new Integer(i3);
        s_propKeys.put(
            DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_ENTITIES,
            val);

        // namespaces
        int i4 = NAMESPACES;
        val = new Integer(i4);
        s_propKeys.put(
            DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_NAMESPACES,
            val);

        // namespace-declarations
        int i5 = NAMESPACEDECLS;
        val = new Integer(i5);
        s_propKeys.put(
            DOMConstants.S_DOM3_PROPERTIES_NS
                + DOMConstants.DOM_NAMESPACE_DECLARATIONS,
            val);

        // split-cdata-sections
        int i6 = SPLITCDATA;
        val = new Integer(i6);
        s_propKeys.put(
            DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_SPLIT_CDATA,
            val);

        // discard-default-content	
        int i7 = WELLFORMED;
        val = new Integer(i7);
        s_propKeys.put(
            DOMConstants.S_DOM3_PROPERTIES_NS + DOMConstants.DOM_WELLFORMED,
            val);

        // discard-default-content	
        int i8 = DISCARDDEFAULT;
        val = new Integer(i8);
        s_propKeys.put(
            DOMConstants.S_DOM3_PROPERTIES_NS
                + DOMConstants.DOM_DISCARD_DEFAULT_CONTENT,
            val);

        // We are interested in these properties, but they don't have a simple
        // bit value to deal with.
        s_propKeys.put(
            DOMConstants.S_DOM3_PROPERTIES_NS
                + DOMConstants.DOM_FORMAT_PRETTY_PRINT,
            "");
        s_propKeys.put(DOMConstants.S_XSL_OUTPUT_OMIT_XML_DECL, "");
        s_propKeys.put(
            DOMConstants.S_XERCES_PROPERTIES_NS + DOMConstants.S_XML_VERSION,
            "");
        s_propKeys.put(DOMConstants.S_XSL_OUTPUT_ENCODING, "");
        s_propKeys.put(DOMConstants.S_XERCES_PROPERTIES_NS + DOMConstants.DOM_ENTITIES, "");
    }

    /**
     * Initializes fFeatures based on the DOMConfiguration Parameters set.
     *
     * @param properties DOMConfiguraiton properties that were set and which are
     * to be used while serializing the DOM. 
     */
    protected void initProperties(Properties properties) {

        for (Enumeration keys = properties.keys(); keys.hasMoreElements();) {

            final String key = (String) keys.nextElement();
    
            // caonical-form
            // Other features will be enabled or disabled when this is set to true or false.

            // error-handler; set via the constructor

            // infoset
            // Other features will be enabled or disabled when this is set to true

            // A quick lookup for the given set of properties (cdata-sections ...)
            final Object iobj = s_propKeys.get(key);
            if (iobj != null) {
                if (iobj instanceof Integer) {
                    // Dealing with a property that has a simple bit value that
                    // we need to set

                    // cdata-sections			
                    // comments
                    // element-content-whitespace
                    // entities
                    // namespaces
                    // namespace-declarations
                    // split-cdata-sections
                    // well-formed
                    // discard-default-content
                    final int BITFLAG = ((Integer) iobj).intValue();
                    if ((properties.getProperty(key).endsWith("yes"))) {
                        fFeatures = fFeatures | BITFLAG;
                    } else {
                        fFeatures = fFeatures & ~BITFLAG;
                    }
                } else {
                    // We are interested in the property, but it is not
                    // a simple bit that we need to set.

                    if ((DOMConstants.S_DOM3_PROPERTIES_NS
                        + DOMConstants.DOM_FORMAT_PRETTY_PRINT)
                        .equals(key)) {
                        // format-pretty-print; set internally on the serializers via xsl:output properties in LSSerializer
                        if ((properties.getProperty(key).endsWith("yes"))) {
                            fSerializer.setIndent(true);
                            fSerializer.setIndentAmount(3);
                        } else {
                            fSerializer.setIndent(false);
                        }
                    } else if (
                        (DOMConstants.S_XSL_OUTPUT_OMIT_XML_DECL).equals(
                            key)) {
                        // omit-xml-declaration; set internally on the serializers via xsl:output properties in LSSerializer
                        if ((properties.getProperty(key).endsWith("yes"))) {
                            fSerializer.setOmitXMLDeclaration(true);
                        } else {
                            fSerializer.setOmitXMLDeclaration(false);
                        }
                    } else if (
                        (
                            DOMConstants.S_XERCES_PROPERTIES_NS
                                + DOMConstants.S_XML_VERSION).equals(
                            key)) {
                        // Retreive the value of the XML Version attribute via the xml-version
                        String version = properties.getProperty(key);
                        if ("1.1".equals(version)) {
                            fIsXMLVersion11 = true;
                            fSerializer.setVersion(version);
                        } else {
                            fSerializer.setVersion("1.0");
                        }
                    } else if (
                        (DOMConstants.S_XSL_OUTPUT_ENCODING).equals(key)) {
                        // Retreive the value of the XML Encoding attribute
                        String encoding = properties.getProperty(key);
                        if (encoding != null) {
                            fSerializer.setEncoding(encoding);
                        }
                    } else if ((DOMConstants.S_XERCES_PROPERTIES_NS
                            + DOMConstants.DOM_ENTITIES).equals(key)) {
                        // Preserve entity references in the document
                        if ((properties.getProperty(key).endsWith("yes"))) {
                            fSerializer.setDTDEntityExpansion(false);
                        }
                        else {
                            fSerializer.setDTDEntityExpansion(true);
                        }
                    } else {
                        // We shouldn't get here, ever, now what?
                    }
                }
            }
        }
        // Set the newLine character to use
        if (fNewLine != null) {
            fSerializer.setOutputProperty(OutputPropertiesFactory.S_KEY_LINE_SEPARATOR, fNewLine);
        }
    }

} //TreeWalker
