001package Torello.HTML; 002 003import java.util.*; 004 005import java.util.function.ObjIntConsumer; 006 007// This is only needed for the Java Doc {@link ...} taglets. 008import Torello.HTML.NodeSearch.TagNodePeekL1Inclusive; 009 010import Torello.Java.LV; 011 012/** 013 * Methods for quickly & efficiently replacing the nodes on a Web-Page. 014 * 015 * <BR /><BR /><EMBED CLASS='external-html' DATA-FILE-ID=REPLACE_NODES> 016 */ 017@Torello.JavaDoc.StaticFunctional 018public class ReplaceNodes 019{ 020 private ReplaceNodes() { } 021 022 /** 023 * Allows a user to quickly alter each <B STYLE='color: red;'>row</B> in an HTML 024 * <B STYLE='color: red;'>table</B>, iteratively, in a manner that offers a tremendous 025 * efficiency-improvement over the HTML {@code Iterator's} in the Node Seach Package. 026 * 027 * <EMBED CLASS='external-html' DATA-FILE-ID=REPL_NODES_FAST DATA-ITEM='table-row'> 028 * 029 * <BR /><BR /><UL CLASS=JDUL> 030 * 031 * <LI> {@code 'page'} is not null. 032 * </LI> 033 * 034 * <LI> {@code 'table'} is non-null, and has {@link DotPair#start} and {@link DotPair#end} 035 * indices with integer-values smaller than the size of {@code 'page'} 036 * </LI> 037 * 038 * <LI> {@code 'table'} has indices which point to {@code TagNode's} in {@code 'page'} that 039 * are opening {@code <TABLE>} and closing {@code </TABLE>} tags. 040 * </LI> 041 * 042 * </UL> 043 * 044 * @param page Any HTML Page or sub-page that has a table. 045 * @param table A pointer to the table start and end index bounds. 046 * 047 * @param tableRowModifier <EMBED CLASS='external-html' DATA-TYPE=Table DATA-ENTITY=Row 048 * DATA-FILE-ID=REPL_NODES_ROW_MOD> 049 * 050 * @return <EMBED CLASS='external-html' DATA-FILE-ID=REPLACEMENT_MRET> 051 * <!-- Bororwed from Replacement.run(...) --> 052 * 053 * @see TagNodePeekL1Inclusive 054 * @see Replacement#run(Vector, Iterable, boolean) 055 * @see DotPair#exceptionCheck(Vector, String[]) 056 * @see SubSection 057 * <!-- In the JD Comments 'external-html/' directory, this is filed under 'r02r03/' --> 058 */ 059 public static Vector<HTMLNode> tableTR( 060 Vector<HTMLNode> page, DotPair table, 061 ObjIntConsumer<Vector<HTMLNode>> tableRowModifier 062 ) 063 { 064 // Ensure that page.elementAt(table.start) contains a "<TABLE>" element, and that 065 // page.elementAt(table.end) contains a "</TABLE>" element. 066 // 067 // If some other type of TagNode, or a non-TagNode is present, this method throws one of 068 // several exceptions to inform the user about the error. 069 070 table.exceptionCheck(page, "table"); 071 072 073 // Retrieve all "<TR> ... </TR>" elements. The "L1Inclusive" stipulates that any potential 074 // inner-table rows (if there are any inner-tables), should be ignored. 075 076 Vector<SubSection> rows = TagNodePeekL1Inclusive.all(page, table.start, table.end, "tr"); 077 078 // All this does is invoke the user-provided function-pointer on each table-row 079 for (int i=0; i < rows.size(); i++) tableRowModifier.accept(rows.elementAt(i).html, i); 080 081 082 // Update all Table-Rows. Remove the old Rows, and insert the new ones. This replace 083 // operation does this much more efficiently than most replacement-code. 084 085 return Replacement.run(page, rows, false).a; 086 } 087 088 /** 089 * Allows a user to quickly alter each <B STYLE='color: red;'>item</B> in an HTML 090 * <B STYLE='color: red;'>list</B> ({@code <OL>, <UL>} or {@code <MENU>}), iteratively, in a 091 * manner that offers a tremendous efficiency-improvement over the HTML {@code Iterator's} in 092 * the Node Seach Package. 093 * 094 * <EMBED CLASS='external-html' DATA-FILE-ID=REPL_NODES_FAST DATA-ITEM='list-item'> 095 * 096 * <BR /><BR /><UL CLASS=JDUL> 097 * 098 * <LI> {@code 'page'} is not null. 099 * </LI> 100 * 101 * <LI> {@code 'list'} is non-null, and has {@link DotPair#start} and {@link DotPair#end} 102 * indices with integer-values smaller than the size of {@code 'page'} 103 * </LI> 104 * 105 * <LI> {@code 'list'} has indices which point to {@code TagNode's} in {@code 'page'} that 106 * are opening-and-closing {@code <UL>, <OL>} or {@code <MENU>} tags. 107 * </LI> 108 * 109 * </UL> 110 * 111 * @param page Any HTML Page or sub-page that has an {@code <OL>, <UL>} or {@code <MENU>}. 112 * @param list A pointer to the list start and end index bounds. 113 * 114 * @param listItemModifier <EMBED CLASS='external-html' DATA-TYPE=List DATA-ENTITY=Item 115 * DATA-FILE-ID=REPL_NODES_ROW_MOD> 116 * 117 * @return <EMBED CLASS='external-html' DATA-FILE-ID=REPLACEMENT_MRET> <!-- Bororwed from R01 RET --> 118 * 119 * @see TagNodePeekL1Inclusive 120 * @see Replacement#run(Vector, Iterable, boolean) 121 * @see DotPair#exceptionCheck(Vector, String[]) 122 * @see SubSection 123 * <!-- In the JD Comments 'external-html/' directory, this is filed under 'r02r03/' --> 124 */ 125 public static Vector<HTMLNode> listLI( 126 Vector<HTMLNode> page, DotPair list, 127 ObjIntConsumer<Vector<HTMLNode>> listItemModifier 128 ) 129 { 130 // Ensure that page.elementAt(list.start) contains an "<OL>", "<UL>", or "<MENU>" element, 131 // and that page.elementAt(list.end) contains an "</OL>", "</UL>" or "</MENU>" element. 132 // 133 // If some other type of TagNode, or a non-TagNode is present, this method throws one of 134 // several exceptions to inform the user about the error. 135 136 list.exceptionCheck(page, "ol", "ul", "menu"); 137 138 139 // Retrieve all "<LI> ... </LI>" elements. The "L1Inclusive" stipulates that any potential 140 // inner-list items (if there are any inner-lists), should be ignored. 141 142 Vector<SubSection> items = TagNodePeekL1Inclusive.all(page, list.start, list.end, "li"); 143 144 // All this does is invoke the user-provided function-pointer on each list-item 145 for (int i=0; i < items.size(); i++) listItemModifier.accept(items.elementAt(i).html, i); 146 147 148 // Update all items. Remove the old-Items, and insert the new ones. This replace 149 // operation does this much more efficiently than most replacement-code. 150 151 return Replacement.run(page, items, false).a; 152 } 153 154 /** 155 * Iterates the integer-pointer values in {@code int[] posArr}, and replaces the nodes inside 156 * {@code 'html'} that have been identified by the {@code 'posArr'} list with a new node 157 * supplied by the {@code interface ReplaceFunction}. It should be obvious, that lambda 158 * expressions may be used here. 159 * 160 * <BR /><BR /><B CLASS=JDDescLabel>Returning 'null':</B> 161 * 162 * <BR />If the Lambda-Target / Functional-Interface {@link ReplaceFunction} (whose method 163 * is named {@link ReplaceFunction#getReplacement(HTMLNode, int, int)} 164 * <B><I STYLE='color: red;'>actually returns <CODE>'null'</CODE></I></B>, 165 * then null will indeed by inserted into the corresponding {@code Vector} position. 166 * 167 * @param html Any HTML page or section that has been loaded already. 168 * 169 * @param posArr This is usually generated by one of the node-search {@code 'Find.all(...)'} 170 * methods. Each and every one of the {@code 'Find.all(...)'} methods in the search package 171 * will return an array of integers. These integers represent positions/locations in the 172 * passed HTML page {@code Vector}. 173 * 174 * @param rf This is just a class that implements the {@code interface ReplaceFunction}. The 175 * interface has a single-method that will receive the position in the {@code Vector}, along 176 * with the {@code HTMLNode} found at that location. It is expected to produce a new version 177 * of the {@code HTMLNode}. This new node will be substituted into the page or sup-page. 178 * 179 * <BR /><BR />This function-pointer may return null, and when it does, <I>the node located at 180 * the current loop-iteration's {@code Vector}-index will not be replaced</I>. 181 * 182 * @return The number of nodes that were succesfully replaced. This number will be equal to 183 * {@code posArr.length} minus the number of times {@code rf} returned null; 184 * 185 * @throws ArrayIndexOutOfBoundsException <B><SPAN STYLE="color: red;">IMPORTANT 186 * NOTE:</B></SPAN> Usually, a position-{@code array} is generated by one of the search-methods 187 * in the NodeSearch package. If, however, the {@code Vector} has since changed and 188 * {@code posArr} contains stale-data, or if for other reasons there are invalid index-pointers 189 * in {@code posArr}, then an {@code ArrayIndexOutOfBoundsException} will, naturally, be thrown 190 * by java's {@code Vector.setElementAt(...)} method. 191 * 192 * @see ReplaceFunction 193 */ 194 public static int r(Vector<HTMLNode> html, int[] posArr, ReplaceFunction rf) 195 { 196 int counter=0, numReplaced=0; 197 HTMLNode n; 198 199 for (int pos : posArr) 200 201 // pos is the vector-position, counter is the "iteration-count" 202 if ((n = rf.getReplacement(html.elementAt(pos), pos, counter++)) != null) 203 { 204 html.setElementAt(n, pos); 205 numReplaced++; 206 } 207 208 return numReplaced; 209 } 210 211 /** 212 * This will replace <I>each and every node indicated by {@code 'posArr'}</I> with the 213 * exact same replacement node {@code 'n'}. 214 * 215 * @param html Any HTML page or section that has been loaded already. 216 * 217 * @param posArr This is usually generated by one of the node-search {@code 'Find.all(...)'} 218 * methods. Each and every one of the {@code 'Find.all(...)'} methods in the search package 219 * will return an array of integers. These integers represent positions/locations in the 220 * passed HTML page {@code Vector}. 221 * 222 * @param n This may be any non-null {@code HTMLNode}. This node shall be inserted (and will 223 * replace) each node indicated by the parameter {@code 'posArr'}. 224 * 225 * @throws ArrayIndexOutOfBoundsException 226 * <B><SPAN STYLE="color: red;">IMPORTANT NOTE:</B></SPAN> 227 * Usually, a position-{@code array} is generated by one of the search-methods in the 228 * NodeSearch package. If, however, the {@code Vector} has since changed and {@code posArr} 229 * contains stale-data, or if for other reasons there are invalid index-pointers in 230 * {@code posArr}, then an {@code ArrayIndexOutOfBoundsException} will, naturally, be thrown by 231 * java's {@code Vector.setElementAt(...)} method. 232 */ 233 public static void r(Vector<HTMLNode> html, int[] posArr, HTMLNode n) 234 { 235 int len= html.size(); 236 for (int i=0; i < len; i++) html.setElementAt(n, i); 237 } 238 239 /** 240 * Convenience Method. 241 * <BR />Invokes: {@link #r(Vector, int, int, ReplaceFunction)} 242 * <BR />Passes: Entire Range of {@code html} into {@code sPos & ePos} 243 */ 244 public static int r(Vector<HTMLNode> html, ReplaceFunction rf) 245 { return r(html, 0, -1, rf); } 246 247 /** 248 * Convenience Method. 249 * <BR />Invokes: {@link #r(Vector, int, int, ReplaceFunction)} 250 * <BR />Passes: {@link DotPair#start} & {@link DotPair#end} into {@code sPos & ePos} 251 */ 252 public static int r(Vector<HTMLNode> html, DotPair range, ReplaceFunction rf) 253 { return r(html, range.start, range.end + 1, rf); } 254 255 /** 256 * Iterates <I>the entire html-page, checking every node</I>, replacing them by the 257 * values returned by {@code 'rf'} (the replace function). The {@link ReplaceFunction} 258 * (parameter {@code 'rf'}) is expected to return values that either: 259 * 260 * <BR /><BR /><UL CLASS=JDUL> 261 * <LI>provide a replacement {@code HTMLNode} for the indicated position</LI> 262 * <LI>return null as a value - in which case, <I>no substitution will occur</I></LI> 263 * </UL> 264 * 265 * <BR /><BR /><B CLASS=JDDescLabel>Returning 'null':</B> 266 * 267 * <BR />If the Lambda-Target / Functional-Interface {@link ReplaceFunction} (whose method 268 * is named {@link ReplaceFunction#getReplacement(HTMLNode, int, int)} 269 * <B><I STYLE='color: red;'>returns <CODE>'null'</CODE></I></B>, 270 * then in this particular method (differing from a previous method in this class), the 271 * returned 'null' will be ignored, and no substitution will be performed. 272 * 273 * @param html Any HTML page or section that has been loaded already. 274 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSVEC> 275 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSVEC> 276 * 277 * @param rf This is just a class that implements the {@code interface ReplaceFunction}. The 278 * interface has a single-method (@code getReplacement(...)} that will receive the position in 279 * the {@code Vector}, along with the {@code HTMLNode} found at that location. It is expected 280 * to return a new version of the {@code HTMLNode}. 281 * 282 * <BR /><BR />This function-pointer may return null, and when it does, <I>the node located at 283 * the current loop-iteration's {@code Vector}-index will not be replaced</I>. 284 * 285 * @return The number of nodes that were succesfully replaced. This number will be equal to 286 * {@code html.size()} minus the number of times {@code rf} returned null; 287 * 288 * @throws IndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=VIOOBEX> 289 * @see ReplaceFunction 290 * @see HTMLNode 291 */ 292 public static int r(Vector<HTMLNode> html, int sPos, int ePos, ReplaceFunction rf) 293 { 294 LV l = new LV(html, sPos, ePos); 295 int numReplaced = 0; 296 297 for (int i=l.start; i < l.end; i++) 298 { 299 // Here the vector-position and iteration-number are the same 300 HTMLNode n = rf.getReplacement(html.elementAt(i), i, i); 301 302 if (n != null) 303 { 304 html.setElementAt(n, i); 305 numReplaced++; 306 } 307 } 308 309 return numReplaced; 310 } 311 312 /** 313 * Iterates the integer-pointer values listed by {@code 'posArr'}, and replaces every position 314 * in {@code 'html'} with an {@code HTMLNode} from the nodes provided by the {@code 'newNodes'} 315 * parameter. 316 * 317 * @param html Any HTML page or section that has been loaded already. 318 * 319 * @param posArr This is usually generated by one of the node-search {@code 'Find.all(...)'} 320 * methods. Each and every one of the {@code 'Find.all(...)'} methods in the search package 321 * will return an {@code int[] array}. These integers represent positions/locations in the 322 * passed HTML page {@code Vector.} 323 * 324 * @param newNodes This list of new nodes must have a length identical to the 325 * {@code int[] posArr} (pointer-Array) length. 326 * 327 * @throws ArrayIndexOutOfBoundsException This exception will throw if any of the elements of 328 * {@code 'posArr'} point to a position in the {@code Vector<HTMLNode> v} parameter that are 329 * out of bounds for that {@code Vector}. 330 * 331 * @throws IllegalArgumentException if the length of the position array (pointer-array) is not 332 * identical to the length of the new-nodes {@code Vector.} 333 */ 334 public static void r(Vector<HTMLNode> html, int[] posArr, Vector<HTMLNode> newNodes) 335 { 336 if (posArr.length != newNodes.size()) throw new ArrayIndexOutOfBoundsException( 337 "The pointer array 'posArr', and the replacement-node array 'newNodes' do not have " + 338 "equal lengths!\n" + 339 "posArr.length=" + posArr.length + ", newNodes.size()=" + newNodes.size() 340 ); 341 342 int newNodesPos = 0; 343 344 for (int pos : posArr) html.setElementAt(newNodes.elementAt(newNodesPos++), pos); 345 } 346 347 /** 348 * Convenience Method. 349 * <BR />Invokes: {@link #r(Vector, int, int, Vector)} 350 */ 351 public static int r(Vector<HTMLNode> html, DotPair range, Vector<HTMLNode> newNodes) 352 { return r(html, range.start, range.end + 1, newNodes); } 353 354 /** 355 * Replaces the nodes currently within the vectorized HTML parameter {@code 'html'}, in the 356 * sub-range provided by the {@code 'sPos'} and {@code 'ePos'} parameters - <I>using the new 357 * nodes provided by {@code Vector}-Parameter {@code 'newNodes'}.</I> This is, essentially, 358 * a sub-range array-replacement operation. 359 * 360 * <BR /><BR />Unless exactly the same number of nodes that are in the {@code 'replaceRange'} 361 * are also in {@code 'newNodes'}, this method shall have to shorten or lengthen the size of 362 * the HTML {@code Vector}. 363 * 364 * @param html This may be any HTML page or sub-page 365 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSVEC> 366 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSVEC> 367 * @param newNodes These are the new {@code HTMLNode's} that are to replace the old ones. 368 * @return The change in the size (size-delta) of the input {@code html} parameter. 369 * @throws IndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=VIOOBEX> 370 */ 371 public static int r(Vector<HTMLNode> html, int sPos, int ePos, Vector<HTMLNode> newNodes) 372 { 373 // The loop variable is needed because its constructor does all of the error checking. 374 // The constructor also checks for the negative-ePos, and changes it if it is negative 375 // 376 // The original version of this method has been deprected, and left as a private method to 377 // this class. It was before noticing the "mirrored" stipulations about Vector-operation 378 // "subList" View the source-code to see the original replace-range method. 379 380 LV l = new LV(html, sPos, ePos); 381 382 List<HTMLNode> list = html.subList(l.start, l.end); 383 384 385 // The Sun-Oracle Docs say that changes to the list returned by sub-list are mirrored into 386 // changes in the original vector. This is how sub-range operations are done. 387 388 list.clear(); 389 list.addAll(newNodes); 390 391 return newNodes.size() - (ePos - sPos); // ==> (newSize - originalSize) 392 } 393 394 395 // This was how to do this, until noticing in the Java-Docs that "subList" is "linked" 396 // to the original list! 397 398 private static void rOLD(Vector<HTMLNode> html, int sPos, int ePos, Vector<HTMLNode> newNodes) 399 { 400 LV l = new LV(html, sPos, ePos); 401 402 403 // Replacement while-loop. This will replace all nodes that can be replaced in the 404 // "replace range" - without growing or shrinking the size of the underlying vector. 405 // 406 // AFTERWARDS If there are still more nodes to insert, they will be inserted by 407 // growing the vector. 408 // 409 // AND ALSO If there were fewer nodes to insert than the number that need to be 410 // removed the Vector will be shortened. 411 412 int i = 0; 413 int j = sPos; 414 415 while ((j < l.end) && (i < newNodes.size())) 416 { 417 html.setElementAt(newNodes.elementAt(i), j); 418 419 i++; j++; 420 } 421 422 423 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 424 // CASE 1: The number of nodes to remove is precisely equal to the number being inserted. 425 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 426 427 if (l.size() == newNodes.size()) return; 428 429 430 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 431 // CASE 2: The number of nodes being removed is greater than the number being inserted 432 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 433 // 434 // Use Util.removeRange(...) to remove the remaining nodes that weren't replaced. 435 // More nodes need to be removed than the number of nodes that have already been inserted 436 // (in the previous loop). In this case the original HTML Vector will SHRINK in SIZE. 437 438 if (j < l.end) { Util.Remove.range(html, j, l.end); return; } 439 440 441 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 442 // CASE 3: There are more nodes being added than the number of nodes being removed. 443 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 444 // 445 // Use Vector.addAll(...) to add the rest which haven't been inserted yet. 446 // The HTML Vector is going to grow. There were fewer nodes removed than the number of 447 // nodes that need to be inserted. 448 // 449 // NOTE: An "intermediate temp Vector" is used since the "Node Shift" is likely done more 450 // efficiently by 'Vector.addAll', than by calling 'Vector.add' multiple times. 451 452 Vector<HTMLNode> temp = new Vector<>(newNodes.size() - i); 453 454 while (i < newNodes.size()) temp.add(newNodes.elementAt(i++)); 455 456 html.addAll(l.end, temp); 457 } 458 459 /** 460 * Convenience Method. 461 * Invokes: {@link #r(Vector, int, int, HTMLNode)} 462 */ 463 public static int r(Vector<HTMLNode> html, DotPair range, HTMLNode newNode) 464 { return r(html, range.start, range.end + 1, newNode); } 465 466 /** 467 * Replaces the nodes currently within the vectorized HTML parameter {@code 'html'}, in the 468 * sub-range provided by the {@code 'sPos'} and {@code 'ePos'} parameters, <I>with a single 469 * new node provided by {@code 'newNode'}.</I> Essentially, this is a <B>Range Removal</B> 470 * Operation, because a complete sublist is removed, and only a single-node replaces it. 471 * 472 * <BR /><BR />Unless the replacement-range (defined by {@code 'sPos'} and {@code 'ePos'}) has 473 * a size equal to {@code '1'}, this operation will (obviously) shorten the size of the input 474 * HTML {@code Vector} by {@code size - 1} nodes. 475 * 476 * @param html This may be any HTML page or sub-page 477 * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSVEC> 478 * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSVEC> 479 * 480 * @param newNode This is the new {@code HTMLNode} that is to replace the (entire) list 481 * specified by parameters {@code 'sPos'} and {@code 'ePos'}. 482 * 483 * @return The change in the size (size-delta) of the input {@code html} parameter. 484 * The number returned will always equal {@code 1 - (ePos - sPos)}. This means the return 485 * value for this method will always be negative (i.e. the {@code Vector} shrunk) - unless 486 * {@code sPos} and {@code ePos} had specified a range that was equal to 1. 487 * 488 * @throws IndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=VIOOBEX> 489 */ 490 public static int r(Vector<HTMLNode> html, int sPos, int ePos, HTMLNode newNode) 491 { 492 // This method doesn't have any "for-loops", but the LV class does all the much needed 493 // exception checks, and conversion computations. (ePos < 0 ==> epos = html.size()) 494 495 LV l = new LV(html, sPos, ePos); 496 497 html.setElementAt(newNode, l.start); 498 499 if (l.size() > 1) 500 501 // Util.removeRange(html, l.start + 1, l.end); // OLD-WAY 502 html.subList(l.start + 1, l.end).clear(); // NEW & IMPROVED WAY 503 504 return 1 - (ePos - sPos); // ==> (newSize - originalSize) 505 } 506 507 /** 508 * Replaces the instance of {@code HTMLNode} located at {@code Vector}-index {@code 'pos'} 509 * with the contents of {@code Vector} parameter {@code 'newNodes'}. This removes just 510 * a single instance of {@code HTMLNode}, and replaces it with a list of nodes. 511 * <BR /><BR />Note that this method will, indeed, lengthen the size of the input HTML 512 * {@code Vector} (unless the {@code 'newNodes' Vector} being inserted has only 1 or 0 513 * elements). 514 * 515 * @param html This may be any HTML page or sub-page. 516 * 517 * @param replacePos The position of the {@code HTMLNode} to be removed and replaced with the 518 * list of nodes. 519 * 520 * @param newNodes These are the new {@code HTMLNode's} that are to replace the old instance 521 * of {@code HTMLNode} at position {@code 'pos'}. 522 * 523 * @return The change in the size (size-delta) of the input {@code html} parameter. 524 * The number returned will always equal {@code newNodes.size() - 1} 525 * 526 * @throws ArrayIndexOutOfBoundsException This exception will throw if the specified 527 * {@code 'pos'} parameter is not within the bounds of the {@code Vector}. 528 */ 529 public static int r(Vector<HTMLNode> html, int replacePos, Vector<HTMLNode> newNodes) 530 { 531 if (replacePos < 0) throw new ArrayIndexOutOfBoundsException( 532 "The position passed to this method [" + replacePos + "] is negative." 533 ); 534 535 if (replacePos >= newNodes.size()) throw new ArrayIndexOutOfBoundsException( 536 "The position passed to this method [" + replacePos + "] is greater than or equal " + 537 " to the size of the input HTML Vector parameter, 'html' [" + html.size() + "]" 538 ); 539 540 html.removeElementAt(replacePos); 541 html.addAll(replacePos, newNodes); 542 543 return newNodes.size() - 1; // ==> (newSize - originalSize) 544 } 545}