001package Torello.HTML; 002 003import java.util.Vector; 004import java.util.NoSuchElementException; 005 006import static Torello.Java.C.BCYAN; 007import static Torello.Java.C.RESET; 008 009import Torello.Java.UnreachableError; 010import Torello.HTML.NodeSearch.*; // Used for JavaDoc Comment Links 011 012/** 013 * The class {@link Replacement} offers a great <B><I>efficiency-improvement</I></B> optimization 014 * for modifying vectorized-HTML. HTML Pages can be very long, and the insertion or removal of a 015 * piece or snippet of HMTL may result in the shifting of hundreds (or even thousands!) of 016 * {@code HTMLNode's}. This can incur a non-trivial performance cost if many there are many 017 * updates and changes to be made to a page. 018 * 019 * <BR /><BR /><HR><BR /> 020 * 021 * <B CLASS=JDDescLabel2>Exceprt from {@link #currentNodes()}:</B> 022 * 023 * <BR />{@code Replaceable's} are, sort-of, <B STYLE='color: red'>the exact opposite</B> of Java's 024 * {@code List} method {@code 'subList'}. According to the Sun / Oracle Documentation for 025 * {@code java.util.List.subList(int fromIndex, int toIndex)}, any changes ffinamade to an instance of a 026 * {@code 'subList'} are immediately reflected back into the original {@code List} from where they 027 * were created. 028 * 029 * <BR /><BR />The {@code List.subList} operation has the advantage of being extremely easy to 030 * work with - however, an HTML-Page {@code Vector} has the potential of being hundreds of 031 * nodes long. Any operations that involve insertion or deletion will likely be terribly 032 * inefficient. 033 * 034 * <BR /><BR /><B STYLE='color: red'><I>When the HTML inside of a {@code Replaceable} is 035 * modified - nothing happens to the original {@code Vector} whatsoever!</I></B>. Until a user 036 * requests that the original HTML-{@code Vector} be updated to reflect all changes that he or 037 * she has made, the original HTML remains untouched. When an update request is finally 038 * issued, all changes are made all at once, and at the same time! 039 * 040 * <BR /><BR />Again - see {@link Replacement#run(Vector, Iterable, boolean)} to understand 041 * how quick updates on HTML-Pages is done using the {@code Replaceable} interface. 042 * 043 * <BR /><BR /><HR><BR /> 044 * 045 * Though this class may look somewhat complicated to understand, in all reality it is 046 * actually very simple. Load a web-page from disk (or download one from the Internet) and run it 047 * through the parser (class {@link HTMLPage}) to make a Vectorized-HTML Page. Next, build a few 048 * instances of {@link SubSection} which hold <B><I>both</I></B> the location of an HTML snippet 049 * <B><I>and</I></B> HTML itself. 050 * 051 * <BR /><Br />Finallly, make whatever modifications you want to those HTML snippets, and call the 052 * <B>{@code Replacement.run()}</B> method! The page should be updated quickly with little cost 053 * overhead. 054 * 055 * <BR /><BR /><HR><BR /> 056 * 057 * <B CLASS=JDDescLabel2>Peek Operation Replaceables</B> 058 * 059 * <BR />The class {@link InnerTagPeekInclusive} and {@link TagNodePeekInclusive} will always 060 * generate properly ordered / sorted <B STYLE='color: red;'><I>references that implement the 061 * {@code Replaceable} interface!</I></B> Furthermore, these instances will be ones that are 062 * sorted and do not overlap. 063 * 064 * <BR /><BR />This means that if a set or collection of {@code Replaceable's} were created using 065 * the {@code NodeSearch 'Peek'} Search-Classes, the 066 * {@link Replacement#run(Vector, Iterable, boolean)} requirements that the 067 * {@code Replaceable's} be ordered, sorted and non-overlapping would be automatically met. 068 * 069 * <BR /><BR />This interface is implemented by all return-values for the {@code NodeSearch} <B>Peek</B> 070 * operations. 071 * 072 * <BR /><BR /><UL CLASS=JDUL> 073 * <LI>{@link TextNodePeek}</LI> 074 * <LI>{@link CommentNodePeek}</LI> 075 * <LI>{@link TagNodePeek}</LI> 076 * <LI>{@link TagNodePeekInclusive}</LI> 077 * <LI>{@link InnerTagPeek}</LI> 078 * <LI>{@link InnerTagPeekInclusive}</LI> 079 * </UL> 080 */ 081public interface Replaceable extends Comparable<Replaceable> 082{ 083 // ******************************************************************************************** 084 // ******************************************************************************************** 085 // basic interface stuff 086 // ******************************************************************************************** 087 // ******************************************************************************************** 088 089 090 /** 091 * Java's {@code Comparable} interface requirements. 092 * 093 * @return An integer based on comparing the starting locations for two {@code Replaceable} 094 * instances. 095 */ 096 public default int compareTo(Replaceable other) 097 { return this.originalLocationStart() - other.originalLocationStart(); } 098 099 /** 100 * Supplies a hash-code 101 * 102 * @return The value returned by {@link #originalLocationStart()}, which must be unique among 103 * any list of {@code Replaceable's}. 104 */ 105 // It say this isn't allowed 106 // public default int hashCode() 107 // { return originalLocationStart(); } 108 109 110 // ******************************************************************************************** 111 // ******************************************************************************************** 112 // The 'addAll' - used by class ReplaceNodes 113 // ******************************************************************************************** 114 // ******************************************************************************************** 115 116 117 /** 118 * Reports how many nodes were copied into {@code this} instance. 119 * For implementing classes that inherit {@link NodeIndex}, this value will always be one. 120 * For others, it should report exactly how many {@code HTMLNode's} were copied. 121 * 122 * @return Number of nodes originally contained by {@code this} instance. 123 * 124 * <A ID=NOTE1> <!-- NOTE --> </A> 125 * 126 * <BR /><BR />The purpose of {@code Replaceable's} is to allow a user to modify HTML using 127 * a smaller sub-list, without having to operate on the entire HTML-{@code Vector} since adding 128 * & removing nodes is one variant of {@code Vector}-modification, the <I>original-size</I> 129 * may often differ from the <I>current-size</I>. 130 * 131 * <BR /><BR />When modifying HTML, if a web-page is broken into smaller-pieces, and changes 132 * are restricted to those smaller sub-lists (and the original page is rebuilt, <I>all at 133 * once</I>, after all changes have been made) then those modifications should require far-fewer 134 * time-consuming list-shift operations, tremendously improving the performance of the code. 135 */ 136 public int originalSize(); 137 138 /** 139 * Returns how many nodes are currently in {@code this} instance. 140 * 141 * @return Number of nodes. See explanation of the <B STYLE='color: red;'>original</B> size, 142 * versus the <B STYLE='color: red;'>current</B> size 143 * <B><CODE><A HREF='#NOTE1'>here</A></CODE></B> 144 */ 145 public int currentSize(); 146 147 /** 148 * Returns the <B STYLE='color: red;'>start</B>-location within the original 149 * page-{@code Vector} from whence the HTML contents of {@code this} instance were retrieved. 150 * 151 * <BR /><BR /><B CLASS=JDDescLabel>Start is Inclusive:</B> 152 * 153 * <BR />The returned value is <B STYLE='color: red;'><I>inclusive</I></B> of the actual, 154 * original-range of {@code this} instance. This means the first {@code HTMLNode} copied into 155 * {@code this} instance' internal data-structure was at {@code originalLocationStart()}. 156 * 157 * <BR /><BR /><B CLASS=JDDescLabel>Implementations of Replaceable:</B> 158 * 159 * <BR />The two concrete implementatons of this interface ({@link NodeIndex} and 160 * {@link SubSection}) - both enforce the {@code 'final'} modifier on their location-fields. 161 * (See: {@link NodeIndex#index} and {@link SubSection#location}). 162 * 163 * @return The {@code Vector} <B STYLE='color: red;'>start</B>-index from whence this HTML was 164 * copied. 165 */ 166 public int originalLocationStart(); 167 168 /** 169 * Returns the <B STYLE='color: red;'>end</B>-location within the original 170 * page-{@code Vector} from whence the HTML contents of {@code this} instance were retrieved. 171 * 172 * <BR /><BR /><B CLASS=JDDescLabel>Start is Exclusive:</B> 173 * 174 * <BR />The returned value is <B STYLE='color: red;'><I>exclusive</I></B> of the actual, 175 * original-range of {@code this} instance. This means the last {@code HTMLNode} copied into 176 * {@code this} instance' internal data-structure was at {@code originalLocationEnd() - 1} 177 * 178 * <BR /><BR /><B CLASS=JDDescLabel>Implementations of Replaceable:</B> 179 * 180 * <BR />The two concrete implementatons of this interface ({@link NodeIndex} and 181 * {@link SubSection}) - both enforce the {@code 'final'} modifier on their location-fields. 182 * (See: {@link NodeIndex#index} and {@link SubSection#location}). 183 * 184 * @return The {@code Vector} <B STYLE='color: red;'>end</B>-index from whence this HTML was 185 * copied. 186 */ 187 public int originalLocationEnd(); 188 189 190 /** 191 * All nodes currently contained by this {@code Replaceable}. The concrete-classes which 192 * implement {@code Replaceable} ({@link SubSection} & {@link TagNodeIndex}) allow for the 193 * html they hold to be modified. The modification to a {@code Replaceable} happens 194 * independently from the original HTML Page out of which it was copied. 195 * 196 * <BR /><BR />{@code Replaceable's} are, sort-of, <B STYLE='color: red'>the exact opposite</B> 197 * of Java's {@code List} method {@code 'subList'}. According to the Sun / Oracle 198 * Documentation for {@code java.util.List.subList(int fromIndex, int toIndex)}, any changes 199 * made to an instance of a {@code 'subList'} are immediately reflected back into the original 200 * {@code List} from where they were created. 201 * 202 * <BR /><BR />The {@code List.subList} operation has the advantage of being extremely easy to 203 * work with - however, an HTML-Page {@code Vector} has the potential of being hundreds of 204 * nodes long. Any operations that involve insertion or deletion will likely be terribly 205 * inefficient. 206 * 207 * <BR /><BR /><B STYLE='color: red'><I>When the HTML inside of a {@code Replaceable} is 208 * modified - nothing happens to the original {@code Vector} whatsoever!</I></B>. Until a user 209 * requests that the original HTML-{@code Vector} be updated to reflect all changes that he or 210 * she has made, the original HTML remains untouched. When an update request is finally 211 * issued, all changes are made all at once, and at the same time! 212 * 213 * <BR /><BR />Again - see {@link Replacement#run(Vector, Iterable, boolean) Replacement.run} 214 * to understand how quick updates on HTML-Pages is done using the {@code Replaceable} 215 * interface. 216 * 217 * @return An HTML-{@code Vector} of the nodes. 218 * 219 * <BR /><BR />The HTML-{@code Vector} which is returned by this method may be modified in any 220 * way that is necessary! If or when a user requests that the original HTML-{@code Vector} be 221 * updated to accomodate the changes that have been made, the contents of the {@code Vector} 222 * which is returned by this method will be used to replace the original-HTML. 223 * 224 * <BR /><BR />If this method is invoked more than once, the same exact {@code Vector} will be 225 * returned each time that the Current-Nodes are requested. The internal "Current-Nodes" 226 * HTML-{@code Vector} is a "per instance" Singleton-Instance {@code Vector}. 227 */ 228 public Vector<HTMLNode> currentNodes(); 229 230 /** 231 * The first node <B STYLE='color: red;'>currently</B> contained by this {@code Replaceable} 232 * @return The First Node 233 */ 234 public HTMLNode firstCurrentNode(); 235 236 /** 237 * The last node <B STYLE='color: red;'>currently</B> contained by this {@code Replaceable} 238 * @return The last node 239 */ 240 public HTMLNode lastCurrentNode(); 241 242 243 // ******************************************************************************************** 244 // ******************************************************************************************** 245 // The 'addAll' - used by class ReplaceNodes 246 // ******************************************************************************************** 247 // ******************************************************************************************** 248 249 250 /** 251 * Add all nodes currently retained in {@code this} instance into the HTML-{@code Vector} 252 * parameter {@code html}. The nodes are appended to the end of {@code 'html'}. Implementing 253 * classes {@link NodeIndex} and {@link SubSection} simply use the Java {@code Vector} method's 254 * {@code add} (for {@code NodeIndex}) and {@code addAll} (for {@code SubSection}). 255 * 256 * @param html The HTML-{@code Vector} into which the nodes will be appended (to the end of 257 * this {@code Vector}, using {@code Vector} methods {@code add} or {@code addAll} dependent 258 * upon whether one or more-than-one nodes are being inserted). 259 * 260 * @return The result of {@code Vector} method {@code add}, or method {@code allAll} 261 */ 262 public boolean addAllInto(Vector<HTMLNode> html); 263 264 /** 265 * Add all nodes currently retained in {@code this} instance into the HTML-{@code Vector} 266 * parameter {@code html}. 267 * 268 * @param index The {@code 'html'} parameter's {@code Vector}-index where these nodes are to 269 * be inserted 270 * 271 * @param html The HTML-{@code Vector} into which the nodes will be appended (to the end of 272 * this {@code Vector}, using {@code Vector} methods {@code add} or {@code addAll} dependent 273 * upon whether one or more-than-one nodes are being inserted). 274 * 275 * @return The result of {@code Vector} method {@code add}, or method {@code allAll} 276 */ 277 public boolean addAllInto(int index, Vector<HTMLNode> html); 278 279 280 // ******************************************************************************************** 281 // ******************************************************************************************** 282 // update - inefficient, unless only used for a single page-update 283 // ******************************************************************************************** 284 // ******************************************************************************************** 285 286 287 /** 288 * <EMBED CLASS='external-html' DATA-FILE-ID=REPL_UPDATE_DESC> 289 * 290 * @param originalHTML The original page-{@code Vector} where the nodes in {@code this} 291 * instance were retrieved 292 * 293 * @return The change in the size of the {@code Vector} 294 * 295 * @see Replacement#run(Vector, Iterable, boolean) 296 * 297 * @throws IndexOutOfBoundsException If {@link #originalLocationStart()} or 298 * {@link #originalLocationEnd()} are not within the bounds of the input html-page. 299 */ 300 public int update(Vector<HTMLNode> originalHTML); 301 302 303 // ******************************************************************************************** 304 // ******************************************************************************************** 305 // Building New Instance: Change the HTML of a Replaceable, **WITHOUT USING SUB-CLASS' FIELDS** 306 // ******************************************************************************************** 307 // ******************************************************************************************** 308 309 310 /** 311 * This method may be used for arbitrary replacements. An instance of {@code NodeIndex} 312 * (one of its sub-classes) only contains a single {@code HTMLNode}. To change that to a list, 313 * or to remove that node altogether, invoke this method, and a new instance of 314 * {@code Replaceable} will be automatically created, and returned. 315 * 316 * <BR /><BR />This may be a little tricky at first, but the primary reason for using this 317 * method is that size-changes that would make a <B STYLE='color: red;'>single-node</B> 318 * ({@link NodeIndex} instance) into a <B STYLE='color: red;'>list</B> ({@link SubSection} 319 * instance), or vice-versa, would require building a different type of {@code Replaceable} 320 * instance. This method will automatically build that instance into a {@code Replaceable} 321 * that retains its <I>original location</I>, but reflects its <I>new contents and size</I>. 322 * 323 * <BR /><BR />Once again, the primary impetus for this method is using it with an in-place 324 * page update having multiple-replacements, <I>vis-a-vis</I> a call to 325 * {@link Replacement#run(Vector, Iterable, boolean)}. 326 * 327 * <EMBED CLASS='external-html' DATA-FILE-ID=REPL_DEF_NOTE> 328 * 329 * @param newHTML The contents of {@code 'this'} replaceable will be assigned to the the html 330 * in this parameter. 331 * 332 * @return a new replaceable whose <I><B STYLE='color: red;'>location</B> has not changed</I>, 333 * but whose contents are the contents of {@code newHTML}. 334 */ 335 public default Replaceable setHTML(Vector<HTMLNode> newHTML) 336 { 337 final int oldSize = this.originalSize(); 338 final int newSize = newHTML.size(); 339 final int sPos = this.originalLocationStart(); 340 final int ePos = this.originalLocationEnd(); 341 342 // SubSection ==> SubSection 343 if ((oldSize > 1) && (newSize > 1)) 344 return new SubSection(new DotPair(sPos, ePos - 1), newHTML); 345 346 // NodeIndex ==> NodeIndex 347 if ((oldSize == 1) && (newSize == 1)) 348 return NodeIndex.newNodeIndex(sPos, newHTML.elementAt(0)); 349 350 // Empty ==> Empty 351 if ((oldSize == 0) && (newSize == 0)) 352 return empty(sPos); 353 354 return new ReplaceableAdapter(sPos, ePos, newHTML); 355 } 356 357 /** 358 * See the description in {@link #setHTML(Vector)} to understand when to use {@code setHTML}. 359 * This method is identical, but accepts a single {@link HTMLNode} instance, instead of an html 360 * list. 361 * 362 * <EMBED CLASS='external-html' DATA-FILE-ID=REPL_DEF_NOTE> 363 * 364 * @param newHTML The contents of {@code 'this'} replaceable will be assigned to the the html 365 * contained by {@code newHTML}. (The returned instance will have the same location values) 366 * 367 * @return a new replaceable whose <I><B STYLE='color: red;'>location</B> has not changed</I>, 368 * but whose contents are {@code newHTML}. 369 * 370 * @see #setHTML(Vector) 371 */ 372 public default Replaceable setHTML(HTMLNode newHTML) 373 { 374 // NodeIndex ==> NodeIndex 375 if (this.originalSize() == 1) 376 return NodeIndex.newNodeIndex(this.originalLocationStart(), newHTML); 377 378 Vector<HTMLNode> v = new Vector<>(); 379 v.add(newHTML); 380 381 return new ReplaceableAdapter 382 (this.originalLocationStart(), this.originalLocationEnd(), v); 383 } 384 385 /** 386 * Removes all HTML from this {@code Replaceable}, such that's {@link #currentNodes()} would 387 * return an empty HTML list. 388 * 389 * <EMBED CLASS='external-html' DATA-FILE-ID=REPL_DEF_NOTE> 390 * 391 * @return a new replaceable whose original <I><B STYLE='color: red;'>location</B> has not 392 * changed</I>, but whose contents are empty. 393 * 394 * @see #setHTML(Vector) 395 */ 396 public default Replaceable clearHTML() 397 { 398 if (currentSize() == 0) return Replaceable.empty(originalLocationStart()); 399 400 return new ReplaceableAdapter 401 (originalLocationStart(), originalLocationEnd(), new Vector<>()); 402 } 403 404 405 // ******************************************************************************************** 406 // ******************************************************************************************** 407 // Creating Replacebles, using the Adapter, avoiding the Concrete-Class' exception checks. 408 // ******************************************************************************************** 409 // ******************************************************************************************** 410 411 412 /** 413 * Provides a mechanism for creating a {@link SubSection} instance whose {@code html} does not 414 * match the size of the {@code location} where that {@code html} is to be placed. 415 * 416 * @param location The range in any HTML Page by which the new {@code html} will be replaced. 417 * 418 * @param html The html that will ultimately be used to replace the current-html, <I>on a 419 * web-page, at the specified {@code location}</I>. 420 * 421 * @return An instance of a {@code Replaceable}, that is, in-effect, a {@link SubSection}, but 422 * one whose location/bounds do not match the size of the new-{@code html}. 423 * 424 * <BR /><BR /><B STYLE='color: red;'>NOTE:</B> This method allows a user to bypass the 425 * exception-check that class {@code SubSection} performs when building an instance of that 426 * class. 427 */ 428 public static Replaceable create(DotPair location, Vector<HTMLNode> html) 429 { return new ReplaceableAdapter(location.start, location.end + 1, html); } 430 431 /** 432 * Creates a new {@code Replaceable} instance whose original-location is just a single-node, 433 * but whose new {@code html} may be an arbitrarily-sized html {@code Vector}. 434 * 435 * @param location The node in any HTML Page which shall be replaced by {@code 'html'} 436 * 437 * @param html The html that will replace the node on an HTML page located at 438 * {@code 'location'} 439 * 440 * @return An instance of a {@code Replaceable} that is, in effect, a {@link SubSection}, 441 * but one whose location/bounds are not (necessarily) a single page-index. 442 * 443 * <BR /><BR /><B STYLE='color: red;'>NOTE:</B> This method allows a user to bypass the 444 * requirement that a {@code NodeIndex} occupy only a single-node. 445 */ 446 public static Replaceable create(int location, Vector<HTMLNode> html) 447 { return new ReplaceableAdapter(location, location + 1, html); } 448 449 /** 450 * Creates a new {@code Replaceable} instance whose original-location had zero-length 451 * 452 * @param location The location in any HTML Page into which the {@code 'html'} shall be 453 * inserted 454 * 455 * @param html The html that will be inserted into an HTML Page at index {@code 'location'} 456 * 457 * @return An instance of a {@code Replaceable} - whose original-location had a zero-length 458 */ 459 public static Replaceable createInsertion(int location, Vector<HTMLNode> html) 460 { return new ReplaceableAdapter(location, location, html); } 461 462 463 // ******************************************************************************************** 464 // ******************************************************************************************** 465 // After updating an HTML-Page, this will incorporate the changed size & location 466 // ******************************************************************************************** 467 // ******************************************************************************************** 468 469 470 /** 471 * This method is mostly of internal-use, mainly by 472 * {@link Replacement#run(Vector, Iterable, boolean)} 473 * 474 * <EMBED CLASS='external-html' DATA-FILE-ID=REPL_DEF_NOTE> 475 * 476 * @param sPos The new location in an html page-{@code Vector} where the contents of this 477 * {@code Replaceable} are now located. 478 * 479 * @return A new instance, whose html-contents are identical, but is located at {@code 'sPos'} 480 * (and having an ending-location of {@code sPos + currentSize()}). 481 */ 482 public default Replaceable moveAndUpdate(int sPos) 483 { 484 // IMPORTANT: This method is extremely un-important! It looks kind of unreadable. 485 // All it is doing is REGISTERING the changes to his SubSection or NodeIndex 486 // by building a new SubSection or new NodeIndex. 487 // 488 // PRIMARILY: Since the *WHOLE POINT* is to make all of the changes to an HTML Page, first, 489 // before doing an update ... Having updated Replaceable's is mostly a waste. 490 // Specifically, after the page has been updated, keeping the sub-parts of the 491 // page would no longer be necessary! 492 // 493 // ReplaceNodes: This class offers the option to 'updateReplaceablesAfterBuild' in case 494 // (for whatever reason) the user has decided another round of page updates is 495 // needed. 496 497 final int SIZE = currentSize(); 498 499 switch (SIZE) 500 { 501 case 0: return Replaceable.empty(sPos); 502 case 1: return NodeIndex.newNodeIndex(sPos, firstCurrentNode()); 503 504 default: 505 return new SubSection( 506 // DotPair.end is inclusive, so subtract 1 507 new DotPair(sPos, sPos + SIZE - 1), 508 509 // The current HTML Vector 510 currentNodes() 511 ); 512 } 513 } 514 515 516 // ******************************************************************************************** 517 // ******************************************************************************************** 518 // Creating an Empty Replaceable 519 // ******************************************************************************************** 520 // ******************************************************************************************** 521 522 523 /** 524 * Returns an empty {@code Replaceable} (an instance having 0 {@code HTMLNode's}) located at 525 * {@code sPos}. 526 * 527 * <BR /><BR /><B CLASS=JDDescLabel>NoSuchElementException:</B> 528 * 529 * <BR />Attempting to retrieve nodes from the returned-instance will generate a 530 * Java {@code NoSuchElementException}. 531 * 532 * @param sPos The location of this zero-element {@code Replaceable} 533 * @return The new instance. 534 * @throws IndexOutOfBoundsException if {@code 'sPos'} is passed a negative number. 535 */ 536 public static Replaceable empty(final int sPos) 537 { 538 if (sPos < 0) throw new IndexOutOfBoundsException 539 ("A negative value, " + sPos + ", was passed to parameter 'sPos'."); 540 541 return new ReplaceableAdapter(sPos, sPos, new Vector<>()); 542 } 543 544 545 // ******************************************************************************************** 546 // ******************************************************************************************** 547 // Synthetic 548 // ******************************************************************************************** 549 // ******************************************************************************************** 550 551 552 /** 553 * Identifies whether or not {@code 'this'} instance is an anonymous class, that was built from 554 * the (internal) {@code ReplaceableAdapter}. 555 * 556 * @return {@code TRUE} if {@code 'this'} is <B STYLE='color: red;'>neither</B> an instance 557 * that inherits {@code NodeIndex} <B STYLE='color: red;'>nor</B> inherits {@link SubSection}. 558 * Such instances are built from an internal {@code ReplaceableAdapter}, and are produced by 559 * the methods: {@link #setHTML(Vector)}, {@link #setHTML(HTMLNode)}, {@link #clearHTML()}, 560 * and {@link #empty(int)}. 561 */ 562 public default boolean isSynthetic() { return false; } 563 564 /** 565 * Simple Default Method which <B><I>does not override</I></B> the standard Java 566 * {@code toString()} method. Generates a small summary of {@code 'this'}, as a 567 * {@code java.lang.String}. 568 * 569 * @param printCurrentNodes May be used to request that the HTML-Nodes themselves be printed. 570 * @return A {@code String} summary of {@code 'this' Replaceable} instance. 571 */ 572 public default String summarize(boolean printCurrentNodes) 573 { 574 final String nodesStr = printCurrentNodes 575 ? (BCYAN + "HTML" + RESET + ":\n[" + Util.pageToString(this.currentNodes()) + "]\n") 576 : ""; 577 578 return 579 BCYAN + "Original Size" + RESET + ": " + this.originalSize() + ", " + 580 BCYAN + "Current Size" + RESET + ": " + this.currentSize() + ", " + 581 BCYAN + "Original Location" + RESET + ": [" + 582 this.originalLocationStart() + ", " + 583 this.originalLocationEnd() + 584 ']' + "\n" + 585 BCYAN + "First Current Node" + RESET + ":\n[" + this.firstCurrentNode() + "]\n" + 586 BCYAN + "Last Current Node" + RESET + ":\n[" + this.lastCurrentNode() + "]\n" + 587 nodesStr; 588 } 589}