1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package Torello.HTML.Tools.JavaDoc;

import java.util.*;

import Torello.HTML.*;

import Torello.Java.Shell.C;

/**
 * <B STYLE='color:darkred;'>Process Java Doc Web-Page:</B>
 * 
 * Makes use of the Java HTML Library {@link StaticFunctional} Annotation to insert a
 * Spaghetti Report&trade; into the web-pages for classes that were annotated with it.
 * 
 * <EMBED CLASS="external-html" DATA-FILE-ID=PKG_PRIVATE_MSG>
 * <EMBED CLASS="external-html" DATA-FILE-ID=STATELESSCL>
 * <EMBED CLASS="external-html" DATA-FILE-ID=STATICFUNC>
 */
@StaticFunctional
public class StatelessClasses
{
    // No Public Constructor
    private StatelessClasses() { }

    /**
     * This is the notice that is inserted into classes that have been targeted by the
     * {@code StaticFunctional} annotation.
     */
    protected static final String DIV_HEADER =
        "\n" +
        "<BR />\n" +
        "<DIV ID=STATELESSCLASS>\n" +
        "<SPAN CLASS=staticFunctional>Stateless Class:</SPAN>\n" +
        "<DIV CLASS=JDTopIndent>\n" +
        "This class neither contains any program-state, nor can it be instantiated.  The " +
        "<CODE>@StaticFunctional</CODE> Annotation may also be called 'The Spaghetti Report'.\n" +
        "<CODE>Static-Functional</CODE> classes are, essentially, C-Styled Files, " +
        "without any <I>constructors</I> or <I>non-static member field</I>.  It is very similar " +
        "to the Java-Bean <CODE>@Stateless</CODE> Annotation.<BR />\n\n" +
        "<UL CLASS=JDUL>\n";

    // This is kept package-private.
    //
    // MESSAGER:
    //  1) USES:        errorContinue (x1), println
    //  2) RETURNS:     true / false on success/error
    //  3) SETS:        processorName, only if error happens
    //  4) THROWS:      DOES NOT HAVE ANY EXPLICIT THROWS STATEMENTS
    //  5) INVOKED-BY:  MainFilesProcessor - once!
    //  6) EXPECTS:     FileName to be set

    static boolean addNotice
        (JavaSourceCodeFile jscf, Vector<HTMLNode> defListsBelowDesc, AnnotationsMirror am)
    {
        // The methods, fields and constructor - as declared in the "Java Source Code File"
        // which was parsed by JavaParser - so it should be an accurate list.

        Method[]        mArr = jscf.getMethods();
        Field[]         fArr = jscf.getFields();
        Constructor[]   cArr = jscf.getConstructors();

        // These "counts" determine whether a method is static-functional
        int numStaticMethods        = 0;
        int numStaticFields         = 0;
        int numFinalFields          = 0;
        int numPrivateConstructors  = 0;

        // Compute the counts
        for (Method me : mArr)      if (me.hasModifier("static"))   numStaticMethods++;
        for (Field f : fArr)        if (f.hasModifier("static"))    numStaticFields++;
        for (Field f : fArr)        if (f.hasModifier("final"))     numFinalFields++;
        for (Constructor c : cArr)  if (c.hasModifier("private"))   numPrivateConstructors++;

        boolean zeroArgConstructor = (cArr.length == 1) && (cArr[0].numParameters() == 0);
            
        // Create the HTML for the CIET Java Doc Documentation page.
        StringBuilder htmlSB = new StringBuilder();

        // NOTE: DIV_HEADER is defined at the top of this class.  It opens two <DIV>'s and a <UL>
        //       This append also inserts (in addition to the opening header stuff) all of the
        //       <LI>'s for that <UL>

        htmlSB.append(

            DIV_HEADER +

            "\t<LI><B>" + cArr.length + "</B> Constructor(s), <B>" +
                numPrivateConstructors + "</B> declared private" +
                (zeroArgConstructor ? ", <I>zero-argument constructor</I>" : "") +
                "</LI>\n" +

            "\t<LI><B>" + mArr.length + "</B> Method(s)" +
                ((mArr.length > 0)
                    ?
                    (", <B>" + numStaticMethods + "</B> declared static")
                    : "") +
                "</LI>\n" +

            "\t<LI><B>" + fArr.length + "</B> Field(s)" +
                ((fArr.length > 0)
                    ?
                    (", <B>" + numStaticFields + "</B> declared static, <B>" +
                    numFinalFields + " </B> declared final")
                    : "") +
                "</LI>\n"
        );

        int numExcused = am.numExcused();

        // Often there aren't any "Excused" (non-final) fields.  If so, just close the 
        // <UL> and the <DIV>'s  
        //
        // All three of those are opened by the HTML inside DIV_HEADER

        if (numExcused == 0) htmlSB.append("</UL>\n</DIV>\n</DIV>\n<BR />\n<BR />\n");

        // Otherwise, you need to list which fields are "Excused", and print the reason
        else
        {
            htmlSB.append(
                "\t<LI>Fields excused from <B>final</B> modifier (with explanation):\n" +
                "\t\t<TABLE>\n"
            );

            // Iterates through the names of the Excused-Fields (for being static, but not final)
            // And prints the reasons why they aren't declared 'final'

            for (int i=0; i < numExcused; i++)

                htmlSB.append(
                    "\t\t<TR>\n\t\t\t<TD><B>Field</B> '" + am.excused(i) +
                    "' is not " +
                    "final.</TD>\n\t\t\t<TD><B>Reason:</B> " + am.excuses(i) +
                    "</TD>\n\t\t</TR>\n"
                );

            // Now Close the <TABLE>, the <UL> and the </DIV>'s
            htmlSB.append("\t\t</TABLE>\n\t</LI>\n</UL>\n</DIV>\n</DIV>\n<BR />\n<BR />\n");
        }

        defListsBelowDesc.addAll(HTMLPage.getPageTokens(htmlSB.toString(), false));

        if (Messager.isVerbose()) Messager.println
            ("    Inserted " + C.BCYAN + "@StaticFunctional" + C.RESET + " notice table.");

        return true;
    }
}