package jdiff;

import java.io.*;
import java.util.*;

/* For SAX XML parsing */
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.*;

/**
 * Creates a Comments from an XML file. The Comments object is the internal 
 * representation of the comments for the changes.
 * All methods in this class for populating a Comments object are static.
 * 
 * See the file LICENSE.txt for copyright details.
 * @author Matthew Doar, mdoar@pobox.com
 */
public class Comments {

    /** 
     * All the possible comments known about, accessible by the commentID.
     */
    public static Hashtable allPossibleComments = new Hashtable();

    /** The old Comments object which is populated from the file read in. */ 
    private static Comments oldComments_ = null;

    /** Default constructor. */
    public Comments() {
        commentsList_ = new ArrayList(); // SingleComment[]
    }   
  
    // The list of comments elements associated with this objects
    public List commentsList_ = null; // SingleComment[]

    /** 
     * Read the file where the XML for comments about the changes between
     * the old API and new API is stored and create a Comments object for 
     * it. The Comments object may be null if no file exists.
     */
    public static Comments readFile(String filename) {
        // If validation is desired, write out the appropriate comments.xsd 
        // file in the same directory as the comments XML file.
        if (XMLToAPI.validateXML) {
            writeXSD(filename);
        }

        // If the file does not exist, return null
        File f = new File(filename);
        if (!f.exists())
            return null;

        // The instance of the Comments object which is populated from the file. 
        oldComments_ = new Comments();
        try {
            DefaultHandler handler = new CommentsHandler(oldComments_);
            XMLReader parser = null;
            try {
                String parserName = System.getProperty("org.xml.sax.driver");
                if (parserName == null) {
                    parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
                } else {
                    // Let the underlying mechanisms try to work out which 
                    // class to instantiate
                    parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader();
                }
            } catch (SAXException saxe) {
                System.out.println("SAXException: " + saxe);
                saxe.printStackTrace();
                System.exit(1);
            }

            if (XMLToAPI.validateXML) {
                parser.setFeature("http://xml.org/sax/features/namespaces", true);
                parser.setFeature("http://xml.org/sax/features/validation", true);
                parser.setFeature("http://apache.org/xml/features/validation/schema", true);
            }
            parser.setContentHandler(handler);
            parser.setErrorHandler(handler);
            parser.parse(new InputSource(new FileInputStream(new File(filename))));
        } catch(org.xml.sax.SAXNotRecognizedException snre) {
            System.out.println("SAX Parser does not recognize feature: " + snre);
            snre.printStackTrace();
            System.exit(1);
        } catch(org.xml.sax.SAXNotSupportedException snse) {
            System.out.println("SAX Parser feature is not supported: " + snse);
            snse.printStackTrace();
            System.exit(1);
        } catch(org.xml.sax.SAXException saxe) {
            System.out.println("SAX Exception parsing file '" + filename + "' : " + saxe);
            saxe.printStackTrace();
            System.exit(1);
        } catch(java.io.IOException ioe) {
            System.out.println("IOException parsing file '" + filename + "' : " + ioe);
            ioe.printStackTrace();
            System.exit(1);
        }

        Collections.sort(oldComments_.commentsList_);
        return oldComments_;
    } //readFile()

