1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html#License 3 /* 4 ******************************************************************************* 5 * Copyright (C) 1996-2015, International Business Machines Corporation and * 6 * others. All Rights Reserved. * 7 ******************************************************************************* 8 */ 9 10 package com.ibm.icu.text; 11 12 import java.text.CharacterIterator; 13 14 /** 15 * <tt>SearchIterator</tt> is an abstract base class that provides 16 * methods to search for a pattern within a text string. Instances of 17 * <tt>SearchIterator</tt> maintain a current position and scan over the 18 * target text, returning the indices the pattern is matched and the length 19 * of each match. 20 * <p> 21 * <tt>SearchIterator</tt> defines a protocol for text searching. 22 * Subclasses provide concrete implementations of various search algorithms. 23 * For example, <tt>StringSearch</tt> implements language-sensitive pattern 24 * matching based on the comparison rules defined in a 25 * <tt>RuleBasedCollator</tt> object. 26 * <p> 27 * Other options for searching include using a BreakIterator to restrict 28 * the points at which matches are detected. 29 * <p> 30 * <tt>SearchIterator</tt> provides an API that is similar to that of 31 * other text iteration classes such as <tt>BreakIterator</tt>. Using 32 * this class, it is easy to scan through text looking for all occurrences of 33 * a given pattern. The following example uses a <tt>StringSearch</tt> 34 * object to find all instances of "fox" in the target string. Any other 35 * subclass of <tt>SearchIterator</tt> can be used in an identical 36 * manner. 37 * <pre><code> 38 * String target = "The quick brown fox jumped over the lazy fox"; 39 * String pattern = "fox"; 40 * SearchIterator iter = new StringSearch(pattern, target); 41 * for (int pos = iter.first(); pos != SearchIterator.DONE; 42 * pos = iter.next()) { 43 * System.out.println("Found match at " + pos + 44 * ", length is " + iter.getMatchLength()); 45 * } 46 * </code></pre> 47 * 48 * @author Laura Werner, synwee 49 * @stable ICU 2.0 50 * @see BreakIterator 51 * @see RuleBasedCollator 52 */ 53 public abstract class SearchIterator 54 { 55 /** 56 * The BreakIterator to define the boundaries of a logical match. 57 * This value can be a null. 58 * See class documentation for more information. 59 * @see #setBreakIterator(BreakIterator) 60 * @see #getBreakIterator 61 * @see BreakIterator 62 * @stable ICU 2.0 63 */ 64 protected BreakIterator breakIterator; 65 66 /** 67 * Target text for searching. 68 * @see #setTarget(CharacterIterator) 69 * @see #getTarget 70 * @stable ICU 2.0 71 */ 72 protected CharacterIterator targetText; 73 /** 74 * Length of the most current match in target text. 75 * Value 0 is the default value. 76 * @see #setMatchLength 77 * @see #getMatchLength 78 * @stable ICU 2.0 79 */ 80 protected int matchLength; 81 82 /** 83 * Java port of ICU4C struct USearch (usrchimp.h) 84 * 85 * Note: 86 * 87 * ICU4J already exposed some protected members such as 88 * targetText, breakIterator and matchedLength as a part of stable 89 * APIs. In ICU4C, they are exposed through USearch struct, 90 * although USearch struct itself is internal API. 91 * 92 * This class was created for making ICU4J code parallel to 93 * ICU4C implementation. ICU4J implementation access member 94 * fields like C struct (e.g. search_.isOverlap_) mostly, except 95 * fields already exposed as protected member (e.g. search_.text()). 96 * 97 */ 98 final class Search { 99 text()100 CharacterIterator text() { 101 return SearchIterator.this.targetText; 102 } 103 setTarget(CharacterIterator text)104 void setTarget(CharacterIterator text) { 105 SearchIterator.this.targetText = text; 106 } 107 108 /** Flag to indicate if overlapping search is to be done. 109 E.g. looking for "aa" in "aaa" will yield matches at offset 0 and 1. */ 110 boolean isOverlap_; 111 112 boolean isCanonicalMatch_; 113 114 ElementComparisonType elementComparisonType_; 115 116 BreakIterator internalBreakIter_; 117 breakIter()118 BreakIterator breakIter() { 119 return SearchIterator.this.breakIterator; 120 } 121 setBreakIter(BreakIterator breakIter)122 void setBreakIter(BreakIterator breakIter) { 123 SearchIterator.this.breakIterator = breakIter; 124 } 125 126 int matchedIndex_; 127 matchedLength()128 int matchedLength() { 129 return SearchIterator.this.matchLength; 130 } 131 setMatchedLength(int matchedLength)132 void setMatchedLength(int matchedLength) { 133 SearchIterator.this.matchLength = matchedLength; 134 } 135 136 /** Flag indicates if we are doing a forwards search */ 137 boolean isForwardSearching_; 138 139 /** Flag indicates if we are at the start of a string search. 140 This indicates that we are in forward search and at the start of m_text. */ 141 boolean reset_; 142 143 // Convenient methods for accessing begin/end index of the 144 // target text. These are ICU4J only and are not data fields. beginIndex()145 int beginIndex() { 146 if (targetText == null) { 147 return 0; 148 } 149 return targetText.getBeginIndex(); 150 } 151 endIndex()152 int endIndex() { 153 if (targetText == null) { 154 return 0; 155 } 156 return targetText.getEndIndex(); 157 } 158 } 159 160 Search search_ = new Search(); 161 162 // public data members ------------------------------------------------- 163 164 /** 165 * DONE is returned by previous() and next() after all valid matches have 166 * been returned, and by first() and last() if there are no matches at all. 167 * @see #previous 168 * @see #next 169 * @stable ICU 2.0 170 */ 171 public static final int DONE = -1; 172 173 // public methods ----------------------------------------------------- 174 175 // public setters ----------------------------------------------------- 176 177 /** 178 * <p> 179 * Sets the position in the target text at which the next search will start. 180 * This method clears any previous match. 181 * </p> 182 * @param position position from which to start the next search 183 * @exception IndexOutOfBoundsException thrown if argument position is out 184 * of the target text range. 185 * @see #getIndex 186 * @stable ICU 2.8 187 */ setIndex(int position)188 public void setIndex(int position) { 189 if (position < search_.beginIndex() 190 || position > search_.endIndex()) { 191 throw new IndexOutOfBoundsException( 192 "setIndex(int) expected position to be between " + 193 search_.beginIndex() + " and " + search_.endIndex()); 194 } 195 search_.reset_ = false; 196 search_.setMatchedLength(0); 197 search_.matchedIndex_ = DONE; 198 } 199 200 /** 201 * Determines whether overlapping matches are returned. See the class 202 * documentation for more information about overlapping matches. 203 * <p> 204 * The default setting of this property is false 205 * 206 * @param allowOverlap flag indicator if overlapping matches are allowed 207 * @see #isOverlapping 208 * @stable ICU 2.8 209 */ setOverlapping(boolean allowOverlap)210 public void setOverlapping(boolean allowOverlap) { 211 search_.isOverlap_ = allowOverlap; 212 } 213 214 /** 215 * Set the BreakIterator that will be used to restrict the points 216 * at which matches are detected. 217 * 218 * @param breakiter A BreakIterator that will be used to restrict the 219 * points at which matches are detected. If a match is 220 * found, but the match's start or end index is not a 221 * boundary as determined by the {@link BreakIterator}, 222 * the match will be rejected and another will be searched 223 * for. If this parameter is <tt>null</tt>, no break 224 * detection is attempted. 225 * @see BreakIterator 226 * @stable ICU 2.0 227 */ setBreakIterator(BreakIterator breakiter)228 public void setBreakIterator(BreakIterator breakiter) { 229 search_.setBreakIter(breakiter); 230 if (search_.breakIter() != null) { 231 // Create a clone of CharacterItearator, so it won't 232 // affect the position currently held by search_.text() 233 if (search_.text() != null) { 234 search_.breakIter().setText((CharacterIterator)search_.text().clone()); 235 } 236 } 237 } 238 239 /** 240 * Set the target text to be searched. Text iteration will then begin at 241 * the start of the text string. This method is useful if you want to 242 * reuse an iterator to search within a different body of text. 243 * 244 * @param text new text iterator to look for match, 245 * @exception IllegalArgumentException thrown when text is null or has 246 * 0 length 247 * @see #getTarget 248 * @stable ICU 2.4 249 */ setTarget(CharacterIterator text)250 public void setTarget(CharacterIterator text) 251 { 252 if (text == null || text.getEndIndex() == text.getIndex()) { 253 throw new IllegalArgumentException("Illegal null or empty text"); 254 } 255 256 text.setIndex(text.getBeginIndex()); 257 search_.setTarget(text); 258 search_.matchedIndex_ = DONE; 259 search_.setMatchedLength(0); 260 search_.reset_ = true; 261 search_.isForwardSearching_ = true; 262 if (search_.breakIter() != null) { 263 // Create a clone of CharacterItearator, so it won't 264 // affect the position currently held by search_.text() 265 search_.breakIter().setText((CharacterIterator)text.clone()); 266 } 267 if (search_.internalBreakIter_ != null) { 268 search_.internalBreakIter_.setText((CharacterIterator)text.clone()); 269 } 270 } 271 272 //TODO: We may add APIs below to match ICU4C APIs 273 // setCanonicalMatch 274 275 // public getters ---------------------------------------------------- 276 277 /** 278 * Returns the index to the match in the text string that was searched. 279 * This call returns a valid result only after a successful call to 280 * {@link #first}, {@link #next}, {@link #previous}, or {@link #last}. 281 * Just after construction, or after a searching method returns 282 * {@link #DONE}, this method will return {@link #DONE}. 283 * <p> 284 * Use {@link #getMatchLength} to get the matched string length. 285 * 286 * @return index of a substring within the text string that is being 287 * searched. 288 * @see #first 289 * @see #next 290 * @see #previous 291 * @see #last 292 * @stable ICU 2.0 293 */ getMatchStart()294 public int getMatchStart() { 295 return search_.matchedIndex_; 296 } 297 298 /** 299 * Return the current index in the text being searched. 300 * If the iteration has gone past the end of the text 301 * (or past the beginning for a backwards search), {@link #DONE} 302 * is returned. 303 * 304 * @return current index in the text being searched. 305 * @stable ICU 2.8 306 */ getIndex()307 public abstract int getIndex(); 308 309 /** 310 * Returns the length of text in the string which matches the search 311 * pattern. This call returns a valid result only after a successful call 312 * to {@link #first}, {@link #next}, {@link #previous}, or {@link #last}. 313 * Just after construction, or after a searching method returns 314 * {@link #DONE}, this method will return 0. 315 * 316 * @return The length of the match in the target text, or 0 if there 317 * is no match currently. 318 * @see #first 319 * @see #next 320 * @see #previous 321 * @see #last 322 * @stable ICU 2.0 323 */ getMatchLength()324 public int getMatchLength() { 325 return search_.matchedLength(); 326 } 327 328 /** 329 * Returns the BreakIterator that is used to restrict the indexes at which 330 * matches are detected. This will be the same object that was passed to 331 * the constructor or to {@link #setBreakIterator}. 332 * If the {@link BreakIterator} has not been set, <tt>null</tt> will be returned. 333 * See {@link #setBreakIterator} for more information. 334 * 335 * @return the BreakIterator set to restrict logic matches 336 * @see #setBreakIterator 337 * @see BreakIterator 338 * @stable ICU 2.0 339 */ getBreakIterator()340 public BreakIterator getBreakIterator() { 341 return search_.breakIter(); 342 } 343 344 /** 345 * Return the string text to be searched. 346 * @return text string to be searched. 347 * @stable ICU 2.0 348 */ getTarget()349 public CharacterIterator getTarget() { 350 return search_.text(); 351 } 352 353 /** 354 * Returns the text that was matched by the most recent call to 355 * {@link #first}, {@link #next}, {@link #previous}, or {@link #last}. 356 * If the iterator is not pointing at a valid match (e.g. just after 357 * construction or after {@link #DONE} has been returned, 358 * returns an empty string. 359 * 360 * @return the substring in the target test of the most recent match, 361 * or null if there is no match currently. 362 * @see #first 363 * @see #next 364 * @see #previous 365 * @see #last 366 * @stable ICU 2.0 367 */ getMatchedText()368 public String getMatchedText() { 369 if (search_.matchedLength() > 0) { 370 int limit = search_.matchedIndex_ + search_.matchedLength(); 371 StringBuilder result = new StringBuilder(search_.matchedLength()); 372 CharacterIterator it = search_.text(); 373 it.setIndex(search_.matchedIndex_); 374 while (it.getIndex() < limit) { 375 result.append(it.current()); 376 it.next(); 377 } 378 it.setIndex(search_.matchedIndex_); 379 return result.toString(); 380 } 381 return null; 382 } 383 384 // miscellaneous public methods ----------------------------------------- 385 386 /** 387 * Returns the index of the next point at which the text matches the 388 * search pattern, starting from the current position 389 * The iterator is adjusted so that its current index (as returned by 390 * {@link #getIndex}) is the match position if one was found. 391 * If a match is not found, {@link #DONE} will be returned and 392 * the iterator will be adjusted to a position after the end of the text 393 * string. 394 * 395 * @return The index of the next match after the current position, 396 * or {@link #DONE} if there are no more matches. 397 * @see #getIndex 398 * @stable ICU 2.0 399 */ next()400 public int next() { 401 int index = getIndex(); // offset = getOffset() in ICU4C 402 int matchindex = search_.matchedIndex_; 403 int matchlength = search_.matchedLength(); 404 search_.reset_ = false; 405 if (search_.isForwardSearching_) { 406 int endIdx = search_.endIndex(); 407 if (index == endIdx || matchindex == endIdx || 408 (matchindex != DONE && 409 matchindex + matchlength >= endIdx)) { 410 setMatchNotFound(); 411 return DONE; 412 } 413 } else { 414 // switching direction. 415 // if matchedIndex == DONE, it means that either a 416 // setIndex (setOffset in C) has been called or that previous ran off the text 417 // string. the iterator would have been set to offset 0 if a 418 // match is not found. 419 search_.isForwardSearching_ = true; 420 if (search_.matchedIndex_ != DONE) { 421 // there's no need to set the collation element iterator 422 // the next call to next will set the offset. 423 return matchindex; 424 } 425 } 426 427 if (matchlength > 0) { 428 // if matchlength is 0 we are at the start of the iteration 429 if (search_.isOverlap_) { 430 index++; 431 } else { 432 index += matchlength; 433 } 434 } 435 436 return handleNext(index); 437 } 438 439 /** 440 * Returns the index of the previous point at which the string text 441 * matches the search pattern, starting at the current position. 442 * The iterator is adjusted so that its current index (as returned by 443 * {@link #getIndex}) is the match position if one was found. 444 * If a match is not found, {@link #DONE} will be returned and 445 * the iterator will be adjusted to the index {@link #DONE}. 446 * 447 * @return The index of the previous match before the current position, 448 * or {@link #DONE} if there are no more matches. 449 * @see #getIndex 450 * @stable ICU 2.0 451 */ previous()452 public int previous() { 453 int index; // offset in ICU4C 454 if (search_.reset_) { 455 index = search_.endIndex(); // m_search_->textLength in ICU4C 456 search_.isForwardSearching_ = false; 457 search_.reset_ = false; 458 setIndex(index); 459 } else { 460 index = getIndex(); 461 } 462 463 int matchindex = search_.matchedIndex_; 464 if (search_.isForwardSearching_) { 465 // switching direction. 466 // if matchedIndex == DONE, it means that either a 467 // setIndex (setOffset in C) has been called or that next ran off the text 468 // string. the iterator would have been set to offset textLength if 469 // a match is not found. 470 search_.isForwardSearching_ = false; 471 if (matchindex != DONE) { 472 return matchindex; 473 } 474 } else { 475 int startIdx = search_.beginIndex(); 476 if (index == startIdx || matchindex == startIdx) { 477 // not enough characters to match 478 setMatchNotFound(); 479 return DONE; 480 } 481 } 482 483 if (matchindex != DONE) { 484 if (search_.isOverlap_) { 485 matchindex += search_.matchedLength() - 2; 486 } 487 488 return handlePrevious(matchindex); 489 } 490 491 return handlePrevious(index); 492 } 493 494 /** 495 * Return true if the overlapping property has been set. 496 * See {@link #setOverlapping(boolean)} for more information. 497 * 498 * @see #setOverlapping 499 * @return true if the overlapping property has been set, false otherwise 500 * @stable ICU 2.8 501 */ isOverlapping()502 public boolean isOverlapping() { 503 return search_.isOverlap_; 504 } 505 506 //TODO: We may add APIs below to match ICU4C APIs 507 // isCanonicalMatch 508 509 /** 510 * Resets the iteration. 511 * Search will begin at the start of the text string if a forward 512 * iteration is initiated before a backwards iteration. Otherwise if a 513 * backwards iteration is initiated before a forwards iteration, the 514 * search will begin at the end of the text string. 515 * 516 * @stable ICU 2.0 517 */ reset()518 public void reset() { 519 setMatchNotFound(); 520 setIndex(search_.beginIndex()); 521 search_.isOverlap_ = false; 522 search_.isCanonicalMatch_ = false; 523 search_.elementComparisonType_ = ElementComparisonType.STANDARD_ELEMENT_COMPARISON; 524 search_.isForwardSearching_ = true; 525 search_.reset_ = true; 526 } 527 528 /** 529 * Returns the first index at which the string text matches the search 530 * pattern. The iterator is adjusted so that its current index (as 531 * returned by {@link #getIndex()}) is the match position if one 532 * 533 * was found. 534 * If a match is not found, {@link #DONE} will be returned and 535 * the iterator will be adjusted to the index {@link #DONE}. 536 * @return The character index of the first match, or 537 * {@link #DONE} if there are no matches. 538 * 539 * @see #getIndex 540 * @stable ICU 2.0 541 */ first()542 public final int first() { 543 int startIdx = search_.beginIndex(); 544 setIndex(startIdx); 545 return handleNext(startIdx); 546 } 547 548 /** 549 * Returns the first index equal or greater than <tt>position</tt> at which the 550 * string text matches the search pattern. The iterator is adjusted so 551 * that its current index (as returned by {@link #getIndex()}) is the 552 * match position if one was found. 553 * If a match is not found, {@link #DONE} will be returned and the 554 * iterator will be adjusted to the index {@link #DONE}. 555 * 556 * @param position where search if to start from. 557 * @return The character index of the first match following 558 * <tt>position</tt>, or {@link #DONE} if there are no matches. 559 * @throws IndexOutOfBoundsException If position is less than or greater 560 * than the text range for searching. 561 * @see #getIndex 562 * @stable ICU 2.0 563 */ following(int position)564 public final int following(int position) { 565 setIndex(position); 566 return handleNext(position); 567 } 568 569 /** 570 * Returns the last index in the target text at which it matches the 571 * search pattern. The iterator is adjusted so that its current index 572 * (as returned by {@link #getIndex}) is the match position if one was 573 * found. 574 * If a match is not found, {@link #DONE} will be returned and 575 * the iterator will be adjusted to the index {@link #DONE}. 576 * 577 * @return The index of the first match, or {@link #DONE} if 578 * there are no matches. 579 * @see #getIndex 580 * @stable ICU 2.0 581 */ last()582 public final int last() { 583 int endIdx = search_.endIndex(); 584 setIndex(endIdx); 585 return handlePrevious(endIdx); 586 } 587 588 /** 589 * Returns the first index less than <tt>position</tt> at which the string 590 * text matches the search pattern. The iterator is adjusted so that its 591 * current index (as returned by {@link #getIndex}) is the match 592 * position if one was found. If a match is not found, 593 * {@link #DONE} will be returned and the iterator will be 594 * adjusted to the index {@link #DONE} 595 * <p> 596 * When the overlapping option ({@link #isOverlapping}) is off, the last index of the 597 * result match is always less than <tt>position</tt>. 598 * When the overlapping option is on, the result match may span across 599 * <tt>position</tt>. 600 * 601 * @param position where search is to start from. 602 * @return The character index of the first match preceding 603 * <tt>position</tt>, or {@link #DONE} if there are 604 * no matches. 605 * @throws IndexOutOfBoundsException If position is less than or greater than 606 * the text range for searching 607 * @see #getIndex 608 * @stable ICU 2.0 609 */ preceding(int position)610 public final int preceding(int position) { 611 setIndex(position); 612 return handlePrevious(position); 613 } 614 615 // protected constructor ---------------------------------------------- 616 617 /** 618 * Protected constructor for use by subclasses. 619 * Initializes the iterator with the argument target text for searching 620 * and sets the BreakIterator. 621 * See class documentation for more details on the use of the target text 622 * and {@link BreakIterator}. 623 * 624 * @param target The target text to be searched. 625 * @param breaker A {@link BreakIterator} that is used to determine the 626 * boundaries of a logical match. This argument can be null. 627 * @exception IllegalArgumentException thrown when argument target is null, 628 * or of length 0 629 * @see BreakIterator 630 * @stable ICU 2.0 631 */ SearchIterator(CharacterIterator target, BreakIterator breaker)632 protected SearchIterator(CharacterIterator target, BreakIterator breaker) 633 { 634 if (target == null 635 || (target.getEndIndex() - target.getBeginIndex()) == 0) { 636 throw new IllegalArgumentException( 637 "Illegal argument target. " + 638 " Argument can not be null or of length 0"); 639 } 640 641 search_.setTarget(target); 642 search_.setBreakIter(breaker); 643 if (search_.breakIter() != null) { 644 search_.breakIter().setText((CharacterIterator)target.clone()); 645 } 646 search_.isOverlap_ = false; 647 search_.isCanonicalMatch_ = false; 648 search_.elementComparisonType_ = ElementComparisonType.STANDARD_ELEMENT_COMPARISON; 649 search_.isForwardSearching_ = true; 650 search_.reset_ = true; 651 search_.matchedIndex_ = DONE; 652 search_.setMatchedLength(0); 653 } 654 655 // protected methods -------------------------------------------------- 656 657 658 /** 659 * Sets the length of the most recent match in the target text. 660 * Subclasses' handleNext() and handlePrevious() methods should call this 661 * after they find a match in the target text. 662 * 663 * @param length new length to set 664 * @see #handleNext 665 * @see #handlePrevious 666 * @stable ICU 2.0 667 */ setMatchLength(int length)668 protected void setMatchLength(int length) 669 { 670 search_.setMatchedLength(length); 671 } 672 673 /** 674 * Abstract method which subclasses override to provide the mechanism 675 * for finding the next match in the target text. This allows different 676 * subclasses to provide different search algorithms. 677 * <p> 678 * If a match is found, the implementation should return the index at 679 * which the match starts and should call 680 * {@link #setMatchLength} with the number of characters 681 * in the target text that make up the match. If no match is found, the 682 * method should return {@link #DONE}. 683 * 684 * @param start The index in the target text at which the search 685 * should start. 686 * @return index at which the match starts, else if match is not found 687 * {@link #DONE} is returned 688 * @see #setMatchLength 689 * @stable ICU 2.0 690 */ handleNext(int start)691 protected abstract int handleNext(int start); 692 693 /** 694 * Abstract method which subclasses override to provide the mechanism for 695 * finding the previous match in the target text. This allows different 696 * subclasses to provide different search algorithms. 697 * <p> 698 * If a match is found, the implementation should return the index at 699 * which the match starts and should call 700 * {@link #setMatchLength} with the number of characters 701 * in the target text that make up the match. If no match is found, the 702 * method should return {@link #DONE}. 703 * 704 * @param startAt The index in the target text at which the search 705 * should start. 706 * @return index at which the match starts, else if match is not found 707 * {@link #DONE} is returned 708 * @see #setMatchLength 709 * @stable ICU 2.0 710 */ handlePrevious(int startAt)711 protected abstract int handlePrevious(int startAt); 712 713 /** 714 * @internal 715 * @deprecated This API is ICU internal only. 716 */ 717 @Deprecated 718 //TODO: This protected method is @stable 2.0 in ICU4C setMatchNotFound()719 protected void setMatchNotFound() { 720 search_.matchedIndex_ = DONE; 721 search_.setMatchedLength(0); 722 } 723 724 /** 725 * Option to control how collation elements are compared. 726 * The default value will be {@link #STANDARD_ELEMENT_COMPARISON}. 727 * <p> 728 * PATTERN_BASE_WEIGHT_IS_WILDCARD supports "asymmetric search" as described in 729 * <a href="http://www.unicode.org/reports/tr10/#Asymmetric_Search"> 730 * UTS #10 Unicode Collation Algorithm</a>, while ANY_BASE_WEIGHT_IS_WILDCARD 731 * supports a related option in which "unmarked" characters in either the 732 * pattern or the searched text are treated as wildcards that match marked or 733 * unmarked versions of the same character. 734 * 735 * @see #setElementComparisonType(ElementComparisonType) 736 * @see #getElementComparisonType() 737 * @stable ICU 53 738 */ 739 public enum ElementComparisonType { 740 /** 741 * Standard collation element comparison at the specified collator strength. 742 * 743 * @stable ICU 53 744 */ 745 STANDARD_ELEMENT_COMPARISON, 746 /** 747 * Collation element comparison is modified to effectively provide behavior 748 * between the specified strength and strength - 1. 749 * <p> 750 * Collation elements in the pattern that have the base weight for the specified 751 * strength are treated as "wildcards" that match an element with any other 752 * weight at that collation level in the searched text. For example, with a 753 * secondary-strength English collator, a plain 'e' in the pattern will match 754 * a plain e or an e with any diacritic in the searched text, but an e with 755 * diacritic in the pattern will only match an e with the same diacritic in 756 * the searched text. 757 * 758 * @stable ICU 53 759 */ 760 PATTERN_BASE_WEIGHT_IS_WILDCARD, 761 762 /** 763 * Collation element comparison is modified to effectively provide behavior 764 * between the specified strength and strength - 1. 765 * <p> 766 * Collation elements in either the pattern or the searched text that have the 767 * base weight for the specified strength are treated as "wildcards" that match 768 * an element with any other weight at that collation level. For example, with 769 * a secondary-strength English collator, a plain 'e' in the pattern will match 770 * a plain e or an e with any diacritic in the searched text, but an e with 771 * diacritic in the pattern will only match an e with the same diacritic or a 772 * plain e in the searched text. 773 * 774 * @stable ICU 53 775 */ 776 ANY_BASE_WEIGHT_IS_WILDCARD 777 } 778 779 /** 780 * Sets the collation element comparison type. 781 * <p> 782 * The default comparison type is {@link ElementComparisonType#STANDARD_ELEMENT_COMPARISON}. 783 * 784 * @see ElementComparisonType 785 * @see #getElementComparisonType() 786 * @stable ICU 53 787 */ setElementComparisonType(ElementComparisonType type)788 public void setElementComparisonType(ElementComparisonType type) { 789 search_.elementComparisonType_ = type; 790 } 791 792 /** 793 * Returns the collation element comparison type. 794 * 795 * @see ElementComparisonType 796 * @see #setElementComparisonType(ElementComparisonType) 797 * @stable ICU 53 798 */ getElementComparisonType()799 public ElementComparisonType getElementComparisonType() { 800 return search_.elementComparisonType_; 801 } 802 } 803