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