001package Torello.JavaDoc;
002
003
004// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
005// Standard-Java Imports
006// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
007
008import java.io.IOException;
009import java.sql.CallableStatement;
010import java.util.Optional;
011
012
013// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
014// Java-HTML Imports
015// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
016
017import Torello.Java.*;
018
019import static Torello.JavaDoc.PF.*;
020
021import Torello.Java.ReadOnly.ReadOnlyList;
022import Torello.Java.ReadOnly.ROArrayListBuilder;
023
024
025// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
026// JDUInternal
027// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
028
029import Torello.JDUInternal.Annotations.EntityAnnotations.EntityAnnotationData;
030import Torello.JDUInternal.Parse.HTML.Signature.D1_CallableSignature;
031
032
033// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
034// The new Source-Code Parser: com.sun.source.*
035// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
036
037import com.sun.source.tree.MethodTree;
038
039
040/**
041 * <B CLASS=JDDescLabel>Reflection Class:</B>
042 * 
043 * <BR />Holds all information extracted from <CODE>'&#46;java'</CODE> Source-Files about
044 * Constructor's identified in that file.
045 * 
046 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_GET_INST>
047 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_CONSTRUCTOR>
048 * <!-- EMBED CLASS='external-html' DATA-FILE-ID=JPB_DIAGRAM -->
049 */
050@JDHeaderBackgroundImg(EmbedTagFileID={"REFLECTION_EXTENSION"})
051public class Constructor extends Callable
052    implements java.io.Serializable, Comparable<Constructor>, Cloneable
053{
054    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
055    public static final long serialVersionUID = 1;
056
057
058    // ********************************************************************************************
059    // ********************************************************************************************
060    // Reference-Hook: com.sun.source.tree
061    // ********************************************************************************************
062    // ********************************************************************************************
063
064
065    /**
066     * <EMBED CLASS='external-html' DATA-FILE-ID=SSTB_HOOK_FIELD>
067     * 
068     * If a user decides to make use of the native Sun/Oracle {@code MethodTree} instance that was
069     * used to build this {@code Constructor} instance, it may be retrieved from this
070     * {@code transient} field.
071     * 
072     * <BR /><BR /><B CLASS=JDDescLabel>{@code MethodTree} Note:</B>
073     * 
074     * <BR />The package {@code com.sun.source.tree} "reuses" or "overloads" the {@code MethodTree}
075     * class.  {@code com.sun.source.tree.MethodTree} can actually represent either a Method, or a
076     * Constructor.
077     * 
078     * <BR /><BR />When a {@code MethodTree} instance is actually representing a constructor, the
079     * name that it uses for the instance will be Java-String {@code '<init>'}, rather than an
080     * actual Method-Name.
081     */
082    public final transient MethodTree methodTree;
083
084
085    // ********************************************************************************************
086    // ********************************************************************************************
087    // Constructor - com.sun.source.tree 
088    // ********************************************************************************************
089    // ********************************************************************************************
090
091
092    /**
093     * <EMBED CLASS="defs" DATA-KIND=Constructor DATA-ENTITY=MethodTree>
094     * <EMBED CLASS='external-html' DATA-FILE-ID=RC_DESCRIPTION>
095     * @param mt <EMBED CLASS='external-html' DATA-FILE-ID=RC_PARAM_TREE>
096     * @param util <EMBED CLASS='external-html' DATA-FILE-ID=RC_PARAM_UTIL>
097     * 
098     * @param constructorName The name of the type (which is also the name of the constructor) has
099     * to be passed here, in order for this constructor to work.
100     */
101    public Constructor(
102            final MethodTree            mt,
103            final EntityAnnotationData  ead,
104            final TreeUtils             util,
105            final String                constructorName
106        )
107    {
108        super(mt, constructorName, Entity.CONSTRUCTOR, ead, util);
109
110        // Only the 2 reference hooks are needed here
111        this.methodTree = mt;
112    }
113
114
115    // ********************************************************************************************
116    // ********************************************************************************************
117    // Constructor: Used Internally by SignatureParse
118    // ********************************************************************************************
119    // ********************************************************************************************
120
121
122    // Ensures that the Version with longer type-information strings is used.
123    // Java Doc often uses longer type strings than is available from the source-code parse
124    // Remember, JavaParser Symbol-Solver doesn't work well, and the Sun/Oracle Parser doesn't have
125    // a linker at all.
126
127    public Constructor(final D1_CallableSignature cSig, final Constructor cFromSourceParser)
128    {
129        // Does the same thing as the loop statement below, but for the "parameterTypes"
130        super(cSig, cFromSourceParser);
131
132        this.methodTree = cFromSourceParser.methodTree;
133    }
134
135    // This is only used to construct a constructor for SYNTHETIC-CONSTRUCTORS.  At the present
136    // moment, that means this is only used when there is a Zero-Argument Constructor that the user
137    // did not actually type into his code, but rather is being auto-added by javac.
138
139    public Constructor(final D1_CallableSignature cSig)
140    {
141        super(cSig, Entity.CONSTRUCTOR);
142
143        this.methodTree = null;
144    }
145
146
147    // ********************************************************************************************
148    // ********************************************************************************************
149    // toString()
150    // ********************************************************************************************
151    // ********************************************************************************************
152
153
154    /**
155     * Generates a string of this constructor, with most information included.
156     * 
157     * <BR /><BR /><B CLASS=JDDescLabel>Reduced Information:</B>
158     * 
159     * <BR />This {@code 'toString'} will not return every piece of information contained by this
160     * class. For example, both the constructor body, and any possible JavaDoc Comments are not
161     * included.  For a more enhanced {@code toString()} method version, invoke the 
162     * {@link #toString(int) toString(PrintFlags)} method which accepts {@link PF Print-Flags}.
163     * 
164     * @return A printable string of this field.
165     * @see PF
166     * @see #toString(int)
167     */
168    public String toString()
169    {
170        return
171            "Name:            [" + name + "]\n" +
172            "Signature:       [" + StrPrint.abbrevEndRDSF(signature, MAX_STR_LEN, true) + "]\n" +
173            "Modifiers:       [" + StrCSV.toCSV(modifiers, true, true, null) + "]\n" +
174            printedParameterNamesTS() +
175            printedParameterTypesTS() +
176            printedExceptionsTS() +
177
178            // This will **NEVER** be null - unless 'this' instance was built from an HTML File,
179            // rather than a source-code file.  Instances like that are only used temporarily, and
180            // are garbage collected instantly.  Do this check anyway (just in case).
181
182            "Location:        " + ((this.location == null)
183                ? "null" 
184                : ('[' + this.location.quickSummary() + ']'));
185    }
186
187    /**
188     * <EMBED CLASS='external-html' DATA-FILE-ID=TO_STR_PF>
189     * @param flags These are defined in the {@link PF Print-Flags} class
190     * @return A printable {@code String} of this {@code Constructor}.
191     * @see #toString()
192     * @see PF
193     */
194    public String toString(int flags)
195    {
196        boolean color = (flags & UNIX_COLORS) > 0;
197
198        return
199            printedName("Constructor", 20, color) + 
200            printedSignature(20, color) +
201            printedModifiers(20) +
202            printedParamNames() + 
203            printedParamTypes(jowFlags(flags)) +
204            printedExceptions() +
205            printedLocation(20, color, (flags & BRIEF_LOCATION) > 0) +
206
207            // The previous method does not add a '\n' end to the end of the returned string
208            // These are both optional, they add a '\n' AT THE BEGINNING if one of them is included
209
210            printedComments(20, color, (flags & JAVADOC_COMMENTS) > 0) +
211            printedCallableBody(flags);
212    }
213
214
215    // ********************************************************************************************
216    // ********************************************************************************************
217    //  CompareTo and Equals
218    // ********************************************************************************************
219    // ********************************************************************************************
220
221
222    /**
223     * Java's {@code interface Comparable<T>} requirements.  This looks at the number of
224     * parameters, and parameter types in making a sort-decision.
225     * 
226     * @param c Any other {@code Constructor} to be compared to {@code 'this' Constructor}
227     * 
228     * @return An integer that fulfills Java's {@code Comparable<Constructor>} interface
229     * requirements.
230     */
231    public int compareTo(Constructor c)
232    {
233        if (this == c) return 0;
234
235        int ret = this.numParameters() - c.numParameters();
236        if (ret != 0) return ret;
237
238        if (this.parameterTypesJOW != null)
239
240            for (int i=0; i < this.parameterTypesJOW.size(); i++)
241            {
242                ret = this.parameterTypesJOW.get(i).compareTo(c.parameterTypesJOW.get(i));
243                if (ret != 0) return ret;
244            }
245
246        return 0;
247    }
248
249    /**
250     * This <I>should be called an "atypical version" of</I> the usual
251     * {@code equals(Object other)} constructor.  This version of equals merely compares the name
252     * and parameters-list of the constructor.  The presumption here is that the definition of a
253     * 'constructor' only has meaning - <I>at all</I> - inside the context of a {@code class} or
254     * {@code enumerated-type} where that constructor is defined. Since inside any {@code '.java'}
255     * source-code file, there may only be one constructor with a given parameter-list, this shall
256     * return {@code TRUE} whenever the constructor being compared has the same parameter types as
257     * {@code 'this'} does.
258     * 
259     * @param other This may be any other constructor.  It is <I><B>strongly suggested</B></I> that
260     * this be a constructor defined in the same {@code '.java'} source-code file as 'this'
261     * constructor.
262     * 
263     * @return This method returns {@code TRUE} when 'this' instance of Constructor has the same
264     * parameter-list as {@code 'other'}.
265     */
266    public boolean equals(Constructor other)
267    {
268        // If the number of parameters in the 'other' instance of Constructor differ from the
269        // number of parameters in 'this' Constructor, then return FALSE immediately.  It cannot be
270        // a match
271
272        if (this.numParameters() != other.numParameters()) return false;
273
274        // If there are no parameters (for either of them), then return true immediately
275        if (this.numParameters() == 0) return true;
276
277        // If any of the parameter-names are different, break immediately and return false;
278        for (int i=0; i < this.parameterNames.size(); i++)
279            if (! this.parameterNames.get(i).equals(other.parameterNames.get(i)))
280                return false;
281
282    
283        // If the parameter-types listed by the javadoc '.html' file differ from parameter-types
284        // listed in the original '.java' source-code file, then break immediately.
285        //
286        // NOTE: The "package-information" for the FULL CLASS OR INTERFACE NAME is not always
287        // available.
288
289        for (int i=0; i < this.parameterTypes.size(); i++)
290            if (! this.parameterTypesJOW.get(i).equals(other.parameterTypesJOW.get(i)))
291                return false;
292
293        // ALL TESTS PASSED
294        return true;
295    }
296
297
298    // ********************************************************************************************
299    // ********************************************************************************************
300    // A.I. Token-Stream Generator-Method
301    // ********************************************************************************************
302    // ********************************************************************************************
303
304
305    public ReadOnlyList<ReadOnlyList<String>> getTokenStreams()
306    {
307        final ROArrayListBuilder<ReadOnlyList<String>>  tokens  = new ROArrayListBuilder<>();
308        ROArrayListBuilder<String>                      b       = new ROArrayListBuilder<>();
309
310        tokens.add(ReadOnlyList.of("SECTION", "entity", "constructor"));
311        tokens.add(ReadOnlyList.of("SECTION", "signature", this.signature));
312
313        if ((this.parameterNames != null) && (this.parameterNames.size() > 0))
314        {
315            b.add("SECTION");
316            b.add("parameters");
317            for (int i = 0; i < this.parameterNames.size(); i++)
318                b.add(this.parameterTypesJOW.get(i) + " " + this.parameterNames.get(i));
319            tokens.add(b.build());
320        }
321
322        if ((this.modifiers != null) && (modifiers.size() > 0))
323        {
324            b = new ROArrayListBuilder<>();
325            b.add("SECTION");
326            b.add("modifiers");
327            for (String m : this.modifiers) b.add(m);
328            tokens.add(b.build());
329        }
330
331        if ((this.exceptions != null) && (this.exceptions.size() > 0))
332        {
333            b = new ROArrayListBuilder<>();
334            b.add("SECTION");
335            b.add("throws");
336            for (String exn : this.exceptions) b.add(exn);
337            tokens.add(b.build());
338        }
339
340        if ((this.annotations != null) && (annotations.size() > 0))
341        {
342            b = new ROArrayListBuilder<>();
343            b.add("SECTION");
344            b.add("annotations");
345            for (String a : this.annotations) b.add(a);
346            tokens.add(b.build());
347        }
348
349        return tokens.build();
350    }
351
352}