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