/**********************************************************
 * ContactPrintout accepts a first name and last name 
 * as command-line parameters. The class then parses the AddressBook.xml file,
 * creating the DOM object (Document) and searches through the DOM for the
 * entered first name and last name node combination. If they're found, the
 * program then traverses backward up the node tree and prints out the relevant
 * content from the nodes that comprise that contact.
 * 
 * 16-Oct-2004
 *
 * Kelli Wiseth
 *
 *
 * XML and Web Services class | NDNU 
 *
 ***********************************************************
 */
 
// Java core packages
import java.io.*;
import java.util.regex.*;

// Java standard extensions
import javax.xml.parsers.*;
import javax.xml.transform.*;

// third-party libraries
import org.w3c.dom.*;
import org.w3c.dom.traversal.*; 
import org.xml.sax.*;

public class ContactPrintout 
{
   String findFirstname = "";
   String findLastname = "";
   String filename = "AddressBook.xml";
   String nodeValue = " ";
   String nodeName = "";
   String textToPrint = "";
   
   boolean lastNameExists = false;
   boolean firstNameExists = false;

   DocumentBuilder addressBookParser;
   Document addressBook;
   Element contact;
   int nodeType;
      
   public ContactPrintout( String findFirstname, String findLastname )
   {
   
   // parse XML, create DOM tree, and find the contact
   try 
   {

   // obtain default parser
   DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
   dbf.setValidating( false );

   DocumentBuilder addressBookParser = dbf.newDocumentBuilder();
   Document addressBook = addressBookParser.parse( new File( filename ) );
   addressBook.getDocumentElement().normalize();
   String firstnameLookup = findFirstname;
   String lastnameLookup = findLastname;
   String spouseName = "";
   NodeList contactsAll = addressBook.getElementsByTagName("Contact");
   NodeList namesAll = addressBook.getElementsByTagName("Name");
   
   for (int ctr1 = 0; ctr1 < contactsAll.getLength(); ctr1++) 
    {
     /*Setup the Nodes in the DOM that we need to get to in order to find the 
      * last name element and subsequently, the first name element.  Cast to 
      * Element as required in to obtain Element tag names and create NodeLists
      * within our found object that comprise the nodes of interest
     */
      

     Node contactName = namesAll.item(ctr1);
     Element names = (Element)namesAll.item(ctr1);
     NodeList lastNameList = names.getElementsByTagName("Last");
     Node lastNameElement =  lastNameList.item(0);
     Node lastNameTextNode = lastNameElement.getFirstChild();
     String lastNameText = lastNameTextNode.getNodeValue().trim();
     NodeList firstNameList = names.getElementsByTagName("First");
     Element firstNameElement = (Element)firstNameList.item(0);
     Node firstNameTextNode = firstNameElement.getFirstChild();
     String firstNameText = firstNameTextNode.getNodeValue().trim();
     if ( lastNameText.equalsIgnoreCase(lastnameLookup) )
        {
        lastNameExists=true;
           if ( firstNameText.equalsIgnoreCase( firstnameLookup ) ) 
              {
              firstNameExists=true;
              Node foundContactName = contactName;
              String foundNickname = names.getAttribute("Nickname");
              Node foundPrimaryInfo = foundContactName.getParentNode();
              Node foundContactRootNode = foundPrimaryInfo.getParentNode();
              Node foundPersonalInfo = foundContactRootNode.getNextSibling();
              Element contactSpecsSubDoc = (Element)foundContactRootNode;
                   if (foundNickname.equals(""))
                 {
                 System.out.println("\nContact printout from address book for " + 
                                 firstNameText + " " + lastNameText + ":");
                 }
              else
                 {
                 System.out.println("\nContact printout from address book for " + 
                                 firstNameText + " " + lastNameText + ":");
                 System.out.println("\nNickname: " + foundNickname);
                 }
              
              if (foundContactRootNode.hasChildNodes())
                 {
                 	
                      System.out.println(getNodeTextWithElements(foundContactRootNode));
                 }
           
              } // if firstNameText equals firstnameLookup
                     
        } // if lastName.equals lastnameLookup
           
    } //for-loop ctr1
              

    if ((!lastNameExists) || (lastNameExists) && (!firstNameExists))
      System.out.println("Contact named " + findFirstname + " " + findLastname + 
                " not found in the address book \nor is not a primary contact.");

   
   } //close try block
   
   /* The parser exceptions aren't needed, since we're not creating a 
    * DOM structure except by passing in a pre-validated XML file, and
    * we've turned off validation. However, this setup will help with the SAX 
    * project and with the further enhancement of the program (add contacts, delete, etc).
  */ 
   
   // handle exception thrown by DocumentBuilder
   catch ( ParserConfigurationException parserException ) 
   {
   parserException.printStackTrace();
   }
      
   // handle exception thrown by Parser
   catch ( SAXException saxException ) 
   {
   saxException.printStackTrace();         
   }
      
   // handle exception thrown when reading data from file
   catch ( IOException ioException ) 
   {
    System.out.print("Syntax: java ContactPrintout <firstname> <lastname> \n");
    System.out.print("Please enter contact's first name and last name, as in: \n\n");
    System.out.print("              java ContactPrintout marie sklodowska \n");
    System.exit( 1 );
    }
 
  } //close constructor
  
  
   public String getNodeTextWithElements(Node node)
  {
   String textToPrint = "";
 
    if (node.hasChildNodes())
      {
       NodeList children = node.getChildNodes();
           for (int i = 0; i < children.getLength(); i++)
           {
            Node child = children.item(i);
            child.normalize();
            int nodeType = child.getNodeType();
           
            if (nodeType == Node.ELEMENT_NODE)
               {
                nodeName = child.getNodeName().trim();
                textToPrint += child.getNodeName().trim() + ": ";
               
                NamedNodeMap attributes = child.getAttributes();
                
                for (int x= 0; x < attributes.getLength(); x++)
                      {
                      Node attribute = attributes.item(x);
                      textToPrint += attribute.getNodeName().trim() + ": ";
                      textToPrint += attribute.getNodeValue().trim() + "\n";
                      }
                 }
            
            if (nodeType == Node.TEXT_NODE)
               if((child.getNodeValue()==null) || (child.getNodeValue().equals("\t")) || (child.getNodeValue().trim().equals("\n")))
                 {
                 //do nothing textToPrint += "";
                 }
                 else 
                 {
                 textToPrint += child.getNodeValue().trim() + " \n";
                 }

               textToPrint += getNodeTextWithElements(child);
              
             } //close for loop
       
       }  // close topmost if
       
    return textToPrint;
   
  } // close getNodeTextwithElements method
  
 
   public static void main( String args[] )
   {
    if ( args.length < 2 ) 
       {
        System.out.print("Syntax: java ContactPrintout <firstname> <lastname> \n");
        System.out.print("Please enter contact's first name and last name, as in: \n\n");
        System.out.print("              java ContactPrintout marie sklodowska \n");
        System.exit( 1 );
        }
    ContactPrintout report = new ContactPrintout( args[0], args[1] );
  
   }//close main method
   
} //close class ContactPrintout
