001package Torello.JavaDoc; 002 003import Torello.HTML.HTMLNode; 004import Torello.HTML.SubSection; 005import Torello.HTML.Replaceable; 006import Torello.HTML.Util; 007 008import Torello.Java.StrPrint; 009import static Torello.Java.C.*; 010 011import Torello.JDUInternal.Messager.Messager; 012import Torello.JDUInternal.Messager.Where.JDUUserAPI; 013import Torello.JDUInternal.Messager.Where.Where_Am_I; 014 015import Torello.JDUInternal.Parse.HTML.HeaderFooter.D1_HeaderFooterRec; 016 017import java.util.Vector; 018 019/** 020 * Encapsulates the HTML placed both the top and the bottom of a JavaDoc Web-Page, including the 021 * Navigation-Bar HTML, the Package-Name, Type-Signature and other Banner-Labesl. 022 * 023 * <EMBED CLASS='external-html' DATA-FILE-ID=PROG_MOD_HTML> 024 * <EMBED CLASS='external-html' DATA-FILE-ID=HEADER_FOOTER> 025 */ 026@JDHeaderBackgroundImg(EmbedTagFileID="REFLECTION_HTML_CLASS") 027public class HeaderFooterHTML 028{ 029 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 030 protected static final long serialVersionUID = 1; 031 032 // When the Messager Reports its errors, this class passes this reference to the Messager 033 // to facilitate the printing of that information (What class encountered an error or warning 034 // that needs to be printed by the Messager). 035 036 private static final Where_Am_I WHERE_AM_I = JDUUserAPI.HeaderFooterHTML; 037 038 039 // ******************************************************************************************** 040 // ******************************************************************************************** 041 // Constructor - Fields are computed in package: Torello.JDUInternal.Parse.HTML.Other 042 // ******************************************************************************************** 043 // ******************************************************************************************** 044 045 046 // This constructor is invoked by JavaDocHTMLFile 047 // The work for this constructor has since been moved into a class inside package: 048 // 049 // Torello.JDUInternal.Parse.HTML.Other 050 // 051 // Keeping HTML-Parsing code in a separate, internal, package allows me to "localize" the 052 // complicated parsing code into a single location - far away from the end user. This code 053 // is dependent upon which of the Java-Doc Versions is being used. 054 // 055 // Since October of 2024, HTML-Parsing Code has been moved to a single, JDUInternal, 056 // suite of directories that are much easier to manage. This constructor, for instance, just 057 // block copies the fields from one of those JDUInternal Data-Record Classes. 058 059 HeaderFooterHTML 060 (final Torello.JDUInternal.Parse.HTML.HeaderFooter.D1_HeaderFooterRec internalDataRec) 061 { 062 this.head = internalDataRec.head; 063 this.topNavBar = internalDataRec.topNavBar; 064 this.packageInfo = internalDataRec.packageInfo; 065 this.title = internalDataRec.title; 066 this.inheritance = internalDataRec.inheritance; 067 this.defListsAboveSig = internalDataRec.defListsAboveSig; 068 this.signature = internalDataRec.signature; 069 this.description = internalDataRec.description; 070 this.defListsBelowDesc = internalDataRec.defListsBelowDesc; 071 this.bottomNavBar = internalDataRec.bottomNavBar; 072 } 073 074 075 // ******************************************************************************************** 076 // ******************************************************************************************** 077 // Private Replaceable-HTML Fields 078 // ******************************************************************************************** 079 // ******************************************************************************************** 080 081 082 private final SubSection head; 083 private final SubSection topNavBar; 084 private final SubSection packageInfo; 085 private final SubSection title; 086 private final SubSection inheritance; 087 private final Replaceable defListsAboveSig; 088 private final SubSection signature; 089 private final Replaceable description; 090 private final Replaceable defListsBelowDesc; 091 private final SubSection bottomNavBar; 092 093 094 // ******************************************************************************************** 095 // ******************************************************************************************** 096 // Public Accessor Methods 097 // ******************************************************************************************** 098 // ******************************************************************************************** 099 100 101 /** 102 * Retrieve the HTML {@code <HEAD>}. 103 * 104 * @return An HTML-{@code Vector} containing all elements between the opening-{@code <HEAD>} 105 * and closing-{@code </HEAD>} tags. This method shall never return null, nor will it return 106 * an empty-{@code Vector} 107 */ 108 public Vector<HTMLNode> head() 109 { return this.head.html; } 110 111 /** 112 * Retrieve the Navigation-Bar HTML at the top of a Java Doc Page. 113 * 114 * @return An HTML-{@code Vector} containing all elements in the Top Navigation-Bar. If there 115 * is no Navigation-Bar at the top, <I>then this method shall return null.</I> 116 */ 117 public Vector<HTMLNode> topNavBar() 118 { return (this.topNavBar != null) ? this.topNavBar.html : null; } 119 120 /** 121 * Retrieve the Type's Package-Information, as an HTML-{@code Vector}. 122 * 123 * @return An HTML-{@code Vector} containing all elements in the package label at the top of a 124 * Java-Doc Page. This method shall never return null, nor will it return an 125 * empty-{@code Vector} 126 */ 127 public Vector<HTMLNode> packageInfo() 128 { return this.packageInfo.html; } 129 130 /** 131 * Retrieve the title of the page, as an HTML-{@code Vector} 132 * 133 * @return An HTML-{@code Vector} containing all elements in the title. This method shall 134 * never return null, nor will it return an empty-{@code Vector} 135 */ 136 public Vector<HTMLNode> title() 137 { return this.title.html; } 138 139 /** 140 * Get the HTML for the Type's inheritance {@code <UL>'s}-List. 141 * 142 * @return An HTML-{@code Vector} containing all elements in the Type Inheritance List. If 143 * the Type is an {@code Interface} that does not have any inheriting-types, or an 144 * {@code @Annotation}, <I>then this method shall return null.</I> 145 */ 146 public Vector<HTMLNode> inheritance() 147 { return (this.inheritance != null) ? this.inheritance.html : null; } 148 149 /** 150 * Get any Definition-Lists that occur above the Type's Signature, which is at the top. 151 * 152 * @return An HTML-{@code Vector} containing all elements in the definition {@code <DL>} lists 153 * below the Yellow-Box Description. This method shall <I>never return null</I>. If there are 154 * no such lists, then an empty HTML-{@code Vector} is returned. 155 * 156 * <BR /><BR />It is perfectly acceptable to add HTML-Content to an empty-list. Here, it would 157 * place such content directly above the Type-Signature {@code <PRE>} box that is located at 158 * the top of the page. 159 */ 160 public Vector<HTMLNode> defListsAboveSig() 161 { return this.defListsAboveSig.currentNodes(); } 162 163 /** 164 * Retrieve the signature HTML from the top of the page. 165 * 166 * @return An HTML-{@code Vector} containing all elements in the Type-Signature {@code <PRE>} 167 * Element. This is located at the top of the class, and is box with a shadow border. This 168 * method shall never return null, nor will it return an empty-{@code Vector} 169 */ 170 public Vector<HTMLNode> signature() 171 { return this.signature.html; } 172 173 /** 174 * Retrieve the description from the top of the page, as HTML. 175 * 176 * @return An HTML-{@code Vector} containing all elements in the description, which is a 177 * Yellow box at the top of the page. This method shall <I>never return null</I>. If there 178 * is no such HTML divider, then an empty HTML-{@code Vector} is returned. 179 * 180 * <BR /><BR />It is perfectly acceptable to add HTML-Content to an empty-list. Here, it would 181 * place such content directly below the Yellow-Description box that is located at the top of 182 * the page. 183 */ 184 public Vector<HTMLNode> description() 185 { return this.description.currentNodes(); } 186 187 /** 188 * Get any Definition-Lists that occur below the Yellow-Box Signature. 189 * 190 * @return An HTML-{@code Vector} containing all elements in the definition {@code <DL>} lists 191 * below the Yellow-Box Description. This method shall <I>never return null</I>. If there are 192 * no such lists, then an empty HTML-{@code Vector} is returned. 193 * 194 * <BR /><BR />It is perfectly acceptable to add HTML-Content to an empty-list. Here, it would 195 * place such content directly below the Yellow-Description box that is located at the top of 196 * the page. 197 */ 198 public Vector<HTMLNode> defListsBelowDesc() 199 { return this.defListsBelowDesc.currentNodes(); } 200 201 /** 202 * Retrieve the Navigation-Bar HTML at the bottom of a Java Doc Page. 203 * 204 * @return An HTML-{@code Vector} containing all elements in the Bottom Navigation-Bar. If 205 * there is no Navigation-Bar at the top, <I>then this method shall return null.</I> 206 */ 207 public Vector<HTMLNode> bottomNavBar() 208 { return (this.bottomNavBar != null) ? this.bottomNavBar.html : null; } 209 210 211 // ******************************************************************************************** 212 // ******************************************************************************************** 213 // DEBUG-PRINTING 214 // ******************************************************************************************** 215 // ******************************************************************************************** 216 217 218 private static final String STARS = 219 BYELLOW + "\n*****************************************\n" + RESET; 220 221 /** 222 * Prints an abbreviated-version of the contents of this instance, to a user-provided 223 * {@code Appendable}. If the HTML requires more than four lines of text, only the first four 224 * lines are printed. 225 * 226 * @param a This may be any Java Appendable. If an {@code IOException} is thrown while writing 227 * to this {@code Appendable}, it will be caught an wrapped in an 228 * {@code IllegalArgumentException}, with the {@code IOException} set as the {@code cause}. 229 * 230 * @throws IllegalArgumentException If {@code 'a'} throws an {@code IOException} 231 * @see StrPrint#firstNLines(String, int) 232 * @see Util#pageToString(Vector) 233 */ 234 public void debugPrint(Appendable a) 235 { 236 try 237 { 238 a.append( 239 STARS + BCYAN + "this.head" + RESET + ':' + STARS + 240 StrPrint.firstNLines(Util.pageToString(head.html), 4) + 241 '\n' 242 ); 243 244 if (topNavBar != null) a.append( 245 STARS + BCYAN + "this.topNavBar" + RESET + ':' + STARS + 246 StrPrint.firstNLines(Util.pageToString(topNavBar.html), 4) + 247 '\n' 248 ); 249 else a.append(STARS + BRED + "this.topNavBar is null" + RESET + STARS); 250 251 a.append( 252 STARS + BCYAN + "this.packageInfo" + RESET + ':' + STARS + 253 StrPrint.firstNLines(Util.pageToString(packageInfo.html), 4) + 254 '\n' 255 ); 256 257 a.append( 258 STARS + BCYAN + "this.title" + RESET + ':' + STARS + 259 StrPrint.firstNLines(Util.pageToString(title.html), 4) + 260 '\n' 261 ); 262 263 if (inheritance != null) a.append( 264 STARS + BCYAN + "this.inheritance" + RESET + ':' + STARS + 265 StrPrint.firstNLines(Util.pageToString(inheritance.html), 4) + 266 '\n' 267 ); 268 else a.append(STARS + BRED + "this.inheritance is null" + RESET + STARS); 269 270 if (defListsAboveSig.currentSize() > 0) a.append( 271 STARS + BCYAN + "this.defListsAboveSig" + RESET + ':' + STARS + 272 StrPrint.firstNLines(Util.pageToString(defListsAboveSig.currentNodes()), 4) + 273 '\n' 274 ); 275 else a.append(STARS + BRED + "this.defListsAboveSig is empty" + RESET + STARS); 276 277 a.append( 278 STARS + BCYAN + "this.signature" + RESET + ':' + STARS + 279 StrPrint.firstNLines(Util.pageToString(signature.html), 4) + 280 '\n' 281 ); 282 283 if (description.currentSize() > 0) a.append( 284 STARS + BCYAN + "this.description" + RESET + ':' + STARS + 285 StrPrint.firstNLines(Util.pageToString(description.currentNodes()), 4) + 286 '\n' 287 ); 288 else a.append(STARS + BRED + "this.description is empty" + RESET + STARS); 289 290 if (defListsBelowDesc.currentSize() > 0) a.append( 291 STARS + BCYAN + "this.defListsBelowDesc" + RESET + ':' + STARS + 292 StrPrint.firstNLines(Util.pageToString(defListsBelowDesc.currentNodes()), 4) + 293 '\n' 294 ); 295 else a.append(STARS + BRED + "this.defListsBelowDesc is empty" + RESET + STARS); 296 297 if (bottomNavBar != null) a.append( 298 STARS + BCYAN + "this.bottomNavBar" + RESET + ':' + STARS + 299 StrPrint.firstNLines(Util.pageToString(bottomNavBar.html), 4) + 300 '\n' 301 ); 302 else a.append(STARS + BRED + "this.bottomNavBar is null" + RESET + STARS); 303 } 304 catch (java.io.IOException ioe) 305 { 306 throw new IllegalArgumentException( 307 "Your Appendable instance has caused an IOException to throw. See getCause() " + 308 "for details", ioe 309 ); 310 } 311 } 312 313 314 // ******************************************************************************************** 315 // ******************************************************************************************** 316 // At the end of the processing of a JavaDoc Web-Page, this gets all the changes that were made 317 // ******************************************************************************************** 318 // ******************************************************************************************** 319 320 321 Vector<Replaceable> allReplaceables() 322 { 323 Vector<Replaceable> ret = new Vector<>(); 324 325 ret.add(head); // Required, always present 326 327 if (topNavBar != null) ret.add(topNavBar); 328 329 ret.add(packageInfo); // Required, always present 330 ret.add(title); // Required, always present 331 332 if (inheritance != null) ret.add(inheritance); 333 334 ret.add(defListsAboveSig); // A "Replaceable" is never null. 335 ret.add(signature); // Required, always present 336 ret.add(description); // A "Replaceable" is never null. 337 ret.add(defListsBelowDesc); // A "Replaceable" is never null. 338 339 if (bottomNavBar != null) ret.add(bottomNavBar); 340 341 return ret; 342 } 343 344 345 // ******************************************************************************************** 346 // ******************************************************************************************** 347 // THE NEW-THING: Garbage-Collector Helper? 348 // ******************************************************************************************** 349 // ******************************************************************************************** 350 // 351 // Does this help? Is this "good" for the Garbage-Collect? Is this going to speed it up, 352 // or slow it down? This is just a "C-Styled" FREE or DESTORY method... 353 // It isn't publicly visible anyway... 354 355 void clear() 356 { 357 // private final SubSection head; 358 // Guaranteed: Never Null, or Messager.assertFailHTML 359 360 head.html.clear(); 361 head.html = null; 362 363 // private final SubSection topNavBar; 364 // Maybe they don't have one 365 366 if (topNavBar != null) 367 { 368 topNavBar.html.clear(); 369 topNavBar.html = null; 370 } 371 372 // private final SubSection packageInfo; 373 // Guaranteed: Never Null, or Messager.assertFailHTML 374 // NOTE: This may one day change... 375 376 if (packageInfo != null) 377 { 378 packageInfo.html.clear(); 379 packageInfo.html = null; 380 } 381 382 // private final SubSection title; 383 // Guaranteed: Never Null, or Messager.assertFailHTML 384 385 title.html.clear(); 386 title.html = null; 387 388 // private final SubSection inheritance; 389 // Maybe they don't have one 390 391 if (inheritance != null) 392 { 393 inheritance.html.clear(); 394 inheritance.html = null; 395 } 396 397 // private final Replaceable defListsAboveSig; 398 // THIS IS A REPLACEABLE: It won't be null, but it may be empty 399 400 if (SubSection.class.isAssignableFrom(defListsAboveSig.getClass())) 401 { 402 ((SubSection) defListsAboveSig).html.clear(); 403 ((SubSection) defListsAboveSig).html = null; 404 } 405 else if (defListsAboveSig.currentSize() > 0) defListsAboveSig.clearHTML(); 406 407 // private final SubSection signature; 408 // Guaranteed: Never Null, or Messager.assertFailHTML 409 410 signature.html.clear(); 411 signature.html = null; 412 413 // private final Replaceable description; 414 // THIS IS A REPLACEABLE: It won't be null, but it may be empty 415 416 if (SubSection.class.isAssignableFrom(description.getClass())) 417 { 418 ((SubSection) description).html.clear(); 419 ((SubSection) description).html = null; 420 } 421 else if (description.currentSize() > 0) description.clearHTML(); 422 423 // private final Replaceable defListsBelowDesc; 424 // THIS IS A REPLACEABLE: It won't be null, but it may be empty 425 426 if (SubSection.class.isAssignableFrom(defListsBelowDesc.getClass())) 427 { 428 ((SubSection) defListsBelowDesc).html.clear(); 429 ((SubSection) defListsBelowDesc).html = null; 430 } 431 else if (defListsBelowDesc.currentSize() > 0) defListsBelowDesc.clearHTML(); 432 433 // private final SubSection bottomNavBar; 434 // Maybe they don't have one 435 436 if (bottomNavBar != null) 437 { 438 bottomNavBar.html.clear(); 439 bottomNavBar.html = null; 440 } 441 } 442}