/* Title:		Identity.java
 * Version	
 * Author		Sada
 * Company: USDA-ARS
 * Date:    July, 2003
 * Description: Identifies a particular operation through 'id' and 'code'.
 * Operation Object.
 */
package usda.weru.mcrew;


import org.w3c.dom.*;
import org.w3c.dom.traversal.*;

/**
 * This class assigns the identity consisting of two parts, first, a numeric id and
 * second the code which together forms the identity of any action object to be used
 * for future data retrieval.
 */
public class Identity implements Cloneable
{
    /**
     * Holds the numeric portion of the identity
     */    
	public int id;

	/**
	 *
	 */
	public String code;
		
        /**
         * Default constructor for the class using default initialization values for an
         * object to be created.
         */        
	public Identity()
	{
		id = 0;
		code = "Z";
	}

    /**
     * Two argument constructor for creating an identity object with numeric id as PID and
     * string part of identity as CODE for processes from crop/operation objects to be
     * recognized.
     * @param pid The numeric part of the identity to be used in identifying a process in an
     * action object.
     * @param pCode The string part of the identity to be used in identifying a process in an
     * action object.
     */    
	public Identity(int pid, String pCode)
	{
		id = pid;
		code = pCode.trim();
	}
	
    /**
     * Two argument constructor for creating an identity object with numeric id as PID and
     * string part of identity as CODE for processes from crop/operation objects to be
     * recognized.
     * @param pid The numeric part of the identity to be used later in identifying a process 
     * in an action object. Here it is input as a string
     * @param pCode The string part of the identity to be used in identifying a process in an
     * action object.
     */    
	public Identity(String pid, String pCode)
	{
		id = Integer.valueOf(pid.trim(),10).intValue();
		code = pCode.trim();
               // //System.out.println("Identity : Constructor : ---- ID is-- : " + id + " ---- Code is --: " + code);
		
	}
	
    /**
     * This method initializes the identity node with the ID and CODE part by 
     * assigning the default values by making the node traversable in a tree format.
     * @param pNode The node whose ID and CODE part is being initialized.
     */    
	public void initialize(Node pNode)
	{
		DocumentTraversal traversable;

		if(pNode.getOwnerDocument() == null)
		{
			traversable = (DocumentTraversal)pNode;
		}
		else
			traversable = (DocumentTraversal)pNode.getOwnerDocument();

		TreeWalker walker = traversable.createTreeWalker(pNode, NodeFilter.SHOW_ALL, null, false);	
		Node nodeChild = walker.firstChild(); // nodeChild is 'id' or 'code'
		
		while(nodeChild != null)
		{
			String nodeChildName = nodeChild.getNodeName();
			if(nodeChildName.equals(XMLConstants.scode))
			{
				code = XMLDoc.getTextData(nodeChild);
			}
			else if(nodeChildName.equals(XMLConstants.sid))
			{
				String idStr = XMLDoc.getTextData(nodeChild);
				id = Integer.valueOf(idStr.trim()).intValue();
			}
			nodeChild = walker.nextSibling();
		}
	}
	
    /**
     * Fetches the hashcode of complete identity which is ID and CODE part together.
     * @return Returns the integer value of ID & Code part together by multiplying it 
     * by a factor of 1000 to accomodate various combinations of ID and code values
     */    
    @Override
	public int hashCode()
	{
		return id + (code.hashCode() * 1000);
	}
	
    /**
     * Determines whether the hashcode of passed object equals the hashcode
     * of this object.
     * @param pObj The object to which this object is beign comapared
     * @return Returns true if objects being compared have same hashcode, else false.
     */    
    @Override
	public boolean equals(Object pObj)                
	{
                if(pObj instanceof Identity){
                    return ( hashCode() == ((Identity)pObj).hashCode() );
                }
                else{
                    return false;
                }
	}
	
    /**
     * Converts an object to a string object. Makes easier for string manipulations.
     * @return The new string object
     */    
    @Override
	public String toString()
	{
		/* Temporary solution - use number format through Java 1.4
		*/
		String idStr = Integer.toString(id);
		if(idStr.length() < 2)
			idStr = "0".concat(idStr);
		//NumberFormat nf = NumberFormat.getIntegerInstance(); Not there in Java 1.3
		//nf.setMinimumIntegerDigits(2);
		
		//return code + " " + (new Integer(id)).toString();
		return code + " "+ idStr;
		
	}
	
	
    /**
     * Fetches the identity node from the document that is passed as an argument.
     * @param doc The document from which the node object is pulled.
     * @return The node object containing the ID and CODE values in a format as
     * described in the crop/operation XML files.
     */    
	public Node getNode(Document doc)
	{
		Node identityNode = doc.createElement(XMLConstants.sidentity);
		
		Node codeNode = doc.createElement(XMLConstants.scode);
		codeNode.appendChild(doc.createTextNode(code));
		
		Node idNode = doc.createElement(XMLConstants.sid);
		String idStr = Integer.toString(id);
		if(idStr.length() < 2)
			idStr = "0".concat(idStr);
		idNode.appendChild(doc.createTextNode(idStr));
		
		identityNode.appendChild(codeNode);
		identityNode.appendChild(idNode);
		
		return identityNode;
	}
	
    /**
     * Makes a copy of the current identity object.
     * @return The new independent copy of the identity object.
     */    
    @Override
	public Object clone()
	{
		try{
			Identity copy = (Identity)super.clone(); // Not really required...?
			copy.id = id;
			copy.code = code;
			
			return copy;
		}
		catch(CloneNotSupportedException e)
		{
			System.err.println("Identity:clone(); " + "CloneNotSupported exception!");
		}
		return null;
	}
}
