001package Torello.HTML; 002 003import Torello.HTML.helper.AttrRegEx; 004 005import Torello.Java.StringParse; 006import Torello.Java.StrCmpr; 007import Torello.Java.StrFilter; 008 009import Torello.HTML.NodeSearch.CSSStrException; 010import Torello.HTML.NodeSearch.TextComparitor; 011 012import Torello.JavaDoc.LinkJavaSource; 013 014import Torello.JavaDoc.IntoHTMLTable; 015import static Torello.JavaDoc.IntoHTMLTable.Background.GreenDither; 016import static Torello.JavaDoc.IntoHTMLTable.Background.BlueDither; 017 018import static Torello.JavaDoc.Entity.METHOD; 019import static Torello.JavaDoc.Entity.FIELD; 020 021import java.util.Vector; 022import java.util.Properties; 023import java.util.Map; 024 025import java.util.regex.Pattern; 026import java.util.regex.Matcher; 027 028import java.util.stream.Stream; 029 030import javax.management.AttributeNotFoundException; 031 032import java.util.function.Predicate; 033 034/** 035 * Represents an HTML Element Tag, and is the flagship class of the Java-HTML Library. 036 * 037 * <EMBED CLASS='external-html' DATA-FILE-ID=TAG_NODE> 038 * <EMBED CLASS='external-html' DATA-FILE-ID=HTML_NODE_SUB_IMG> 039 * 040 * @see TextNode 041 * @see CommentNode 042 * @see HTMLNode 043 */ 044@Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="HTML_NODE_SUBCLASS") 045public final class TagNode 046 extends HTMLNode 047 implements CharSequence, java.io.Serializable, Cloneable, Comparable<TagNode> 048{ 049 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 050 public static final long serialVersionUID = 1; 051 052 053 // ******************************************************************************************** 054 // ******************************************************************************************** 055 // NON-STATIC FIELDS 056 // ******************************************************************************************** 057 // ******************************************************************************************** 058 059 060 /** <EMBED CLASS='external-html' DATA-FILE-ID=TAGNODE_TOK> */ 061 public final String tok; 062 063 /** <EMBED CLASS='external-html' DATA-FILE-ID=TAGNODE_IS_CLOSING> */ 064 public final boolean isClosing; 065 066 067 068 // ******************************************************************************************** 069 // ******************************************************************************************** 070 // Package-Private Constructors - NO ERROR CHECKING DONE WHATSOEVER 071 // ******************************************************************************************** 072 // ******************************************************************************************** 073 074 075 // ONLY USED BY THE "TagNodeHelpers" and in conjunction with "Generate Element String" 076 // 077 // It presumes that the node was properly constructed and needs to error-checking 078 // It is only used for opening TagNode's 079 080 TagNode(String tok, String str) 081 { 082 super(str); 083 084 this.tok = HTMLTags.getTag_MEM_HEAP_CHECKOUT_COPY(tok); 085 this.isClosing = false; 086 } 087 088 089 // USED-INTERNALLY - bypasses all checks. used when creating new HTML Element-Names 090 // ONLY: class 'HTMLTags' via method 'addTag(...)' shall ever invoke this constructor. 091 // 092 // NOTE: This only became necessary because of the MEM_COPY_HEAP optimization. This 093 // optimization expects that there is already a TagNode with element 'tok' in 094 // the TreeSet, which is always OK - except for the method that CREATES NEW HTML 095 // TAGS... a.k.a. HTMLTags.addTag(String). 096 097 TagNode(String token, TC openOrClosed) 098 { 099 super("<" + ((openOrClosed == TC.ClosingTags) ? "/" : "") + token + ">"); 100 101 // ONLY CHANGE CASE HERE, NOT IN PREVIOUS-LINE. PAY ATTENTION. 102 this.tok = token.toLowerCase(); 103 104 this.isClosing = (openOrClosed == TC.ClosingTags) ? true : false; 105 } 106 107 108 // ******************************************************************************************** 109 // ******************************************************************************************** 110 // Public Constructors 111 // ******************************************************************************************** 112 // ******************************************************************************************** 113 114 115 /** 116 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_C_DESC_1> 117 * 118 * @param s Any valid HTML tag, for instance: {@code <H1>, <A HREF="somoe url">, 119 * <DIV ID="some id">} etc... 120 * 121 * @throws MalformedTagNodeException If the passed {@code String} wasn't valid - meaning <I>it 122 * did not match the regular-expression {@code parser}.</I> 123 * 124 * @throws HTMLTokException If the {@code String} found where the usual HTML token-element is 125 * situated <I>is not a valid HTML element</I> then the {@code HTMLTokException} will be 126 * thrown. 127 * 128 * @see HTMLTags#getTag_MEM_HEAP_CHECKOUT_COPY(String) 129 */ 130 public TagNode(String s) 131 { 132 super(s); 133 134 // If the second character of the string is a forward-slash, this must be a closing-element 135 // For Example: </SPAN>, </DIV>, </A>, etc... 136 137 isClosing = s.charAt(1) == '/'; 138 139 // This is the Element & Attribute Matcher used by the RegEx Parser. If this Matcher 140 // doesn't find a match, the parameter 's' cannot be a valid HTML Element. NOTE: The 141 // results of this matcher are also used to retrieve attribute-values, but here below, 142 // its results are ignored. 143 144 Matcher m = HTMLRegEx.P1.matcher(s); 145 146 if (! m.find()) throw new MalformedTagNodeException( 147 "The parser's regular-expression did not match the constructor-string.\n" + 148 "The exact input-string was: [" + s + "]\n" + 149 "NOTE: The parameter-string is included as a field (ex.str) to this Exception.", s 150 ); 151 152 if ((m.start() != 0) || (m.end() != s.length())) 153 154 throw new MalformedTagNodeException( 155 "The parser's regular-expression did not match the entire-string-length of the " + 156 "string-parameter to this constructor: m.start()=" + m.start() + ", m.end()=" + 157 m.end() + ".\nHowever, the length of the Input-Parameter String was " + 158 '[' + s.length() + "]\nThe exact input-string was: [" + s + "]\nNOTE: The " + 159 "parameter-string is included as a field (ex.str) to this Exception.", s 160 ); 161 162 // MINOR/MAJOR IMPROVEMENT... REUSE THE "ALLOCATED STRING TOKEN" from HTMLTag's class 163 // THINK: Let the Garbage Collector take out as many duplicate-strings as is possible.. 164 // AND SOONER. DECEMBER 2019: "Optimization" or ... "Improvement" 165 // 166 // Get a copy of the 'tok' string that was already allocated on the heap; (OPTIMIZATON) 167 // 168 // NOTE: There are already myriad strings for the '.str' field. 169 // 170 // ALSO: Don't pay much attention to this line if it doesn't make sense... it's not 171 // that important. If the HTML Token found was not a valid HTML5 token, this field 172 // will be null. 173 // 174 // Java 14+ has String.intern() - that's what this is.... 175 176 this.tok = HTMLTags.getTag_MEM_HEAP_CHECKOUT_COPY(m.group(1)); 177 178 // Now do the usual error check. 179 if (this.tok == null) throw new HTMLTokException( 180 "The HTML Tag / Token Element that is specified by the input string " + 181 "[" + m.group(1).toLowerCase() + "] is not a valid HTML Element Name.\n" + 182 "The exact input-string was: [" + s + "]" 183 ); 184 } 185 186 /** 187 * Convenience Constructor. 188 * <BR />Invokes: {@link #TagNode(String, Properties, Iterable, SD, boolean)} 189 * <BR />Passes: null to the Boolean / Key-Only Attributes {@code Iterable} 190 */ 191 public TagNode( 192 String tok, 193 Properties attributes, 194 SD quotes, 195 boolean addEndingForwardSlash 196 ) 197 { 198 this( 199 tok, 200 GeneralPurpose.generateElementString( 201 tok, 202 attributes, 203 null, // keyOnlyAttributes, 204 quotes, 205 addEndingForwardSlash 206 )); 207 } 208 209 /** 210 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_C_DESC_2> 211 * @param tok <EMBED CLASS='external-html' DATA-FILE-ID=TN_C_TOK> 212 * @param attributes <EMBED CLASS='external-html' DATA-FILE-ID=TN_C_ATTRIBUTES> 213 * @param keyOnlyAttributes <EMBED CLASS='external-html' DATA-FILE-ID=TN_C_KO_ATTRIBUTES> 214 * @param quotes <EMBED CLASS='external-html' DATA-FILE-ID=TN_C_QUOTES> 215 * @param addEndingForwardSlash <EMBED CLASS='external-html' DATA-FILE-ID=TN_C_AEFS> 216 * @throws InnerTagKeyException <EMBED CLASS='external-html' DATA-FILE-ID=IT_KEY_EX_PROP_TN> 217 * @throws QuotesException <EMBED CLASS='external-html' DATA-FILE-ID=QEX> 218 * 219 * @throws HTMLTokException if an invalid HTML 4 or 5 token is not present 220 * <B>(check is {@code CASE_INSENSITIVE})</B>, or a token which has been registered with class 221 * {@code HTMLTags}. 222 * 223 * @see InnerTagKeyException#check(String, String) 224 * @see QuotesException#check(String, SD, String) 225 */ 226 public TagNode( 227 String tok, 228 Properties attributes, 229 Iterable<String> keyOnlyAttributes, 230 SD quotes, 231 boolean addEndingForwardSlash 232 ) 233 { 234 this( 235 tok, 236 GeneralPurpose.generateElementString 237 (tok, attributes, keyOnlyAttributes, quotes, addEndingForwardSlash) 238 ); 239 } 240 241 242 // ******************************************************************************************** 243 // ******************************************************************************************** 244 // HTMLNode Overidden - Loop & Stream Optimization Methods 245 // ******************************************************************************************** 246 // ******************************************************************************************** 247 248 249 /** 250 * This method identifies that {@code 'this'} instance of (abstract parent-class) 251 * {@link HTMLNode} is, indeed, an instance of sub-class {@code TagNode}. 252 * 253 * <BR /><BR /><B CLASS=JDDescLabel>Final Method:</B> 254 * 255 * <BR />This method is final, and cannot be modified by sub-classes. 256 * 257 * @return This method shall always return {@code TRUE} It overrides the parent-class 258 * {@code HTMLNode} method {@link #isTagNode()}, which always returns {@code FALSE}. 259 */ 260 @Override 261 public final boolean isTagNode() { return true; } 262 263 /** 264 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_IF_TN_DESC> 265 * <BR /><BR /><B CLASS=JDDescLabel>Final Method:</B> 266 * <BR />This method is final, and cannot be modified by sub-classes. 267 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_IF_TN_RET> 268 */ 269 @Override 270 public final TagNode ifTagNode() { return this; } 271 272 /** 273 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_OPENTAG_PWA_DESC> 274 * <BR /><BR /><B CLASS=JDDescLabel>Final Method:</B> 275 * <BR />This method is final, and cannot be modified by sub-classes. 276 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_OPENTAG_PWA_RET> 277 */ 278 @Override 279 public final TagNode openTagPWA() 280 { 281 // Closing TagNode's simply may not have attributes 282 if (this.isClosing) return null; 283 284 // A TagNode whose '.str' field is not AT LEAST 4 characters LONGER than the length of the 285 // HTML-Tag / Token, simply cannot have an attribute. 286 // 287 // NOTE: Below is the shortest possible HTML tag that could have an attribute. 288 // COMPUTE: '<' + TOK.LENGTH + SPACE + 'c' + '>' 289 290 if (this.str.length() < (this.tok.length() + 4)) return null; 291 292 // This TagNode is an opening HTML tag (like <DIV ...>, rather than </DIV>), 293 // and there are at least two additional characters after the token, such as: <DIV A...> 294 // It is not guaranteed that this tag has attributes, but it is possibly - based on these 295 /// optimization methods, and further investigation would have merit. 296 297 return this; 298 } 299 300 /** 301 * This is a loop-optimization method that makes finding opening {@code TagNode's} - <B>with 302 * attribute-</B><B STYLE='color: red;'>values</B> - quites a bit faster. All {@link HTMLNode} 303 * subclasses implement this method, but only {@code TagNode} instances will ever return a 304 * non-null value. 305 * 306 * <BR /><BR /><B CLASS=JDDescLabel>Final Method:</B> 307 * 308 * <BR />This method is final, and cannot be modified by sub-classes. 309 * 310 * @return Returns null if and only if {@code 'this'} instance' {@link #isClosing} field is 311 * false. When a non-null return-value is acheived, that value will always be {@code 'this'} 312 * instance. 313 */ 314 @Override 315 public final TagNode openTag() 316 { return isClosing ? null : this; } 317 318 /** 319 * This method is an optimization method that overrides the one by the same name in class 320 * {@link HTMLNode}. 321 * 322 * {@inheritdoc} 323 */ 324 @Override 325 public boolean isOpenTagPWA() 326 { 327 if (this.isClosing) return false; 328 if (this.str.length() < (this.tok.length() + 4)) return false; 329 return true; 330 } 331 332 /** 333 * This method is an optimization method that overrides the one by the same name in class 334 * {@link HTMLNode}. 335 * 336 * {@inheritdoc} 337 */ 338 @Override 339 public boolean isOpenTag() 340 { return ! isClosing; } 341 342 343 // ******************************************************************************************** 344 // ******************************************************************************************** 345 // isTag 346 // ******************************************************************************************** 347 // ******************************************************************************************** 348 349 350 /** 351 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_IS_TAG1_DESC> 352 * @param possibleTags A non-null list of potential HTML tags to be checked again {@link #tok} 353 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_IS_TAG1_RET> 354 * @see #tok 355 */ 356 public boolean isTag(String... possibleTags) 357 { 358 for (String htmlTag : possibleTags) if (htmlTag.equalsIgnoreCase(this.tok)) return true; 359 return false; 360 } 361 362 /** 363 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_IS_TAG_EX1_DESC> 364 * @param possibleTags A non-null list of potential HTML tags to be checked again {@link #tok} 365 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_IS_TAG_EX1_RET> 366 * @see #tok 367 * @see #isTag(String[]) 368 */ 369 public boolean isTagExcept(String... possibleTags) 370 { 371 for (String htmlTag : possibleTags) if (htmlTag.equalsIgnoreCase(this.tok)) return false; 372 return true; 373 } 374 375 /** 376 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_IS_TAG2_DESC> 377 * @param tagCriteria <EMBED CLASS='external-html' DATA-FILE-ID=TN_IS_TAG2_PARAM> 378 * @param possibleTags A non-null list of potential HTML tags to be checked again {@link #tok} 379 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_IS_TAG2_RET> 380 * @see #tok 381 */ 382 @LinkJavaSource(handle="IsTag", name="isTag") 383 public boolean isTag(TC tagCriteria, String... possibleTags) 384 { return IsTag.isTag(this, tagCriteria, possibleTags); } 385 386 /** 387 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_IS_TAG_EX2_DESC> 388 * @param tagCriteria <EMBED CLASS='external-html' DATA-FILE-ID=TN_IS_TAG_EX2_PARAM> 389 * @param possibleTags A non-null list of potential HTML tags to be checked again {@link #tok} 390 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_IS_TAG_EX2_RET> 391 * @see #tok 392 */ 393 @LinkJavaSource(handle="IsTag", name="isTagExcept") 394 public boolean isTagExcept(TC tagCriteria, String... possibleTags) 395 { return IsTag.isTagExcept(this, tagCriteria, possibleTags); } 396 397 398 // ******************************************************************************************** 399 // ******************************************************************************************** 400 // Main Method 'AV' 401 // ******************************************************************************************** 402 // ******************************************************************************************** 403 404 405 /** 406 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_AV_DESC> 407 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_AV_DESC_EXAMPLE> 408 * @param innerTagAttribute <EMBED CLASS='external-html' DATA-FILE-ID=TN_AV_ITA> 409 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_AV_RET> 410 * @see StringParse#ifQuotesStripQuotes(String) 411 */ 412 @LinkJavaSource(handle="GetSetAttr", name="AV") 413 public String AV(String innerTagAttribute) 414 { return GetSetAttr.AV(this, innerTagAttribute, false); } 415 416 /** 417 * Identical to {@link #AV(String)}, except that if the 418 * Attribute-<B STYLE='color: red;'>value</B> had quotes surrounding it, those are included in 419 * the returned {@code String}. 420 */ 421 // To-Do, finish this after brekfast 422 // public String preserveQuotesAV(String innerTagAttribute) 423 // { return GetSetAttr.AV(this, innerTagAttribute, true); } 424 425 /** 426 * <B STYLE='color: red;'>AVOPT: Attribute-Value - Optimized</B> 427 * 428 * <BR /><BR /> This is an "optimized" version of method {@link #AV(String)}. This method does 429 * the exact same thing as {@code AV(...)}, but leaves out parameter-checking and 430 * error-checking. This is used internally (and repeatedly) by the NodeSearch Package Search 431 * Loops. 432 * 433 * @param innerTagAttribute This is the inner-tag / attribute <B STYLE='color: red;'>name</B> 434 * whose <B STYLE='color: red;'>value</B> is hereby being requested. 435 * 436 * @return {@code String}-<B STYLE='color: red;'>value</B> of this inner-tag / attribute. 437 * 438 * @see StringParse#ifQuotesStripQuotes(String) 439 * @see #str 440 */ 441 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 442 public String AVOPT(String innerTagAttribute) 443 { 444 // COPIED DIRECTLY FROM class TagNode, leaves off initial tests. 445 446 // Matches "Attribute / Inner-Tag Key-Value" Pairs. 447 Matcher m = AttrRegEx.KEY_VALUE_REGEX.matcher(this.str); 448 449 // This loop iterates the KEY_VALUE PAIRS THAT HAVE BEEN FOUND. 450 /// NOTE: The REGEX Matches on Key-Value Pairs. 451 452 while (m.find()) 453 454 // m.group(2) is the "KEY" of the Attribute KEY-VALUE Pair 455 // m.group(3) is the "VALUE" of the Attribute. 456 457 if (m.group(2).equalsIgnoreCase(innerTagAttribute)) 458 return StringParse.ifQuotesStripQuotes(m.group(3)); 459 460 // This means the attribute name provided to parameter 'innerTagAttribute' was not found. 461 return null; 462 } 463 464 465 // ******************************************************************************************** 466 // ******************************************************************************************** 467 // Attribute Modify-Value methods 468 // ******************************************************************************************** 469 // ******************************************************************************************** 470 471 472 /** 473 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_AV_DESC> 474 * @param attribute <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_AV_ATTR> 475 * 476 * @param value Any valid attribute-<B STYLE='color: red;'>value</B>. This parameter may not 477 * be null, or a {@code NullPointerException} will throw. 478 * 479 * @param quote <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_AV_QUOTE> 480 * @throws InnerTagKeyException <EMBED CLASS='external-html' DATA-FILE-ID=IT_KEY_EX_TN> 481 * @throws QuotesException <EMBED CLASS='external-html' DATA-FILE-ID=QEX> 482 * @throws ClosingTagNodeException <EMBED CLASS='external-html' DATA-FILE-ID=CTNEX> 483 * 484 * @throws HTMLTokException If an invalid HTML 4 or 5 token is not present 485 * (<B>{@code CASE_INSENSITIVE}</B>). 486 * 487 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_AV_RET> 488 * @see ClosingTagNodeException#check(TagNode) 489 * @see #setAV(Properties, SD) 490 * @see #str 491 * @see #isClosing 492 */ 493 @LinkJavaSource(handle="GetSetAttr", name="setAV", paramCount=4) 494 public TagNode setAV(String attribute, String value, SD quote) 495 { return GetSetAttr.setAV(this, attribute, value, quote); } 496 497 /** 498 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_AV_NQ_DESC> 499 * @param attribute <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_AV_ATTR> 500 * @param value <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_AV_NQ_VALUE> 501 * @return An updated instance, with the new Attribute-<B STYLE='color: red;'>value</B> set. 502 * @throws InnerTagValueException If <B STYLE='color:red'>value</B> contains whitespace. 503 * @throws InnerTagKeyException <EMBED CLASS='external-html' DATA-FILE-ID=IT_KEY_EX_TN> 504 * @throws ClosingTagNodeException <EMBED CLASS='external-html' DATA-FILE-ID=CTNEX> 505 * @see ClosingTagNodeException#check(TagNode) 506 * @see StringParse#hasWhiteSpace(String) 507 */ 508 @LinkJavaSource(handle="GetSetAttr", name="setAVNoQuotes") 509 public TagNode setAVNoQuotes(String attribute, String value) 510 { return GetSetAttr.setAVNoQuotes(this, attribute, value); } 511 512 /** 513 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_AV2_DESC> 514 * @param attributes These are the new attribute <B STYLE='color: red;'>key-value</B> pairs to 515 * be inserted. 516 * 517 * @param defaultQuote <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_AV2_DQ_PARAM> 518 * @throws InnerTagKeyException <EMBED CLASS='external-html' DATA-FILE-ID=IT_KEY_EX_PROP_TN> 519 * 520 * @throws QuotesException if there are "quotes within quotes" problems, due to the 521 * <B STYLE='color: red;'>values</B> of the <B STYLE='color: red;'>key-value</B> pairs. 522 * 523 * @throws HTMLTokException if an invalid HTML 4 or 5 token is not present 524 * <B>({@code CASE_INSENSITIVE})</B> 525 * 526 * @throws ClosingTagNodeException <EMBED CLASS='external-html' DATA-FILE-ID=CTNEX> 527 * 528 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_AV2_RET> 529 * @see ClosingTagNodeException#check(TagNode) 530 * @see #setAV(String, String, SD) 531 * @see #isClosing 532 */ 533 @LinkJavaSource(handle="GetSetAttr", name="setAV", paramCount=3) 534 public TagNode setAV(Properties attributes, SD defaultQuote) 535 { return GetSetAttr.setAV(this, attributes, defaultQuote); } 536 537 /** 538 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_APD_AV_DESC> 539 * @param attribute <EMBED CLASS=external-html DATA-FILE-ID=TN_APD_AV_P_ATTR> 540 * @param appendStr <EMBED CLASS=external-html DATA-FILE-ID=TN_APD_AV_P_APDSTR> 541 * @param startOrEnd <EMBED CLASS=external-html DATA-FILE-ID=TN_APD_AV_P_S_OR_E> 542 * @param quote <EMBED CLASS=external-html DATA-FILE-ID=TGND_QUOTE_EXPL> 543 * <EMBED CLASS=external-html DATA-FILE-ID=TN_APD_AV_P_QXTRA> 544 * @return <EMBED CLASS=external-html DATA-FILE-ID=TN_APD_AV_RET> 545 * @see #AV(String) 546 * @see #setAV(String, String, SD) 547 * @see ClosingTagNodeException#check(TagNode) 548 * @throws ClosingTagNodeException <EMBED CLASS='external-html' DATA-FILE-ID=CTNEX> 549 * 550 * @throws QuotesException The <B><A HREF=#QUOTEEX>rules</A></B> for quotation usage apply 551 * here too, and see that explanation for how how this exception could be thrown. 552 */ 553 @LinkJavaSource(handle="GetSetAttr", name="appendToAV") 554 public TagNode appendToAV(String attribute, String appendStr, boolean startOrEnd, SD quote) 555 { return GetSetAttr.appendToAV(this, attribute, appendStr, startOrEnd, quote); } 556 557 558 // ******************************************************************************************** 559 // ******************************************************************************************** 560 // Attribute Removal Operations 561 // ******************************************************************************************** 562 // ******************************************************************************************** 563 564 565 /** 566 * Convenience Method. 567 * <BR />See Documentation: {@link #removeAttributes(String[])} 568 */ 569 @LinkJavaSource(handle="RemoveAttributes", name="removeAttributes") 570 public TagNode remove(String attributeName) 571 { 572 return RemoveAttributes.removeAttributes 573 (this, (String attr) -> ! attr.equalsIgnoreCase(attributeName)); 574 } 575 576 /** 577 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_REM_ATTR_DESC> 578 * @param attributes <EMBED CLASS='external-html' DATA-FILE-ID=TN_REM_ATTR_ATTR> 579 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_REM_ATTR_RET> 580 * @throws ClosingTagNodeException <EMBED CLASS='external-html' DATA-FILE-ID=CTNEX> 581 * @see ClosingTagNodeException#check(TagNode) 582 */ 583 @LinkJavaSource(handle="RemoveAttributes", name="removeAttributes") 584 public TagNode removeAttributes(String... attributes) 585 { 586 return RemoveAttributes.removeAttributes 587 (this, (String attr) -> StrCmpr.equalsNAND_CI(attr, attributes)); 588 } 589 590 /** 591 * Filter's attributes using an Attribute-<B STYLE='color:red'>Name</B> 592 * {@code String-Predicate} 593 * 594 * @param attrNameTest Any Java {@code String-Predicate}. It will be used to test whether or 595 * not to keep or filter/reject an attribute from {@code 'this' TagNode}. 596 * 597 * <BR /><BR /><B STYLE='color: red;'>NOTE:</B> Like all filter-{@code Predicate's}, this 598 * test's expected behavior is such that it should return {@code TRUE} when it would like to 599 * keep an attribute having a particular <B STYLE='color: red;'>name</B>, and return 600 * {@code FALSE} when it would like to see the attribute removed from the HTML Tag. 601 * 602 * @return Removes any Attributes whoe <B STYLE='color: red;'>name</B> as per the rules of the 603 * User-Provided {@code String-Predicate} parameter {@code 'attrNameTest'}. As with all 604 * {@code TagNode} modification operations, if any changes are, indeed, made to a new instance 605 * of {@code TagNode} will be created and returned. 606 */ 607 @LinkJavaSource(handle="RemoveAttributes", name="removeAttributes") 608 public TagNode removeAttributes(Predicate<String> attrNameTest) 609 { return RemoveAttributes.removeAttributes(this, attrNameTest); } 610 611 /** 612 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_REM_ALL_AV_DESC> 613 * @return <EMBED CLASS=external-html DATA-FILE-ID=TN_REM_ALL_AV_RET> 614 * @throws ClosingTagNodeException <EMBED CLASS=external-html DATA-FILE-ID=CTNEX> 615 * @see ClosingTagNodeException#check(TagNode) 616 * @see #getInstance(String, TC) 617 * @see TC#OpeningTags 618 */ 619 public TagNode removeAllAV() 620 { 621 ClosingTagNodeException.check(this); 622 623 // NOTE: We *CANNOT* use the 'tok' field to instantiate the TagNode here, because the 'tok' 624 // String-field is *ALWAYS* guaranteed to be in a lower-case format. The 'str' 625 // String-field, however uses the original case that was found on the HTML Document by the 626 // parser (or in the Constructor-Parameters that were passed to construct 'this' instance 627 // of TagNode. 628 629 return getInstance(this.str.substring(1, 1 + tok.length()), TC.OpeningTags); 630 } 631 632 633 // ******************************************************************************************** 634 // ******************************************************************************************** 635 // Retrieve all attributes 636 // ******************************************************************************************** 637 // ******************************************************************************************** 638 639 640 /** 641 * Convenience Method. 642 * <BR />See Documentation: {@link #allAV(boolean, boolean)} 643 * <BR />Attribute-<B STYLE='color: red;'>names</B> will be in lower-case. 644 */ 645 @LinkJavaSource(handle="RetrieveAllAttr", name="allAV") 646 public Properties allAV() 647 { return RetrieveAllAttr.allAV(this, false, false); } 648 649 /** 650 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_ALL_AV_DESC> 651 * @param keepQuotes <EMBED CLASS='external-html' DATA-FILE-ID=TN_ALL_AV_KQ_PARAM> 652 * @param preserveKeysCase <EMBED CLASS='external-html' DATA-FILE-ID=TN_ALL_AV_PKC_PARAM> 653 * <EMBED CLASS='external-html' DATA-FILE-ID=TAGNODE_PRESERVE_C> 654 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_ALL_AV_RET> 655 * @see StringParse#ifQuotesStripQuotes(String) 656 */ 657 @LinkJavaSource(handle="RetrieveAllAttr", name="allAV") 658 public Properties allAV(boolean keepQuotes, boolean preserveKeysCase) 659 { return RetrieveAllAttr.allAV(this, keepQuotes, preserveKeysCase); } 660 661 /** 662 * Convenience Method. 663 * <BR />See Documentation: {@link #allAN(boolean, boolean)} 664 * <BR />Attribute-<B STYLE='color: red;'>names</B> will be in lower-case 665 */ 666 @LinkJavaSource(handle="RetrieveAllAttr", name="allAN") 667 public Stream<String> allAN() 668 { return RetrieveAllAttr.allAN(this, false, false); } 669 670 /** 671 * This method will only return a list of attribute-<B STYLE='color: red;'>names</B>. The 672 * attribute-<B STYLE="color: red">values</B> shall <B>NOT</B> be included in the result. The 673 * {@code String's} returned can have their "case-preserved" by passing {@code TRUE} to the 674 * input boolean parameter {@code 'preserveKeysCase'}. 675 * 676 * @param preserveKeysCase If this is parameter receives {@code TRUE} then the case of the 677 * attribute-<B STYLE='color: red;'>names</B> shall be preserved. 678 * 679 * <EMBED CLASS='external-html' DATA-FILE-ID=TAGNODE_PRESERVE_C> 680 * 681 * @param includeKeyOnlyAttributes When this parameter receives {@code TRUE}, then any 682 * "Boolean Attributes" or "Key-Only, No-Value-Assignment" Inner-Tags will <B>ALSO</B> be 683 * included in the {@code Stream<String>} returned by this method. 684 * 685 * @return an instance of {@code Stream<String>} containing all 686 * attribute-<B STYLE='color: red;'>names</B> identified in {@code 'this'} instance of 687 * {@code TagNode}. A {@code java.util.stream.Stream} is used because it's contents can easily 688 * be converted to just about any data-type. 689 * 690 * <EMBED CLASS='external-html' DATA-FILE-ID=STRMCNVT> 691 * 692 * <BR /><B>NOTE:</B> This method shall never return {@code 'null'} - even if there are no 693 * attribute <B STYLE='color: red;'>key-value</B> pairs contained by {@code 'this' TagNode}. 694 * If there are strictly zero attributes, an empty {@code Stream} shall be returned, instead. 695 * 696 * @see #allKeyOnlyAttributes(boolean) 697 * @see #allAN() 698 */ 699 @LinkJavaSource(handle="RetrieveAllAttr", name="allAN") 700 public Stream<String> allAN(boolean preserveKeysCase, boolean includeKeyOnlyAttributes) 701 { return RetrieveAllAttr.allAN(this, preserveKeysCase, includeKeyOnlyAttributes); } 702 703 704 // ******************************************************************************************** 705 // ******************************************************************************************** 706 // Key only attributes 707 // ******************************************************************************************** 708 // ******************************************************************************************** 709 710 711 /** 712 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_ALL_KOA_DESC> 713 * @param preserveKeysCase <EMBED CLASS='external-html' DATA-FILE-ID=TN_ALL_KOA_PKC> 714 * <EMBED CLASS='external-html' DATA-FILE-ID=TAGNODE_PRESERVE_C> 715 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_ALL_KOA_RET> 716 * <EMBED CLASS='external-html' DATA-FILE-ID=STRMCNVT> 717 */ 718 @LinkJavaSource(handle="KeyOnlyAttributes", name="allKeyOnlyAttributes") 719 public Stream<String> allKeyOnlyAttributes(boolean preserveKeysCase) 720 { return KeyOnlyAttributes.allKeyOnlyAttributes(this, preserveKeysCase); } 721 722 /** 723 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_HAS_KOA_DESC> 724 * @param keyOnlyAttribute <EMBED CLASS='external-html' DATA-FILE-ID=TN_HAS_KOA_KOA> 725 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_HAS_KOA_RET> 726 * @throws IllegalArgumentException <EMBED CLASS='external-html' DATA-FILE-ID=TN_HAS_KOA_IAEX> 727 */ 728 @LinkJavaSource(handle="KeyOnlyAttributes", name="hasKeyOnlyAttribute") 729 public boolean hasKeyOnlyAttribute(String keyOnlyAttribute) 730 { return KeyOnlyAttributes.hasKeyOnlyAttribute(this, keyOnlyAttribute); } 731 732 733 // ******************************************************************************************** 734 // ******************************************************************************************** 735 // testAV 736 // ******************************************************************************************** 737 // ******************************************************************************************** 738 739 740 /** 741 * <BR>See Documentation: {@link #testAV(String, Predicate)} 742 * <BR>Passes: {@code String.equalsIgnoreCase(attributeValue)} to the Test-{@code Predicate} 743 */ 744 @IntoHTMLTable(background=GreenDither, title="Test an Attribute-Value using String-Equality") 745 @LinkJavaSource(handle="HasAndTest", name="testAV") 746 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 747 public boolean testAV(String attributeName, String attributeValue) 748 { 749 return HasAndTest.testAV 750 (this, attributeName, (String s) -> s.equalsIgnoreCase(attributeValue)); 751 } 752 753 /** 754 * <BR>See Documentation: {@link #testAV(String, Predicate)} 755 * <BR>Passes: {@code attributeValueTest.asPredicate()} to the Test-{@code Predicate} 756 */ 757 @IntoHTMLTable(background=BlueDither, title="Test an Attribute-Value using a Reg-Ex") 758 @LinkJavaSource(handle="HasAndTest", name="testAV") 759 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 760 public boolean testAV(String attributeName, Pattern attributeValueTest) 761 { return HasAndTest.testAV(this, attributeName, attributeValueTest.asPredicate()); } 762 763 /** 764 * <BR>See Documentation: {@link #testAV(String, Predicate)} 765 * <BR>Passes: {@link TextComparitor#test(String, String[])} to the Test-{@code Predicate} 766 */ 767 @IntoHTMLTable(background=GreenDither, title="Test an Attribute-Value using a Text-Comparitor") 768 @LinkJavaSource(handle="HasAndTest", name="testAV") 769 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 770 public boolean testAV 771 (String attributeName, TextComparitor attributeValueTester, String... compareStrs) 772 { 773 return HasAndTest.testAV 774 (this, attributeName, (String s) -> attributeValueTester.test(s, compareStrs)); 775 } 776 777 /** 778 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_TEST_AV_DESC> 779 * @param attributeName <EMBED CLASS='external-html' DATA-FILE-ID=TN_TEST_AV_PARAM> 780 * @param attributeValueTest Any {@code java.util.function.Predicate<String>} 781 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_TEST_AV_RET> 782 * @see StringParse#ifQuotesStripQuotes(String) 783 */ 784 @LinkJavaSource(handle="HasAndTest", name="testAV") 785 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 786 public boolean testAV(String attributeName, Predicate<String> attributeValueTest) 787 { return HasAndTest.testAV(this, attributeName, attributeValueTest); } 788 789 790 // ******************************************************************************************** 791 // ******************************************************************************************** 792 // has-attribute boolean-logic methods 793 // ******************************************************************************************** 794 // ******************************************************************************************** 795 796 797 /** 798 * <BR>See Documentation: {@link #hasXOR(boolean, String...)} 799 * <BR>Passes: AND Boolean Logic 800 * <BR>COL-SPAN-2: 801 * Check that <B STYLE='color: red;'><I>all</I></B> Attributes are Found 802 */ 803 @IntoHTMLTable(background=GreenDither, 804 title="Check that <B><I>every</I></B> Attribute which has been specified is Present") 805 @LinkJavaSource(handle="HasAndTest", name="hasLogicOp") 806 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 807 public boolean hasAND(boolean checkAttributeStringsForErrors, String... attributes) 808 { 809 // First-Function: Tells the logic to *IGNORE* intermediate matches (returns NULL) 810 // (This is *AND*, so wait until all attributes have been found, or at 811 // the very least all tags in the element tested, and failed. 812 // 813 // Second-Function: At the End of the Loops, all Attributes have either been found, or 814 // at least all attributes in 'this' tag have been tested. Note that the 815 // first-function is only called on a MATCH, and that 'AND' requires to 816 // defer a response until all attributes have been tested.. Here, simply 817 // RETURN WHETHER OR NOT the MATCH-COUNT equals the number of matches in 818 // the user-provided String-array. 819 820 return HasAndTest.hasLogicOp( 821 this, 822 checkAttributeStringsForErrors, 823 (int matchCount) -> null, 824 (int matchCount) -> (matchCount == attributes.length), 825 attributes 826 ); 827 } 828 829 /** 830 * <BR>See Documentation: {@link #hasXOR(boolean, String...)} 831 * <BR>Passes: OR Boolean Logic 832 * <BR>COL-SPAN-2: 833 * Checks that <B STYLE='color: red;'><I>at least one</I></B> of the Attributes Match 834 */ 835 @IntoHTMLTable(background=BlueDither, 836 title="Check whether or not <B><I>any</I></B> of the Specified-Attributes are Present") 837 @LinkJavaSource(handle="HasAndTest", name="hasLogicOp") 838 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 839 public boolean hasOR(boolean checkAttributeStringsForErrors, String... attributes) 840 { 841 // First-Function: Tells the logic to return TRUE on any match IMMEDIATELY 842 // 843 // Second-Function: At the End of the Loops, all Attributes have been tested. SINCE the 844 // previous function returns on match immediately, AND SINCE this is an 845 // OR, therefore FALSE must be returned (since there were no matches!) 846 847 return HasAndTest.hasLogicOp( 848 this, 849 checkAttributeStringsForErrors, 850 (int matchCount) -> true, 851 (int matchCount) -> false, 852 attributes 853 ); 854 } 855 856 /** 857 * <BR>See Documentation: {@link #hasXOR(boolean, String...)} 858 * <BR>Passes: NAND Boolean Logic 859 * <BR>COL-SPAN-2: 860 * Check that <B STYLE='color: red;'><I>none</I></B> of the Attributes Match 861 */ 862 @IntoHTMLTable(background=GreenDither, 863 title="Check that <B><I>none</I></B> of the Specified-Attributes are Present") 864 @LinkJavaSource(handle="HasAndTest", name="hasLogicOp") 865 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 866 public boolean hasNAND(boolean checkAttributeStringsForErrors, String... attributes) 867 { 868 // First-Function: Tells the logic to return FALSE on any match IMMEDIATELY 869 // 870 // Second-Function: At the End of the Loops, all Attributes have been tested. SINCE 871 // the previous function returns on match immediately, AND SINCE this is 872 // a NAND, therefore TRUE must be returned (since there were no matches!) 873 874 return HasAndTest.hasLogicOp( 875 this, 876 checkAttributeStringsForErrors, 877 (int matchCount) -> false, 878 (int matchCount) -> true, 879 attributes 880 ); 881 } 882 883 /** 884 * <BR />Passes: XOR Boolean Logic 885 * <BR />Checks that <B STYLE='color: red;'><I>precisely-one</I></B> Attribute is found 886 * <BR /><BR /><IMG SRC='doc-files/img/hasAND.png' CLASS=JDIMG ALT=Example> 887 * 888 * @param checkAttributeStringsForErrors 889 * <EMBED CLASS='external-html' DATA-FILE-ID=TAGNODE_HAS_BOOL> 890 * 891 * <BR /><BR /><B>NOTE:</B> If this method is passed a zero-length {@code String}-array to the 892 * {@code 'attributes'} parameter, this method shall exit immediately and return {@code FALSE}. 893 * 894 * @throws InnerTagKeyException If any of the {@code 'attributes'} are not valid HTML 895 * attributes, <I><B>and</B></I> the user has passed {@code TRUE} to parameter 896 * {@code checkAttributeStringsForErrors}. 897 * 898 * @throws NullPointerException If any of the {@code 'attributes'} are null. 899 * @throws ClosingTagNodeException <EMBED CLASS='external-html' DATA-FILE-ID=CTNEX> 900 * @throws IllegalArgumentException If the {@code 'attributes'} parameter has length zero. 901 * @see InnerTagKeyException#check(String[]) 902 */ 903 @LinkJavaSource(handle="HasAndTest", name="hasLogicOp") 904 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 905 public boolean hasXOR(boolean checkAttributeStringsForErrors, String... attributes) 906 { 907 // First-Function: Tells the logic to IGNORE the FIRST MATCH, and any matches afterwards 908 // should produce a FALSE result immediately 909 // (XOR means ==> one-and-only-one) 910 // 911 // Second-Function: At the End of the Loops, all Attributes have been tested. Just 912 // return whether or not the match-count is PRECISELY ONE. 913 914 return HasAndTest.hasLogicOp( 915 this, 916 checkAttributeStringsForErrors, 917 (int matchCount) -> (matchCount == 1) ? null : false, 918 (int matchCount) -> (matchCount == 1), 919 attributes 920 ); 921 } 922 923 924 // ******************************************************************************************** 925 // ******************************************************************************************** 926 // has methods - extended, variable attribute-names 927 // ******************************************************************************************** 928 // ******************************************************************************************** 929 930 931 /** 932 * <BR>See Documentation: {@link #has(Predicate)} 933 * <BR>Passes: {@code String.equalsIgnoreCase(attributeName)} as the test-{@code Predicate} 934 */ 935 @IntoHTMLTable(background=GreenDither, 936 title="Check whether or not an Attribute is Present, using String-Equality") 937 @LinkJavaSource(handle="HasAndTest", name="has") 938 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 939 public boolean has(String attributeName) 940 { return HasAndTest.has(this, (String s) -> s.equalsIgnoreCase(attributeName)); } 941 942 /** 943 * <BR>See Documentation: {@link #has(Predicate)} 944 * <BR>Passes: {@code Pattern.asPredicate()} 945 */ 946 @IntoHTMLTable(background=BlueDither, 947 title="Check whether or not an Attribute is Present, by means of a Reg-Ex") 948 @LinkJavaSource(handle="HasAndTest", name="has") 949 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 950 public boolean has(Pattern attributeNameRegExTest) 951 { return HasAndTest.has(this, attributeNameRegExTest.asPredicate()); } 952 953 /** 954 * <BR>See Documentation: {@link #has(Predicate)} 955 * <BR>Passes: {@link TextComparitor#test(String, String[])} as the test-{@code Predicate} 956 */ 957 @IntoHTMLTable(background=GreenDither, 958 title="Check whether or not an Attribute is Present, by means of a TextComparitor") 959 @LinkJavaSource(handle="HasAndTest", name="has") 960 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 961 public boolean has(TextComparitor tc, String... compareStrs) 962 { return HasAndTest.has(this, (String s) -> tc.test(s, compareStrs)); } 963 964 /** 965 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_HAS_DESC2> 966 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_HAS_NOTE> 967 * @param attributeNameTest <EMBED CLASS='external-html' DATA-FILE-ID=TN_HAS_ANT> 968 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_HAS_RET2> 969 * @see StrFilter 970 */ 971 @LinkJavaSource(handle="HasAndTest", name="has") 972 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 973 public boolean has(Predicate<String> attributeNameTest) 974 { return HasAndTest.has(this, attributeNameTest); } 975 976 977 // ******************************************************************************************** 978 // ******************************************************************************************** 979 // hasValue(...) methods 980 // ******************************************************************************************** 981 // ******************************************************************************************** 982 983 984 /** 985 * <BR>See Documentation: {@link #hasValue(Predicate, boolean, boolean)} 986 * <BR>Passes: {@code String.equals(attributeValue)} as the test-{@code Predicate} 987 */ 988 @IntoHTMLTable(background=GreenDither, 989 title="Find an Attribute by Attribute-Value, using String-Equality") 990 @LinkJavaSource(handle="HasAndTest", name="hasValue") 991 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 992 public Map.Entry<String, String> hasValue 993 (String attributeValue, boolean retainQuotes, boolean preserveKeysCase) 994 { 995 return HasAndTest.hasValue 996 (this, (String s) -> attributeValue.equals(s), retainQuotes, preserveKeysCase); 997 } 998 999 /** 1000 * <BR>See Documentation: {@link #hasValue(Predicate, boolean, boolean)} 1001 * <BR>Passes: {@code attributeValueRegExTest.asPredicate()} 1002 */ 1003 @IntoHTMLTable(background=BlueDither, 1004 title="Find an Attribute by Attribute-Value, by means of a Reg-Ex") 1005 @LinkJavaSource(handle="HasAndTest", name="hasValue") 1006 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 1007 public Map.Entry<String, String> hasValue 1008 (Pattern attributeValueRegExTest, boolean retainQuotes, boolean preserveKeysCase) 1009 { 1010 return HasAndTest.hasValue 1011 (this, attributeValueRegExTest.asPredicate(), retainQuotes, preserveKeysCase); 1012 } 1013 1014 /** 1015 * <BR>See Documentation: {@link #hasValue(Predicate, boolean, boolean)} 1016 * <BR>Passes: {@link TextComparitor#test(String, String[])} as the test-{@code Predicate} 1017 */ 1018 @IntoHTMLTable(background=GreenDither, 1019 title="Find an Attribute by Attribute-Value, by means of a Text-Comparitor") 1020 @LinkJavaSource(handle="HasAndTest", name="hasValue") 1021 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 1022 public Map.Entry<String, String> hasValue( 1023 boolean retainQuotes, boolean preserveKeysCase, TextComparitor attributeValueTester, 1024 String... compareStrs 1025 ) 1026 { 1027 return HasAndTest.hasValue( 1028 this, 1029 (String s) -> attributeValueTester.test(s, compareStrs), 1030 retainQuotes, 1031 preserveKeysCase 1032 ); 1033 } 1034 1035 /** 1036 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_HASVAL_DESC2> 1037 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_HASVAL_DNOTE> 1038 * @param attributeValueTest <EMBED CLASS='external-html' DATA-FILE-ID=TN_HASVAL_AVT> 1039 * @param retainQuotes <EMBED CLASS='external-html' DATA-FILE-ID=TN_HASVAL_RQ> 1040 * @param preserveKeysCase <EMBED CLASS='external-html' DATA-FILE-ID=TN_HASVAL_PKC> 1041 * <EMBED CLASS='external-html' DATA-FILE-ID=TAGNODE_PRESERVE_C> 1042 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_HASVAL_RET2> 1043 * @see StrFilter 1044 */ 1045 @LinkJavaSource(handle="HasAndTest", name="hasValue") 1046 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 1047 public Map.Entry<String, String> hasValue 1048 (Predicate<String> attributeValueTest, boolean retainQuotes, boolean preserveKeysCase) 1049 { return HasAndTest.hasValue(this, attributeValueTest, retainQuotes, preserveKeysCase); } 1050 1051 1052 // ******************************************************************************************** 1053 // ******************************************************************************************** 1054 // getInstance() 1055 // ******************************************************************************************** 1056 // ******************************************************************************************** 1057 1058 1059 /** 1060 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_GETINST_DESC> 1061 * @param tok Any valid HTML tag. 1062 * @param openOrClosed <EMBED CLASS='external-html' DATA-FILE-ID=TN_GETINST_OOC> 1063 * @return An instance of this class 1064 * 1065 * @throws IllegalArgumentException If parameter {@code TC openOrClose} is {@code null} or 1066 * {@code TC.Both} 1067 * 1068 * @throws HTMLTokException If the parameter {@code String tok} is not a valid HTML-tag 1069 * 1070 * @throws SingletonException If the token requested is a {@code singleton} (self-closing) tag, 1071 * but the Tag-Criteria {@code 'TC'} parameter is requesting a closing-version of the tag. 1072 * 1073 * @see HTMLTags#hasTag(String, TC) 1074 * @see HTMLTags#isSingleton(String) 1075 */ 1076 public static TagNode getInstance(String tok, TC openOrClosed) 1077 { 1078 if (openOrClosed == null) 1079 throw new NullPointerException("The value of openOrClosed cannot be null."); 1080 1081 if (openOrClosed == TC.Both) 1082 throw new IllegalArgumentException("The value of openOrClosed cannot be TC.Both."); 1083 1084 if (HTMLTags.isSingleton(tok) && (openOrClosed == TC.ClosingTags)) 1085 1086 throw new SingletonException( 1087 "The value of openOrClosed is TC.ClosingTags, but unfortunately you have asked " + 1088 "for a [" + tok + "] HTML element, which is a singleton element, and therefore " + 1089 "cannot have a closing-tag instance." 1090 ); 1091 1092 TagNode ret = HTMLTags.hasTag(tok, openOrClosed); 1093 1094 if (ret == null) 1095 throw new HTMLTokException 1096 ("The HTML-Tag provided isn't valid!\ntok: " + tok + "\nTC: " + openOrClosed); 1097 1098 return ret; 1099 } 1100 1101 1102 // ******************************************************************************************** 1103 // ******************************************************************************************** 1104 // Methods for "CSS Classes" 1105 // ******************************************************************************************** 1106 // ******************************************************************************************** 1107 1108 1109 /** 1110 * Convenience Method. 1111 * <BR />Invokes: {@link #cssClasses()} 1112 * <BR />Catches-Exception 1113 */ 1114 public Stream<String> cssClassesNOCSE() 1115 { try { return cssClasses(); } catch (CSSStrException e) { return Stream.empty(); } } 1116 1117 /** 1118 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_CSS_CL_DESC> 1119 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_CSS_CL_RET> 1120 * <EMBED CLASS='external-html' DATA-FILE-ID=STRMCNVT> 1121 * @throws CSSStrException <EMBED CLASS='external-html' DATA-FILE-ID=TN_CSS_CL_CSSSE> 1122 * @see #cssClasses() 1123 * @see #AV(String) 1124 * @see StringParse#WHITE_SPACE_REGEX 1125 * @see CSSStrException#check(Stream) 1126 */ 1127 @LinkJavaSource(handle="ClassIDStyle", name="cssClasses") 1128 public Stream<String> cssClasses() 1129 { return ClassIDStyle.cssClasses(this); } 1130 1131 /** 1132 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_CSS_CL_DESC> 1133 * @param quote <EMBED CLASS='external-html' DATA-FILE-ID=TGND_QUOTE_EXPL> 1134 * @param appendOrClobber <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_CSS_CL_AOC> 1135 * @param cssClasses <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_CSS_CL_CCL> 1136 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_CSS_CL_RET> 1137 * 1138 * @throws CSSStrException This exception shall throw if any of the {@code 'cssClasses'} in the 1139 * var-args {@code String...} parameter do not meet the HTML 5 CSS {@code Class} naming rules. 1140 * 1141 * @throws ClosingTagNodeException <EMBED CLASS=external-html DATA-FILE-ID=CTNEX> 1142 * @throws QuotesException <EMBED CLASS=external-html DATA-FILE-ID=TN_SET_CSS_CL_QEX> 1143 * @see CSSStrException#check(String[]) 1144 * @see CSSStrException#VALID_CSS_CLASS_OR_NAME_TOKEN 1145 * @see #appendToAV(String, String, boolean, SD) 1146 * @see #setAV(String, String, SD) 1147 */ 1148 @LinkJavaSource(handle="ClassIDStyle", name="setCSSClasses") 1149 public TagNode setCSSClasses(SD quote, boolean appendOrClobber, String... cssClasses) 1150 { return ClassIDStyle.setCSSClasses(this, quote, appendOrClobber, cssClasses); } 1151 1152 /** 1153 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_APD_CSS_CL_DESC> 1154 * @param cssClass This is the CSS-{@code Class} name that is being inserted into 1155 * {@code 'this'} instance of {@code TagNode} 1156 * 1157 * @param quote <EMBED CLASS=external-html DATA-FILE-ID=TGND_QUOTE_EXPL> 1158 * @return A new {@code TagNode} with updated CSS {@code Class} Name(s) 1159 * @throws CSSStrException <EMBED CLASS=external-html DATA-FILE-ID=TN_APD_CSS_CL_CSSSE> 1160 * @throws ClosingTagNodeException <EMBED CLASS=external-html DATA-FILE-ID=CTNEX> 1161 * @throws QuotesException <EMBED CLASS=external-html DATA-FILE-ID=TN_APD_CSS_CL_QEX> 1162 * @see CSSStrException#check(String[]) 1163 * @see #setAV(String, String, SD) 1164 * @see #appendToAV(String, String, boolean, SD) 1165 */ 1166 @LinkJavaSource(handle="ClassIDStyle", name="appendCSSClass") 1167 public TagNode appendCSSClass(String cssClass, SD quote) 1168 { return ClassIDStyle.appendCSSClass(this, cssClass, quote); } 1169 1170 1171 // ******************************************************************************************** 1172 // ******************************************************************************************** 1173 // Methods for "CSS Style" 1174 // ******************************************************************************************** 1175 // ******************************************************************************************** 1176 1177 1178 /** 1179 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_CSS_STYLE_DESC> 1180 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_CSS_STYLE_DESCEX> 1181 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_CSS_STYLE_RET> 1182 */ 1183 @LinkJavaSource(handle="ClassIDStyle", name="cssStyle") 1184 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="CSS_INLINE_STYLE_REGEX") 1185 public Properties cssStyle() 1186 { return ClassIDStyle.cssStyle(this); } 1187 1188 /** 1189 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_CSS_STY_DESC> 1190 * @param p <EMBED CLASS=external-html DATA-FILE-ID=TN_SET_CSS_STY_P> 1191 * @param quote <EMBED CLASS=external-html DATA-FILE-ID=TGND_QUOTE_EXPL> 1192 * @param appendOrClobber <EMBED CLASS=external-html DATA-FILE-ID=TN_SET_CSS_STY_AOC> 1193 * @return <EMBED CLASS=external-html DATA-FILE-ID=TN_SET_CSS_STY_RET> 1194 * @throws ClosingTagNodeException <EMBED CLASS=external-html DATA-FILE-ID=CTNEX> 1195 * @throws CSSStrException If there is an invalid CSS Style Property Name. 1196 * 1197 * @throws QuotesException If the style-element's quotation marks are incompatible with any 1198 * and all quotation marks employed by the style-element definitions. 1199 * 1200 * @see CSSStrException#VALID_CSS_CLASS_OR_NAME_TOKEN 1201 * @see #appendToAV(String, String, boolean, SD) 1202 * @see #setAV(String, String, SD) 1203 */ 1204 @LinkJavaSource(handle="ClassIDStyle", name="setCSSStyle") 1205 public TagNode setCSSStyle(Properties p, SD quote, boolean appendOrClobber) 1206 { return ClassIDStyle.setCSSStyle(this, p, quote, appendOrClobber); } 1207 1208 1209 // ******************************************************************************************** 1210 // ******************************************************************************************** 1211 // Methods for "CSS ID" 1212 // ******************************************************************************************** 1213 // ******************************************************************************************** 1214 1215 1216 /** 1217 * Convenience Method. 1218 * <BR />Invokes: {@link #AV(String)} 1219 * <BR />Passes: {@code String "id"}, the CSS-ID attribute-<B STYLE='color: red;'>name</B> 1220 */ 1221 public String getID() 1222 { 1223 String id = AV("ID"); 1224 return (id == null) ? null : id.trim(); 1225 } 1226 1227 /** 1228 * This merely sets the current CSS {@code 'ID'} Attribute <B STYLE='color: red;'>Value</B>. 1229 * 1230 * @param id This is the new CSS {@code 'ID'} attribute-<B STYLE='color: red;'>value</B> that 1231 * the user would like applied to {@code 'this'} instance of {@code TagNode}. 1232 * 1233 * @param quote <EMBED CLASS='external-html' DATA-FILE-ID=TGND_QUOTE_EXPL> 1234 * 1235 * @return Returns a new instance of {@code TagNode} that has an updated {@code 'ID'} 1236 * attribute-<B STYLE='color: red;'>value</B>. 1237 * 1238 * @throws IllegalArgumentException This exception shall throw if an invalid 1239 * {@code String}-token has been passed to parameter {@code 'id'}. 1240 * 1241 * <BR /><BR /><B>BYPASS NOTE:</B> If the user would like to bypass this exception-check, for 1242 * instance because he / she is using a CSS Pre-Processor, then applying the general-purpose 1243 * method {@code TagNode.setAV("id", "some-new-id")} ought to suffice. This other method will 1244 * not apply validity checking, beyond scanning for the usual "quotes-within-quotes" problems, 1245 * which is always disallowed. 1246 * 1247 * @throws ClosingTagNodeException <EMBED CLASS='external-html' DATA-FILE-ID=CTNEX> 1248 * 1249 * @see CSSStrException#VALID_CSS_CLASS_OR_NAME_TOKEN 1250 * @see #setAV(String, String, SD) 1251 */ 1252 public TagNode setID(String id, SD quote) 1253 { 1254 if (! CSSStrException.VALID_CSS_CLASS_OR_NAME_TOKEN_PRED.test(id)) 1255 1256 throw new IllegalArgumentException( 1257 "The id parameter provide: [" + id + "], does not conform to the standard CSS " + 1258 "Names.\nEither try using the generic TagNode.setAV(\"id\", yourNewId, quote); " + 1259 "method to bypass this check, or change the value passed to the 'id' parameter " + 1260 "here." 1261 ); 1262 1263 return setAV("id", id.trim(), quote); 1264 } 1265 1266 1267 // ******************************************************************************************** 1268 // ******************************************************************************************** 1269 // Attributes that begin with "data-..." 1270 // ******************************************************************************************** 1271 // ******************************************************************************************** 1272 1273 1274 /** 1275 * Convenience Method. 1276 * <BR />See Documentation: {@link #AV(String)} 1277 * <BR />Passes: {@code "data-"} prepended to parameter {@code 'dataName'} for the 1278 * attribute-<B STYLE='color:red'>name</B> 1279 */ 1280 @LinkJavaSource(handle="GetSetAttr", name="AV") 1281 public String dataAV(String dataName) 1282 { return GetSetAttr.AV(this, "data-" + dataName, false); } 1283 1284 /** 1285 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_REM_DATTR_DESC> 1286 * @return <EMBED CLASS=external-html DATA-FILE-ID=TN_REM_DATTR_RET> 1287 * @throws ClosingTagNodeException <EMBED CLASS=external-html DATA-FILE-ID=TN_REM_DATTR_CTNEX> 1288 */ 1289 @LinkJavaSource(handle="RemoveAttributes", name="removeAttributes") 1290 public TagNode removeDataAttributes() 1291 { 1292 return RemoveAttributes.removeAttributes 1293 (this, (String attr) -> ! StrCmpr.startsWithIgnoreCase(attr, "data-") ); 1294 } 1295 1296 /** 1297 * Convenience Method. 1298 * <BR />See Documentation: {@link #getDataAV(boolean)} 1299 * <BR />Attribute-<B STYLE='color: red;'>names</B> will be in lower-case 1300 */ 1301 @LinkJavaSource(handle="DataAttributes", name="getDataAV") 1302 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="DATA_ATTRIBUTE_REGEX") 1303 public Properties getDataAV() 1304 { return DataAttributes.getDataAV(this, false); } 1305 1306 /** 1307 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_GET_DATA_AV_DESC> 1308 * @param preserveKeysCase <EMBED CLASS='external-html' DATA-FILE-ID=TN_GET_DATA_AV_PAR> 1309 * <EMBED CLASS='external-html' DATA-FILE-ID=TAGNODE_PRESERVE_C> 1310 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_GET_DATA_AV_RET> 1311 */ 1312 @LinkJavaSource(handle="DataAttributes", name="getDataAV") 1313 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="DATA_ATTRIBUTE_REGEX") 1314 public Properties getDataAV(boolean preserveKeysCase) 1315 { return DataAttributes.getDataAV(this, preserveKeysCase); } 1316 1317 /** 1318 * Convenience Method. 1319 * <BR />See Documentation: {@link #getDataAN(boolean)} 1320 * <BR />Attribute-<B STYLE='color: red;'>names</B> will be in lower-case 1321 */ 1322 public Stream<String> getDataAN() 1323 { return DataAttributes.getDataAN(this, false); } 1324 1325 /** 1326 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_GET_DATA_AN_DESC> 1327 * @param preserveKeysCase <EMBED CLASS='external-html' DATA-FILE-ID=TN_GET_DATA_AN_PAR> 1328 * <EMBED CLASS='external-html' DATA-FILE-ID=TAGNODE_PRESERVE_C> 1329 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_GET_DATA_AN_RET> 1330 * <EMBED CLASS='external-html' DATA-FILE-ID=STRMCNVT> 1331 */ 1332 @LinkJavaSource(handle="DataAttributes", name="getDataAN") 1333 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="DATA_ATTRIBUTE_REGEX") 1334 public Stream<String> getDataAN(boolean preserveKeysCase) 1335 { return DataAttributes.getDataAN(this, preserveKeysCase); } 1336 1337 1338 // ******************************************************************************************** 1339 // ******************************************************************************************** 1340 // Java Methods 1341 // ******************************************************************************************** 1342 // ******************************************************************************************** 1343 1344 1345 /** 1346 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_TOSTR_AV_DESC> 1347 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_TOSTR_AV_RET> 1348 * @see HTMLNode#toString() 1349 */ 1350 @LinkJavaSource(handle="GeneralPurpose", name="toStringAV") 1351 public String toStringAV() 1352 { return GeneralPurpose.toStringAV(this); } 1353 1354 /** 1355 * Java's {@code interface Cloneable} requirements. This instantiates a new {@code TagNode} 1356 * with identical <SPAN STYLE='color: red;'>{@code String str}</SPAN> fields, and also 1357 * identical <SPAN STYLE='color: red;'>{@code boolean isClosing}</SPAN> and 1358 * <SPAN STYLE='color: red;'>{@code String tok}</SPAN> fields. 1359 * 1360 * @return A new {@code TagNode} whose internal fields are identical to this one. 1361 */ 1362 public TagNode clone() { return new TagNode(str); } 1363 1364 /** 1365 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_COMPARETO_DESC> 1366 * @param n Any other {@code TagNode} to be compared to {@code 'this' TagNode} 1367 * @return An integer that fulfils Java's {@code Comparable} interface-method requirements. 1368 */ 1369 public int compareTo(TagNode n) 1370 { 1371 // Utilize the standard "String.compare(String)" method with the '.tok' string field. 1372 // All 'tok' fields are stored as lower-case strings. 1373 int compare1 = this.tok.compareTo(n.tok); 1374 1375 // Comparison #1 will be non-zero if the two TagNode's being compared had different 1376 // .tok fields 1377 if (compare1 != 0) return compare1; 1378 1379 // If the '.tok' fields were the same, use the 'isClosing' field for comparison instead. 1380 // This comparison will only be used if they are different. 1381 if (this.isClosing != n.isClosing) return (this.isClosing == false) ? -1 : 1; 1382 1383 // Finally try using the entire element '.str' String field, instead. 1384 return this.str.length() - n.str.length(); 1385 } 1386 1387 1388 // ******************************************************************************************** 1389 // ******************************************************************************************** 1390 // toUpperCase 1391 // ******************************************************************************************** 1392 // ******************************************************************************************** 1393 1394 1395 /** 1396 * <EMBED CLASS=defs DATA-CASE=Upper DATA-CAPITAL=""> 1397 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_TO_UPLOW_1_DESC> 1398 * @param justTag_Or_TagAndAttributeNames 1399 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_TO_UPLOW_1_PARAM> 1400 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_TO_UPLOW_1_RET> 1401 */ 1402 @LinkJavaSource(handle="CaseChange", name="toCaseInternal", paramCount=3) 1403 public TagNode toUpperCase(boolean justTag_Or_TagAndAttributeNames) 1404 { 1405 return CaseChange.toCaseInternal 1406 (this, justTag_Or_TagAndAttributeNames, String::toUpperCase); 1407 } 1408 1409 /** 1410 * Convenience Method. 1411 * <BR />See Documentation: {@link #toUpperCase(boolean, Predicate)} 1412 * <BR />Passes: {@code StrCmpr.equalsXOR_CI(attrName, attributeNames)} 1413 * @see StrCmpr#equalsXOR_CI(String, String...) 1414 */ 1415 @LinkJavaSource(handle="CaseChange", name="toCaseInternal", paramCount=4) 1416 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 1417 public TagNode toUpperCase(boolean tag, String... attributeNames) 1418 { 1419 return CaseChange.toCaseInternal( 1420 this, 1421 tag, 1422 (String attrName) -> StrCmpr.equalsXOR_CI(attrName, attributeNames), 1423 String::toUpperCase 1424 ); 1425 } 1426 1427 /** 1428 * <EMBED CLASS=defs DATA-CASE=Upper DATA-CAPITAL=""> 1429 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_TO_UPLOW_2_DESC> 1430 * @param tag Indicates whether or not the Tag-Name should be capitalized 1431 * @param attrNameTest <EMBED CLASS='external-html' DATA-FILE-ID=TN_TO_UPLOW_2_PARAM> 1432 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_TO_UPLOW_2_RET> 1433 */ 1434 @LinkJavaSource(handle="CaseChange", name="toCaseInternal", paramCount=4) 1435 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 1436 public TagNode toUpperCase(boolean tag, Predicate<String> attrNameTest) 1437 { return CaseChange.toCaseInternal(this, tag, attrNameTest, String::toUpperCase); } 1438 1439 1440 // ******************************************************************************************** 1441 // ******************************************************************************************** 1442 // toLowerCase 1443 // ******************************************************************************************** 1444 // ******************************************************************************************** 1445 1446 1447 /** 1448 * <EMBED CLASS=defs DATA-CASE=Lower DATA-CAPITAL="de-"> 1449 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_TO_UPLOW_1_DESC> 1450 * @param justTag_Or_TagAndAttributeNames 1451 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_TO_UPLOW_1_PARAM> 1452 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_TO_UPLOW_1_RET> 1453 */ 1454 @LinkJavaSource(handle="CaseChange", name="toCaseInternal", paramCount=3) 1455 public TagNode toLowerCase(boolean justTag_Or_TagAndAttributeNames) 1456 { 1457 return CaseChange.toCaseInternal 1458 (this, justTag_Or_TagAndAttributeNames, String::toLowerCase); 1459 } 1460 1461 /** 1462 * Convenience Method. 1463 * <BR />See Documentation: {@link #toLowerCase(boolean, Predicate)} 1464 * <BR />Passes: {@code StrCmpr.equalsXOR_CI(attrName, attributeNames)} 1465 * @see StrCmpr#equalsXOR_CI(String, String...) 1466 */ 1467 @LinkJavaSource(handle="CaseChange", name="toCaseInternal", paramCount=4) 1468 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 1469 public TagNode toLowerCase(boolean tag, String... attributeNames) 1470 { 1471 return CaseChange.toCaseInternal( 1472 this, 1473 tag, 1474 (String attrName) -> StrCmpr.equalsXOR_CI(attrName, attributeNames), 1475 String::toLowerCase 1476 ); 1477 } 1478 1479 /** 1480 * <EMBED CLASS=defs DATA-CASE=Lower DATA-CAPITAL="de-"> 1481 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_TO_UPLOW_2_DESC> 1482 * @param tag Indicates whether or not the Tag-Name should be decapitalized 1483 * @param attrNameTest <EMBED CLASS='external-html' DATA-FILE-ID=TN_TO_UPLOW_2_PARAM> 1484 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_TO_UPLOW_2_RET> 1485 */ 1486 @LinkJavaSource(handle="CaseChange", name="toCaseInternal", paramCount=4) 1487 @LinkJavaSource(handle="AttrRegEx", entity=FIELD, name="KEY_VALUE_REGEX") 1488 public TagNode toLowerCase(boolean tag, Predicate<String> attrNameTest) 1489 { return CaseChange.toCaseInternal(this, tag, attrNameTest, String::toLowerCase); } 1490 1491 1492 // ******************************************************************************************** 1493 // ******************************************************************************************** 1494 // Attribute-Value Quotation-Marks - REMOVE 1495 // ******************************************************************************************** 1496 // ******************************************************************************************** 1497 1498 1499 /** 1500 * Convenience Method. 1501 * <BR />See Documentation: {@link #removeAVQuotes(Predicate)} 1502 * <BR />Removes Quotation-Marks from <B STYLE='color: red;'>Value</B> whose Inner-Tag 1503 * <B STYLE='color: red;'>Name</B> matches {@code 'attributeName'} 1504 */ 1505 @LinkJavaSource(handle="QuotationMarks", name="removeAVQuotes") 1506 public TagNode removeAVQuotes(String attributeName) 1507 { 1508 return QuotationMarks.removeAVQuotes 1509 (this, (String attr) -> attr.equalsIgnoreCase(attributeName)); 1510 } 1511 1512 /** 1513 * Convenience Method. 1514 * <BR />See Documentation: {@link #removeAVQuotes(Predicate)} 1515 * <BR />Removes Quotation-Marks from all Inner-Tag <B STYLE='color: red;'>Values</B> 1516 */ 1517 @LinkJavaSource(handle="QuotationMarks", name="removeAVQuotes") 1518 public TagNode removeAllAVQuotes() 1519 { return QuotationMarks.removeAVQuotes(this, (String attr) -> true); } 1520 1521 /** 1522 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_REM_QUOTES_DESC> 1523 * @param attrNameTest <EMBED CLASS='external-html' DATA-FILE-ID=TN_REM_QUOTES_PARAM> 1524 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_REM_QUOTES_RET> 1525 * @throws QuotesException If the resulting <CODE>TagNode</CODE> contains Quotation-Errors 1526 */ 1527 @LinkJavaSource(handle="QuotationMarks", name="removeAVQuotes") 1528 public TagNode removeAVQuotes(Predicate<String> attrNameTest) 1529 { return QuotationMarks.removeAVQuotes(this, attrNameTest); } 1530 1531 1532 // ******************************************************************************************** 1533 // ******************************************************************************************** 1534 // Attribute-Value Quotation-Marks - SET 1535 // ******************************************************************************************** 1536 // ******************************************************************************************** 1537 1538 1539 /** 1540 * Convenience Method. 1541 * <BR />See Documentation: {@link #setAVQuotes(Predicate, SD)}} 1542 * <BR />Set Quotation-Marks for the Attribute whose <B STYLE='color: red;'>Name</B> matches 1543 * {@code 'attributeName'} 1544 */ 1545 @LinkJavaSource(handle="QuotationMarks", name="setAVQuotes") 1546 public TagNode setAVQuotes(String attributeName, SD quote) 1547 { 1548 return QuotationMarks.setAVQuotes 1549 (this, (String attr) -> attr.equalsIgnoreCase(attributeName), quote); 1550 } 1551 1552 /** 1553 * Convenience Method. 1554 * <BR />See Documentation: {@link #setAVQuotes(Predicate, SD)}} 1555 * <BR />Set the Quotation-Marks which are used with all Attribute's contained by 1556 * {@code 'this'} Tag. 1557 */ 1558 @LinkJavaSource(handle="QuotationMarks", name="setAVQuotes") 1559 public TagNode setAllAVQuotes(SD quote) 1560 { return QuotationMarks.setAVQuotes(this, (String attr) -> true, quote); } 1561 1562 /** 1563 * <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_QUOTES_DESC> 1564 * @param attrNameTest <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_QUOTES_PARAM> 1565 * @param quote The new Quotation-Mark to apply 1566 * @return <EMBED CLASS='external-html' DATA-FILE-ID=TN_SET_QUOTES_RET> 1567 * @throws QuotesException If the resulting <CODE>TagNode</CODE> contains Quotation-Errors 1568 * @throws NullPointerException If either parameter is passed null. 1569 */ 1570 @LinkJavaSource(handle="QuotationMarks", name="setAVQuotes") 1571 public TagNode setAVQuotes(Predicate<String> attrNameTest, SD quote) 1572 { return QuotationMarks.setAVQuotes(this, attrNameTest, quote); } 1573 1574 1575 // ******************************************************************************************** 1576 // ******************************************************************************************** 1577 // Attribute-Value Quotation-Marks - GET 1578 // ******************************************************************************************** 1579 // ******************************************************************************************** 1580 1581}