001package Torello.HTML.Tools.JavaDoc;
002
003import java.util.*;
004
005import Torello.HTML.*;
006
007import Torello.Java.Shell.C;
008
009/**
010 * <B STYLE='color:darkred;'>Process Java Doc Web-Page:</B>
011 * 
012 * Makes use of the Java HTML Library {@link StaticFunctional} Annotation to insert a
013 * Spaghetti Report&trade; into the web-pages for classes that were annotated with it.
014 * 
015 * <EMBED CLASS="external-html" DATA-FILE-ID=PKG_PRIVATE_MSG>
016 * <EMBED CLASS="external-html" DATA-FILE-ID=STATELESSCL>
017 * <EMBED CLASS="external-html" DATA-FILE-ID=STATICFUNC>
018 */
019@StaticFunctional
020public class StatelessClasses
021{
022    // No Public Constructor
023    private StatelessClasses() { }
024
025    /**
026     * This is the notice that is inserted into classes that have been targeted by the
027     * {@code StaticFunctional} annotation.
028     */
029    protected static final String DIV_HEADER =
030        "\n" +
031        "<BR />\n" +
032        "<DIV ID=STATELESSCLASS>\n" +
033        "<SPAN CLASS=staticFunctional>Stateless Class:</SPAN>\n" +
034        "<DIV CLASS=JDTopIndent>\n" +
035        "This class neither contains any program-state, nor can it be instantiated.  The " +
036        "<CODE>@StaticFunctional</CODE> Annotation may also be called 'The Spaghetti Report'.\n" +
037        "<CODE>Static-Functional</CODE> classes are, essentially, C-Styled Files, " +
038        "without any <I>constructors</I> or <I>non-static member field</I>.  It is very similar " +
039        "to the Java-Bean <CODE>@Stateless</CODE> Annotation.<BR />\n\n" +
040        "<UL CLASS=JDUL>\n";
041
042    // This is kept package-private.
043    //
044    // MESSAGER:
045    //  1) USES:        errorContinue (x1), println
046    //  2) RETURNS:     true / false on success/error
047    //  3) SETS:        processorName, only if error happens
048    //  4) THROWS:      DOES NOT HAVE ANY EXPLICIT THROWS STATEMENTS
049    //  5) INVOKED-BY:  MainFilesProcessor - once!
050    //  6) EXPECTS:     FileName to be set
051
052    static boolean addNotice
053        (JavaSourceCodeFile jscf, Vector<HTMLNode> defListsBelowDesc, AnnotationsMirror am)
054    {
055        // The methods, fields and constructor - as declared in the "Java Source Code File"
056        // which was parsed by JavaParser - so it should be an accurate list.
057
058        Method[]        mArr = jscf.getMethods();
059        Field[]         fArr = jscf.getFields();
060        Constructor[]   cArr = jscf.getConstructors();
061
062        // These "counts" determine whether a method is static-functional
063        int numStaticMethods        = 0;
064        int numStaticFields         = 0;
065        int numFinalFields          = 0;
066        int numPrivateConstructors  = 0;
067
068        // Compute the counts
069        for (Method me : mArr)      if (me.hasModifier("static"))   numStaticMethods++;
070        for (Field f : fArr)        if (f.hasModifier("static"))    numStaticFields++;
071        for (Field f : fArr)        if (f.hasModifier("final"))     numFinalFields++;
072        for (Constructor c : cArr)  if (c.hasModifier("private"))   numPrivateConstructors++;
073
074        boolean zeroArgConstructor = (cArr.length == 1) && (cArr[0].numParameters() == 0);
075            
076        // Create the HTML for the CIET Java Doc Documentation page.
077        StringBuilder htmlSB = new StringBuilder();
078
079        // NOTE: DIV_HEADER is defined at the top of this class.  It opens two <DIV>'s and a <UL>
080        //       This append also inserts (in addition to the opening header stuff) all of the
081        //       <LI>'s for that <UL>
082
083        htmlSB.append(
084
085            DIV_HEADER +
086
087            "\t<LI><B>" + cArr.length + "</B> Constructor(s), <B>" +
088                numPrivateConstructors + "</B> declared private" +
089                (zeroArgConstructor ? ", <I>zero-argument constructor</I>" : "") +
090                "</LI>\n" +
091
092            "\t<LI><B>" + mArr.length + "</B> Method(s)" +
093                ((mArr.length > 0)
094                    ?
095                    (", <B>" + numStaticMethods + "</B> declared static")
096                    : "") +
097                "</LI>\n" +
098
099            "\t<LI><B>" + fArr.length + "</B> Field(s)" +
100                ((fArr.length > 0)
101                    ?
102                    (", <B>" + numStaticFields + "</B> declared static, <B>" +
103                    numFinalFields + " </B> declared final")
104                    : "") +
105                "</LI>\n"
106        );
107
108        int numExcused = am.numExcused();
109
110        // Often there aren't any "Excused" (non-final) fields.  If so, just close the 
111        // <UL> and the <DIV>'s  
112        //
113        // All three of those are opened by the HTML inside DIV_HEADER
114
115        if (numExcused == 0) htmlSB.append("</UL>\n</DIV>\n</DIV>\n<BR />\n<BR />\n");
116
117        // Otherwise, you need to list which fields are "Excused", and print the reason
118        else
119        {
120            htmlSB.append(
121                "\t<LI>Fields excused from <B>final</B> modifier (with explanation):\n" +
122                "\t\t<TABLE>\n"
123            );
124
125            // Iterates through the names of the Excused-Fields (for being static, but not final)
126            // And prints the reasons why they aren't declared 'final'
127
128            for (int i=0; i < numExcused; i++)
129
130                htmlSB.append(
131                    "\t\t<TR>\n\t\t\t<TD><B>Field</B> '" + am.excused(i) +
132                    "' is not " +
133                    "final.</TD>\n\t\t\t<TD><B>Reason:</B> " + am.excuses(i) +
134                    "</TD>\n\t\t</TR>\n"
135                );
136
137            // Now Close the <TABLE>, the <UL> and the </DIV>'s
138            htmlSB.append("\t\t</TABLE>\n\t</LI>\n</UL>\n</DIV>\n</DIV>\n<BR />\n<BR />\n");
139        }
140
141        defListsBelowDesc.addAll(HTMLPage.getPageTokens(htmlSB.toString(), false));
142
143        if (Messager.isVerbose()) Messager.println
144            ("    Inserted " + C.BCYAN + "@StaticFunctional" + C.RESET + " notice table.");
145
146        return true;
147    }
148}