Package Torello.HTML
Interface Replaceable
-
- All Superinterfaces:
java.lang.Comparable<Replaceable>
- All Known Implementing Classes:
CommentNodeIndex,NodeIndex,SubSection,TagNodeIndex,TextNodeIndex
public interface Replaceable extends java.lang.Comparable<Replaceable>
The classReplacementoffers a great efficiency-improvement optimization for modifying vectorized-HTML. HTML Pages can be very long, and the insertion or removal of a piece or snippet of HMTL may result in the shifting of hundreds (or even thousands!) ofHTMLNode's. This can incur a non-trivial performance cost if many there are many updates and changes to be made to a page.
Exceprt fromcurrentNodes():Replaceable'sare, sort-of, the exact opposite of Java'sListmethod'subList'. According to the Sun / Oracle Documentation forjava.util.List.subList(int fromIndex, int toIndex), any changes ffinamade to an instance of a'subList'are immediately reflected back into the originalListfrom where they were created.
TheList.subListoperation has the advantage of being extremely easy to work with - however, an HTML-PageVectorhas the potential of being hundreds of nodes long. Any operations that involve insertion or deletion will likely be terribly inefficient.
When the HTML inside of aReplaceableis modified - nothing happens to the originalVectorwhatsoever!. Until a user requests that the original HTML-Vectorbe updated to reflect all changes that he or she has made, the original HTML remains untouched. When an update request is finally issued, all changes are made all at once, and at the same time!
Again - seeReplacement.run(Vector, Iterable, boolean)to understand how quick updates on HTML-Pages is done using theReplaceableinterface.
Though this class may look somewhat complicated to understand, in all reality it is actually very simple. Load a web-page from disk (or download one from the Internet) and run it through the parser (classHTMLPage) to make a Vectorized-HTML Page. Next, build a few instances ofSubSectionwhich hold both the location of an HTML snippet and HTML itself.
Finallly, make whatever modifications you want to those HTML snippets, and call theReplacement.run()method! The page should be updated quickly with little cost overhead.
Peek Operation Replaceables
The classInnerTagPeekInclusiveandTagNodePeekInclusivewill always generate properly ordered / sorted references that implement theReplaceableinterface! Furthermore, these instances will be ones that are sorted and do not overlap.
This means that if a set or collection ofReplaceable'swere created using theNodeSearch 'Peek'Search-Classes, theReplacement.run(Vector, Iterable, boolean)requirements that theReplaceable'sbe ordered, sorted and non-overlapping would be automatically met.
This interface is implemented by all return-values for theNodeSearchPeek operations.
Hi-Lited Source-Code:- View Here: Torello/HTML/Replaceable.java
- Open New Browser-Tab: Torello/HTML/Replaceable.java
File Size: 28,717 Bytes Line Count: 591 '\n' Characters Found
-
-
Method Summary
Number / Vector-Size of Nodes Modifier and Type Method intcurrentSize()intoriginalSize()Location of the Node(s) in the Original-Vector Modifier and Type Method intoriginalLocationEnd()intoriginalLocationStart()Retrieving the Node(s) Modifier and Type Method Vector<HTMLNode>currentNodes()HTMLNodefirstCurrentNode()HTMLNodelastCurrentNode()Updating the Original-Vector, from whence these Node(s) were Extracted Modifier and Type Method intupdate(Vector<HTMLNode> originalHTML)Insert the Node(s) within this Instance into an HTML-Vector Modifier and Type Method booleanaddAllInto(int index, Vector<HTMLNode> html)booleanaddAllInto(Vector<HTMLNode> html)Build new Replaceable which Reflects New Nodes & Size, Incorprates New Location Modifier and Type Method default ReplaceablemoveAndUpdate(int sPos)Build new Replaceable using Original-Location, but having New Nodes & Size Modifier and Type Method default ReplaceableclearHTML()default ReplaceablesetHTML(Vector<HTMLNode> newHTML)default ReplaceablesetHTML(HTMLNode newHTML)Build an Empty Replaceable Modifier and Type Method static Replaceableempty(int sPos)Create a new Replaceable, avoiding the Limitations of SubSection&NodeIndexModifier and Type Method static Replaceablecreate(int location, Vector<HTMLNode> html)static Replaceablecreate(DotPair location, Vector<HTMLNode> html)static ReplaceablecreateInsertion(int location, Vector<HTMLNode> html)Methods: interface java.lang.Comparable Modifier and Type Method default intcompareTo(Replaceable other)Test if thisInstance is an Anonymous ClassModifier and Type Method default booleanisSynthetic()Default-Method which generates a String-Summary of 'this'; doesn't override toString() Modifier and Type Method default Stringsummarize(boolean printCurrentNodes)
-
-
-
Method Detail
-
compareTo
default int compareTo(Replaceable other)
Java'sComparableinterface requirements.- Specified by:
compareToin interfacejava.lang.Comparable<Replaceable>- Returns:
- An integer based on comparing the starting locations for two
Replaceableinstances. - Code:
- Exact Method Body:
return this.originalLocationStart() - other.originalLocationStart();
-
originalSize
int originalSize()
Reports how many nodes were copied intothisinstance. For implementing classes that inheritNodeIndex, this value will always be one. For others, it should report exactly how manyHTMLNode'swere copied.- Returns:
- Number of nodes originally contained by
thisinstance.
The purpose ofReplaceable'sis to allow a user to modify HTML using a smaller sub-list, without having to operate on the entire HTML-Vectorsince adding & removing nodes is one variant ofVector-modification, the original-size may often differ from the current-size.
When modifying HTML, if a web-page is broken into smaller-pieces, and changes are restricted to those smaller sub-lists (and the original page is rebuilt, all at once, after all changes have been made) then those modifications should require far-fewer time-consuming list-shift operations, tremendously improving the performance of the code.
-
currentSize
int currentSize()
Returns how many nodes are currently inthisinstance.- Returns:
- Number of nodes. See explanation of the original size,
versus the current size
here
-
originalLocationStart
int originalLocationStart()
Returns the start-location within the original page-Vectorfrom whence the HTML contents ofthisinstance were retrieved.
Start is Inclusive:
The returned value is inclusive of the actual, original-range ofthisinstance. This means the firstHTMLNodecopied intothisinstance' internal data-structure was atoriginalLocationStart().
Implementations of Replaceable:
The two concrete implementatons of this interface (NodeIndexandSubSection) - both enforce the'final'modifier on their location-fields. (See:NodeIndex.indexandSubSection.location).- Returns:
- The
Vectorstart-index from whence this HTML was copied.
-
originalLocationEnd
int originalLocationEnd()
Returns the end-location within the original page-Vectorfrom whence the HTML contents ofthisinstance were retrieved.
Start is Exclusive:
The returned value is exclusive of the actual, original-range ofthisinstance. This means the lastHTMLNodecopied intothisinstance' internal data-structure was atoriginalLocationEnd() - 1
Implementations of Replaceable:
The two concrete implementatons of this interface (NodeIndexandSubSection) - both enforce the'final'modifier on their location-fields. (See:NodeIndex.indexandSubSection.location).- Returns:
- The
Vectorend-index from whence this HTML was copied.
-
currentNodes
java.util.Vector<HTMLNode> currentNodes()
All nodes currently contained by thisReplaceable. The concrete-classes which implementReplaceable(SubSection&TagNodeIndex) allow for the html they hold to be modified. The modification to aReplaceablehappens independently from the original HTML Page out of which it was copied.Replaceable'sare, sort-of, the exact opposite of Java'sListmethod'subList'. According to the Sun / Oracle Documentation forjava.util.List.subList(int fromIndex, int toIndex), any changes made to an instance of a'subList'are immediately reflected back into the originalListfrom where they were created.
TheList.subListoperation has the advantage of being extremely easy to work with - however, an HTML-PageVectorhas the potential of being hundreds of nodes long. Any operations that involve insertion or deletion will likely be terribly inefficient.
When the HTML inside of aReplaceableis modified - nothing happens to the originalVectorwhatsoever!. Until a user requests that the original HTML-Vectorbe updated to reflect all changes that he or she has made, the original HTML remains untouched. When an update request is finally issued, all changes are made all at once, and at the same time!
Again - seeReplacement.runto understand how quick updates on HTML-Pages is done using theReplaceableinterface.- Returns:
- An HTML-
Vectorof the nodes.
The HTML-Vectorwhich is returned by this method may be modified in any way that is necessary! If or when a user requests that the original HTML-Vectorbe updated to accomodate the changes that have been made, the contents of theVectorwhich is returned by this method will be used to replace the original-HTML.
If this method is invoked more than once, the same exactVectorwill be returned each time that the Current-Nodes are requested. The internal "Current-Nodes" HTML-Vectoris a "per instance" Singleton-InstanceVector.
-
firstCurrentNode
HTMLNode firstCurrentNode()
The first node currently contained by thisReplaceable- Returns:
- The First Node
-
lastCurrentNode
HTMLNode lastCurrentNode()
The last node currently contained by thisReplaceable- Returns:
- The last node
-
addAllInto
boolean addAllInto(java.util.Vector<HTMLNode> html)
Add all nodes currently retained inthisinstance into the HTML-Vectorparameterhtml. The nodes are appended to the end of'html'. Implementing classesNodeIndexandSubSectionsimply use the JavaVectormethod'sadd(forNodeIndex) andaddAll(forSubSection).- Parameters:
html- The HTML-Vectorinto which the nodes will be appended (to the end of thisVector, usingVectormethodsaddoraddAlldependent upon whether one or more-than-one nodes are being inserted).- Returns:
- The result of
Vectormethodadd, or methodallAll
-
addAllInto
boolean addAllInto(int index, java.util.Vector<HTMLNode> html)
Add all nodes currently retained inthisinstance into the HTML-Vectorparameterhtml.- Parameters:
index- The'html'parameter'sVector-index where these nodes are to be insertedhtml- The HTML-Vectorinto which the nodes will be appended (to the end of thisVector, usingVectormethodsaddoraddAlldependent upon whether one or more-than-one nodes are being inserted).- Returns:
- The result of
Vectormethodadd, or methodallAll
-
update
int update(java.util.Vector<HTMLNode> originalHTML)
Replaces the original range of nodes insideoriginalHTMLwith the current-nodes ofthisinstance, using the original-location of the node(s).
Replaceable's Primary Value:
The main value of using theReplaceableinterface is to allow for more expedient replacing / modifying HTML Pages. If many changes need to be made to a page, first extracting and copying the sub-sections that need changing intoReplaceable'sinstances (using the Peek operations in package NodeSearch), and then re-copying those sections back into the original page-Vectorafter changing them - avoids the cost that would be incurred from repeatedly inserting and shifting a long list of nodes in a large HTML Page.
Therefore, this method is probably best avoided, as it is defeating the entire-purpose of aRelaceable. This method will update the nodes at the location in the original-Vector, which is fine, but if more than one update / change is needed, using this method over-and-over again will re-introduce the exact shifting that was supposed to be avoided by (and is the whole reason for...) usingReplaceable'sin the first place!
The following example should make this clear:
Example:
Vector<HTMLNode> page = HTMLPage.getPageTokens(new URL("http://some.url.com/"), false); Vector<SubSection> myTableRows = TagNodePeekInclusive.all(page, "tr"); TagNode OPEN_SPAN = HTMLTags.hasTag("SPAN", TC.OpeningTags); TagNode CLOSE_SPAN = HTMLTags.hasTag("SPAN", TC.ClosingTags); int counter = 1; for (SubSection tableRow : myTableRows) { // Retrieve the <TR> Tag & Give it a CSS-ID TagNode tr = tableRow.html.elementAt(0).asTagNode().setID("ROW" + counter++, null); // Put the newly created <TR ID=..> into the vector. It was the first-element in the SubSection tableRow.html.setElementAt(tr, 0); // Add a <SPAN>...</SPAN> surrounding the first line of text // NOTE: This assumes that tableRow[1] (second SubSection node) is a TextNode with text tableRow.html.insertElementAt(OPEN_SPAN, 1); tableRow.html.insertElementAt(CLOSE_SPAN, 3); } // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // This version DESTROYS THE BENEFIT of using TagNodePeekInclusive // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // // Here, if the original html-page was thousands of nodes long, every table-row // update will force thousands of nodes to be shifted to the right over-and-over // again! for (SubSection tableRow : myTableRows) tableRow.update(page); // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // This builds a new Vector much more efficiently, avoiding costly node-shifting // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** page = ReplaceNodes.r(page, myTableRows, false).a;
- Parameters:
originalHTML- The original page-Vectorwhere the nodes inthisinstance were retrieved- Returns:
- The change in the size of the
Vector - Throws:
java.lang.IndexOutOfBoundsException- IforiginalLocationStart()ororiginalLocationEnd()are not within the bounds of the input html-page.- See Also:
Replacement.run(Vector, Iterable, boolean)
-
setHTML
default Replaceable setHTML(java.util.Vector<HTMLNode> newHTML)
This method may be used for arbitrary replacements. An instance ofNodeIndex(one of its sub-classes) only contains a singleHTMLNode. To change that to a list, or to remove that node altogether, invoke this method, and a new instance ofReplaceablewill be automatically created, and returned.
This may be a little tricky at first, but the primary reason for using this method is that size-changes that would make a single-node (NodeIndexinstance) into a list (SubSectioninstance), or vice-versa, would require building a different type ofReplaceableinstance. This method will automatically build that instance into aReplaceablethat retains its original location, but reflects its new contents and size.
Once again, the primary impetus for this method is using it with an in-place page update having multiple-replacements, vis-a-vis a call toReplacement.run(Vector, Iterable, boolean).
Generates New Instance:
This is an Interface-Default method. This method generates a new, anonymous, instance of theReplaceableinterface. This means that it is imperative if you are using a reference,ListorVectorcontaining a class that implements theReplaceable-Interface, to update your reference with the Object-Instance that is returned by this method!- Parameters:
newHTML- The contents of'this'replaceable will be assigned to the the html in this parameter.- Returns:
- a new replaceable whose location has not changed,
but whose contents are the contents of
newHTML. - Code:
- Exact Method Body:
final int oldSize = this.originalSize(); final int newSize = newHTML.size(); final int sPos = this.originalLocationStart(); final int ePos = this.originalLocationEnd(); // SubSection ==> SubSection if ((oldSize > 1) && (newSize > 1)) return new SubSection(new DotPair(sPos, ePos - 1), newHTML); // NodeIndex ==> NodeIndex if ((oldSize == 1) && (newSize == 1)) return NodeIndex.newNodeIndex(sPos, newHTML.elementAt(0)); // Empty ==> Empty if ((oldSize == 0) && (newSize == 0)) return empty(sPos); return new ReplaceableAdapter(sPos, ePos, newHTML);
-
setHTML
default Replaceable setHTML(HTMLNode newHTML)
See the description insetHTML(Vector)to understand when to usesetHTML. This method is identical, but accepts a singleHTMLNodeinstance, instead of an html list.
Generates New Instance:
This is an Interface-Default method. This method generates a new, anonymous, instance of theReplaceableinterface. This means that it is imperative if you are using a reference,ListorVectorcontaining a class that implements theReplaceable-Interface, to update your reference with the Object-Instance that is returned by this method!- Parameters:
newHTML- The contents of'this'replaceable will be assigned to the the html contained bynewHTML. (The returned instance will have the same location values)- Returns:
- a new replaceable whose location has not changed,
but whose contents are
newHTML. - See Also:
setHTML(Vector)- Code:
- Exact Method Body:
// NodeIndex ==> NodeIndex if (this.originalSize() == 1) return NodeIndex.newNodeIndex(this.originalLocationStart(), newHTML); Vector<HTMLNode> v = new Vector<>(); v.add(newHTML); return new ReplaceableAdapter (this.originalLocationStart(), this.originalLocationEnd(), v);
-
clearHTML
default Replaceable clearHTML()
Removes all HTML from thisReplaceable, such that'scurrentNodes()would return an empty HTML list.
Generates New Instance:
This is an Interface-Default method. This method generates a new, anonymous, instance of theReplaceableinterface. This means that it is imperative if you are using a reference,ListorVectorcontaining a class that implements theReplaceable-Interface, to update your reference with the Object-Instance that is returned by this method!- Returns:
- a new replaceable whose original location has not changed, but whose contents are empty.
- See Also:
setHTML(Vector)- Code:
- Exact Method Body:
if (currentSize() == 0) return Replaceable.empty(originalLocationStart()); return new ReplaceableAdapter (originalLocationStart(), originalLocationEnd(), new Vector<>());
-
create
static Replaceable create(DotPair location, java.util.Vector<HTMLNode> html)
Provides a mechanism for creating aSubSectioninstance whosehtmldoes not match the size of thelocationwhere thathtmlis to be placed.- Parameters:
location- The range in any HTML Page by which the newhtmlwill be replaced.html- The html that will ultimately be used to replace the current-html, on a web-page, at the specifiedlocation.- Returns:
- An instance of a
Replaceable, that is, in-effect, aSubSection, but one whose location/bounds do not match the size of the new-html.This method allows a user to bypass the exception-check that classSubSectionperforms when building an instance of that class. - Code:
- Exact Method Body:
return new ReplaceableAdapter(location.start, location.end + 1, html);
-
create
static Replaceable create(int location, java.util.Vector<HTMLNode> html)
Creates a newReplaceableinstance whose original-location is just a single-node, but whose newhtmlmay be an arbitrarily-sized htmlVector.- Parameters:
location- The node in any HTML Page which shall be replaced by'html'html- The html that will replace the node on an HTML page located at'location'- Returns:
- An instance of a
Replaceablethat is, in effect, aSubSection, but one whose location/bounds are not (necessarily) a single page-index.This method allows a user to bypass the requirement that aNodeIndexoccupy only a single-node. - Code:
- Exact Method Body:
return new ReplaceableAdapter(location, location + 1, html);
-
createInsertion
static Replaceable createInsertion(int location, java.util.Vector<HTMLNode> html)
Creates a newReplaceableinstance whose original-location had zero-length- Parameters:
location- The location in any HTML Page into which the'html'shall be insertedhtml- The html that will be inserted into an HTML Page at index'location'- Returns:
- An instance of a
Replaceable- whose original-location had a zero-length - Code:
- Exact Method Body:
return new ReplaceableAdapter(location, location, html);
-
moveAndUpdate
default Replaceable moveAndUpdate(int sPos)
This method is mostly of internal-use, mainly byReplacement.run(Vector, Iterable, boolean)
Generates New Instance:
This is an Interface-Default method. This method generates a new, anonymous, instance of theReplaceableinterface. This means that it is imperative if you are using a reference,ListorVectorcontaining a class that implements theReplaceable-Interface, to update your reference with the Object-Instance that is returned by this method!- Parameters:
sPos- The new location in an html page-Vectorwhere the contents of thisReplaceableare now located.- Returns:
- A new instance, whose html-contents are identical, but is located at
'sPos'(and having an ending-location ofsPos + currentSize()). - Code:
- Exact Method Body:
// IMPORTANT: This method is extremely un-important! It looks kind of unreadable. // All it is doing is REGISTERING the changes to his SubSection or NodeIndex // by building a new SubSection or new NodeIndex. // // PRIMARILY: Since the *WHOLE POINT* is to make all of the changes to an HTML Page, first, // before doing an update ... Having updated Replaceable's is mostly a waste. // Specifically, after the page has been updated, keeping the sub-parts of the // page would no longer be necessary! // // ReplaceNodes: This class offers the option to 'updateReplaceablesAfterBuild' in case // (for whatever reason) the user has decided another round of page updates is // needed. final int SIZE = currentSize(); switch (SIZE) { case 0: return Replaceable.empty(sPos); case 1: return NodeIndex.newNodeIndex(sPos, firstCurrentNode()); default: return new SubSection( // DotPair.end is inclusive, so subtract 1 new DotPair(sPos, sPos + SIZE - 1), // The current HTML Vector currentNodes() ); }
-
empty
static Replaceable empty(int sPos)
Returns an emptyReplaceable(an instance having 0HTMLNode's) located atsPos.
NoSuchElementException:
Attempting to retrieve nodes from the returned-instance will generate a JavaNoSuchElementException.- Parameters:
sPos- The location of this zero-elementReplaceable- Returns:
- The new instance.
- Throws:
java.lang.IndexOutOfBoundsException- if'sPos'is passed a negative number.- Code:
- Exact Method Body:
if (sPos < 0) throw new IndexOutOfBoundsException ("A negative value, " + sPos + ", was passed to parameter 'sPos'."); return new ReplaceableAdapter(sPos, sPos, new Vector<>());
-
isSynthetic
default boolean isSynthetic()
Identifies whether or not'this'instance is an anonymous class, that was built from the (internal)ReplaceableAdapter.- Returns:
TRUEif'this'is neither an instance that inheritsNodeIndexnor inheritsSubSection. Such instances are built from an internalReplaceableAdapter, and are produced by the methods:setHTML(Vector),setHTML(HTMLNode),clearHTML(), andempty(int).- Code:
- Exact Method Body:
return false;
-
summarize
default java.lang.String summarize(boolean printCurrentNodes)
Simple Default Method which does not override the standard JavatoString()method. Generates a small summary of'this', as ajava.lang.String.- Parameters:
printCurrentNodes- May be used to request that the HTML-Nodes themselves be printed.- Returns:
- A
Stringsummary of'this' Replaceableinstance. - Code:
- Exact Method Body:
final String nodesStr = printCurrentNodes ? (BCYAN + "HTML" + RESET + ":\n[" + Util.pageToString(this.currentNodes()) + "]\n") : ""; return BCYAN + "Original Size" + RESET + ": " + this.originalSize() + ", " + BCYAN + "Current Size" + RESET + ": " + this.currentSize() + ", " + BCYAN + "Original Location" + RESET + ": [" + this.originalLocationStart() + ", " + this.originalLocationEnd() + ']' + "\n" + BCYAN + "First Current Node" + RESET + ":\n[" + this.firstCurrentNode() + "]\n" + BCYAN + "Last Current Node" + RESET + ":\n[" + this.lastCurrentNode() + "]\n" + nodesStr;
-
-