001package Torello.JavaDoc;
002
003import Torello.HTML.*;
004import Torello.HTML.NodeSearch.*;
005import Torello.Java.*;
006
007import static Torello.Java.C.*;
008
009import java.util.*;
010
011import java.io.Serializable;
012
013import Torello.JDUInternal.GeneralPurpose.Messager;
014
015/**
016 * This class stores the HTML Detail-Descriptions retrieved from a Java Doc web-page 'Details
017 * Section', and simultaneously, holds the reflection-data extracted from the
018 * <CODE>'&#46;java'</CODE> corresponding source-code files - facilitating all changes to a Java
019 * Doc Page deemed necessary.
020 * 
021 * <EMBED CLASS='external-html' DATA-FILE-ID=PROG_MOD_HTML>
022 * <EMBED CLASS='external-html' DATA-FILE-ID=REFLHTML>
023 * 
024 * @param <ENTITY> This will take one of five type's: {@link Method}, {@link Constructor},
025 * {@link Field}, {@link EnumConstant}, or {@link AnnotationElem}.   The HTML contained by an
026 * instance of this class corresponds directly to the HTML contained by a detail section of one of
027 * one of these five Members / Entities.
028 */
029@JDHeaderBackgroundImg(EmbedTagFileID="REFLECTION_HTML_CLASS")
030@SuppressWarnings("rawtypes")
031public class ReflHTML<ENTITY extends Declaration>
032    implements java.io.Serializable, java.lang.Comparable<ReflHTML>
033{
034    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
035    protected static final long serialVersionUID = 1;
036
037
038    // ********************************************************************************************
039    // ********************************************************************************************
040    // HTML Processor's Special Access Stuff
041    // ********************************************************************************************
042    // ********************************************************************************************
043
044
045    /**
046     * This points to the opening {@code <UL>} tag for the detail.  It's contents may be modified
047     * to include CSS classes or id's.
048     */
049    public final TagNodeIndex openingUL;
050
051    private static final TagNode OPEN_DL    = HTMLTags.hasTag("dl", TC.OpeningTags);
052    private static final TagNode CLOSE_DL   = HTMLTags.hasTag("dl", TC.ClosingTags);
053
054    private Replaceable hiLitedCode = null;
055
056    private final boolean needToAddOpenCloseDLsForHiLitedDetails;
057
058    public void insertHiLitedDetail(Vector<HTMLNode> hiLitedDetail)
059    {
060        if (needToAddOpenCloseDLsForHiLitedDetails)
061        {
062            hiLitedDetail.insertElementAt(OPEN_DL, 0);
063            hiLitedDetail.add(CLOSE_DL);
064        }
065
066        this.hiLitedCode = this.hiLitedCode.setHTML(hiLitedDetail);
067    }
068
069
070    // ********************************************************************************************
071    // ********************************************************************************************
072    // Main Fields
073    // ********************************************************************************************
074    // ********************************************************************************************
075
076
077    /**
078     * This is the actual type-reflection (type-mirror) of the {@code Entity} extracted from the
079     * Java Doc {@code '.html'} web-page file, <I><B>and</B> from the </I> {@code '.java'} Source
080     * Code File.
081     * 
082     * <BR /><BR />Since the type-parameter {@code ENTITY} must extend {@link Declaration}, this
083     * field will hold all of the information that was parsed &amp; extracted by Java Parser.
084     * Depending on what type of instance of {@code Declaration} this represents, this will field
085     * will contain all of the parameter-names, parameter-types, modifiers, and exceptions that
086     * are associated with the entity.
087     * 
088     * <BR /><BR />This will take one of five type's: {@link Method}, {@link Constructor},
089     * {@link Field}, {@link EnumConstant}, {@link AnnotationElem}.  This allows you to retrieve
090     * all reflected information, quickly and easily, associated with the Java Doc HTML "Detail
091     * Section" for a particular method, field, constructor etc...
092     */
093    public final ENTITY entity;
094
095    /**
096     * This is used as a 'faster-way' to retrieve what type of Entity this "Reference-HTML" 
097     * detail-section is being represented here.  This makes the code more readable than using
098     * Java's {@code 'getClass()'} reflection to identify whether this 'Detail Section HTML' holds
099     * the HTML for a Method, Field, Constructor, Enumeration, etc...
100     * 
101     * <BR /><BR />The value in {@code 'entityAsEnum'} shall always be identical to the type of
102     * the {@link #entity}.  So for instance, if {@link #entity} contained a {@link Field} instance,
103     * this field would be equal to {@link Entity#FIELD}.  If this entity represented a
104     * {@link Method} HTML Detail-Section element, then this field would hold
105     * {@link Entity#METHOD}.
106     */
107    public final Entity entityAsEnum;
108
109    // The location in the parsed Java Doc '.html' web-page from whence this HTML was retrieved.
110    // This field is declared final.  The many sections, parts, and segments of a Java Doc
111    // generated page can have their contents added, abbreviated, and extended, but they cannot be
112    // moved to different places on the page.
113
114    private final DotPair location;
115
116    // This is used to insert two "wrapper dividers" - the HTML <DIV> Elements that "wrap" around
117    // the contents of a ReflHTML.  These wrapper DIV's (of which there are two) are need for the 
118    // maximize, minimize & partialize buttons.  Both of the two DIV's have **BOTH** a CSS-ID
119    // **AND** a CSS-CLASS that are used by two-line Java-Script methods that set the CSS "display"
120    // property to "block" and "none" (for hiding and showing these Refl's at the click of a
121    // button)
122
123    private final int endingLI;
124
125
126    // ********************************************************************************************
127    // ********************************************************************************************
128    // EVERYTHING ELSE
129    // ********************************************************************************************
130    // ********************************************************************************************
131
132
133    /**
134     * Each Deteail Entity on a JavaDoc Page has a <I>small and empty</I> Anchor-Link, <I>with an
135     * ID Attribute</I> that allows the browser to redirect to the detail on a JavaDoc page using
136     * a relative URL to redirect to the details location on the web-page.  If that detail element
137     * was found, it's will be stored in this field.  (Otherwise, this field will contain null)
138     * 
139     * <BR /><BR />Below is the <CODE>&lt;A ID=..&gt;</CODE> generated by Java Doc for a method
140     * that is named {@code 'length'}, and takes zero parameters as input.
141     * 
142     * <DIV CLASS=HTML>{@code
143     * <a id="length()">
144     * <!--   -->
145     * </a>
146     * }</DIV>
147     */
148    public final String htmlID;
149
150
151    // Every Detail-Element (Method, Field, Constructor, Enum-Constant and Annotation-Element)
152    // **MUST** have a name.  This should be a member field, instead of an entry in the
153    // TreeMap of 'possible' subsections
154
155    private final SubSection name;
156    private final SubSection signature;
157
158    // This Vector's contents are auto-inserted by the "NavButtons" class
159    private final Vector<HTMLNode> detailNavBar = new Vector<>();
160
161
162
163    // This is a TreeMap that will hold all of the 'optional' Detail-Elements.  Many of the
164    // entries in this TreeMap will be very common (at least as far as Java-HTML Type's goes),
165    // but *NONE* of them are 'mandatory' - Java Doc will not auto-create the detail-elements
166    // that are stored in this map.  They must be explicitly added by the user with taglets
167
168    private final TreeMap<Character, SubSection> subSections = new TreeMap<>();
169
170    // These are all of the keys that are used for the SubSections that will be stored inside
171    // this TreeMap
172
173    private static final Character DESCRIPTION_KEY          = 'a';
174    private static final Character ANNOTATION_DEFAULT_KEY   = 'b';
175    private static final Character RETURNS_KEY              = 'c';
176    private static final Character SEE_ALSO_KEY             = 'd';
177    private static final Character THROWS_KEY               = 'e';
178    private static final Character PARAMETERS_KEY           = 'f';
179    private static final Character TYPE_PARAMETERS_KEY      = 'g';
180    private static final Character OVERRIDES_KEY            = 'h';
181    private static final Character SPECIFIED_BY_KEY         = 'i';
182    private static final Character AUTHOR_KEY               = 'j';
183    private static final Character SINCE_KEY                = 'k';
184
185    // The other 'simpleTagLabels' just have their index and value saved, furthermore this
186    // array-list is only built if one is found/identified in the JavaDoc page.  99% of the
187    // types in JavaHTML do not have these...
188
189    private ArrayList<TagNodeIndex> miscSimpleTagLabels = null;
190
191    /**
192     * This boolean indicates that the HTML description provided by this JavaDoc Detail has
193     * been copied from an parent-class or from an interface.  In cases where an abstract method
194     * is implemented, the programmer may "opt-out" of typing anything about what the method's
195     * purpose is.  If so, JavaDoc automatically copies the abstract (or parent) method's
196     * description, and leaves a little note saying so.
197     * 
198     * <BR /><BR />Note that when this occurs, there will by two HTML {@code <DIV CLASS="block">}
199     * elements on the page for that detail.
200     */
201    public final boolean descFromTypeLabel;
202
203
204    // ********************************************************************************************
205    // ********************************************************************************************
206    // SubSection Accessor Methods
207    // ********************************************************************************************
208    // ********************************************************************************************
209
210
211    /**
212     * Returns an HTML-{@code Vector} of the HTML used to display the
213     * <B STYLE='color: red;'>name</B> of a detail element.
214     * 
215     * <BR /><BR />This also contains the same information as in the field
216     * {@link Declaration#name}, which is reflected (using <B>{@code Java Parer}</B>) from the
217     * associated {@code 'java'} source-code file.  The HTML for this segment is listed, here
218     * below:
219     * 
220     * <DIV CLASS=HTML>{@code
221     * <h4> [Name] </h4>
222     * }</DIV>
223     * 
224     * <EMBED CLASS='external-html' DATA-FILE-ID=REFL_MODIFY>
225     * 
226     * @return An HTML-{@code Vector} of the Java Doc <B STYLE='color: red;'>name</B>
227     * segment of this detail.  This method will never return null, as all detail-elements have
228     * a name.
229     * 
230     * @see Declaration#name
231     */
232    public Vector<HTMLNode> name() { return name.html; }
233
234    /**
235     * Returns an HTML-{@code Vector} of the HTML used to display the
236     * <B STYLE='color: red;'>signature</B> of a detail element.
237     * 
238     * <BR /><BR />This also contains the same information as in the field
239     * {@link Declaration#signature}, which is reflected (using <B>{@code Java Parer}</B>) from the
240     * associated {@code 'java'} source-code file.  In the HTML below it is the text that appears
241     * between the <CODE>&lt;PRE&gt;</CODE> tags.  Note that the HTML {@code 'class'} attribute
242     * (present, below) will not always be included in every detail element.
243     * 
244     * <DIV CLASS=HTML>{@code
245     * <h4> [Name] </h4>
246     * <pre class="Signature"> ... </pre>
247     * }</DIV>
248     * 
249     * <EMBED CLASS='external-html' DATA-FILE-ID=REFL_MODIFY>
250     * 
251     * @return An HTML-{@code Vector} of the Java Doc <B STYLE='color: red;'>signature</B>
252     * segment of this detail.  This method will never return null, as all detail-elements have
253     * a signature.
254     * 
255     * @see Declaration#signature
256     */
257    public Vector<HTMLNode> signature() { return signature.html; }
258
259    /**
260     * Returns an HTML-{@code Vector} of the HTML used to display the
261     * <B STYLE='color: red;'>description</B> of a detail element.
262     * 
263     * <BR /><BR />This HTML is generated by the Java Doc Tool using the text provided by a
264     * programmer in his Java Doc Comments directly above the code in a {@code '.java'} file.  In
265     * a Java Doc {@code '.html'} file, the description is always surrounded by an HTML divider
266     * ({@code '<DIV>'}) element, as appears below:
267     * 
268     * <DIV CLASS=HTML>{@code
269     * <div class="block"> ... [Text-Description of Method, Field, etc...] ... </div>
270     * }</DIV>
271     * 
272     * <EMBED CLASS='external-html' DATA-FILE-ID=REFL_MODIFY>
273     * 
274     * @return An HTML-{@code Vector} of the Java Doc <B STYLE='color: red;'>description</B>
275     * segment of this detail.  Since a description is not mandatory, and it is not an
276     * auto-generated segment of a detail element, <I>this method will return null if a programmer
277     * has not written or included a description for this particular detail element in his
278     * source-code for this detail element.</I>
279     * 
280     */
281    public final Vector<HTMLNode> description()
282    {
283        SubSection s = subSections.get(DESCRIPTION_KEY);
284        return (s!= null) ? s.html : null;
285    }
286
287    /**
288     * Returns an HTML-{@code Vector} of the HTML used to display the
289     * <B STYLE='color: red;'>Default Annotation Element Value</B> of an Annotation-Detail element.
290     * 
291     * <BR /><BR />This also contains the same information as in the field
292     * {@link AnnotationElem#defaultValue}, which is reflected (using <B>{@code Java Parer}</B>)
293     * from the associated {@code 'java'} source-code file.  The HTML for this segment is listed,
294     * here below:
295     * 
296     * <DIV CLASS=HTML>{@code
297     * <dl>
298     * <dt>Default:</dt>
299     * <dd> [ some values possibly inserted here ]</dd>
300     * </dl>
301     * }</DIV>
302     * 
303     * <EMBED CLASS='external-html' DATA-FILE-ID=REFL_MODIFY>
304     * 
305     * <BR /><BR />Unless this detail is an "Annotation Detail", calling this method will generate
306     * an exception-throw.
307     * 
308     * @return An HTML-{@code Vector} of an annotation detail element's
309     * <B STYLE='color: red;'>Default Value</B>.  If the annotation does not have a default value
310     * assigned, or it is not present on the Java Doc Page, this method will return null.
311     * 
312     * @throws DetailsException If the {@code ReflHTML} instance on which this method is being
313     * invoked is not for an Annotation Detail, the invocation will generate a
314     * {@code DetailsException}
315     * 
316     * @see AnnotationElem#defaultValue
317     */
318    public Vector<HTMLNode> annotationDefault()
319    {
320        if (entityAsEnum != Entity.ANNOTATION_ELEM)
321
322            throw new DetailsException(
323                "This ReflHTML is a Reflection of a(n) " + entityAsEnum.toString() + " details, " +
324                "however only Annotations may have Annotation-Element Default Values."
325            );
326
327        SubSection s = subSections.get(ANNOTATION_DEFAULT_KEY);
328        return (s!= null) ? s.html : null;
329    }
330
331    /**
332     * Returns an HTML-{@code Vector} of the HTML used to display the
333     * <B STYLE='color: red;'>Returns:</B> segment of a Method Detail element.
334     * 
335     * <BR /><BR />This also contains some of the information present in the field
336     * {@link Method#returnType}, which is reflected (using <B>{@code Java Parer}</B>) from the
337     * associated {@code 'java'} source-code file.
338     * 
339     * <BR /><BR />This HTML is auto-generated by Java Doc using the
340     * <B><CODE STYLE='color: blue;'>&commat;return</CODE></B> taglet's, which may be provided
341     * by a programmer in his {@code '.java'} source-code file.  The HTML output generated by Java
342     * Doc is as below:
343     * 
344     * <DIV CLASS=HTML>{@code
345     * <dt><span class="returnLabel">Returns:</span></dt>
346     * <dd> [User-Provided Return-Value Information, as HTML, Here] </dd>
347     * }</DIV>
348     * 
349     * <EMBED CLASS='external-html' DATA-FILE-ID=REFL_MODIFY>
350     * 
351     * <BR /><BR />Only methods may have return-values.  Furthermore, only methods for which the
352     * programmer has provided a <B><CODE STYLE='color: blue;'>&commat;return</CODE></B>
353     * taglet entry will the result of this method be non-null.
354     * 
355     * @return An HTML-{@code Vector} of a method detail element's
356     * <B STYLE='color: red;'>Returns:</B> label.  If the method does not have such a label,
357     * because the programmer did not provide a
358     * <B><CODE STYLE='color: blue;'>&commat;return</CODE></B> taglet, this method will
359     * return null.
360     * 
361     * @throws DetailsException If the {@code ReflHTML} instance on which this method is being
362     * invoked is not for an Method Detail, the invocation will generate a
363     * {@code DetailsException}
364     * 
365     * @see Method#returnType
366     */
367    public Vector<HTMLNode> returns()
368    {
369        if (entityAsEnum != Entity.METHOD)
370
371            throw new DetailsException(
372                "This ReflHTML is a Reflection of a(n) " + entityAsEnum.toString() + " details, " +
373                "however only Methods may have Return-Values."
374            );
375
376        SubSection s = subSections.get(RETURNS_KEY);
377        return (s!= null) ? s.html : null;
378    }
379
380    /**
381     * Returns an HTML-{@code Vector} of the HTML used to display the
382     * <B STYLE='color: red;'>See Also:</B> segment of any detail element.
383     * 
384     * <BR /><BR />This HTML is auto-generated by Java Doc using the
385     * <B><CODE STYLE='color: blue;'>&commat;see</CODE></B> taglet's, which may be provided
386     * by a programmer in his {@code '.java'} source-code file.  The HTML output generated by Java
387     * Doc is as below:
388     * 
389     * <DIV CLASS=HTML>{@code
390     * <dt><span class="seeLabel">See Also:</span></dt>
391     * <dd><a href="#someMethod()"><code>someMethod()</code></a></dd>
392     * }</DIV>
393     * 
394     * <EMBED CLASS='external-html' DATA-FILE-ID=REFL_MODIFY>
395     * 
396     * <BR /><BR />Only detail elements for which the programmer has provided at least one
397     * <B><CODE STYLE='color: blue;'>&commat;see</CODE></B> taglet entry will the result of
398     * this method be non-null.
399     * 
400     * @return An HTML-{@code Vector} of a method detail element's
401     * <B STYLE='color: red;'>See Also:</B> label.  If the method does not have such a label,
402     * because the programmer did not provide any
403     * <B><CODE STYLE='color: blue;'>&commat;see</CODE></B> taglet, this method will
404     * return null.
405     * 
406     */
407    public Vector<HTMLNode> seeAlso()
408    {
409        SubSection s = subSections.get(SEE_ALSO_KEY);
410        return (s!= null) ? s.html : null;
411    }
412
413    /**
414     * Returns an HTML-{@code Vector} of the HTML used to display the
415     * <B STYLE='color: red;'>Throws:</B> segment of a Method or Constructor Detail element.
416     * 
417     * <BR /><BR />This also contains some of the information present in the field
418     * {@link Callable#exceptions}, which is reflected (using <B>{@code Java Parer}</B>) from the
419     * associated {@code 'java'} source-code file.
420     * 
421     * <BR /><BR />This HTML is auto-generated by Java Doc using the
422     * <B><CODE STYLE='color: blue;'>&commat;throws</CODE></B> taglet's, which may be provided
423     * by a programmer in his {@code '.java'} source-code file.  If a method or constructor is
424     * throwing <I>checked exceptions</I>, Java Doc will auto-create a 'Throws:' label / segment.
425     * The HTML output generated by Java Doc is as below:
426     * 
427     * <DIV CLASS=HTML>{@code
428     * <dt><span class="throwsLabel">Throws:</span></dt>
429     * <dd> [Text explaining thrown exceptions by a method or constructor]</dd>
430     * }</DIV>
431     * 
432     * <EMBED CLASS='external-html' DATA-FILE-ID=REFL_MODIFY>
433     * 
434     * <BR /><BR />Only methods and constructors are capable of throwing exceptions.  Furthermore,
435     * only details for which the programmer has provided a
436     * <B><CODE STYLE='color: blue;'>&commat;throws</CODE></B> taglet entry (or which throw
437     * checked-exceptions) will the result of this method be non-null.
438     * 
439     * @return An HTML-{@code Vector} of a method or constructor detail element's
440     * <B STYLE='color: red;'>Throws:</B> label.  If the detail does not have such a label, this
441     * method will return null.
442     * 
443     * @throws DetailsException If the {@code ReflHTML} instance on which this method is being
444     * invoked is <I><B>neither</B></I> a Method Detail <B><I>nor</I></B> a Constructor Detail, the
445     * invocation will generate a {@code DetailsException}
446     * 
447     * @see Callable#exceptions
448     */
449    public Vector<HTMLNode> throwing()
450    {
451        if ((entityAsEnum != Entity.METHOD) && (entityAsEnum != Entity.CONSTRUCTOR))
452
453            throw new DetailsException(
454                "This ReflHTML is a Reflection of a(n) " + entityAsEnum.toString() + " details, " +
455                "however only Methods and Constructors may throw Exceptions."
456            );
457
458        SubSection s = subSections.get(THROWS_KEY);
459        return (s!= null) ? s.html : null;
460    }
461
462    /**
463     * Returns an HTML-{@code Vector} of the HTML used to display the
464     * <B STYLE='color: red;'>Parmeters:</B> segment of a Method or Constructor Detail element.
465     * 
466     * <BR /><BR />This also contains some of the information present in the fields
467     * {@link Callable#parameterNames} and {@link Callable#parameterTypes}, which is reflected
468     * (using <B>{@code Java Parer}</B>) from the associated {@code 'java'} source-code file.
469     * 
470     * <BR /><BR />This HTML is auto-generated by Java Doc using the
471     * <B><CODE STYLE='color: blue;'>&commat;param</CODE></B> taglet's, which may be provided
472     * by a programmer in his {@code '.java'} source-code file.  The HTML output generated by Java
473     * Doc is as below:
474     * 
475     * <DIV CLASS=HTML>{@code
476     * <dt><span class="paramLabel">Parameters:</span></dt>
477     * <dd><code>[Parameter Name]</code> - [Some Parameter Description]</dd>
478     * }</DIV>
479     * 
480     * <EMBED CLASS='external-html' DATA-FILE-ID=REFL_MODIFY>
481     * 
482     * <BR /><BR />Only methods and constructors may accept input parameters.  Furthermore,
483     * only details for which the programmer has provided a
484     * <B><CODE STYLE='color: blue;'>&commat;param</CODE></B> taglet entry will there be 
485     * parameter descriptive-text on a Java Doc Page. The result of this method will be non-null,
486     * only in cases where such descriptions have been included in their JavaDoc commenting.
487     * 
488     * @return An HTML-{@code Vector} of a method or constructor detail element's
489     * <B STYLE='color: red;'>Parameters:</B> label.  If the detail does not have such a label,
490     * this method will return null.
491     * 
492     * @throws DetailsException If the {@code ReflHTML} instance on which this method is being
493     * invoked is <I><B>neither</B></I> a Method Detail <B><I>nor</I></B> a Constructor Detail, the
494     * invocation will generate a {@code DetailsException}
495     * 
496     * @see Callable#parameterNames
497     * @see Callable#parameterTypes
498     */
499    public Vector<HTMLNode> parameters()
500    {
501        if ((entityAsEnum != Entity.METHOD) && (entityAsEnum != Entity.CONSTRUCTOR))
502
503            throw new DetailsException(
504                "This ReflHTML is a Reflection of a " + entityAsEnum.toString() + " details, " +
505                "however only Methods and Constructors may have Parameters."
506            );
507
508        SubSection s = subSections.get(PARAMETERS_KEY);
509        return (s!= null) ? s.html : null;
510    }
511
512    /**
513     * Returns an HTML-{@code Vector} of the HTML used to display the
514     * <B STYLE='color: red;'>Type Parmeters:</B> segment of a Method or Constructor Detail
515     * element.
516     * 
517     * <BR /><BR />This HTML is auto-generated by Java Doc using the
518     * <B><CODE STYLE='color: blue;'>&commat;param</CODE> <CODE>&lt;T&gt;</CODE></B> taglet's,
519     * which may be provided by a programmer in his {@code '.java'} source-code file.  The HTML
520     * output generated by Java Doc is as below:
521     * 
522     * <DIV CLASS=HTML>{@code
523     * <dt><span class="paramLabel">Type Parameters:</span></dt>
524     * <dd><code>[Type Parameter <T>]</code> - [Some Type Parameter Description]</dd>
525     * }</DIV>
526     * 
527     * <EMBED CLASS='external-html' DATA-FILE-ID=REFL_MODIFY>
528     * 
529     * <BR /><BR />Only methods and constructors will allow type-parameters.  Furthermore,
530     * only details for which the programmer has provided a
531     * <B><CODE STYLE='color: blue;'>&commat;param</CODE> <CODE>&lt;T&gt;</CODE></B> taglet
532     * entry will there be parameter descriptive-text on a Java Doc Page. The result of this method
533     * will be non-null, only in cases where such descriptions have been included in their
534     * JavaDoc commenting.
535     * 
536     * @return An HTML-{@code Vector} of a method or constructor detail element's
537     * <B STYLE='color: red;'>Type Parameters:</B> label.  If the detail does not have such a
538     * label, this method will return null.
539     * 
540     * @throws DetailsException If the {@code ReflHTML} instance on which this method is being
541     * invoked is <I><B>neither</B></I> a Method Detail <B><I>nor</I></B> a Constructor Detail, the
542     * invocation will generate a {@code DetailsException}
543     */
544    public Vector<HTMLNode> typeParameters()
545    {
546        if ((entityAsEnum != Entity.METHOD) && (entityAsEnum != Entity.CONSTRUCTOR))
547
548            throw new DetailsException(
549                "This ReflHTML is a Reflection of a(n) " + entityAsEnum.toString() + " details, " +
550                "however only Methods and Constructors may have Type-Parameters."
551            );
552
553        SubSection s = subSections.get(TYPE_PARAMETERS_KEY);
554        return (s!= null) ? s.html : null;
555    }
556
557    /**
558     * Returns an HTML-{@code Vector} of the HTML used to display the
559     * <B STYLE='color: red;'>Overrides:</B> segment of a Method Detail element.
560     * 
561     * <BR /><BR />This HTML is auto-generated by Java Doc, for methods which override a parent
562     * class or interface. The HTML output generated by Java Doc is as below:
563     * 
564     * <DIV CLASS=HTML>{@code
565     * <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
566     * <dd><code> [ Some Name ]</code>&nbsp;in interface&nbsp;<code> [Interface Name] </code></dd>
567     * }</DIV>
568     * 
569     * <EMBED CLASS='external-html' DATA-FILE-ID=REFL_MODIFY>
570     * 
571     * <BR /><BR />Only methods may override other methods.  The result of this method will
572     * be non-null, only in cases where the Method Detail on which this invocation was made is
573     * actually an overrided method.
574     * 
575     * @return An HTML-{@code Vector} of a method detail element's
576     * <B STYLE='color: red;'>Overrides:</B> label.  If the detail does not have such a label, this
577     * method will return null.
578     * 
579     * @throws DetailsException If the {@code ReflHTML} detail instance on which this method is
580     * being invoked is not a Method Detail, then a {@code DetailsException} will throw.
581     */
582    public Vector<HTMLNode> overrides()
583    {
584        if (entityAsEnum != Entity.METHOD)
585
586            throw new DetailsException(
587                "This ReflHTML is a Reflection of a(n) " + entityAsEnum.toString() + " details, " +
588                "however only Methods may have \"Overrides:\" Labels."
589            );
590
591        SubSection s = subSections.get(OVERRIDES_KEY);
592        return (s!= null) ? s.html : null;
593    }
594
595    /**
596     * Returns an HTML-{@code Vector} of the HTML used to display the
597     * <B STYLE='color: red;'>Specified by:</B> segment of a Method Detail element.
598     * 
599     * <BR /><BR />This HTML is auto-generated by Java Doc, for methods which implement another
600     * method that was specified by an interface which the type implements, or a method specified
601     * by an abstract parent super-class.  The HTML output generated by Java Doc is as below:
602     * 
603     * <DIV CLASS=HTML>{@code
604     * <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
605     * <dd><code> [ Some Name ]</code>&nbsp;in interface&nbsp;<code> [Interface Name] </code></dd>
606     * }</DIV>
607     * 
608     * <EMBED CLASS='external-html' DATA-FILE-ID=REFL_MODIFY>
609     * 
610     * <BR /><BR />Only methods may implement a "specified-method" (obviously!)  The result of this
611     * method will be non-null - only in cases where the Method Detail on which this invocation was
612     * made <I>actually implements another abstract method declaration.</I>
613     * 
614     * @return An HTML-{@code Vector} of a method detail element's
615     * <B STYLE='color: red;'>Specified by:</B> label.  If the detail does not have such a label,
616     * this method will return null.
617     * 
618     * @throws DetailsException If the {@code ReflHTML} detail instance on which this method is
619     * being invoked is not a Method Detail, then a {@code DetailsException} will throw.
620     */
621    public Vector<HTMLNode> specifiedBy()
622    {
623        if (entityAsEnum != Entity.METHOD)
624
625            throw new DetailsException(
626                "This ReflHTML is a Reflection of a(n) " + entityAsEnum.toString() + " details, " +
627                "however only Methods may have \"Specified-By:\" Labels."
628            );
629
630        SubSection s = subSections.get(SPECIFIED_BY_KEY);
631        return (s!= null) ? s.html : null;
632    }
633
634    /** This will be implented at a later date.  For now, this throws an exception. */
635    public Vector<HTMLNode> author()
636    {
637        if (1 == 1) throw new Torello.Java.ToDoException("Not Tested Yet");
638
639        SubSection s = subSections.get(AUTHOR_KEY);
640        return (s!= null) ? s.html : null;
641    }
642
643    /**
644     * Returns an HTML-{@code Vector} of the HTML used to display the
645     * <B STYLE='color: red;'>Specified by:</B> segment of a Method Detail element.  
646     *  
647     * <DIV CLASS=HTML>{@code
648     * <dt><span class="simpleTagLabel">Since:</span></dt>
649     * <dd> [ Version Number Information ]</dd>
650     * }</DIV>
651     * 
652     * <EMBED CLASS='external-html' DATA-FILE-ID=REFL_MODIFY>
653     * 
654     * <BR /><BR />Only details for which the programmer has provided a
655     * <B><CODE STYLE='color: blue;'>&commat;since</CODE></B> taglet entry will there be 'since'
656     * descriptive-text on a Java Doc Page. The result of this method will be non-null, only in
657     * cases where such version-information has been included in their JavaDoc commenting.
658     * 
659     * @return An HTML-{@code Vector} of a method detail element's
660     * <B STYLE='color: red;'>Since:</B> label.  If the detail does not have such a label, this
661     * method will return null. 
662     */
663    public Vector<HTMLNode> since()
664    {
665        SubSection s = subSections.get(SINCE_KEY);
666        return (s!= null) ? s.html : null;
667    }
668
669    /**
670     * Returns an HTML-{@code Vector} of the HTML used to display the
671     * <B STYLE='color: red;'>Navigation Button-Bar</B> of a detail element.
672     * 
673     * <BR /><BR />This is a row of buttons that is present directly below the signature of an
674     * HTML Detail-Entry.  This row of buttons is automatically generated by the Java-Doc Upgrader
675     * Tool.  It isn't Standard JavaDoc HTML.
676     * 
677     * <BR /><BR />The actual HTML inserted by the Upgrader-Tool is included directly below:
678     * 
679     * <DIV CLASS=HTML>{@code
680     * <DIV CLASS=DetailNav>
681     *      <A HREF='#openTagPWA()'>&#129093;</A>
682     *      &nbsp;<A HREF='#isOpenTagPWA()'>&#129095;</A>
683     *      &nbsp;<A onclick="flashSumm('MD244')">&#8648;</A>
684     *      &nbsp;<A HREF='hilite-files/HTMLNode.java.html#L273'>&#11179;</A>
685     *      <SPAN>
686     *          <A onclick='minimize(244)'>&#x1F5D5;</A>
687     *          &nbsp;<A onclick='partialize(244)'>&#x1F5D7;</A>
688     *          &nbsp;<A onclick='maximize(244)'>&#x1F5D6;</A>
689     *      </SPAN>
690     *      <NOSCRIPT>
691     *      <DIV ID=NoScriptMPMAB>JavaScript is disabled on your browser.</DIV>
692     *      </NOSCRIPT>
693     * </DIV>
694     * }</DIV>
695     * 
696     * <EMBED CLASS='external-html' DATA-FILE-ID=REFL_MODIFY>
697     * 
698     * @return An HTML-{@code Vector} of the Java Doc
699     * <B STYLE='color: red;'>Navigation Button-Bar</B> segment of this detail.  This method will
700     * never return null, as all detail-elements have these buttons.
701     */
702    public Vector<HTMLNode> detailNavBar()
703    { return detailNavBar; }
704
705
706    // ********************************************************************************************
707    // ********************************************************************************************
708    // Constructor
709    // ********************************************************************************************
710    // ********************************************************************************************
711
712
713    private String detErrMsg(Vector<HTMLNode> html, DotPair location)
714    {
715        String htmlStr = Util.rangeToString(html, location);
716        return StrPrint.abbrevEnd(htmlStr, false, 300);
717    }
718
719    /**
720     * Constructs an instance of this class.
721     * 
722     * @param entity This identifies which "Entity-Type" from which the HTML provided was derived.
723     * If the HTML-{@code Vector} passed to this constructor were taken from a "Method Detail" part
724     * of a Java Doc Web-Page, then this parameter would be passed {@code Entity.METHOD}
725     * 
726     * @param location The exact location on the Java Doc Web-Page from whence the HTML was
727     * extracted.  It is important to note that this class facilitates changes, additions, and
728     * removal of HTML tags to a specific Detail-Segment of a CIET <B>"Details Section"</B>.
729     * 
730     * <BR /><BR />After the changes have been made, and all other HTML processors in this package
731     * have completed their updates, this HTML will need to replace the old-stuff in the page
732     * {@code Vector}.  Keeping this location around makes this a simple replacement that has been
733     * optimized.
734     * 
735     * <BR /><BR />Note that changing nodes in a {@code Vector<HTMLNode>}) can become profusely
736     * in-efficient <I>if those changes are done in-place!</I>  By extracting small portions of
737     * the HTML-Vector, and only modifying small parts (all the while saving the original location
738     * of the HTMl) modifying HTML can be quickly and efficiently - <I>even when not using DOM
739     * Tree like data-structures.</I>
740     * 
741     * @param entityAsEnum If it is necessary to ask whether this "Reference HTML SubSection"
742     * is an HTML sub-section for a Method, Field or Constructor etc...  Rather than using the
743     * {@code getClass()} on field {@code entity}, you may use this Enumeration, instead.
744     * 
745     * @param html The HTML of a Java Doc detail-section
746     * 
747     * @throws IllegalArgumentException If the parameter {@code 'entity'} and
748     * {@code 'entityAsEnum'} do not reference the same type of detail-section.  This is a quick
749     * check that isn't costly.  In the HTML file processors of this package, this won't ever be
750     * thrown.
751     */
752
753    // The ReflHTML-Constructor: is only called from JavaDocHTMLFile
754    // USES: Messager.assertFailHTML() (JavaDocHTMLParseException)
755
756    ReflHTML(
757            ENTITY              entity,
758            DotPair             location,
759            Vector<HTMLNode>    html,
760            Entity              entityAsEnum,
761            String              htmlID,
762            String              srcAsHTMLFileURL
763        )
764    {
765        this.entity         = entity;
766        this.location       = location;
767        this.entityAsEnum   = entityAsEnum;
768        this.htmlID         = htmlID;
769
770        // This will never happen.  ReflHTML's are constructed properly in JavaDocHTMLFile.
771        // This switch statement is practically-free, so, this prevents possible errors later on.
772
773        switch (entityAsEnum)
774        {
775            case METHOD:            if (! (entity instanceof Method))
776                                        throw ENTITY_MATCH(entity, entityAsEnum);
777                                    break;
778
779            case FIELD:             if (! (entity instanceof Field))
780                                        throw ENTITY_MATCH(entity, entityAsEnum);
781                                    break;
782
783            case CONSTRUCTOR:       if (! (entity instanceof Constructor))
784                                        throw ENTITY_MATCH(entity, entityAsEnum);
785                                    break;
786
787            case ENUM_CONSTANT:     if (! (entity instanceof EnumConstant))
788                                        throw ENTITY_MATCH(entity, entityAsEnum);
789                                    break;
790
791            case ANNOTATION_ELEM:   if (! (entity instanceof AnnotationElem))
792                                        throw ENTITY_MATCH(entity, entityAsEnum);
793                                    break;
794        }
795
796
797        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
798        // This is used over and over again, in every Messager.assertFailHTML
799        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
800
801        final String sig = this.entity.signature; // Makes for easier typing
802
803
804        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
805        // Partialize, Maximize & Minimize Buttons: "Wrapper <DIV>'s" location/placement
806        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
807
808        this.endingLI = TagNodeFind.last(html, location.start, location.end, TC.ClosingTags, "LI");
809
810        if (this.endingLI == -1) Messager.assertFailHTML
811            ("There was no closing HTML <LI> Element in this Refl-Detail", sig);
812
813
814        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
815        // Convenience Method's & Constructor's add a CSS Class to the first <UL>
816        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
817
818        TagNode tn = html.elementAt(location.start).ifTagNode();
819
820        if (tn == null) Messager.assertFailHTML(
821            "The first node in this detail is not a <UL>:\n" + detErrMsg(html, location),
822            sig
823        );
824
825        this.openingUL = new TagNodeIndex(location.start, tn);
826
827
828        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
829        // HiLitedDetails needs an insertion-point
830        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
831
832        // There is a <DL>...</DL> (HTML Definitions List) that Java Doc uses.  There should be one
833        // at the end of the Detail-Section, which is where the HiLited Detail is placed.  If a
834        // closing </DL> is not found, then an opening and closing <DL> ... </DL> needs to created
835        // and inserted at the end
836        // 
837        // REMEMBER: 'hiLitedDetail' is wrapped in a <DD>...</DD><DT>...</DT>
838
839        int insertionPoint = TagNodeFind.last
840            (html, location.start, location.end, TC.ClosingTags, "dl");
841
842        this.needToAddOpenCloseDLsForHiLitedDetails = insertionPoint == -1;
843
844        // If a </DL> wasn't found, a new <DL> (Definition List), needs to be built.  Also a new
845        // insertion point is needed.  The details section ends with a closing '</LI>' element,
846        // which is where to insert the new <DL>...</DL>
847        //
848        // NOTE: **FIELDS** are the Detail-Elements that usually do not have a <DL>...</DL>, because
849        //       there aren't many <SPAN> Label-Banners present in a field
850
851        if (insertionPoint == -1)
852        {
853            insertionPoint = TagNodeFind.last
854                (html, location.start, location.end, TC.ClosingTags, "li");
855
856            if (insertionPoint == -1) Messager.assertFailHTML
857                ("There is a detail with no ending </DL> and no ending </LI>", sig);
858        }
859
860        this.hiLitedCode = Replaceable.empty(insertionPoint);
861
862
863        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
864        // Mandatory HTML Fields: name & signature
865        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
866
867        // One precaution is that this <H4> must be among the first 8 nodes in the sub-page,
868        // Except for Annotation Elements, which have several HTML Nodes at the start of the detail
869
870        this.name = TagNodePeekInclusive.first(
871            html, location.start,
872            ((this.entityAsEnum == Entity.ANNOTATION_ELEM) ? location.end : (location.start + 8)),
873            "h4"
874        );
875
876        if (this.name == null)
877
878            Messager.assertFailHTML(
879                "There was no name <H4> found in the detail:\n" +
880                // StrIndent.indent(Util.pageToString(html), 4),
881                detErrMsg(html, location),
882                sig
883            );
884
885        int sPos = this.name.location.end + 1;
886
887        // Here, it is required that the <PRE> have a class that has the word "Signature"
888        // Unfortunately, javadoc doesn't always insert the class...
889
890        this.signature = TagNodePeekInclusive.first(html, sPos, location.end, "pre");
891
892        if (this.signature == null)
893
894            Messager.assertFailHTML(
895                "There was no signature <PRE> found in the detail:\n" +
896                // StrIndent.indent(Util.pageToString(html), 4),
897                detErrMsg(html, location),
898                sig
899            );
900
901
902        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
903        // UPDATE "/src-html/" URL FOR INNER-CLASSES
904        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
905        //
906        // This may seem **TOTALLY AND COMPLETELY** out of place, but this minor clean-up is going
907        // to be done, **RIGHT HERE**, in the Refl...
908        //
909        // When applied to the Java-HTML JAR, this saves 100 MB of Java-Doc Files...
910        //
911        // NOTE: The check for whether this is done is done inside the calling class - which 
912        //       happens to be JavaDocHTMLFIle.  If this URL-HREF replacement DOES-NOT need to
913        //       happen, then the URL 'srcAsHTMLFileURL' will be null.
914        //
915        // If this "ReflHTML" instance is a emmber of a Nested-Type / Inner-Type, then and only
916        // then should this be needed...
917
918        if (srcAsHTMLFileURL != null)
919        {
920            TagNodeIndex tni = InnerTagPeek.first
921                (signature.html, "a", "href", href -> href.contains("/src-html/"));
922
923            if (tni == null) Messager.assertFailGeneralPurpose(
924                "Could not locate the link to the /src-html/ file, but srcAsHTMLFileURL " +
925                '[' + srcAsHTMLFileURL + "] exists",
926                sig
927            );
928
929            String href = srcAsHTMLFileURL;
930
931            if (entity.location != null) href += "#line." + ((entity.location.jdcStartLine == -1)
932                ? entity.location.signatureStartLine
933                : entity.location.jdcStartLine);
934
935            signature.html.setElementAt(tni.n.setAV("HREF", href, SD.SingleQuotes), tni.index);
936        }
937
938
939        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
940        // Description HTML Field, it is not Mandatory
941        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
942
943        sPos = this.signature.location.end + 1;
944
945        SubSection subSection = InnerTagPeekInclusive.first
946            (html, sPos, location.end, "div", "class", TextComparitor.C, "block");
947
948        if (subSection != null)
949        {
950            // JavaDoc Inserts a cute little note whenever a method overrides another method
951            // stating that the description has been copied from the overriden method.  Afterwards,
952            // **A SECOND DIV IS INSERTED** that contains the text of the description from the
953            // method that is being overriden.  This only occurs when the method that is doing the
954            // overriding (the method from 'this' ReflHTML) - does not contain any description-text
955            //
956            // When this happens, just insert **BOTH** <DIV> Elements into the Vector
957
958            /*
959            // Somewhat inefficient.  This code is executed 10,000 times - for each and
960            // every detail element on each and every JavaDoc Page
961
962            int copiedPos = InnerTagFind.first(
963                html, subSection.location.start + 1, subSection.location.end,
964                "span", "class", TextComparitor.C, "descfrmTypeLabel"
965            );
966            */
967            String classStr;
968
969            if (
970                    // Much faster short-circuit boolean-evaluation
971                    ((tn = html.elementAt(subSection.location.start + 1).ifTagNode()) != null)
972                &&  tn.tok.equals("span")
973                &&  ((classStr = tn.AV("class")) != null)
974                &&  classStr.equals("descfrmTypeLabel")
975            )
976            // if (copiedPos != -1)
977            {
978                // This part of the loop is almost never executed (unless the class) was
979                // actually found.  Out of 10,000 Details there are probably 20 methods like
980                // this.
981
982                this.descFromTypeLabel = true;
983
984                // Make sure to skip the text</SPAN></DIV>
985                SubSection ssCopied = InnerTagPeekInclusive.first(
986                    html, subSection.location.start + 4, location.end,
987                    "div", "class", TextComparitor.C, "block"
988                );
989
990                if (ssCopied == null) Messager.assertFailHTML(
991                    "A <SPAN CLASS=descfrmTypeLabel> Label was Found, but there was not a " +
992                    "second <DIV CLASS=\"block\">:\n" +
993                    detErrMsg(html, location),
994                    sig
995                );
996
997                /*
998                System.out.println(
999                    "\n=====================================================" +
1000                    "\ncopiedPos: "     + copiedPos +
1001                    "\nlocation.end: "  + location.end +
1002                    "\n\nSubSection: "  + subSection.toString() +
1003                    "\nLocation: "      + subSection.location.toString() +
1004                    "\n\nssCopied: "    + ssCopied.toString() +
1005                    "\nLocation: "      + ssCopied.location.toString() +
1006                    "\n=====================================================" 
1007                );
1008                */
1009
1010                subSection = new SubSection(
1011                    new DotPair(subSection.location.start, ssCopied.location.end),
1012                    Util.cloneRange(html, subSection.location.start, ssCopied.location.end + 1)
1013                );
1014            }
1015            else this.descFromTypeLabel = false;
1016
1017            // For whichever of the two cases that has occured, just insert the HTML into the table
1018            sPos = subSection.location.end + 1;
1019            subSections.put(DESCRIPTION_KEY, subSection);
1020        }
1021        else this.descFromTypeLabel = false;
1022
1023
1024        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1025        // Annotations Have this little "Default" thing
1026        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1027        //
1028        // <dt><SPAN CLASS=C21>Default:</SPAN></dt>
1029        // <dd>{}</dd>
1030
1031        // NOTE: This is 'temp' variable that is reused over and over in this method
1032        DotPair dp = TagNodeFindInclusive.first(html, sPos, -1, "dl");
1033
1034        if (dp != null)
1035        {
1036            int defPos = TextNodeFind.first
1037                (html, dp.start, dp.end, s -> s.equals("Default:"));
1038
1039            if (defPos != -1)
1040            {
1041                dp = Surrounding.first(html, defPos, "dt");
1042                subSections.put
1043                    (ANNOTATION_DEFAULT_KEY, new SubSection(dp, Util.cloneRange(html, dp)));
1044            }
1045        }
1046
1047
1048        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1049        // <DL> Labels: <DT><SPAN CLASS="someLabel">Some Label</SPAN></DT><DD>...</DD> Fields.  
1050        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1051
1052        final String[] spanClasses = {
1053            "paramLabel", "returnLabel", "seeLabel", "throwsLabel", "overrideSpecifyLabel",
1054            "simpleTagLabel"
1055        };
1056
1057        int[] spans = InnerTagFind.all
1058            (html, sPos, location.end, "span", "class", TextComparitor.EQ, spanClasses);
1059
1060        for (int spanPos : spans)
1061        {
1062            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1063            // Build the 'location' (DotPair) of the HTML that "surrounds" the SPAN (DT/DD's)
1064            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1065            //
1066            //  <DT><SPAN CLASS='someLabel'>Some Label</SPAN></DT>
1067            //  <DD> Some User Code Information </DD>
1068            //  <DD> For Parameters & Throws, there are multiple DD's </DD>
1069
1070            // First ensure that there is an opening <DT> directly befofre the <SPAN CLASS=Label>
1071            // The 'tn' was declared at the top of this method, it is a re-usable temp variable
1072
1073            tn = html.elementAt(spanPos - 1).openTag();
1074
1075            if ((tn == null) || (! tn.tok.equals("dt"))) Messager.assertFailHTML(
1076                "There is a " + BGREEN + html.elementAt(spanPos).str + RESET + "\n" +
1077                "Not preceeded by an opening " + BGREEN + "<DT>" + RESET + "\n" +
1078                "Instead there is a " + BGREEN + html.elementAt(spanPos - 1).str +
1079                RESET,
1080                sig
1081            );
1082
1083            // Passed the above requirement/test, so this is the start of the SubSection
1084            int locStart = spanPos - 1;
1085
1086            // The particular section we are observing ends as soon as another section begins, or
1087            // we encounter a </DL> element.  a <DT> element implies a new section is starting, and
1088            // a </DL> element means all of the labels have been handled
1089            //
1090            // Find the ending </DD> of the last <DD>...</DD> pair
1091
1092            int locEnd = -1, len = html.size();
1093
1094            // Find either a closing </DL> (meaning no more <SPAN CLASS='someLabel'> elements),
1095            // or an oopening <DT> - which is starting a new SPAN-LABEL
1096
1097            INNER_FOR_LOOP:
1098            for (int i = (spanPos + 1); i < len; i++)
1099
1100                if ((tn = html.elementAt(i).ifTagNode()) != null)
1101
1102                    if (    (tn.tok.equals("dl") &&  tn.isClosing)      // Closing </DL>
1103                        ||  (tn.tok.equals("dt") &&  (! tn.isClosing))  // Opening <DT>
1104                    )
1105                    {
1106                        locEnd = i;
1107                        break INNER_FOR_LOOP;
1108                    }
1109
1110            // I still haven't found what I'm looking for...
1111            // There was not closing </DL>, nor an new, opening <DT>
1112
1113            if (locEnd == -1) Messager.assertFailHTML(
1114                "There is a " + BGREEN + html.elementAt(spanPos).str + RESET + ' ' +
1115                "which isn't terminated by a new <DT> or a closing </DL>",
1116                sig
1117            );
1118
1119            // Back up through any TextNodes - which, usually, is just a '\n' newline character.
1120            while ((tn = html.elementAt(--locEnd).ifTagNode()) == null);
1121
1122            // Finally, make sure there is a closing </DD> which is the end of the 
1123            // <DT>...</DT><DD>...</DD> Combination.  Remember, there may only be one <DT>..<DT>
1124            // (with a <SPAN CLASS='someLabel'), but that <DT> may be followed by more than one
1125            // <DD>...</DD> list.  Parameters and Throws Labels have severl <DD> pairs!
1126
1127            if ((! tn.isClosing) || (! tn.tok.equals("dd"))) Messager.assertFailHTML(
1128                "There is a " + BGREEN + html.elementAt(spanPos).str + RESET + ' ' +
1129                "which is missing a <DD> definition",
1130                sig
1131            );
1132
1133
1134            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1135            // Finished Searching. Build the "SubSection" instance, and start the switch-statement
1136            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1137
1138            // 'dp' is a temp variable that was first used earlier
1139            dp = new DotPair(locStart, locEnd);
1140
1141            // A 'SubSection' includes both the location, and the HTML put together in a
1142            // wrapper-class (SubSection is wrapper for Vector<HTMLNode> & DotPair)
1143
1144            SubSection section = new SubSection(dp, Util.cloneRange(html, dp));
1145
1146            // Temporary Variables for the switch statement
1147            String      kind;
1148            TextNode    txn;
1149
1150            // In case you missed it, the six labels that were searched are:
1151            // "paramLabel", "returnLabel", "seeLabel", "throwsLabel", "overrideSpecifyLabel",
1152            // and "simpleTagLabel"
1153
1154            CASE:
1155            switch (html.elementAt(spanPos).asTagNode().AV("class"))
1156            {
1157                case "returnLabel" :
1158
1159                    if (subSections.containsKey(RETURNS_KEY))
1160                        Messager.assertFailHTML("There is a second 'returnLabel", sig);
1161                    else
1162                        subSections.put(RETURNS_KEY, section);
1163
1164                    break CASE;
1165
1166                case "seeLabel" :
1167
1168                    if (subSections.containsKey(SEE_ALSO_KEY))
1169                        Messager.assertFailHTML("There is a second 'seeLabel", sig);
1170                    else
1171                        subSections.put(SEE_ALSO_KEY, section);
1172
1173                    break CASE;
1174
1175                case "throwsLabel" :
1176
1177                    if (subSections.containsKey(THROWS_KEY))
1178                        Messager.assertFailHTML("There is a second 'throwsLabel", sig);
1179                    else
1180                        subSections.put(THROWS_KEY, section);
1181
1182                    break CASE;
1183
1184
1185                // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1186                // There can be two kinds of "paramLabel" 
1187                // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1188                //
1189                // One is used for regular-parameters, which is the most common, while the second
1190                // is for "Type-Parameters" (rare, but useful)
1191
1192                case "paramLabel" :
1193
1194                    if ((txn = html.elementAt(spanPos + 1).ifTextNode()) == null)
1195                        Messager.assertFailHTML
1196                            ("There is a 'paramLabel' not followed by a TextNode", sig);
1197
1198                    kind = txn.str;
1199
1200                    if (kind.equals("Parameters:"))
1201                    {
1202                        if (subSections.containsKey(PARAMETERS_KEY))
1203                            Messager.assertFailHTML
1204                                ("There is a second 'paramLabel' for parameters", sig);
1205                        else
1206                            subSections.put(PARAMETERS_KEY, section);
1207                    }
1208                    else if (kind.equals("Type Parameters:"))
1209                    {
1210                        if (subSections.containsKey(TYPE_PARAMETERS_KEY))
1211                            Messager.assertFailHTML
1212                                ("There is a second 'paramLabel' for type-parameters", sig);
1213                        else
1214                            subSections.put(TYPE_PARAMETERS_KEY, section);
1215                    }
1216
1217                    else Messager.assertFailHTML(
1218                        "Unknown Parameter Label Found:\n" +
1219                        StrIndent.indent(Util.pageToString(section.html), 4),
1220                        sig
1221                    );
1222
1223                    break CASE;
1224
1225
1226                // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1227                // There can be two kinds of "overrideSpecifyLabel"
1228                // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1229                // (surprise, "override" and "specified by")
1230
1231                case "overrideSpecifyLabel" :
1232
1233                    if ((txn = html.elementAt(spanPos + 1).ifTextNode()) == null)
1234                        Messager.assertFailHTML
1235                            ("There is a 'overrideSpecifyLabel' not followed by a TextNode", sig);
1236
1237                    kind = txn.str;
1238
1239                    if (kind.equals("Specified by:"))
1240                    {
1241                        if (subSections.containsKey(SPECIFIED_BY_KEY))
1242                        {
1243                            SubSection first = subSections.get(SPECIFIED_BY_KEY);
1244
1245                            if ((dp.start - first.location.end) > 2)
1246
1247                                Messager.assertFailHTML(
1248                                    "There is a second 'overrideSpecifyLabel' for 'Specified " +
1249                                    "by:', and unfortunately it is not contiguous with the " +
1250                                    "previous one.",
1251                                    sig
1252                                );
1253
1254                            dp = new DotPair(first.location.start, dp.end);
1255                            section = new SubSection(dp, Util.cloneRange(html, dp));
1256                        }
1257
1258                        subSections.put(SPECIFIED_BY_KEY, section);
1259                    }
1260
1261                    else if (kind.equals("Overrides:"))
1262                    {
1263                        if (subSections.containsKey(OVERRIDES_KEY))
1264                            Messager.assertFailHTML
1265                                ("There is a second 'Overrides' label", sig);
1266                        else
1267                            subSections.put(OVERRIDES_KEY, section);
1268                    }
1269
1270                    else Messager.assertFailHTML(
1271                        "Unknown Overrides/Specified-By Label Found:\n" +
1272                        StrIndent.indent(Util.pageToString(section.html), 4),
1273                        sig
1274                    );
1275
1276                    break CASE;
1277
1278
1279                // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1280                // There can many kinds of "simpleTagLabel"
1281                // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1282
1283                case "simpleTagLabel" :
1284
1285                    if ((txn = html.elementAt(spanPos + 1).ifTextNode()) == null)
1286                        Messager.assertFailHTML
1287                            ("There is a 'simpleTagLabel' not followed by a TextNode", sig);
1288
1289                    kind = txn.str;
1290
1291                    if (kind.equals("Since:"))
1292                    {
1293                        if (subSections.containsKey(SINCE_KEY))
1294                            Messager.assertFailHTML
1295                                ("There is a second 'simpleTagLabel' for 'since'", sig);
1296                        else
1297                            subSections.put(SINCE_KEY, section);
1298                    }
1299                    else
1300                    {
1301                        // 99% of the classes in JavaHTML do not have these, no need to build
1302                        // this array-list at construction-time, only build if used
1303
1304                        if (miscSimpleTagLabels == null)
1305                            miscSimpleTagLabels = new ArrayList<>();
1306
1307                        miscSimpleTagLabels.add
1308                            (new TagNodeIndex(spanPos, html.elementAt(spanPos).asTagNode()));
1309                    }
1310            }
1311        }
1312    }
1313
1314    // This should never happend
1315    private IllegalArgumentException ENTITY_MATCH(Declaration entity, Entity entityAsEnum)
1316    {
1317        return new IllegalArgumentException(
1318            "The 'Entity' passed to parameter 'entityAsEnum' [" + entityAsEnum + "], does " +
1319            "not match the type of parameter 'entity' [" + entity.getClass().getSimpleName() +
1320            "].  They must be the same."
1321        );
1322    }
1323
1324    /**
1325     * Clone Constructor.
1326     * @param other Another instance of {@code ReflHTML}
1327     * @see #clone()
1328     */
1329    @SuppressWarnings("unchecked")
1330    ReflHTML(ReflHTML<ENTITY> other)
1331    {
1332        this.entity             = other.entity; /* not cloned, the reflected entity */
1333        this.entityAsEnum       = other.entityAsEnum;
1334        this.location           = other.location; /* immutable, no need to clone */
1335        this.endingLI           = other.endingLI;
1336        this.htmlID             = other.htmlID;
1337        this.openingUL          = other.openingUL;
1338        this.name               = other.name.clone();
1339        this.signature          = other.signature.clone();
1340        this.descFromTypeLabel  = other.descFromTypeLabel;
1341
1342        // The Code-HiLited Details "Special Additions"
1343        this.hiLitedCode = other.hiLitedCode;
1344        this.needToAddOpenCloseDLsForHiLitedDetails = other.needToAddOpenCloseDLsForHiLitedDetails;
1345
1346        // Cannot 'clone' the other.subSections, it assigned a value at initialization (at the top
1347        // where it is declared). Use 'TreeMap.putAll' instead
1348
1349        this.subSections.putAll(other.subSections);
1350
1351        // This is not inialized unless there are actually 'simpleTagLabels' in the detail
1352        this.miscSimpleTagLabels = (other.miscSimpleTagLabels != null)
1353            ? ((ArrayList<TagNodeIndex>) other.miscSimpleTagLabels.clone())
1354            : null;
1355    }
1356
1357
1358    // ********************************************************************************************
1359    // ********************************************************************************************
1360    // java.lang.Cloneable, java.lang.Comparable
1361    // ********************************************************************************************
1362    // ********************************************************************************************
1363
1364
1365    /**
1366     * Java's {@code interface Cloneable} requirements.  This provides a "Deep Clone", where all
1367     * internal {@code Vector's} and {@code SubSection's} are also cloned, rather than a
1368     * "Shallow Clone", having identical references.
1369     * 
1370     * @return A new {@code ReflHTML} whose internal fields are identical to this one.
1371     */
1372    public ReflHTML<ENTITY> clone() { return new ReflHTML<>(this); }
1373
1374    /**
1375     * Java's {@code interface Comparable<T>} requirements.  This does a very simple comparison
1376     * using the {@code location} field.
1377     * 
1378     * <BR /><BR /><B><SPAN STYLE="color: red;">FINAL METHOD:</B></SPAN> This method is declared 
1379     * {@code final}, and cannot be modified by sub-classes.
1380     * 
1381     * @param other Any other {@code ReflHTML} to be compared to {@code 'this' ReflHTML}
1382     * 
1383     * @return An integer that fulfils Java's {@code interface Comparable<T> public boolean
1384     * compareTo(T t)} method requirements.
1385     * 
1386     * @see DotPair#compareTo(DotPair)
1387     */
1388    public final int compareTo(ReflHTML other)
1389    { return this.location.compareTo(other.location); }
1390
1391
1392    // ********************************************************************************************
1393    // ********************************************************************************************
1394    // Rebuilding a ReflHTML from it's pieces
1395    // ********************************************************************************************
1396    // ********************************************************************************************
1397
1398
1399    private static final Vector<HTMLNode> TEMP_END_VEC = new Vector<>(1);
1400
1401    TreeSet<Replaceable> allReplaceables()
1402    {
1403        TreeSet<Replaceable> replaceables = new TreeSet<>();
1404        SubSection ss = null;
1405
1406        replaceables.add(openingUL);
1407        replaceables.add(this.name);
1408
1409        replaceables.add
1410            (Replaceable.createInsertion(this.name.location.end + 1, this.detailNavBar));
1411
1412        replaceables.add(this.signature);
1413
1414
1415        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1416        // Add "Maximize-Partialize-Minimize" Button <DIV>'s - EMBARRASING THAT THIS IS DONE HERE
1417        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1418        //
1419        // It seems like this isn't the best place to do this, but I simply am at a loss for words
1420        // about where I *SHOULD* put this stuff.
1421
1422        this.signature.html.add(
1423            0,
1424            new TextNode("<DIV CLASS=ORD ID=ORD" + this.entity.id + ">\n")
1425        );
1426
1427        this.signature.html.add
1428            (new TextNode("\n<DIV CLASS=IRD ID=IRD" + this.entity.id + ">\n"));
1429
1430        Vector<HTMLNode> TEMP_VEC = new Vector<>();
1431
1432        TEMP_VEC.add(
1433            new TextNode(
1434                "\n</DIV> <!-- IRD" + this.entity.id + " -->" +
1435                "\n</DIV> <!-- ORD" + this.entity.id + " -->\n\n"
1436            )
1437        );
1438
1439        replaceables.add(Replaceable.createInsertion(endingLI, TEMP_VEC));
1440
1441    
1442        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1443        // All of the other's
1444        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
1445
1446        if ((ss = subSections.get(DESCRIPTION_KEY)) != null)        replaceables.add(ss);
1447        if ((ss = subSections.get(ANNOTATION_DEFAULT_KEY)) != null) replaceables.add(ss);
1448        if ((ss = subSections.get(RETURNS_KEY)) != null)            replaceables.add(ss);
1449        if ((ss = subSections.get(SEE_ALSO_KEY)) != null)           replaceables.add(ss);
1450        if ((ss = subSections.get(THROWS_KEY)) != null)             replaceables.add(ss);
1451        if ((ss = subSections.get(PARAMETERS_KEY)) != null)         replaceables.add(ss);
1452        if ((ss = subSections.get(TYPE_PARAMETERS_KEY)) != null)    replaceables.add(ss);
1453        if ((ss = subSections.get(OVERRIDES_KEY)) != null)          replaceables.add(ss);
1454        if ((ss = subSections.get(SPECIFIED_BY_KEY)) != null)       replaceables.add(ss);
1455        if ((ss = subSections.get(AUTHOR_KEY)) != null)             replaceables.add(ss);
1456        if ((ss = subSections.get(SINCE_KEY)) != null)              replaceables.add(ss);
1457
1458        replaceables.add(hiLitedCode);
1459
1460        return replaceables;
1461    }
1462
1463
1464    // ********************************************************************************************
1465    // ********************************************************************************************
1466    // THE NEW-THING: Garbage-Collector Helper?
1467    // ********************************************************************************************
1468    // ********************************************************************************************
1469    // 
1470    // Does this help?  Is this "good" for the Garbage-Collect?  Is this going to speed it up,
1471    // or slow it down?  This is just a "C-Styled" FREE or DESTORY method...
1472    // It isn't publicly visible anyway...
1473    //
1474    // NOTE: Many of the null checks are completely superfluous, but not all of them...
1475    //       In any case, the worst feeling in the world would be NPE for this silly little
1476    //       "optimization"
1477
1478    void clear()
1479    {
1480        // public final TagNodeIndex openingUL;
1481        if (openingUL != null) openingUL.n = null;
1482
1483        // private final SubSection name;
1484        if (name != null) { name.html.clear(); name.html = null; }
1485
1486        // private final SubSection signature;
1487        if (signature != null) { signature.html.clear(); signature.html = null; }
1488
1489        // private final TreeMap<Character, SubSection> subSections = new TreeMap<>();
1490        if (subSections != null)
1491        {
1492            for (SubSection ss : subSections.values())
1493            {
1494                ss.html.clear();
1495                ss.html = null;
1496            }
1497
1498            subSections.clear();
1499        }
1500
1501        // private Replaceable hiLitedCode = null;
1502        if (hiLitedCode != null) { hiLitedCode.clearHTML(); hiLitedCode = null; }
1503
1504        // private ArrayList<TagNodeIndex> miscSimpleTagLabels = null;
1505        if (miscSimpleTagLabels != null)
1506        {
1507            miscSimpleTagLabels.clear();
1508            miscSimpleTagLabels = null;
1509        }
1510    }
1511}