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     * &amp; 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} &amp; {@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}