Package Torello.HTML.NodeSearch
Class HNLI<E extends HTMLNode>
- java.lang.Object
-
- Torello.HTML.NodeSearch.AbstractHNLI<E,E>
-
- Torello.HTML.NodeSearch.HNLI<E>
-
- Type Parameters:
E
- The type ofHTMLNode
being iterated.
- All Implemented Interfaces:
java.util.Iterator<E>
,java.util.ListIterator<E>
public class HNLI<E extends HTMLNode> extends AbstractHNLI<E,E>
HNLI: HTMLNode ListIterator
This is anIterator
class that has been heavily improved to allow for all types of updates, additions, removals, etc. to a vectorized-html web-page. The methods provided here allow a user to request anIterator
from the three primaryIterator
retrieval classes in this Node-Search Package.
HNLI<E> Generator Classes:- Class:
TagNodeIterator
- Class:
TextNodeIterator
- Class:
CommentNodeIterator
- Class:
InnerTagIterator
A Java GenericIterator
-Class that for iteratingTagNode
,TextNode
andCommentNode
instances which match user-provided search-criteria.
This interface builds on Java's 'ListIterator<E>' interface.
Iterator<E>
public interfacejava.util.Iterator<E>
exports these methods:boolean hasNext()
default void forEachRemaining(Consumer<? super E> action)
E next()
default void remove()
ListIterator<E>
public interfacejava.util.ListIterator<E>
extends the previousIterator
with these methods:void add(E e)
boolean hasNext()
boolean hasPrevious()
E next()
int nextIndex()
E previous()
int previousIndex()
void remove()
void set(E e)
ThisIterator
class further extends Java'sListIterator<E>
to add severalHTMLNode
andVector<HTMLNode>
specific insertion, deletion, and replacement operations. These methods are all properly-listed below in the Method-Summary Section of this class' Java-Doc Documentation-Page.
Easy to Use:
Generally, it is sometimes apparent that Java's introduction of the concept of generics - and particularly theIterator<E>
andListIterator<E>
has been somewhat down-played in some circles. The value of anIterator
is sometimes over-looked when applied to data-modification. 4 out of 6 of thestatic
method-based class-types in this package:Find, Get, Peek, Count
andCount
provide only "data-observation" of the underlying Vectorized-HTML. The other twoPoll
andRemove
, however, modify the underlyingVector
.
All of these work fine without an using anIterator
, however, there may be cases where node-replacement and node-removal on a case-by-case basis will be necessary. And that can lead to problems caused by stale data pointers.
Stale Data-Pointers Helper:
If an array of index pointers is requested:
int[] posArr = TagNodeFind.all(...)
When the user begins replacing and removing nodes using this array... if at any point the size of theVector
is changed, the entire pointer-array will immediately contain stale-data!
This can be overcome by maintaining a'Vector-size delta'
value, and offsetting each value in the pointer-array. Other tricks include modifying the data inside theVector
in reverse-order. Working with the last index-pointers first means that when or if the size of a HTML-Vector
changes, the earlier pointers will not become stale. Remember, after an insert or remove operation is done on a list, only the nodes that lay after the insert-index or remove-index are shifted!
Indeed, however, this is exactly what theHNLI
andHNLIInclusive
iterators do internally! If a programmer employs theset(...), add(...)
andremove(...)
methods provided by theIterator
-classes both in this package, and the java-interfaces they inherit, internally a size-delta and acursor
are maintained by theIterator
when & if elements are added, updated and removed.
As long long as the underlyingVector
is not modified by code outside of theIterator
methods, stale and invalid data-pointers will never be returned by the getter methods of this class. Index-Pointer Arrays are often useful, but less-so when the user plans on changing or adding sections ofHTMLNode
that change how many nodes are in the underlyingVector
.
Iterator Efficiency:
If large numbers of changes are going to be made to big Vectorized-HTML web-pages, it is much more efficient to use theReplaceable
interface than anIterator
! However, in cases where several quick change or retrieval operations are needed (and to smaller pages), and where efficiency is not imperative, writing HTML-Retrieval or Update Code using anHNLI
will usually be code that is world's easier to understand, read and write.
Hi-Lited Source-Code:- View Here: Torello/HTML/NodeSearch/HNLI.java
- Open New Browser-Tab: Torello/HTML/NodeSearch/HNLI.java
File Size: 13,971 Bytes Line Count: 344 '\n' Characters Found
-
-
Field Summary
-
Fields inherited from class Torello.HTML.NodeSearch.AbstractHNLI
c, cursor, expectedSize, maxCursor, minCursor, modifiedSince, p, v
-
-
Method Summary
Method: Next & Previous Modifier and Type Method boolean
hasNext()
boolean
hasPrevious()
Retrieve Vector Indices (Pointers) Modifier and Type Method int
firstIndex()
int
lastIndex()
int
nextIndex()
int
previousIndex()
Retrieve HTMLNode's Modifier and Type Method E
first()
E
last()
E
next()
E
previous()
-
Methods inherited from class Torello.HTML.NodeSearch.AbstractHNLI
add, add, add, addHTMLNode, CHECK_CME, CHECK_EXCEPTIONS, CHECK_EXCEPTIONS, CHECK_EXCEPTIONS, CHECK_EXCEPTIONS, clearCursorBounds, cursorLocation, insertAt, insertAt, insertAt, MODIFIED, moveCursor, moveCursorToEnd, moveCursorToStart, remove, removeElementAt, removeElements, removeRange, removeRange, replaceRange, replaceRange, restrictCursor, restrictCursor, restrictCursor, set, set, set, setHTMLNode
-
-
-
-
Method Detail
-
hasPrevious
public boolean hasPrevious()
Use this method to find out whether the underlyingVector
and currentcursor
position would retrieve another match if'previous()'
or'previousIndex()'
were called.- Returns:
- This shall return
TRUE
if calling theprevious()
, orpreviousIndex()
methods would return another node-match. This method shall returnFALSE
if callingprevious
would generate / throw a'NoSuchElementException'
- because there are no more matches in the underlyingVector
, given the currentcursor
position. - Throws:
java.util.ConcurrentModificationException
- Internal to thisIterator's
state is a privateint
-field named'expectedSize'
that is consistently maintained to know the current size of the underlying HTML-Vector
. Whenever modifications are made to that HTML with this class' Add, Set & Remove methods - this class code will also, simultaenously, update the'expectedSize'
field.
If changes to the HTML-Vector
are made outside of this class' Add, Set, Remove or Update interface-methods, then the value of this internal integer-field ('expectedSize'
) will stop being consistent with the actual size of the HTML-Vector
.
When the size of the internal HTML-Vector
does not equal the value stored inside field'expectedSize'
, this class' code will throw aConcurrentModificationException
.
NOTE: Changes to the underlyingVector
that do not modify theVector's
size simply won't be detected. This is (somewhat) due to 'a bug' in the JDK implementation ofAbstractList
where the integer-field named'modCount'
is assigned'protected'
visibility, rendering it somewhat useless.
RESET NOTE: Any call made to a variant of the providedfirst(...)
orlast(...)
methods will force a reset of this the internal integer-field'expected-size'
(to theVector's
actual size). When this field is reset, it will actually prevent theConcurrentModificationException
from throwing - even if code from outside this class has changed the size of the HTML-Vector
- because it becomes impossible to detect that change.- Code:
- Exact Method Body:
CHECK_CME(); if (hasPrevVectorPos != -1) return true; Object o; // Temp Object int LOOP_BOUNDARY = (minCursor == -1) ? 0 : minCursor; if (cursor == -1) cursor = LOOP_BOUNDARY; // will return false // System.out.println("Loop Boundary: " + LOOP_BOUNDARY + ", cursor: " + cursor); while (--cursor >= LOOP_BOUNDARY) if (c.isInstance(o = v.elementAt(cursor)) && p.test(c.cast(o))) { hasPrevVectorPos = cursor; return true; } return false;
-
previous
public E previous()
Returns the nearest node-match in the underlyingVector
, given the currentcursor
position - when searching in the left-direction, or in the direction of decreasingVector
-indices.- Returns:
- This shall return the node-match that is directly previous to the current
cursor
position. - Throws:
java.util.ConcurrentModificationException
- Internal to thisIterator's
state is a privateint
-field named'expectedSize'
that is consistently maintained to know the current size of the underlying HTML-Vector
. Whenever modifications are made to that HTML with this class' Add, Set & Remove methods - this class code will also, simultaenously, update the'expectedSize'
field.
If changes to the HTML-Vector
are made outside of this class' Add, Set, Remove or Update interface-methods, then the value of this internal integer-field ('expectedSize'
) will stop being consistent with the actual size of the HTML-Vector
.
When the size of the internal HTML-Vector
does not equal the value stored inside field'expectedSize'
, this class' code will throw aConcurrentModificationException
.
NOTE: Changes to the underlyingVector
that do not modify theVector's
size simply won't be detected. This is (somewhat) due to 'a bug' in the JDK implementation ofAbstractList
where the integer-field named'modCount'
is assigned'protected'
visibility, rendering it somewhat useless.
RESET NOTE: Any call made to a variant of the providedfirst(...)
orlast(...)
methods will force a reset of this the internal integer-field'expected-size'
(to theVector's
actual size). When this field is reset, it will actually prevent theConcurrentModificationException
from throwing - even if code from outside this class has changed the size of the HTML-Vector
- because it becomes impossible to detect that change.java.util.NoSuchElementException
- If there aren't any more matches available, this exception shall throw. Avoid having to catch this exception by always calling method'hasPrevious'
, and only invoking'previous'
if that method returnedTRUE
.- Code:
- Exact Method Body:
return (E) v.elementAt(previousIndex());
-
previousIndex
public int previousIndex()
Returns the nearest node-match, as an integerVector
-index, in the underlyingVector
, given the currentcursor
position - when searching in the left-direction, or in the direction of decreasingVector
-indices.- Returns:
- This shall return the node-match that is directly previous to the current
cursor
position. - Throws:
java.util.ConcurrentModificationException
- Internal to thisIterator's
state is a privateint
-field named'expectedSize'
that is consistently maintained to know the current size of the underlying HTML-Vector
. Whenever modifications are made to that HTML with this class' Add, Set & Remove methods - this class code will also, simultaenously, update the'expectedSize'
field.
If changes to the HTML-Vector
are made outside of this class' Add, Set, Remove or Update interface-methods, then the value of this internal integer-field ('expectedSize'
) will stop being consistent with the actual size of the HTML-Vector
.
When the size of the internal HTML-Vector
does not equal the value stored inside field'expectedSize'
, this class' code will throw aConcurrentModificationException
.
NOTE: Changes to the underlyingVector
that do not modify theVector's
size simply won't be detected. This is (somewhat) due to 'a bug' in the JDK implementation ofAbstractList
where the integer-field named'modCount'
is assigned'protected'
visibility, rendering it somewhat useless.
RESET NOTE: Any call made to a variant of the providedfirst(...)
orlast(...)
methods will force a reset of this the internal integer-field'expected-size'
(to theVector's
actual size). When this field is reset, it will actually prevent theConcurrentModificationException
from throwing - even if code from outside this class has changed the size of the HTML-Vector
- because it becomes impossible to detect that change.java.util.NoSuchElementException
- If there aren't any more matches available, this exception shall throw. Avoid having to catch this exception by always calling method'hasPrevious()'
, and only invoking'previousIndex()'
if that method returned TRUE.- Code:
- Exact Method Body:
CHECK_CME(); int temp = hasPrevVectorPos; hasPrevVectorPos = hasNextVectorPos = -1; modifiedSince = false; if (temp != -1) return temp; Object o; // Temp Object int LOOP_BOUNDARY = (minCursor == -1) ? 0 : minCursor; if (cursor == -1) cursor = LOOP_BOUNDARY; // will throw exception while (--cursor >= LOOP_BOUNDARY) if (c.isInstance(o = v.elementAt(cursor)) && p.test(c.cast(o))) return cursor; throw new NoSuchElementException("There are no more 'previous' elements available.");
-
hasNext
public boolean hasNext()
Use this method to find out whether the underlyingVector
and currentcursor
position would retrieve another match if'next()'
or'nextIndex()'
were called.- Returns:
- This shall return
TRUE
if calling thenext()
, ornextIndex()
methods would return another node-match. This method shall returnFALSE
if callingnext()
would generate / throw a'NoSuchElementException'
- because there are no more matches in the underlyingVector
, given the currentcursor
position. - Throws:
java.util.ConcurrentModificationException
- Internal to thisIterator's
state is a privateint
-field named'expectedSize'
that is consistently maintained to know the current size of the underlying HTML-Vector
. Whenever modifications are made to that HTML with this class' Add, Set & Remove methods - this class code will also, simultaenously, update the'expectedSize'
field.
If changes to the HTML-Vector
are made outside of this class' Add, Set, Remove or Update interface-methods, then the value of this internal integer-field ('expectedSize'
) will stop being consistent with the actual size of the HTML-Vector
.
When the size of the internal HTML-Vector
does not equal the value stored inside field'expectedSize'
, this class' code will throw aConcurrentModificationException
.
NOTE: Changes to the underlyingVector
that do not modify theVector's
size simply won't be detected. This is (somewhat) due to 'a bug' in the JDK implementation ofAbstractList
where the integer-field named'modCount'
is assigned'protected'
visibility, rendering it somewhat useless.
RESET NOTE: Any call made to a variant of the providedfirst(...)
orlast(...)
methods will force a reset of this the internal integer-field'expected-size'
(to theVector's
actual size). When this field is reset, it will actually prevent theConcurrentModificationException
from throwing - even if code from outside this class has changed the size of the HTML-Vector
- because it becomes impossible to detect that change.- Code:
- Exact Method Body:
CHECK_CME(); if (hasNextVectorPos != -1) return true; Object o; // Temp Object int LOOP_BOUNDARY = (maxCursor == -1) ? (v.size() - 1) : maxCursor; if (cursor == -1) cursor = (minCursor == -1) ? -1 : (minCursor-1); // System.out.println("Loop Boundary: " + LOOP_BOUNDARY + ", cursor: " + cursor); while (++cursor <= LOOP_BOUNDARY) if (c.isInstance(o = v.elementAt(cursor)) && p.test(c.cast(o))) { hasNextVectorPos=cursor; return true; } return false;
-
next
public E next()
Returns the nearest node-match in the underlyingVector
, given the currentcursor
position - when searching in the right-direction, or in the direction of increasingVector
-indices.- Returns:
- This shall return the node-match that is directly next to the current
cursor
position. - Throws:
java.util.ConcurrentModificationException
- Internal to thisIterator's
state is a privateint
-field named'expectedSize'
that is consistently maintained to know the current size of the underlying HTML-Vector
. Whenever modifications are made to that HTML with this class' Add, Set & Remove methods - this class code will also, simultaenously, update the'expectedSize'
field.
If changes to the HTML-Vector
are made outside of this class' Add, Set, Remove or Update interface-methods, then the value of this internal integer-field ('expectedSize'
) will stop being consistent with the actual size of the HTML-Vector
.
When the size of the internal HTML-Vector
does not equal the value stored inside field'expectedSize'
, this class' code will throw aConcurrentModificationException
.
NOTE: Changes to the underlyingVector
that do not modify theVector's
size simply won't be detected. This is (somewhat) due to 'a bug' in the JDK implementation ofAbstractList
where the integer-field named'modCount'
is assigned'protected'
visibility, rendering it somewhat useless.
RESET NOTE: Any call made to a variant of the providedfirst(...)
orlast(...)
methods will force a reset of this the internal integer-field'expected-size'
(to theVector's
actual size). When this field is reset, it will actually prevent theConcurrentModificationException
from throwing - even if code from outside this class has changed the size of the HTML-Vector
- because it becomes impossible to detect that change.java.util.NoSuchElementException
- If there aren't any more matches available, this exception shall throw. Avoid having to catch this exception by always calling method'hasNext()'
, and only invoking'next()'
if that method returnedTRUE
.- Code:
- Exact Method Body:
return (E) v.elementAt(nextIndex());
-
nextIndex
public int nextIndex()
Returns the nearest node-match, as an integerVector
-index, in the underlyingVector
, given the currentcursor
position - when searching in the right-direction, or in the direction of increasingVector
-indices.- Returns:
- This shall return the node-match that is directly next to the current
cursor
position. - Throws:
java.util.ConcurrentModificationException
- Internal to thisIterator's
state is a privateint
-field named'expectedSize'
that is consistently maintained to know the current size of the underlying HTML-Vector
. Whenever modifications are made to that HTML with this class' Add, Set & Remove methods - this class code will also, simultaenously, update the'expectedSize'
field.
If changes to the HTML-Vector
are made outside of this class' Add, Set, Remove or Update interface-methods, then the value of this internal integer-field ('expectedSize'
) will stop being consistent with the actual size of the HTML-Vector
.
When the size of the internal HTML-Vector
does not equal the value stored inside field'expectedSize'
, this class' code will throw aConcurrentModificationException
.
NOTE: Changes to the underlyingVector
that do not modify theVector's
size simply won't be detected. This is (somewhat) due to 'a bug' in the JDK implementation ofAbstractList
where the integer-field named'modCount'
is assigned'protected'
visibility, rendering it somewhat useless.
RESET NOTE: Any call made to a variant of the providedfirst(...)
orlast(...)
methods will force a reset of this the internal integer-field'expected-size'
(to theVector's
actual size). When this field is reset, it will actually prevent theConcurrentModificationException
from throwing - even if code from outside this class has changed the size of the HTML-Vector
- because it becomes impossible to detect that change.java.util.NoSuchElementException
- If there aren't any more matches available, this exception shall throw. Avoid having to catch this exception by always calling method'hasNext()'
, and only invoking'nextIndex()'
if that method returned TRUE.- Code:
- Exact Method Body:
CHECK_CME(); int temp = hasNextVectorPos; hasPrevVectorPos = hasNextVectorPos = -1; modifiedSince = false; if (temp != -1) return temp; Object o; // Temp Object int LOOP_BOUNDARY = (maxCursor == -1) ? (v.size() - 1) : maxCursor; if (cursor == -1) cursor = (minCursor == -1) ? -1 : (minCursor-1); while (++cursor <= LOOP_BOUNDARY) if (c.isInstance(o = v.elementAt(cursor)) && p.test(c.cast(o))) return cursor; throw new NoSuchElementException("There are no more 'next' elements available.");
-
firstIndex
public int firstIndex()
This method will "reset the internalcursor
" to the beginning, and return the index of the first node-match (rather than the node itself).
Cursor Reset Method:
This method is (somewhat / sort-of) of a Reset-Method - because the internal-cursor
is moved to the beginning of the underlying-Vector
. Whenever the cursor is moved (or restricted), this class' code will check for the possibility of aConcurrentModificationException
.
In normal situations, when statements or method's from outside the update methods in this class, modify the underlying html-Vector
aConcurrentModificationException
shall throw. However, whenever anHTML Node List Iterator
method moves the cursor, the logic for checking Concurrent-Modification will reset (by setting the internal'expectedSize'
field tov.size()
).
This 'resetting' of the internal'expectedSize'
field is precisely how to prevent an exception throw due to outside modification of the underlyingVector
.- Returns:
- The index of the very-first node-match in this list. As with other
Iterator
-retrieval methods, if the underlyingVector
has been changed using calls to:set, remove,
oradd
, then this method will return the first-integer index of the node-match for the modified-Vector
. - Code:
- Exact Method Body:
cursor = (minCursor == -1) ? 0 : minCursor; hasNextVectorPos = hasPrevVectorPos = -1; expectedSize = v.size(); // NOTE: A call to first, last, firstIndex, or lastIndex // "resets" the CME Monitor-Logic ==> expectedSize = v.size(); return nextIndex();
-
lastIndex
public int lastIndex()
This method will "advance the internalcursor
" to the end of theVector
, and return the index of the last node-match (rather than the node itself).
Cursor Reset Method:
This method is (somewhat / sort-of) of a Reset-Method - because the internal-cursor
is moved to the beginning of the underlying-Vector
. Whenever the cursor is moved (or restricted), this class' code will check for the possibility of aConcurrentModificationException
.
In normal situations, when statements or method's from outside the update methods in this class, modify the underlying html-Vector
aConcurrentModificationException
shall throw. However, whenever anHTML Node List Iterator
method moves the cursor, the logic for checking Concurrent-Modification will reset (by setting the internal'expectedSize'
field tov.size()
).
This 'resetting' of the internal'expectedSize'
field is precisely how to prevent an exception throw due to outside modification of the underlyingVector
.- Returns:
- The index of the very-last node-match in this list. As with other
Iterator
-retrieval methods, if the underlyingVector
has been changed using calls to:set, remove,
oradd
, then this method will return the last-integer index of the node-match for the modified-Vector
. - Code:
- Exact Method Body:
cursor = (maxCursor == -1) ? (v.size() - 1) : maxCursor; hasNextVectorPos = hasPrevVectorPos = -1; expectedSize = v.size(); // NOTE: A call to first, last, firstIndex, or lastIndex // "resets" the CME Monitor-Logic ==> expectedSize = v.size(); return previousIndex();
-
-