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