001package Torello.JavaDoc;
002
003
004// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
005// Standard-Java Imports
006// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
007
008import java.io.IOException;
009import java.util.List;
010import java.util.function.Consumer;
011import java.util.Optional;
012
013
014// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
015// Java-HTML Imports
016// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
017
018import Torello.Java.*;
019
020import static Torello.JavaDoc.PF.*;
021import static Torello.Java.C.*;
022
023import Torello.Java.Additional.Ret4;
024import Torello.Java.Function.IntTFunction;
025import Torello.Java.ReadOnly.ROArrayListBuilder;
026import Torello.Java.ReadOnly.ReadOnlyArrayList;
027import Torello.Java.ReadOnly.ReadOnlyList;
028
029
030// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
031// JDUInternal
032// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
033
034import Torello.JDUInternal.Annotations.EntityAnnotations.EntityAnnotationData;
035import Torello.JDUInternal.Parse.HTML.Signature.D1_CallableSignature;
036
037
038// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
039// The new Source-Code Parser: com.sun.source.*
040// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
041
042import com.sun.source.tree.*;
043
044
045/**
046 * <B CLASS=JDDescLabel>Reflection Class:</B>
047 * 
048 * <BR />Common-Root Ancestor Class of both {@link Method} and {@link Constructor}.
049 * 
050 * <BR /><BR />
051 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_CALLBL>
052 */
053@JDHeaderBackgroundImg
054public abstract class Callable extends Declaration implements java.io.Serializable
055{
056    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
057    public static final long serialVersionUID = 1;
058
059    // COMPLETELY UN-USED RIGHT NOW, EXPERIMENTAL-ONLY
060    public final String autoFindID;
061
062    @Override
063    String codeHiLiteString()
064    { return (this.body == null) ? null : StrIndent.chompCallableBraces(this.body); }
065
066
067    // ********************************************************************************************
068    // ********************************************************************************************
069    // protected final String[] parameterNames;
070    // ********************************************************************************************
071    // ********************************************************************************************
072
073
074    /**
075     * The names of all parameters to this {@code Method} or {@code Constructor}.
076     *  
077     * <BR /><BR /><B CLASS=JDDescLabel>Parallel List:</B>
078     * 
079     * <BR />This list must be considered a parallel list to the other parameter-related list:
080     * {@link #parameterTypes}, {@link #parameterTypesJOW} and {@link #parameterAnnotations}
081     */
082    public final ReadOnlyList<String> parameterNames;
083
084    /**
085     * This contains the types of the parameters, stored as {@code String's}.  The contents of
086     * these {@code String's} do include: <I>package-name, containing classes (if
087     * inner-classes), and generic-parameter expressions (if generic-types).</I>  These names are
088     * as fully-qualified as the AST Parser allows.
089     * 
090     * <BR /><BR /><B CLASS=JDDescLabel>JOW Alternative:</B>
091     * 
092     * <BR />The {@code ReadOnlyList} {@link #parameterTypesJOW} reduces these types (as
093     * {@code String's}) to a single-word.  If a {@link Method} or a {@link Constructor} that
094     * accepts a paremeter such as {@code java.util.Iterable<Integer>}, and it seems
095     * <I>'difficult to work with'</I> - the entry in {@link #parameterTypesJOW} at the
096     * same array-location would contain, simply, the Java {@code String 'Iterable'}.
097     * 
098     * <BR /><BR /><B CLASS=JDDescLabel>Parallel List:</B>
099     * 
100     * <BR />This list must be considered a parallel list to the other parameter-related list:
101     * {@link #parameterNames}, {@link #parameterTypesJOW} and {@link #parameterAnnotations}
102     */
103    public final ReadOnlyList<String> parameterTypes;
104
105    /**
106     * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_JOW_TITLE>
107     * 
108     * <BR /><BR /><B CLASS=JDDescLabel>Parallel List:</B>
109     * 
110     * <BR />This list must be considered a parallel list to the other parameter-related list:
111     * {@link #parameterNames}, {@link #parameterTypes} and {@link #parameterAnnotations}
112     */
113    public final ReadOnlyList<String> parameterTypesJOW;
114
115    /**
116     * Any parameters that are annotated will have the <I>exact text-{@code String} of the
117     * annotations that were used in the source-code for that parameter</I> stored in this
118     * two-dimensional {@code String[][]} array.
119     * 
120     * <BR /><BR />This list will retrieve and contain the actual character data that may be found
121     * in the source-code file for an element in a {@code com.sun.source} 'AST' (Abstract Syntax
122     * Tree).  The list of annotations on a parameter (if any) will each be saved as a
123     * {@code java.lang.String}.
124     * 
125     * <BR /><BR /><B CLASS=JDDescLabel>Null Warning:</B>
126     * 
127     * <BR />Unlike the other lists in class {@code Callable}, when there are no parameters for 
128     * a {@code Callabe}, or when there are parameters, but none of them have been annotated,
129     * <I>for the purposes of efficiency and better memory management, this field will simply be
130     * assigned null</I>.
131     * 
132     * <BR /><BR />In almost all cases (particularly in the Java HTML Library), this
133     * two-dimensional list, itself, really will be null - <I>since parameter annotations are
134     * quite uncommon</I>.  Perhaps, some users make use of them from time to time.
135     *  
136     * <BR /><BR /><B CLASS=JDDescLabel>Parallel List:</B>
137     * 
138     * <BR />This list must be considered a parallel list to the other parameter-related list:
139     * {@link #parameterNames}, {@link #parameterTypes} and {@link #parameterTypesJOW}
140     */
141    public final ReadOnlyList<ReadOnlyList<String>> parameterAnnotations;
142
143    /**
144     * The names of all {@code Exception, Error} and {@code Throwable} that may be thrown by this
145     * {@code Constructor} or {@code Method}.
146     * 
147     * <BR /><BR /><B STYLE='color: red;'>NOTE:</B> Only exceptions which are included in the
148     * actual {@link Declaration#signature}, inside the original {@code '.java'} source-file for
149     * this {@code Callable} will be listed in this array.
150     */
151    public final ReadOnlyList<String> exceptions;
152
153
154    // ********************************************************************************************
155    // ********************************************************************************************
156    // Quick Parameter Helper Methods
157    // ********************************************************************************************
158    // ********************************************************************************************
159
160
161    /**
162     * Retrieves the number of parameters utilized by the {@link Method} or {@link Constructor}
163     * ({@code Callable})
164     * 
165     * @return The size of all three of the parameter {@link ReadOnlyList}'s'
166     */
167    public int numParameters()
168    { return parameterNames.size(); }
169
170    /**
171     * This will retrieve the type of the parameter (as a {@code String}) that has the name
172     * {@code 'parameterName'}.  This method will simply return null, gracefully, if this
173     * {@link Method} or {@link Constructor} does not have a parameter with that name.  This method
174     * will not throw an exception in such cases.
175     * 
176     * @param parameterName The name of the parameter whose type you are requesting.
177     * 
178     * @return The fully-qualified type of the parameter, as a {@code String} having the name
179     * {@code 'parameterName'}, or null if no such type exists.
180     * 
181     * @see #parameterTypes
182     * @see #parameterNames
183     */
184    public String getParameterType(String parameterName)
185    {
186        for (int i=0; i < parameterNames.size(); i++)
187            if (parameterNames.get(i).equals(parameterName))
188                return parameterTypes.get(i);
189
190        return null;
191    }
192
193    /** 
194     * This will retrieve the type of the parameter (as a {@code String}) that has the name
195     * {@code 'parameterName'}.  This method will simply return null, gracefully, if this
196     * {@link Method} or {@link Constructor} does not have a parameter with that name.  This
197     * method will not throw an exception in such cases.
198     * 
199     * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_C_JOW_NOTE>
200     * 
201     * @param parameterName The name of the parameter whose type you are requesting.
202     * 
203     * @return The type of the parameter, as a <B>one-word {@code String}</B> having the name
204     * {@code 'parameterName'}.
205     * 
206     * @see #parameterTypesJOW
207     * @see #parameterTypes
208     * @see #parameterNames
209     */
210    public String getParameterTypeJOW(String parameterName)
211    {
212        if (parameterNames != null)
213            for (int i=0; i < parameterNames.size(); i++)
214                if (parameterNames.get(i).equals(parameterName))
215                    return parameterTypesJOW.get(i);
216
217        return null;
218    }
219
220    /**
221     * This will retrieve the annotations-list that may (or may not) adorn the parameter which uses
222     * the name {@code 'parameterName'}.
223     * 
224     * <BR /><BR />This method will simply return null, gracefully, if this {@link Method} or
225     * {@link Constructor} does not have a parameter with that name.  This method will not throw
226     * an exception in such cases.
227     * 
228     * <BR /><BR /><B>NOTE:</B>This method will also return null even if a parameter having the
229     * provided name is found, but that parameter wasn't annotated with anything.  If a null is
230     * returned, distinguishing between the case where {@code 'parameterName'} just wasn't found,
231     * and the case where that parameter wasn't annotated - isn't possible here.
232     * 
233     * @param parameterName The name of the parameter whose annotation-list you are requesting.
234     * 
235     * @return The type of the parameter having the name {@code 'parameterName'}.
236     * 
237     * @see #parameterAnnotations
238     * @see #parameterNames
239     */
240    public ReadOnlyList<String> getParameterAnnotations(String parameterName)
241    {
242        if (parameterAnnotations == null) return null;
243
244        for (int i=0; i < parameterNames.size(); i++)
245
246            if (parameterNames.get(i).equals(parameterName))
247                return parameterAnnotations.get(i);
248                    // In the line above, if a parameter isnt annotated, that location in the 
249                    // array will have a 'null'
250
251        return null;
252    }
253
254    /**
255     * This will look at each parmeter's annotation array to see if there are any parameters in
256     * this {@code Callable's} invocation parameter-list that were annotated with anything.
257     * 
258     * @return {@code TRUE} if there are any parameters that were annotated with something, and
259     * false if <B><I>every parameter</I></B> in the parameter-list had a 'null' {@code String}
260     * array of parameter-annotations.
261     * 
262     * <BR /><BR />If this instance of {@code Callable} is one which does not accept any
263     * parameters, this methhod will return {@code FALSE} immediately.
264     * 
265     * <BR /><BR /><B STYLE='color:red;'>NOTE:</B> The internal {@code 'parameterAnnotations'}
266     * field for class {@code Callable} is implemented as a two-dimensional {@code String}-array.
267     * There may be any number of parameters that are passed to a {@link Method} or
268     * {@code Constructor}, and each of those parameters may have any number of annotations that
269     * were attached to them.
270     * 
271     * <BR /><BR /><B>SANITY-CHECK</B> Likely {@code 99.99%} of the parameters in the Java HTML
272     * library do not have any parameter's that are annotated.
273     * 
274     * @see #parameterAnnotations
275     */
276    public boolean hasAnnotatedParameters()
277    { return parameterAnnotations != null; }
278
279    /**
280     * Reports how many of the parameters in the internal list of parameters that had annotations
281     * attached to them.
282     * 
283     * <BR /><BR /><B>SANITY-CHECK</B> Likely {@code 99.99%} of the parameters in the Java HTML
284     * library do not have any parameter's that are annotated.
285     * 
286     * @return This will count how many parameters which are used by this {@code Callable}
287     * (either {@link Method} or {@link Field}) that have annotations that were attached to
288     * the parameter.
289     * 
290     * @see #parameterAnnotations
291     */
292    public int numAnnotatedParameters()
293    {
294        int count = 0;
295
296        if (parameterAnnotations == null) return 0;
297
298        // NOTE: each parameter has an "Annotation List" stored in a 2-D array.  This is why
299        //       this for-loop is using 'String[]', rather than 'String' ...
300        //       A parameter may be annotated with zero annotations, one, or many annotations.
301
302        for (ReadOnlyList<String> paList : parameterAnnotations)
303            if (paList.size() > 0) count++;
304
305        return count;
306    }
307
308
309    // ********************************************************************************************
310    // ********************************************************************************************
311    // Constructor - com.sun.source.tree 
312    // ********************************************************************************************
313    // ********************************************************************************************
314
315
316    // package-private: Only used by subclasses.
317    Callable(
318            final MethodTree            methodOrConstructor,
319            final String                methodOrConstructorName,
320            final Entity                entity,
321            final EntityAnnotationData  ead,
322            final TreeUtils             util
323        )
324    {
325        super(
326            ead,                                // Stuff for building EntityAnnotationMirrors
327            util,                               // Big Ret4 thing
328            methodOrConstructor,                // com.sun.source.Tree.MethodTree instance
329            methodOrConstructor.getModifiers(), // Annotation **AND** public, static, final
330            methodOrConstructorName,            // Method-Name or "<init>"
331            entity,                             // Entity.METHOD or Entity.CONSTRUCTOR
332            methodOrConstructor.getBody()
333        );
334
335
336        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
337        // Callable Parameters
338        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
339
340        List<? extends VariableTree> pList = methodOrConstructor.getParameters();
341
342        if ((pList == null) || (pList.size() == 0))
343        {
344            this.parameterNames         =  EMPTY_READONLY_LIST;
345            this.parameterTypes         =  EMPTY_READONLY_LIST;
346            this.parameterTypesJOW      =  EMPTY_READONLY_LIST;
347            this.parameterAnnotations   =  null;
348        }
349
350        else 
351        {
352            int SIZE = pList.size();
353            boolean atLeastOneAnnotatedParameter = false;
354
355            // For efficiency, use the ROAL-Builder, because otherwise (using ReadOnlyArrayList
356            // constructor), the Iterator would have to be run 4 separate times.
357
358            ROArrayListBuilder<String> bParameterNames      = new ROArrayListBuilder<>(SIZE);
359            ROArrayListBuilder<String> bParameterTypes      = new ROArrayListBuilder<>(SIZE);
360            ROArrayListBuilder<String> bParameterTypesJOW   = new ROArrayListBuilder<>(SIZE);
361    
362            ROArrayListBuilder<ReadOnlyList<String>> bParameterAnnotations =
363                new ROArrayListBuilder<>();
364
365            for (VariableTree vt : pList)
366            {
367                bParameterNames.add(vt.getName().toString());
368
369                String type = vt.getType().toString();
370    
371                bParameterTypes.add(type);
372                bParameterTypesJOW.add(StrSource.typeToJavaIdentifier(type));
373
374                // NOTE: You **WILL TRY** again...  It cannot be done - a Var-Args Parameter is auto
375                // converted into an Array by com.sun.souce.tree.  There isn't a way to know that it
376                // was a Var-Args.  (Other than by parsing the JavaDocHTMLFile)
377                //
378                // System.out.println("    " + this.parameterTypes[i] + "  ==>  " +
379                //      this.parameterTypesJOW[i]);
380
381                // List<? extends AnnotationTree> annotList = ...
382                @SuppressWarnings("unchecked")
383                List<AnnotationTree> annotList = 
384                    (List<AnnotationTree>) vt.getModifiers().getAnnotations();
385
386                if ((annotList == null) || (annotList.size() == 0))
387                    bParameterAnnotations.add(null);
388                else
389                {
390                    atLeastOneAnnotatedParameter = true;
391
392                    bParameterAnnotations.add(
393                        new ReadOnlyArrayList<String>(
394                            annotList,
395                            (AnnotationTree at) -> at.toString().trim(),
396                            annotList.size()
397                        ));
398                }
399            }
400
401            this.parameterNames     =  bParameterNames.build();
402            this.parameterTypes     =  bParameterTypes.build();
403            this.parameterTypesJOW  =  bParameterTypesJOW.build();
404
405            this.parameterAnnotations = atLeastOneAnnotatedParameter
406                ? bParameterAnnotations.build()
407                : null;
408        }
409
410
411        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
412        // Throws Clauses Declared by this Callable
413        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
414
415        @SuppressWarnings("unchecked")
416        // List<? extends ExpressionTree> tl = ...
417        List<ExpressionTree> tl = (List<ExpressionTree>) methodOrConstructor.getThrows();
418
419        if ((tl == null) || (tl.size() == 0))
420            this.exceptions = EMPTY_READONLY_LIST;
421
422        else this.exceptions = new ReadOnlyArrayList<String>
423            (tl, (ExpressionTree et) -> et.toString().trim(), tl.size());
424
425
426        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
427        // FINISHED
428        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
429        //
430        // Currently Unused / Experimental
431        // this.autoFindID = AnnotationsMirror.processAutoFindID(annotations, signature);
432
433        this.autoFindID = "";
434    }
435
436
437    // ********************************************************************************************
438    // ********************************************************************************************
439    // Package-Private Constructor: Used Internally by 'JDUInternal.ParseHTML.SignatureParse'
440    // ********************************************************************************************
441    // ********************************************************************************************
442
443
444    // Ensures that the Version with longer type-information strings is used.
445    // Java Doc often uses longer type strings
446    //
447    // This cannot be public because this "Merge" expects that both of these constructors are
448    // identical - with the only noted difference being one was from JavaDoc and one was from the
449    // source-code.  The array-lengths need to be equal or else IndexOutOfBoundsException will
450    // start throwing.  Plus, this is not useful outside of the upgrade application.
451    //
452    // This "merging" of two instances of Callable is **ONLY NEEDED** for Methods and Constructors,
453    // **AND NOT** for Fields, Enum-Constants or Annotation-Elements.
454
455    Callable(final D1_CallableSignature cSig, final Callable cFromSourceParser)
456    {
457        // Calls the super 'clone' constructor for Declaration
458        // Java Parser has much more information for everything, except the "Parameter Types"
459        // JP elects to leave off the "Package Information" for types - while Java Doc includes
460        // it (**unless** it can provide an <A HREF=...> for the type, then it leaves it off too!)
461
462        super(cFromSourceParser);
463
464        this.parameterNames         = cFromSourceParser.parameterNames;
465        this.parameterTypesJOW      = cFromSourceParser.parameterTypesJOW;
466        this.exceptions             = cFromSourceParser.exceptions;
467        this.parameterAnnotations   = cFromSourceParser.parameterAnnotations;
468
469        // Currently Unused / Experimental
470        this.autoFindID = cFromSourceParser.autoFindID;
471
472        if (cFromSourceParser.parameterTypes.size() == 0)
473            this.parameterTypes = EMPTY_READONLY_LIST;
474
475        else
476        {
477            ROArrayListBuilder<String> roalb =
478                new ROArrayListBuilder<>(cFromSourceParser.parameterTypes.size());
479
480            // Java Doc always produces "java.lang.String", while JP just gives "String"
481            // REMEMBER: JP is lazy when it comes to "Package Information" for types.
482            //           Java-Doc includes it often - BUT NOT ALWAYS.  (See above comment)
483            // Remember, though, the rest of the JavaParser fields are filled out, Java Doc
484            // leaves out all the other information that JP retrieves.
485
486            for (int i=0; i < cFromSourceParser.parameterTypes.size(); i++)
487
488                roalb.add(
489                    (cSig.parameterTypes.get(i).length() >
490                        cFromSourceParser.parameterTypes.get(i).length())
491
492                        ? cSig.parameterTypes.get(i)
493                        : cFromSourceParser.parameterTypes.get(i)
494                );
495
496            this.parameterTypes = roalb.build();
497        }
498    }
499
500    Callable(final D1_CallableSignature cSig, final Entity entity)
501    {
502        super(cSig.name, entity, cSig.signature);
503
504        this.parameterNames         = cSig.parameterNames;
505        this.parameterTypes         = cSig.parameterTypes;
506        this.parameterTypesJOW      = cSig.parameterTypesJOW;
507        this.exceptions             = null;
508        this.autoFindID             = null;
509        this.parameterAnnotations   = null;
510    }
511
512
513    // ********************************************************************************************
514    // ********************************************************************************************
515    // NEW HELPER
516    // ********************************************************************************************
517    // ********************************************************************************************
518
519
520    /**
521     * An internally used utility that is accessed from outside this package.  This method allows a
522     * user to check whether {@code 'this'} method has an identical signature to the input instance
523     * of {@code 'D1_CallableSignature'}.
524     * 
525     * <BR /><BR />Because this Upgrader <B STYLE='cplor:red;'><I>does not </I></B> execute an
526     * actual Compiler Linking-Pass, only the <B STYLE='cplor:red;'><I>'JOW' (Just One
527     * Word)</I></B> of the input Parameter Types are checked.
528     * 
529     * @param cSig The Type Signature for any Method or Constructor.
530     * 
531     * @return {@code TRUE} if the Parameter-Names fpr {@code 'this'} Callable are all equal to the
532     * names in {@code 'cSig'} <B>AND</B> the "Just One Word" types match those in {@code 'cSig'}.
533     * 
534     * <BR /><BR />If either pf these two tests fail, then {@code FALSE} is returned.
535     */
536    public boolean nearlyEqualsCallableSig(D1_CallableSignature cSig)
537    {
538        // This works for Methods and Constructors.  This method used to be in the actual 'Method'
539        // and 'Constructor' sub-class due to this one-line optimization.  (This is an un-necessary
540        // check for Constructors, but not for methods).
541
542        if (this.numParameters() != cSig.parameterNames.size()) return false;
543
544        // If there are no parameters (for either of them), then return true immediately
545        if (this.numParameters() == 0) return true;
546
547        // If any of the parameter-names are different, break immediately and return false;
548        for (int i=0; i < this.parameterNames.size(); i++)
549            if (! this.parameterNames.get(i).equals(cSig.parameterNames.get(i)))
550                return false;
551
552        // If the parameter-types listed by the javadoc '.html' file differ from parameter-types
553        // listed in the original '.java' source-code file, then break immediately.
554        //
555        // NOTE: The "package-information" for the FULL CLASS OR INTERFACE NAME is not always
556        // available.
557
558        for (int i=0; i < this.parameterTypes.size(); i++)
559            if (! this.parameterTypesJOW.get(i).equals(cSig.parameterTypesJOW.get(i)))
560                return false;
561
562        // ALL TESTS PASSED
563        return true;
564    }
565
566
567    // ********************************************************************************************
568    // ********************************************************************************************
569    // HELPERS - toString(int flags)
570    // ********************************************************************************************
571    // ********************************************************************************************
572
573
574    String printedParamNames()
575    {
576        return
577            "Parameter Names:    " +
578            "[" + 
579                ((parameterNames != null)
580                    ? StrCSV.toCSV(parameterNames, true, true, null) : "") +
581            "]\n";
582    }
583
584    String printedParamTypes(Torello.Java.Additional.Ret2<Boolean, Boolean> jow)
585    {
586        boolean b = parameterTypesJOW == null;
587
588        if (jow.b /*onlyJOW*/) return
589            "Simple Param-Types: " +
590            "[" + 
591                (b ? "" : StrCSV.toCSV(parameterTypesJOW, true, true, null)) +
592            "]\n";
593
594        else if (jow.a /*addJOW*/) return
595            "Parameter Types:    " +
596            "[" + 
597                (b ? "" : StrCSV.toCSV(parameterTypes, true, true, null)) +
598            "]\n" +
599            "Simple Param-Types: " +
600            "[" +
601                (b ? "" : StrCSV.toCSV(parameterTypesJOW, true, true, null)) +
602            "]\n";
603
604        else return
605            "Parameter Types:    " +
606            "[" +
607                (b ? "" : StrCSV.toCSV(parameterTypes, true, true, null)) +
608            "]\n";
609    }
610
611    String printedExceptions()
612    {
613        return
614            "Exceptions:         " +
615            "[" +
616                ((exceptions == null) ? "" : StrCSV.toCSV(exceptions, true, true, null)) +
617            "]\n";
618    }
619
620    String printedCallableBody(int flags)
621    {
622        boolean methodBody      = (flags & BODY) > 0;
623        boolean shortMethodBody = (flags & BODY_SHORT) > 0;
624
625        // "shortMethodBody" has a higher FLAG-PRECEDENCE
626        if (methodBody && shortMethodBody) methodBody = false;
627
628        if ((! methodBody) && (! shortMethodBody)) return "";
629
630        String bodyStr = (this.body != null) ? codeHiLiteString() : "Not Defined";
631
632        // "Synthetic Methods" do not have a body.  Interface Methods also do not have one, either
633        // If this was built from the JavaDoc Signature, it will *ALSO* have no body...
634
635        if (shortMethodBody) bodyStr = StrPrint.abbrevEndRDSF(bodyStr, MAX_STR_LEN, true);
636
637        if (    shortMethodBody
638            ||  ((bodyStr.indexOf('\n') == -1) && (bodyStr.length() <= MAX_STR_LEN))
639        )
640            return "\nCallable Body:      [" + bodyStr + " ]";
641        else if (methodBody)
642            return "\nCallable Body:      [\n" + bodyStr + "\n]";
643        else
644            return "";   
645    }
646
647    /**
648     * Dummy Method.  Overriden by Concrete Sub-Classes.
649     * @see Method#toString()
650     * @see Constructor#toString()
651     */
652    public String toString()
653    { return "Callable is Abstract, all Concrete Sub-Classes Override this method."; }
654
655    /**
656     * Dummy Method.  Overriden by Concrete Sub-Classes.
657     * @see Method#toString(int)
658     * @see Constructor#toString(int)
659     */
660    public String toString(int flags)
661    { return "Callable is Abstract, all Concrete Sub-Classes Override this method."; }
662
663
664    // ********************************************************************************************
665    // ********************************************************************************************
666    // HELPERS - toString() - NO FLAGS
667    // ********************************************************************************************
668    // ********************************************************************************************
669
670
671    String printedParameterNamesTS()
672    {
673        return
674            "Parameter Names: [" + 
675                    ((parameterNames == null)
676                        ? ""
677                        : StrCSV.toCSV(parameterNames, true, true, null)
678                    ) + "]\n";
679    }
680
681    String printedParameterTypesTS()
682    {
683        return
684            "Parameter Types: [" +
685                    ((parameterTypesJOW == null)
686                        ? ""
687                        : StrCSV.toCSV(parameterTypesJOW, true, true, null)
688                    ) + "]\n";
689    }
690
691    String printedExceptionsTS()
692    {
693        return
694            "Exceptions:      [" +
695                ((exceptions == null)
696                    ? ""
697                    : StrCSV.toCSV(exceptions, true, true, null)
698                 ) + "]\n";
699    }
700}