]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_8_1_1/main/classes/core/src/com/ibm/icu/text/BreakIterator.java
Added flags.
[Dictionary.git] / jars / icu4j-4_8_1_1 / main / classes / core / src / com / ibm / icu / text / BreakIterator.java
1 /*
2  *******************************************************************************
3  * Copyright (C) 1996-2010, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7
8 package com.ibm.icu.text;
9
10 import java.lang.ref.SoftReference;
11 import java.text.CharacterIterator;
12 import java.text.StringCharacterIterator;
13 import java.util.Locale;
14 import java.util.MissingResourceException;
15
16 import com.ibm.icu.impl.ICUDebug;
17 import com.ibm.icu.util.ULocale;
18
19 /**
20  * {@icuenhanced java.text.BreakIterator}.{@icu _usage_}
21  *
22  * <p>A class that locates boundaries in text.  This class defines a protocol for
23  * objects that break up a piece of natural-language text according to a set
24  * of criteria.  Instances or subclasses of BreakIterator can be provided, for
25  * example, to break a piece of text into words, sentences, or logical characters
26  * according to the conventions of some language or group of languages.
27  *
28  * We provide five built-in types of BreakIterator:
29  * <ul><li>getTitleInstance() returns a BreakIterator that locates boundaries
30  * between title breaks.
31  * <li>getSentenceInstance() returns a BreakIterator that locates boundaries
32  * between sentences.  This is useful for triple-click selection, for example.
33  * <li>getWordInstance() returns a BreakIterator that locates boundaries between
34  * words.  This is useful for double-click selection or "find whole words" searches.
35  * This type of BreakIterator makes sure there is a boundary position at the
36  * beginning and end of each legal word.  (Numbers count as words, too.)  Whitespace
37  * and punctuation are kept separate from real words.
38  * <li>getLineInstance() returns a BreakIterator that locates positions where it is
39  * legal for a text editor to wrap lines.  This is similar to word breaking, but
40  * not the same: punctuation and whitespace are generally kept with words (you don't
41  * want a line to start with whitespace, for example), and some special characters
42  * can force a position to be considered a line-break position or prevent a position
43  * from being a line-break position.
44  * <li>getCharacterInstance() returns a BreakIterator that locates boundaries between
45  * logical characters.  Because of the structure of the Unicode encoding, a logical
46  * character may be stored internally as more than one Unicode code point.  (A with an
47  * umlaut may be stored as an a followed by a separate combining umlaut character,
48  * for example, but the user still thinks of it as one character.)  This iterator allows
49  * various processes (especially text editors) to treat as characters the units of text
50  * that a user would think of as characters, rather than the units of text that the
51  * computer sees as "characters".</ul>
52  *
53  * BreakIterator's interface follows an "iterator" model (hence the name), meaning it
54  * has a concept of a "current position" and methods like first(), last(), next(),
55  * and previous() that update the current position.  All BreakIterators uphold the
56  * following invariants:
57  * <ul><li>The beginning and end of the text are always treated as boundary positions.
58  * <li>The current position of the iterator is always a boundary position (random-
59  * access methods move the iterator to the nearest boundary position before or
60  * after the specified position, not _to_ the specified position).
61  * <li>DONE is used as a flag to indicate when iteration has stopped.  DONE is only
62  * returned when the current position is the end of the text and the user calls next(),
63  * or when the current position is the beginning of the text and the user calls
64  * previous().
65  * <li>Break positions are numbered by the positions of the characters that follow
66  * them.  Thus, under normal circumstances, the position before the first character
67  * is 0, the position after the first character is 1, and the position after the
68  * last character is 1 plus the length of the string.
69  * <li>The client can change the position of an iterator, or the text it analyzes,
70  * at will, but cannot change the behavior.  If the user wants different behavior, he
71  * must instantiate a new iterator.</ul>
72  *
73  * BreakIterator accesses the text it analyzes through a CharacterIterator, which makes
74  * it possible to use BreakIterator to analyze text in any text-storage vehicle that
75  * provides a CharacterIterator interface.
76  *
77  * <b>Note:</b>  Some types of BreakIterator can take a long time to create, and
78  * instances of BreakIterator are not currently cached by the system.  For
79  * optimal performance, keep instances of BreakIterator around as long as makes
80  * sense.  For example, when word-wrapping a document, don't create and destroy a
81  * new BreakIterator for each line.  Create one break iterator for the whole document
82  * (or whatever stretch of text you're wrapping) and use it to do the whole job of
83  * wrapping the text.
84  *
85   * <P>
86  * <strong>Examples</strong>:<P>
87  * Creating and using text boundaries
88  * <blockquote>
89  * <pre>
90  * public static void main(String args[]) {
91  *      if (args.length == 1) {
92  *          String stringToExamine = args[0];
93  *          //print each word in order
94  *          BreakIterator boundary = BreakIterator.getWordInstance();
95  *          boundary.setText(stringToExamine);
96  *          printEachForward(boundary, stringToExamine);
97  *          //print each sentence in reverse order
98  *          boundary = BreakIterator.getSentenceInstance(Locale.US);
99  *          boundary.setText(stringToExamine);
100  *          printEachBackward(boundary, stringToExamine);
101  *          printFirst(boundary, stringToExamine);
102  *          printLast(boundary, stringToExamine);
103  *      }
104  * }
105  * </pre>
106  * </blockquote>
107  *
108  * Print each element in order
109  * <blockquote>
110  * <pre>
111  * public static void printEachForward(BreakIterator boundary, String source) {
112  *     int start = boundary.first();
113  *     for (int end = boundary.next();
114  *          end != BreakIterator.DONE;
115  *          start = end, end = boundary.next()) {
116  *          System.out.println(source.substring(start,end));
117  *     }
118  * }
119  * </pre>
120  * </blockquote>
121  *
122  * Print each element in reverse order
123  * <blockquote>
124  * <pre>
125  * public static void printEachBackward(BreakIterator boundary, String source) {
126  *     int end = boundary.last();
127  *     for (int start = boundary.previous();
128  *          start != BreakIterator.DONE;
129  *          end = start, start = boundary.previous()) {
130  *         System.out.println(source.substring(start,end));
131  *     }
132  * }
133  * </pre>
134  * </blockquote>
135  *
136  * Print first element
137  * <blockquote>
138  * <pre>
139  * public static void printFirst(BreakIterator boundary, String source) {
140  *     int start = boundary.first();
141  *     int end = boundary.next();
142  *     System.out.println(source.substring(start,end));
143  * }
144  * </pre>
145  * </blockquote>
146  *
147  * Print last element
148  * <blockquote>
149  * <pre>
150  * public static void printLast(BreakIterator boundary, String source) {
151  *     int end = boundary.last();
152  *     int start = boundary.previous();
153  *     System.out.println(source.substring(start,end));
154  * }
155  * </pre>
156  * </blockquote>
157  *
158  * Print the element at a specified position
159  * <blockquote>
160  * <pre>
161  * public static void printAt(BreakIterator boundary, int pos, String source) {
162  *     int end = boundary.following(pos);
163  *     int start = boundary.previous();
164  *     System.out.println(source.substring(start,end));
165  * }
166  * </pre>
167  * </blockquote>
168  *
169  * Find the next word
170  * <blockquote>
171  * <pre>
172  * public static int nextWordStartAfter(int pos, String text) {
173  *     BreakIterator wb = BreakIterator.getWordInstance();
174  *     wb.setText(text);
175  *     int last = wb.following(pos);
176  *     int current = wb.next();
177  *     while (current != BreakIterator.DONE) {
178  *         for (int p = last; p < current; p++) {
179  *             if (Character.isLetter(text.charAt(p)))
180  *                 return last;
181  *         }
182  *         last = current;
183  *         current = wb.next();
184  *     }
185  *     return BreakIterator.DONE;
186  * }
187  * </pre>
188  * (The iterator returned by BreakIterator.getWordInstance() is unique in that
189  * the break positions it returns don't represent both the start and end of the
190  * thing being iterated over.  That is, a sentence-break iterator returns breaks
191  * that each represent the end of one sentence and the beginning of the next.
192  * With the word-break iterator, the characters between two boundaries might be a
193  * word, or they might be the punctuation or whitespace between two words.  The
194  * above code uses a simple heuristic to determine which boundary is the beginning
195  * of a word: If the characters between this boundary and the next boundary
196  * include at least one letter (this can be an alphabetical letter, a CJK ideograph,
197  * a Hangul syllable, a Kana character, etc.), then the text between this boundary
198  * and the next is a word; otherwise, it's the material between words.)
199  * </blockquote>
200  *
201  * @see CharacterIterator
202  * @stable ICU 2.0
203  *
204  */
205
206 public abstract class BreakIterator implements Cloneable
207 {
208
209     private static final boolean DEBUG = ICUDebug.enabled("breakiterator");
210
211     /**
212      * Default constructor.  There is no state that is carried by this abstract
213      * base class.
214      * @stable ICU 2.0
215      */
216     protected BreakIterator()
217     {
218     }
219
220     /**
221      * Clone method.  Creates another BreakIterator with the same behavior and
222      * current state as this one.
223      * @return The clone.
224      * @stable ICU 2.0
225      */
226     public Object clone()
227     {
228         try {
229             return super.clone();
230         }
231         catch (CloneNotSupportedException e) {
232             ///CLOVER:OFF
233             throw new IllegalStateException();
234             ///CLOVER:ON
235         }
236     }
237
238     /**
239      * DONE is returned by previous() and next() after all valid
240      * boundaries have been returned.
241      * @stable ICU 2.0
242      */
243     public static final int DONE = -1;
244
245     /**
246      * Return the first boundary position.  This is always the beginning
247      * index of the text this iterator iterates over.  For example, if
248      * the iterator iterates over a whole string, this function will
249      * always return 0.  This function also updates the iteration position
250      * to point to the beginning of the text.
251      * @return The character offset of the beginning of the stretch of text
252      * being broken.
253      * @stable ICU 2.0
254      */
255     public abstract int first();
256
257     /**
258      * Return the last boundary position.  This is always the "past-the-end"
259      * index of the text this iterator iterates over.  For example, if the
260      * iterator iterates over a whole string (call it "text"), this function
261      * will always return text.length().  This function also updated the
262      * iteration position to point to the end of the text.
263      * @return The character offset of the end of the stretch of text
264      * being broken.
265      * @stable ICU 2.0
266      */
267     public abstract int last();
268
269     /**
270      * Advances the specified number of steps forward in the text (a negative
271      * number, therefore, advances backwards).  If this causes the iterator
272      * to advance off either end of the text, this function returns DONE;
273      * otherwise, this function returns the position of the appropriate
274      * boundary.  Calling this function is equivalent to calling next() or
275      * previous() n times.
276      * @param n The number of boundaries to advance over (if positive, moves
277      * forward; if negative, moves backwards).
278      * @return The position of the boundary n boundaries from the current
279      * iteration position, or DONE if moving n boundaries causes the iterator
280      * to advance off either end of the text.
281      * @stable ICU 2.0
282      */
283     public abstract int next(int n);
284
285     /**
286      * Advances the iterator forward one boundary.  The current iteration
287      * position is updated to point to the next boundary position after the
288      * current position, and this is also the value that is returned.  If
289      * the current position is equal to the value returned by last(), or to
290      * DONE, this function returns DONE and sets the current position to
291      * DONE.
292      * @return The position of the first boundary position following the
293      * iteration position.
294      * @stable ICU 2.0
295      */
296     public abstract int next();
297
298     /**
299      * Advances the iterator backward one boundary.  The current iteration
300      * position is updated to point to the last boundary position before
301      * the current position, and this is also the value that is returned.  If
302      * the current position is equal to the value returned by first(), or to
303      * DONE, this function returns DONE and sets the current position to
304      * DONE.
305      * @return The position of the last boundary position preceding the
306      * iteration position.
307      * @stable ICU 2.0
308      */
309     public abstract int previous();
310
311     /**
312      * Sets the iterator's current iteration position to be the first
313      * boundary position following the specified position.  (Whether the
314      * specified position is itself a boundary position or not doesn't
315      * matter-- this function always moves the iteration position to the
316      * first boundary after the specified position.)  If the specified
317      * position is the past-the-end position, returns DONE.
318      * @param offset The character position to start searching from.
319      * @return The position of the first boundary position following
320      * "offset" (whether or not "offset" itself is a boundary position),
321      * or DONE if "offset" is the past-the-end offset.
322      * @stable ICU 2.0
323      */
324     public abstract int following(int offset);
325
326     /**
327      * Sets the iterator's current iteration position to be the last
328      * boundary position preceding the specified position.  (Whether the
329      * specified position is itself a boundary position or not doesn't
330      * matter-- this function always moves the iteration position to the
331      * last boundary before the specified position.)  If the specified
332      * position is the starting position, returns DONE.
333      * @param offset The character position to start searching from.
334      * @return The position of the last boundary position preceding
335      * "offset" (whether of not "offset" itself is a boundary position),
336      * or DONE if "offset" is the starting offset of the iterator.
337      * @stable ICU 2.0
338      */
339     public int preceding(int offset) {
340         // NOTE:  This implementation is here solely because we can't add new
341         // abstract methods to an existing class.  There is almost ALWAYS a
342         // better, faster way to do this.
343         int pos = following(offset);
344         while (pos >= offset && pos != DONE)
345             pos = previous();
346         return pos;
347     }
348
349     /**
350      * Return true if the specfied position is a boundary position.  If the
351      * function returns true, the current iteration position is set to the
352      * specified position; if the function returns false, the current
353      * iteration position is set as though following() had been called.
354      * @param offset the offset to check.
355      * @return True if "offset" is a boundary position.
356      * @stable ICU 2.0
357      */
358     public boolean isBoundary(int offset) {
359         // Again, this is the default implementation, which is provided solely because
360         // we couldn't add a new abstract method to an existing class.  The real
361         // implementations will usually need to do a little more work.
362         if (offset == 0) {
363             return true;
364         }
365         else
366             return following(offset - 1) == offset;
367     }
368
369     /**
370      * Return the iterator's current position.
371      * @return The iterator's current position.
372      * @stable ICU 2.0
373      */
374     public abstract int current();
375
376     /**
377      * Returns a CharacterIterator over the text being analyzed.
378      * For at least some subclasses of BreakIterator, this is a reference
379      * to the <b>actual iterator being used</b> by the BreakIterator,
380      * and therefore, this function's return value should be treated as
381      * <tt>const</tt>.  No guarantees are made about the current position
382      * of this iterator when it is returned.  If you need to move that
383      * position to examine the text, clone this function's return value first.
384      * @return A CharacterIterator over the text being analyzed.
385      * @stable ICU 2.0
386      */
387     public abstract CharacterIterator getText();
388
389     /**
390      * Sets the iterator to analyze a new piece of text.  The new
391      * piece of text is passed in as a String, and the current
392      * iteration position is reset to the beginning of the string.
393      * (The old text is dropped.)
394      * @param newText A String containing the text to analyze with
395      * this BreakIterator.
396      * @stable ICU 2.0
397      */
398     public void setText(String newText)
399     {
400         setText(new StringCharacterIterator(newText));
401     }
402
403     /**
404      * Sets the iterator to analyze a new piece of text.  The
405      * BreakIterator is passed a CharacterIterator through which
406      * it will access the text itself.  The current iteration
407      * position is reset to the CharacterIterator's start index.
408      * (The old iterator is dropped.)
409      * @param newText A CharacterIterator referring to the text
410      * to analyze with this BreakIterator (the iterator's current
411      * position is ignored, but its other state is significant).
412      * @stable ICU 2.0
413      */
414     public abstract void setText(CharacterIterator newText);
415
416     /**
417      * {@icu}
418      * @stable ICU 2.4
419      */
420     public static final int KIND_CHARACTER = 0;
421     /**
422      * {@icu}
423      * @stable ICU 2.4
424      */
425     public static final int KIND_WORD = 1;
426     /** 
427      * {@icu}
428      * @stable ICU 2.4
429      */
430     public static final int KIND_LINE = 2;
431     /** 
432      * {@icu}
433      * @stable ICU 2.4
434      */
435     public static final int KIND_SENTENCE = 3;
436     /** 
437      * {@icu}
438      * @stable ICU 2.4
439      */
440     public static final int KIND_TITLE = 4;
441
442     /**
443      * @since ICU 2.8
444      */
445     private static final int KIND_COUNT = 5;
446
447     private static final SoftReference<?>[] iterCache = new SoftReference<?>[5];
448
449     /**
450      * Returns a new instance of BreakIterator that locates word boundaries.
451      * This function assumes that the text being analyzed is in the default
452      * locale's language.
453      * @return An instance of BreakIterator that locates word boundaries.
454      * @stable ICU 2.0
455      */
456     public static BreakIterator getWordInstance()
457     {
458         return getWordInstance(ULocale.getDefault());
459     }
460
461     /**
462      * Returns a new instance of BreakIterator that locates word boundaries.
463      * @param where A locale specifying the language of the text to be
464      * analyzed.
465      * @return An instance of BreakIterator that locates word boundaries.
466      * @stable ICU 2.0
467      */
468     public static BreakIterator getWordInstance(Locale where)
469     {
470         return getBreakInstance(ULocale.forLocale(where), KIND_WORD);
471     }
472
473     /**
474      * {@icu} Returns a new instance of BreakIterator that locates word boundaries.
475      * @param where A locale specifying the language of the text to be
476      * analyzed.
477      * @return An instance of BreakIterator that locates word boundaries.
478      * @stable ICU 3.2
479      */
480     public static BreakIterator getWordInstance(ULocale where)
481     {
482         return getBreakInstance(where, KIND_WORD);
483     }
484
485     /**
486      * Returns a new instance of BreakIterator that locates legal line-
487      * wrapping positions.  This function assumes the text being broken
488      * is in the default locale's language.
489      * @return A new instance of BreakIterator that locates legal
490      * line-wrapping positions.
491      * @stable ICU 2.0
492      */
493     public static BreakIterator getLineInstance()
494     {
495         return getLineInstance(ULocale.getDefault());
496     }
497
498     /**
499      * Returns a new instance of BreakIterator that locates legal line-
500      * wrapping positions.
501      * @param where A Locale specifying the language of the text being broken.
502      * @return A new instance of BreakIterator that locates legal
503      * line-wrapping positions.
504      * @stable ICU 2.0
505      */
506     public static BreakIterator getLineInstance(Locale where)
507     {
508         return getBreakInstance(ULocale.forLocale(where), KIND_LINE);
509     }
510
511     /**
512      * {@icu} Returns a new instance of BreakIterator that locates legal line-
513      * wrapping positions.
514      * @param where A Locale specifying the language of the text being broken.
515      * @return A new instance of BreakIterator that locates legal
516      * line-wrapping positions.
517      * @stable ICU 3.2
518      */
519     public static BreakIterator getLineInstance(ULocale where)
520     {
521         return getBreakInstance(where, KIND_LINE);
522     }
523
524     /**
525      * Returns a new instance of BreakIterator that locates logical-character
526      * boundaries.  This function assumes that the text being analyzed is
527      * in the default locale's language.
528      * @return A new instance of BreakIterator that locates logical-character
529      * boundaries.
530      * @stable ICU 2.0
531      */
532     public static BreakIterator getCharacterInstance()
533     {
534         return getCharacterInstance(ULocale.getDefault());
535     }
536
537     /**
538      * Returns a new instance of BreakIterator that locates logical-character
539      * boundaries.
540      * @param where A Locale specifying the language of the text being analyzed.
541      * @return A new instance of BreakIterator that locates logical-character
542      * boundaries.
543      * @stable ICU 2.0
544      */
545     public static BreakIterator getCharacterInstance(Locale where)
546     {
547         return getBreakInstance(ULocale.forLocale(where), KIND_CHARACTER);
548     }
549
550     /**
551      * {@icu} Returns a new instance of BreakIterator that locates logical-character
552      * boundaries.
553      * @param where A Locale specifying the language of the text being analyzed.
554      * @return A new instance of BreakIterator that locates logical-character
555      * boundaries.
556      * @stable ICU 3.2
557      */
558     public static BreakIterator getCharacterInstance(ULocale where)
559     {
560         return getBreakInstance(where, KIND_CHARACTER);
561     }
562
563     /**
564      * Returns a new instance of BreakIterator that locates sentence boundaries.
565      * This function assumes the text being analyzed is in the default locale's
566      * language.
567      * @return A new instance of BreakIterator that locates sentence boundaries.
568      * @stable ICU 2.0
569      */
570     public static BreakIterator getSentenceInstance()
571     {
572         return getSentenceInstance(ULocale.getDefault());
573     }
574
575     /**
576      * Returns a new instance of BreakIterator that locates sentence boundaries.
577      * @param where A Locale specifying the language of the text being analyzed.
578      * @return A new instance of BreakIterator that locates sentence boundaries.
579      * @stable ICU 2.0
580      */
581     public static BreakIterator getSentenceInstance(Locale where)
582     {
583         return getBreakInstance(ULocale.forLocale(where), KIND_SENTENCE);
584     }
585
586     /**
587      * {@icu} Returns a new instance of BreakIterator that locates sentence boundaries.
588      * @param where A Locale specifying the language of the text being analyzed.
589      * @return A new instance of BreakIterator that locates sentence boundaries.
590      * @stable ICU 3.2
591      */
592     public static BreakIterator getSentenceInstance(ULocale where)
593     {
594         return getBreakInstance(where, KIND_SENTENCE);
595     }
596
597     /**
598      * {@icu} Returns a new instance of BreakIterator that locates title boundaries.
599      * This function assumes the text being analyzed is in the default locale's
600      * language. The iterator returned locates title boundaries as described for
601      * Unicode 3.2 only. For Unicode 4.0 and above title boundary iteration,
602      * please use a word boundary iterator. {@link #getWordInstance}
603      * @return A new instance of BreakIterator that locates title boundaries.
604      * @stable ICU 2.0
605      */
606     public static BreakIterator getTitleInstance()
607     {
608         return getTitleInstance(ULocale.getDefault());
609     }
610
611     /**
612      * {@icu} Returns a new instance of BreakIterator that locates title boundaries.
613      * The iterator returned locates title boundaries as described for
614      * Unicode 3.2 only. For Unicode 4.0 and above title boundary iteration,
615      * please use Word Boundary iterator.{@link #getWordInstance}
616      * @param where A Locale specifying the language of the text being analyzed.
617      * @return A new instance of BreakIterator that locates title boundaries.
618      * @stable ICU 2.0
619      */
620     public static BreakIterator getTitleInstance(Locale where)
621     {
622         return getBreakInstance(ULocale.forLocale(where), KIND_TITLE);
623     }
624
625     /**
626      * {@icu} Returns a new instance of BreakIterator that locates title boundaries.
627      * The iterator returned locates title boundaries as described for
628      * Unicode 3.2 only. For Unicode 4.0 and above title boundary iteration,
629      * please use Word Boundary iterator.{@link #getWordInstance}
630      * @param where A Locale specifying the language of the text being analyzed.
631      * @return A new instance of BreakIterator that locates title boundaries.
632      * @stable ICU 3.2
633 s     */
634     public static BreakIterator getTitleInstance(ULocale where)
635     {
636         return getBreakInstance(where, KIND_TITLE);
637     }
638
639     /**
640      * {@icu} Registers a new break iterator of the indicated kind, to use in the given
641      * locale.  Clones of the iterator will be returned if a request for a break iterator
642      * of the given kind matches or falls back to this locale.
643      * @param iter the BreakIterator instance to adopt.
644      * @param locale the Locale for which this instance is to be registered
645      * @param kind the type of iterator for which this instance is to be registered
646      * @return a registry key that can be used to unregister this instance
647      * @stable ICU 2.4
648      */
649     public static Object registerInstance(BreakIterator iter, Locale locale, int kind) {
650         return registerInstance(iter, ULocale.forLocale(locale), kind);
651     }
652
653     /**
654      * {@icu} Registers a new break iterator of the indicated kind, to use in the given
655      * locale.  Clones of the iterator will be returned if a request for a break iterator
656      * of the given kind matches or falls back to this locale.
657      * @param iter the BreakIterator instance to adopt.
658      * @param locale the Locale for which this instance is to be registered
659      * @param kind the type of iterator for which this instance is to be registered
660      * @return a registry key that can be used to unregister this instance
661      * @stable ICU 3.2
662      */
663     public static Object registerInstance(BreakIterator iter, ULocale locale, int kind) {
664         // If the registered object matches the one in the cache, then
665         // flush the cached object.
666         if (iterCache[kind] != null) {
667             BreakIteratorCache cache = (BreakIteratorCache) iterCache[kind].get();
668             if (cache != null) {
669                 if (cache.getLocale().equals(locale)) {
670                     iterCache[kind] = null;
671                 }
672             }
673         }
674         return getShim().registerInstance(iter, locale, kind);
675     }
676
677     /**
678      * {@icu} Unregisters a previously-registered BreakIterator using the key returned
679      * from the register call.  Key becomes invalid after this call and should not be used
680      * again.
681      * @param key the registry key returned by a previous call to registerInstance
682      * @return true if the iterator for the key was successfully unregistered
683      * @stable ICU 2.4
684      */
685     public static boolean unregister(Object key) {
686         if (key == null) {
687             throw new IllegalArgumentException("registry key must not be null");
688         }
689         // TODO: we don't do code coverage for the following lines
690         // because in getBreakInstance we always instantiate the shim,
691         // and test execution is such that we always instantiate a
692         // breakiterator before we get to the break iterator tests.
693         // this is for modularization, and we could remove the
694         // dependencies in getBreakInstance by rewriting part of the
695         // LocaleData code, or perhaps by accepting it into the
696         // module.
697         ///CLOVER:OFF
698         if (shim != null) {
699             // Unfortunately, we don't know what is being unregistered
700             // -- what `kind' and what locale -- so we flush all
701             // caches.  This is safe but inefficient if people are
702             // actively registering and unregistering.
703             for (int kind=0; kind<KIND_COUNT; ++kind) {
704                 iterCache[kind] = null;
705             }
706             return shim.unregister(key);
707         }
708         return false;
709         ///CLOVER:ON
710     }
711
712     // end of registration
713
714     /**
715      * Returns a particular kind of BreakIterator for a locale.
716      * Avoids writing a switch statement with getXYZInstance(where) calls.
717      * @internal
718      * @deprecated This API is ICU internal only.
719      */
720     public static BreakIterator getBreakInstance(ULocale where, int kind) {
721
722         if (iterCache[kind] != null) {
723             BreakIteratorCache cache = (BreakIteratorCache)iterCache[kind].get();
724             if (cache != null) {
725                 if (cache.getLocale().equals(where)) {
726                     return cache.createBreakInstance();
727                 }
728             }
729         }
730
731         // sigh, all to avoid linking in ICULocaleData...
732         BreakIterator result = getShim().createBreakIterator(where, kind);
733
734         BreakIteratorCache cache = new BreakIteratorCache(where, result);
735         iterCache[kind] = new SoftReference<BreakIteratorCache>(cache);
736         return result;
737     }
738
739
740     /**
741      * Returns a list of locales for which BreakIterators can be used.
742      * @return An array of Locales.  All of the locales in the array can
743      * be used when creating a BreakIterator.
744      * @stable ICU 2.6
745      */
746     public static synchronized Locale[] getAvailableLocales()
747     {
748         // to avoid linking ICULocaleData
749         return getShim().getAvailableLocales();
750     }
751
752     /**
753      * {@icu} Returns a list of locales for which BreakIterators can be used.
754      * @return An array of Locales.  All of the locales in the array can
755      * be used when creating a BreakIterator.
756      * @draft ICU 3.2 (retain)
757      * @provisional This API might change or be removed in a future release.
758      */
759     public static synchronized ULocale[] getAvailableULocales()
760     {
761         // to avoid linking ICULocaleData
762         return getShim().getAvailableULocales();
763     }
764
765     private static final class BreakIteratorCache {
766
767         private BreakIterator iter;
768         private ULocale where;
769
770         BreakIteratorCache(ULocale where, BreakIterator iter) {
771             this.where = where;
772             this.iter = (BreakIterator) iter.clone();
773         }
774
775         ULocale getLocale() {
776             return where;
777         }
778
779         BreakIterator createBreakInstance() {
780             return (BreakIterator) iter.clone();
781         }
782     }
783
784     static abstract class BreakIteratorServiceShim {
785         public abstract Object registerInstance(BreakIterator iter, ULocale l, int k);
786         public abstract boolean unregister(Object key);
787         public abstract Locale[] getAvailableLocales();
788         public abstract ULocale[] getAvailableULocales();
789         public abstract BreakIterator createBreakIterator(ULocale l, int k);
790     }
791
792     private static BreakIteratorServiceShim shim;
793     private static BreakIteratorServiceShim getShim() {
794         // Note: this instantiation is safe on loose-memory-model configurations
795         // despite lack of synchronization, since the shim instance has no state--
796         // it's all in the class init.  The worst problem is we might instantiate
797         // two shim instances, but they'll share the same state so that's ok.
798         if (shim == null) {
799             try {
800                 Class<?> cls = Class.forName("com.ibm.icu.text.BreakIteratorFactory");
801                 shim = (BreakIteratorServiceShim)cls.newInstance();
802             }
803             catch (MissingResourceException e)
804             {
805                 throw e;
806             }
807             catch (Exception e) {
808                 ///CLOVER:OFF
809                 if(DEBUG){
810                     e.printStackTrace();
811                 }
812                 throw new RuntimeException(e.getMessage());
813                 ///CLOVER:ON
814             }
815         }
816         return shim;
817     }
818
819     // -------- BEGIN ULocale boilerplate --------
820
821     /**
822      * {@icu} Returns the locale that was used to create this object, or null.
823      * This may may differ from the locale requested at the time of
824      * this object's creation.  For example, if an object is created
825      * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
826      * drawn from <tt>en</tt> (the <i>actual</i> locale), and
827      * <tt>en_US</tt> may be the most specific locale that exists (the
828      * <i>valid</i> locale).
829      *
830      * <p>Note: The <i>actual</i> locale is returned correctly, but the <i>valid</i>
831      * locale is not, in most cases.
832      * @param type type of information requested, either {@link
833      * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
834      * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
835      * @return the information specified by <i>type</i>, or null if
836      * this object was not constructed from locale data.
837      * @see com.ibm.icu.util.ULocale
838      * @see com.ibm.icu.util.ULocale#VALID_LOCALE
839      * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
840      * @draft ICU 2.8 (retain)
841      * @provisional This API might change or be removed in a future release.
842      */
843     public final ULocale getLocale(ULocale.Type type) {
844         return type == ULocale.ACTUAL_LOCALE ?
845             this.actualLocale : this.validLocale;
846     }
847
848     /**
849      * Set information about the locales that were used to create this
850      * object.  If the object was not constructed from locale data,
851      * both arguments should be set to null.  Otherwise, neither
852      * should be null.  The actual locale must be at the same level or
853      * less specific than the valid locale.  This method is intended
854      * for use by factories or other entities that create objects of
855      * this class.
856      * @param valid the most specific locale containing any resource
857      * data, or null
858      * @param actual the locale containing data used to construct this
859      * object, or null
860      * @see com.ibm.icu.util.ULocale
861      * @see com.ibm.icu.util.ULocale#VALID_LOCALE
862      * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
863      */
864     final void setLocale(ULocale valid, ULocale actual) {
865         // Change the following to an assertion later
866         if ((valid == null) != (actual == null)) {
867             ///CLOVER:OFF
868             throw new IllegalArgumentException();
869             ///CLOVER:ON
870         }
871         // Another check we could do is that the actual locale is at
872         // the same level or less specific than the valid locale.
873         this.validLocale = valid;
874         this.actualLocale = actual;
875     }
876
877     /**
878      * The most specific locale containing any resource data, or null.
879      * @see com.ibm.icu.util.ULocale
880      */
881     private ULocale validLocale;
882
883     /**
884      * The locale containing data used to construct this object, or
885      * null.
886      * @see com.ibm.icu.util.ULocale
887      */
888     private ULocale actualLocale;
889
890     // -------- END ULocale boilerplate --------
891 }