package com.icl.saxon.tinytree;
import com.icl.saxon.om.*;
import com.icl.saxon.Context;
import com.icl.saxon.output.Outputter;

import org.w3c.dom.Node;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.DOMException;

import javax.xml.transform.TransformerException;


/**
  * A node in the XML parse tree representing an attribute. Note that this is
  * generated only "on demand", when the attribute is selected by a select pattern.<P>
  * @author <A HREF="mailto:mhkay@iclway.co.uk>Michael H. Kay</A> 
  */

final class TinyAttributeImpl extends TinyNodeImpl implements Attr {

    public TinyAttributeImpl(TinyDocumentImpl doc, int nodeNr) {
        this.document = doc;
        this.nodeNr = nodeNr;
    }

    /**
    * Get the parent node
    */

    public NodeInfo getParent() {
        return document.getNode(document.attParent[nodeNr]);
    }

    /**
    * Get the node sequence number (in document order). Sequence numbers are monotonic but not
    * consecutive. In the current implementation, parent nodes (elements and roots) have a zero
    * least-significant word, while namespaces, attributes, text nodes, comments, and PIs have
    * the top word the same as their owner and the bottom half reflecting their relative position.
    */

    protected long getSequenceNumber() {
        // need the variable as workaround for a Java HotSpot problem, reported 11 Oct 2000
        long z =
            ((TinyNodeImpl)getParent()).getSequenceNumber()
            + 0x8000 +
            (nodeNr - document.offset[document.attParent[nodeNr]]);
        return z;
        // note the 0x8000 is to leave room for namespace nodes
    }

    /**
    * Return the type of node.
    * @return Node.ATTRIBUTE
    */

    public final short getNodeType() {
        return ATTRIBUTE;
    }

    /**
    * Return the character value of the node. 
    * @return the attribute value
    */

    public String getStringValue() {
        return document.attValue[nodeNr];
    }

	/**
	* Get the fingerprint of the node, used for matching names
	*/
	
	public int getFingerprint() {
		return document.attCode[nodeNr] & 0xfffff;
	}

	/**
	* Get the name code of the node, used for finding names in the name pool
	*/
	
	public int getNameCode() {
		return document.attCode[nodeNr];
	}

    /**
    * Get the prefix part of the name of this node. This is the name before the ":" if any.
    * @return the prefix part of the name. For an unnamed node, return null.
    */

    public String getPrefix() {
    	int code = document.attCode[nodeNr];
    	if ((code>>20 & 0xff) == 0) return "";
    	return document.getNamePool().getPrefix(code);
    }
    
    /**
    * Get the display name of this node. For elements and attributes this is [prefix:]localname.
    * For unnamed nodes, it is an empty string.
    * @return The display name of this node. 
    * For a node with no name, return an empty string.
    */

    public String getDisplayName() {
        return document.getNamePool().getDisplayName(document.attCode[nodeNr]);
    }


    /**
    * Get the local name of this node. 
    * @return The local name of this node. 
    * For a node with no name, return an empty string.
    */

    public String getLocalName() {
        return document.getNamePool().getLocalName(document.attCode[nodeNr]);
    }

    /**
    * Get the URI part of the name of this node. 
    * @return The URI of the namespace of this node. For the default namespace, return an
    * empty string
    */

    public final String getURI() {
        return document.getNamePool().getURI(document.attCode[nodeNr]);
    }

    /**
    * Generate id. Returns key of owning element with the attribute name as a suffix
    */

    public String generateId() {
        return (getParent()).generateId() + "_" + getDisplayName();
    }
    
    /**
    * Copy this node to a given outputter
    */

    public void copy(Outputter out) throws TransformerException {
		int nameCode = document.attCode[nodeNr];
    	if ((nameCode>>20 & 0xff) != 0) {	// non-null prefix
    		// check there is no conflict of namespaces    	    	
			nameCode = out.checkAttributePrefix(nameCode);
		}
        out.writeAttribute(nameCode, getStringValue());
    }
   
    /**
    * Get the line number of the node within its source document entity
    */

    public int getLineNumber() {
        return getParent().getLineNumber();
    }

}

//
// The contents of this file are subject to the Mozilla Public License Version 1.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.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: all this file. 
//
// The Initial Developer of the Original Code is
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
//
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved. 
//
// Contributor(s): none. 
//
