1 /*
2  * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 package test.java.text.BreakIterator;
25 
26 import java.text.BreakIterator;
27 import java.text.CharacterIterator;
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.NoSuchElementException;
33 
34 public class MirroredBreakIterator extends BreakIterator {
35     private final List<Integer> boundaries;
36     private int charIndex;
37     private int boundaryIndex;
38 
MirroredBreakIterator(BreakIterator bi)39     MirroredBreakIterator(BreakIterator bi) {
40         List<Integer> b = new ArrayList<Integer>();
41         int i = bi.first();
42         charIndex = i;
43         for (; i != DONE; i = bi.next()) {
44             b.add(i);
45         }
46         boundaries = Collections.unmodifiableList(b);
47     }
48 
49     @Override
clone()50     public Object clone() {
51         try {
52             return super.clone();
53         } catch (Exception e) {
54             throw new RuntimeException("clone failed", e);
55         }
56     }
57 
58     @Override
first()59     public int first() {
60         return changeIndices(0);
61     }
62 
63     @Override
last()64     public int last() {
65         return changeIndices(boundaries.size() - 1);
66     }
67 
68     @Override
next(int n)69     public int next(int n) {
70         if (n == 0) {
71             return current();
72         }
73         int newBoundary = boundaryIndex + n;
74         if (newBoundary < 0) {
75             first();
76             return DONE;
77         }
78         if (newBoundary > lastBoundary()) {
79             last();
80             return DONE;
81         }
82         return changeIndices(newBoundary);
83     }
84 
85     @Override
next()86     public int next() {
87         if (boundaryIndex == lastBoundary()) {
88             return DONE;
89         }
90         return changeIndices(boundaryIndex + 1);
91     }
92 
93     @Override
previous()94     public int previous() {
95         if (boundaryIndex == 0) {
96             return DONE;
97         }
98         return changeIndices(boundaryIndex - 1);
99     }
100 
101     @Override
following(int offset)102     public int following(int offset) {
103         validateOffset(offset);
104         for (int b = 0; b <= lastBoundary(); b++) {
105             int i = boundaries.get(b);
106             if (i > offset) {
107                 return changeIndices(i, b);
108             }
109         }
110         return DONE;
111     }
112 
113     @Override
preceding(int offset)114     public int preceding(int offset) {
115         validateOffset(offset);
116         for (int b = lastBoundary(); b >= 0; b--) {
117             int i = boundaries.get(b);
118             if (i < offset) {
119                 return changeIndices(i, b);
120             }
121         }
122         return DONE;
123     }
124 
125     @Override
isBoundary(int offset)126     public boolean isBoundary(int offset) {
127         // Call the default impelementation in BreakIterator
128         return super.isBoundary(offset);
129     }
130 
131     @Override
current()132     public int current() {
133         return charIndex;
134     }
135 
136     @Override
getText()137     public CharacterIterator getText() {
138         throw new UnsupportedOperationException();
139     }
140 
141     @Override
setText(CharacterIterator newText)142     public void setText(CharacterIterator newText) {
143         throw new UnsupportedOperationException();
144     }
145 
lastBoundary()146     private int lastBoundary() {
147         return boundaries.size() - 1;
148     }
149 
changeIndices(int newCharIndex, int newBoundary)150     private int changeIndices(int newCharIndex, int newBoundary) {
151         boundaryIndex = newBoundary;
152         return charIndex = newCharIndex;
153     }
154 
changeIndices(int newBoundary)155     private int changeIndices(int newBoundary) {
156         try {
157             return changeIndices(boundaries.get(newBoundary), newBoundary);
158         } catch (IndexOutOfBoundsException e) {
159             throw new IllegalArgumentException(e);
160         }
161     }
162 
validateOffset(int offset)163     private void validateOffset(int offset) {
164         if (offset < boundaries.get(0) || offset > boundaries.get(lastBoundary())) {
165             throw new IllegalArgumentException();
166         }
167     }
168 }
169