    /**
     * Write the XML Schema file used for validation.
     */
    public static void writeXSD(String filename) {
        String xsdFileName = filename;
        int idx = xsdFileName.lastIndexOf('\\');
        int idx2 = xsdFileName.lastIndexOf('/');
        if (idx == -1 && idx2 == -1) {
            xsdFileName = "";
        } else if (idx == -1 && idx2 != -1) {
            xsdFileName = xsdFileName.substring(0, idx2+1);
        } else if (idx != -1  && idx2 == -1) {
            xsdFileName = xsdFileName.substring(0, idx+1);
        } else if (idx != -1  && idx2 != -1) {
            int max = idx2 > idx ? idx2 : idx;
            xsdFileName = xsdFileName.substring(0, max+1);
        }
        xsdFileName += "comments.xsd";
        try {
            FileOutputStream fos = new FileOutputStream(xsdFileName);
            PrintWriter xsdFile = new PrintWriter(fos);
            // The contents of the comments.xsd file
            xsdFile.println("<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"no\"?>");
            xsdFile.println("<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">");
            xsdFile.println();
            xsdFile.println("<xsd:annotation>");
            xsdFile.println("  <xsd:documentation>");
            xsdFile.println("  Schema for JDiff comments.");
            xsdFile.println("  </xsd:documentation>");
            xsdFile.println("</xsd:annotation>");
            xsdFile.println();
            xsdFile.println("<xsd:element name=\"comments\" type=\"commentsType\"/>");
            xsdFile.println();
            xsdFile.println("<xsd:complexType name=\"commentsType\">");
            xsdFile.println("  <xsd:sequence>");
            xsdFile.println("    <xsd:element name=\"comment\" type=\"commentType\" minOccurs='0' maxOccurs='unbounded'/>");
            xsdFile.println("  </xsd:sequence>");
            xsdFile.println("  <xsd:attribute name=\"name\" type=\"xsd:string\"/>");
            xsdFile.println("  <xsd:attribute name=\"jdversion\" type=\"xsd:string\"/>");
            xsdFile.println("</xsd:complexType>");
            xsdFile.println();
            xsdFile.println("<xsd:complexType name=\"commentType\">");
            xsdFile.println("  <xsd:sequence>");
            xsdFile.println("    <xsd:element name=\"identifier\" type=\"identifierType\" minOccurs='1' maxOccurs='unbounded'/>");
            xsdFile.println("    <xsd:element name=\"text\" type=\"xsd:string\" minOccurs='1' maxOccurs='1'/>");
            xsdFile.println("  </xsd:sequence>");
            xsdFile.println("</xsd:complexType>");
            xsdFile.println();
            xsdFile.println("<xsd:complexType name=\"identifierType\">");
            xsdFile.println("  <xsd:attribute name=\"id\" type=\"xsd:string\"/>");
            xsdFile.println("</xsd:complexType>");
            xsdFile.println();
            xsdFile.println("</xsd:schema>");
            xsdFile.close();
        } catch(IOException e) {
            System.out.println("IO Error while attempting to create " + xsdFileName);
            System.out.println("Error: " +  e.getMessage());
            System.exit(1);
        }
    }

//
// Methods to add data to a Comments object. Called by the XML parser and the 
// report generator.
//

    /**
     * Add the SingleComment object to the list of comments kept by this 
     * object. 
     */
    public void addComment(SingleComment comment) {
        commentsList_.add(comment); 
    }

//
// Methods to get data from a Comments object. Called by the report generator
//

    /** 
     * The text placed into XML comments file where there is no comment yet.
     * It never appears in reports.
     */
    public static final String placeHolderText = "InsertCommentsHere";
    
    /** 
     * Return the comment associated with the given id in the Comment object.
     * If there is no such comment, return the placeHolderText.
     */
    public static String getComment(Comments comments, String id) {
        if (comments == null)
            return placeHolderText;
        SingleComment key = new SingleComment(id, null);
        int idx = Collections.binarySearch(comments.commentsList_, key);
        if (idx < 0) {
            return placeHolderText;
        } else {
            int startIdx = comments.commentsList_.indexOf(key);
            int endIdx = comments.commentsList_.indexOf(key);
            int numIdx = endIdx - startIdx + 1;
            if (numIdx != 1) {
                System.out.println("Warning: " + numIdx + " identical ids in the existing comments file. Using the first instance.");
            }
            SingleComment singleComment = (SingleComment)(comments.commentsList_.get(idx));
            // Convert @link tags to links
            return singleComment.text_;
        }
    }

    /** 
     * Convert @link tags to HTML links. 
     */
    public static String convertAtLinks(String text, String currentElement, 
                                        PackageAPI pkg, ClassAPI cls) {
        if (text == null)
            return null;
	
        StringBuffer result = new StringBuffer();
        
        int state = -1;
        
        final int NORMAL_TEXT = -1;
        final int IN_LINK = 1;
        final int IN_LINK_IDENTIFIER = 2;
        final int IN_LINK_IDENTIFIER_REFERENCE = 3;
        final int IN_LINK_IDENTIFIER_REFERENCE_PARAMS = 6;
        final int IN_LINK_LINKTEXT = 4;
        final int END_OF_LINK = 5;

        StringBuffer identifier = null;
        StringBuffer identifierReference = null;
        StringBuffer linkText = null;
        
        // Figure out relative reference if required.
        String ref = "";
        if (currentElement.compareTo("class") == 0 ||
            currentElement.compareTo("interface") == 0) {
	    ref = pkg.name_ + "." + cls.name_ + ".";
        } else if (currentElement.compareTo("package") == 0) {
	    ref = pkg.name_ + ".";
        }
        ref = ref.replace('.', '/');        
        
        for (int i=0; i < text.length(); i++) {
	    char c = text.charAt( i);
	    char nextChar = i < text.length()-1 ? text.charAt( i+1) : (char)-1;
	    int remainingChars = text.length() - i;
          
	    switch (state) {
	    case NORMAL_TEXT:
		if (c == '{' && remainingChars >= 5) {
		    if ("{@link".equals(text.substring(i, i + 6))) {
			state = IN_LINK;
			identifier = null;
			identifierReference = null;
			linkText = null;
			i += 5;
			continue;
		    }
		}
		result.append( c);
		break;
	    case IN_LINK:
		if (Character.isWhitespace(nextChar)) continue;
		if (nextChar == '}') {
		    // End of the link
		    state = END_OF_LINK;
		} else if (!Character.isWhitespace(nextChar)) {
		    state = IN_LINK_IDENTIFIER;
		}
		break;
            case IN_LINK_IDENTIFIER:
		if (identifier == null) {
		    identifier = new StringBuffer();
		}
            
		if (c == '#') {
		    // We have a reference.
		    state = IN_LINK_IDENTIFIER_REFERENCE;
		    // Don't append #
		    continue;
		} else if (Character.isWhitespace(c)) {
		    // We hit some whitespace: the next character is the beginning
		    // of the link text.
		    state = IN_LINK_LINKTEXT;
		    continue;
		}
		identifier.append(c);              
		// Check for a } that ends the link.
		if (nextChar == '}') {
		    state = END_OF_LINK;
		}
		break;
            case IN_LINK_IDENTIFIER_REFERENCE:
		if (identifierReference == null) {
		    identifierReference = new StringBuffer();
		}
		if (Character.isWhitespace(c)) {
		    state = IN_LINK_LINKTEXT;
		    continue;
		}
		identifierReference.append(c);
              
		if (c == '(') {
		    state = IN_LINK_IDENTIFIER_REFERENCE_PARAMS;
		}
              
		if (nextChar == '}') {
		    state = END_OF_LINK;
		}
		break;
            case IN_LINK_IDENTIFIER_REFERENCE_PARAMS:
		// We're inside the parameters of a reference. Spaces are allowed.
		if (c == ')') {
		    state = IN_LINK_IDENTIFIER_REFERENCE;
		}
		identifierReference.append(c);
		if (nextChar == '}') {
		    state = END_OF_LINK;
		}
		break;
            case IN_LINK_LINKTEXT:
		if (linkText == null) linkText = new StringBuffer();
              
		linkText.append(c);
              
		if (nextChar == '}') {
		    state = END_OF_LINK;
		}
		break;
            case END_OF_LINK:
		if (identifier != null) {
		    result.append("<A HREF=\"");
		    result.append(HTMLReportGenerator.newDocPrefix);
		    result.append(ref);
		    result.append(identifier.toString().replace('.', '/'));
		    result.append(".html");
		    if (identifierReference != null) {
			result.append("#");
			result.append(identifierReference);
		    }
		    result.append("\">");   // target=_top?
                
		    result.append("<TT>");
		    if (linkText != null) {
			result.append(linkText);
		    } else {
			result.append(identifier);
			if (identifierReference != null) {
			    result.append(".");
			    result.append(identifierReference);
			}
		    }
		    result.append("</TT>");
		    result.append("</A>");
		}
		state = NORMAL_TEXT;
		break;
	    }
        }
        return result.toString();
    }

//
// Methods to write a Comments object out to a file.
//

    /**
     * Write the XML representation of comments to a file.
     *
     * @param outputFileName The name of the comments file.
     * @param oldComments The old comments on the changed APIs.
     * @param newComments The new comments on the changed APIs.
     * @return true if no problems encountered
     */
    public static boolean writeFile(String outputFileName, 
                                    Comments newComments) {
        try {
            FileOutputStream fos = new FileOutputStream(outputFileName);
            outputFile = new PrintWriter(fos);
            newComments.emitXMLHeader(outputFileName);
            newComments.emitComments();
            newComments.emitXMLFooter();
            outputFile.close();
        } catch(IOException e) {
            System.out.println("IO Error while attempting to create " + outputFileName);
            System.out.println("Error: "+ e.getMessage());
            System.exit(1);
        }
        return true;
    }
    
    /**
     * Write the Comments object out in XML.
     */
    public void emitComments() {
        Iterator iter = commentsList_.iterator();
        while (iter.hasNext()) {
            SingleComment currComment = (SingleComment)(iter.next());
            if (!currComment.isUsed_)
                outputFile.println("<!-- This comment is no longer used ");
            outputFile.println("<comment>");
            outputFile.println("  <identifier id=\"" + currComment.id_ + "\"/>");
            outputFile.println("  <text>");
            outputFile.println("    " + currComment.text_);
            outputFile.println("  </text>");
            outputFile.println("</comment>");
            if (!currComment.isUsed_)
                outputFile.println("-->");
        }        
    }

    /** 
     * Dump the contents of a Comments object out for inspection.
     */
    public void dump() {
        Iterator iter = commentsList_.iterator();
        int i = 0;
        while (iter.hasNext()) {
            i++;
            SingleComment currComment = (SingleComment)(iter.next());
            System.out.println("Comment " + i);
            System.out.println("id = " + currComment.id_);
            System.out.println("text = \"" + currComment.text_ + "\"");
            System.out.println("isUsed = " + currComment.isUsed_);
        }        
    }

    /**
     * Emit messages about which comments are now unused and which are new.
     */
    public static void noteDifferences(Comments oldComments, Comments newComments) {
        if (oldComments == null) {
            System.out.println("Note: all the comments have been newly generated");
            return;
        }
        
        // See which comment ids are no longer used and add those entries to 
        // the new comments, marking them as unused.
        Iterator iter = oldComments.commentsList_.iterator();
        while (iter.hasNext()) {
            SingleComment oldComment = (SingleComment)(iter.next());
            int idx = Collections.binarySearch(newComments.commentsList_, oldComment);
            if (idx < 0) {
                System.out.println("Warning: comment \"" + oldComment.id_ + "\" is no longer used.");
                oldComment.isUsed_ = false;
                newComments.commentsList_.add(oldComment);
            }
        }        
        
    }

    /**
     * Emit the XML header.
     */
    public void emitXMLHeader(String filename) {
        outputFile.println("<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"no\"?>");
        outputFile.println("<comments");
        outputFile.println("  xmlns:xsi='" + RootDocToXML.baseURI + "/2001/XMLSchema-instance'");
        outputFile.println("  xsi:noNamespaceSchemaLocation='comments.xsd'");
        // Extract the identifier from the filename by removing the suffix
        int idx = filename.lastIndexOf('.');
        String apiIdentifier = filename.substring(0, idx);
        // Also remove the output directory and directory separator if present
        if (HTMLReportGenerator.commentsDir != null)
	    apiIdentifier = apiIdentifier.substring(HTMLReportGenerator.commentsDir.length()+1);
        else if (HTMLReportGenerator.outputDir != null)
            apiIdentifier = apiIdentifier.substring(HTMLReportGenerator.outputDir.length()+1);
        // Also remove "user_comments_for_"
        apiIdentifier = apiIdentifier.substring(18);
        outputFile.println("  name=\"" + apiIdentifier + "\"");
        outputFile.println("  jdversion=\"" + JDiff.version + "\">");
        outputFile.println();
        outputFile.println("<!-- Use this file to enter an API change description. For example, when you remove a class, ");
        outputFile.println("     you can enter a comment for that class that points developers to the replacement class. ");
        outputFile.println("     You can also provide a change summary for modified API, to give an overview of the changes ");
        outputFile.println("     why they were made, workarounds, etc.  -->");
        outputFile.println();
        outputFile.println("<!-- When the API diffs report is generated, the comments in this file get added to the tables of ");
        outputFile.println("     removed, added, and modified packages, classes, methods, and fields. This file does not ship ");
        outputFile.println("     with the final report. -->");
        outputFile.println();
        outputFile.println("<!-- The id attribute in an identifier element identifies the change as noted in the report. ");
        outputFile.println("     An id has the form package[.class[.[ctor|method|field].signature]], where [] indicates optional ");
        outputFile.println("     text. A comment element can have multiple identifier elements, which will will cause the same ");
        outputFile.println("     text to appear at each place in the report, but will be converted to separate comments when the ");
        outputFile.println("     comments file is used. -->");
        outputFile.println();
        outputFile.println("<!-- HTML tags in the text field will appear in the report. You also need to close p HTML elements, ");
        outputFile.println("     used for paragraphs - see the top-level documentation. -->");
        outputFile.println();
        outputFile.println("<!-- You can include standard javadoc links in your change descriptions. You can use the @first command  ");
        outputFile.println("     to cause jdiff to include the first line of the API documentation. You also need to close p HTML ");
        outputFile.println("     elements, used for paragraphs - see the top-level documentation. -->");
        outputFile.println();
    }

    /**
     * Emit the XML footer.
     */
    public void emitXMLFooter() {
        outputFile.println();
        outputFile.println("</comments>");
    }

    private static List oldAPIList = null;
    private static List newAPIList = null;

    /** 
     * Return true if the given HTML tag has no separate </tag> end element. 
     *
     * If you want to be able to use sloppy HTML in your comments, then you can
     * add the element, e.g. li back into the condition here. However, if you 
     * then become more careful and do provide the closing tag, the output is 
     * generally just the closing tag, which is incorrect.
     *
     * tag.equalsIgnoreCase("tr") || // Is sometimes minimized
     * tag.equalsIgnoreCase("th") || // Is sometimes minimized
     * tag.equalsIgnoreCase("td") || // Is sometimes minimized
     * tag.equalsIgnoreCase("dt") || // Is sometimes minimized
     * tag.equalsIgnoreCase("dd") || // Is sometimes minimized
     * tag.equalsIgnoreCase("img") || // Is sometimes minimized
     * tag.equalsIgnoreCase("code") || // Is sometimes minimized (error)
     * tag.equalsIgnoreCase("font") || // Is sometimes minimized (error)
     * tag.equalsIgnoreCase("ul") || // Is sometimes minimized
     * tag.equalsIgnoreCase("ol") || // Is sometimes minimized
     * tag.equalsIgnoreCase("li") // Is sometimes minimized
     */
    public static boolean isMinimizedTag(String tag) {
        if (tag.equalsIgnoreCase("p") ||
            tag.equalsIgnoreCase("br") ||
            tag.equalsIgnoreCase("hr")
            ) {
            return true;
	}
        return false;
    }

    /** 
     * The file where the XML representing the new Comments object is stored. 
     */
    private static PrintWriter outputFile = null;
    
}


