Clean up the Java side of the ICU interface a bit.
My original intention was just to add the missing "final" on a few classes,
but our BreakIterator implementation struck me as excessively bloated and
confusing.
Change-Id: I2d2dccafe8ec91124f3c83909c9ec647cc2d51e2
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/lang/UCharacter.java b/libcore/icu/src/main/java/com/ibm/icu4jni/lang/UCharacter.java
index 2839ac3..dc351f4 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/lang/UCharacter.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/lang/UCharacter.java
@@ -18,7 +18,7 @@
import java.lang.Character.UnicodeBlock;
-public class UCharacter {
+public final class UCharacter {
public static native boolean isDefined(int codePoint);
public static native boolean isDigit(int codePoint);
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/regex/NativeRegEx.java b/libcore/icu/src/main/java/com/ibm/icu4jni/regex/NativeRegEx.java
index bdfff5b..789c75b 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/regex/NativeRegEx.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/regex/NativeRegEx.java
@@ -16,7 +16,7 @@
package com.ibm.icu4jni.regex;
-public class NativeRegEx {
+public final class NativeRegEx {
/**
* Opens (compiles) an ICU regular expression.
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/text/BreakIterator.java b/libcore/icu/src/main/java/com/ibm/icu4jni/text/BreakIterator.java
deleted file mode 100644
index aa925aa..0000000
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/text/BreakIterator.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.ibm.icu4jni.text;
-
-import com.ibm.icu4jni.util.Resources;
-import java.text.CharacterIterator;
-import java.text.StringCharacterIterator;
-import java.util.Locale;
-
-public abstract class BreakIterator implements Cloneable
-{
- protected static final int BI_CHAR_INSTANCE = 1;
- protected static final int BI_WORD_INSTANCE = 2;
- protected static final int BI_LINE_INSTANCE = 3;
- protected static final int BI_SENT_INSTANCE = 4;
-
- protected int type = 0;
-
- public static Locale[] getAvailableLocales() {
- return Resources.localesFromStrings(NativeBreakIterator.getAvailableLocalesImpl());
- }
-
- public static BreakIterator getCharacterInstance() {
- int iter = NativeBreakIterator.getCharacterInstanceImpl("");
- return new RuleBasedBreakIterator(iter, BI_CHAR_INSTANCE);
- }
-
- public static BreakIterator getCharacterInstance(Locale where) {
- int iter = NativeBreakIterator.getCharacterInstanceImpl(where.toString());
- return new RuleBasedBreakIterator(iter, BI_CHAR_INSTANCE);
- }
-
- public static BreakIterator getLineInstance() {
- int iter = NativeBreakIterator.getLineInstanceImpl("");
- return new RuleBasedBreakIterator(iter, BI_LINE_INSTANCE);
- }
-
- public static BreakIterator getLineInstance(Locale where) {
- int iter = NativeBreakIterator.getLineInstanceImpl(where.toString());
- return new RuleBasedBreakIterator(iter, BI_LINE_INSTANCE);
- }
-
- public static BreakIterator getSentenceInstance() {
- int iter = NativeBreakIterator.getSentenceInstanceImpl("");
- return new RuleBasedBreakIterator(iter, BI_SENT_INSTANCE);
- }
-
- public static BreakIterator getSentenceInstance(Locale where) {
- int iter = NativeBreakIterator.getSentenceInstanceImpl(where.toString());
- return new RuleBasedBreakIterator(iter, BI_SENT_INSTANCE);
- }
-
- public static BreakIterator getWordInstance() {
- int iter = NativeBreakIterator.getWordInstanceImpl("");
- return new RuleBasedBreakIterator(iter, BI_WORD_INSTANCE);
- }
-
- public static BreakIterator getWordInstance(Locale where) {
- int iter = NativeBreakIterator.getWordInstanceImpl(where.toString());
- return new RuleBasedBreakIterator(iter, BI_WORD_INSTANCE);
- }
-
- public void setText(String newText) {
- setText(new StringCharacterIterator(newText));
- }
-
- public abstract boolean isBoundary(int offset);
-
- public abstract int preceding(int offset);
-
- public abstract Object clone();
-
- public abstract int current();
-
- public abstract int first();
-
- public abstract int following(int offset);
-
- public abstract CharacterIterator getText();
-
- public abstract int last();
-
- public abstract int next(int n);
-
- public abstract int next();
-
- public abstract int previous();
-
- public abstract void setText(CharacterIterator newText);
-
-}
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/text/NativeBreakIterator.java b/libcore/icu/src/main/java/com/ibm/icu4jni/text/NativeBreakIterator.java
index e318e47..161f542 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/text/NativeBreakIterator.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/text/NativeBreakIterator.java
@@ -16,39 +16,146 @@
package com.ibm.icu4jni.text;
-final class NativeBreakIterator {
- private NativeBreakIterator() {
+import com.ibm.icu4jni.util.Resources;
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.Locale;
+
+public final class NativeBreakIterator implements Cloneable {
+ // Acceptable values for the 'type' field.
+ private static final int BI_CHAR_INSTANCE = 1;
+ private static final int BI_WORD_INSTANCE = 2;
+ private static final int BI_LINE_INSTANCE = 3;
+ private static final int BI_SENT_INSTANCE = 4;
+
+ private final int addr;
+ private final int type;
+ private CharacterIterator charIter;
+
+ private NativeBreakIterator(int iterAddr, int type) {
+ this.addr = iterAddr;
+ this.type = type;
+ this.charIter = new StringCharacterIterator("");
}
- static native String[] getAvailableLocalesImpl();
+ @Override
+ public Object clone() {
+ int cloneAddr = cloneImpl(this.addr);
+ NativeBreakIterator clone = new NativeBreakIterator(cloneAddr, this.type);
+ // The RI doesn't clone the CharacterIterator.
+ clone.charIter = this.charIter;
+ return clone;
+ }
- static native int getCharacterInstanceImpl(String locale);
-
- static native int getWordInstanceImpl(String locale);
-
- static native int getLineInstanceImpl(String locale);
-
- static native int getSentenceInstanceImpl(String locale);
+ @Override
+ public boolean equals(Object object) {
+ if (object == null || !(object instanceof NativeBreakIterator)) {
+ return false;
+ }
+ // TODO: is this sufficient? shouldn't we be checking the underlying rules?
+ NativeBreakIterator rhs = (NativeBreakIterator) object;
+ return type == rhs.type && charIter.equals(rhs.charIter);
+ }
- static native void closeBreakIteratorImpl(int biaddress);
-
- static native void setTextImpl(int biaddress, String text);
-
- static native int cloneImpl(int biaddress);
-
- static native int precedingImpl(int biaddress, int offset);
+ @Override
+ public int hashCode() {
+ return 42; // No-one uses BreakIterator as a hash key.
+ }
- static native boolean isBoundaryImpl(int biaddress, int offset);
+ @Override
+ protected void finalize() {
+ closeBreakIteratorImpl(this.addr);
+ }
- static native int nextImpl(int biaddress, int n);
+ public int current() {
+ return currentImpl(this.addr);
+ }
- static native int previousImpl(int biaddress);
+ public int first() {
+ return firstImpl(this.addr);
+ }
- static native int currentImpl(int biaddress);
+ public int following(int offset) {
+ return followingImpl(this.addr, offset);
+ }
- static native int firstImpl(int biaddress);
+ public CharacterIterator getText() {
+ int newLoc = currentImpl(this.addr);
+ this.charIter.setIndex(newLoc);
+ return this.charIter;
+ }
- static native int followingImpl(int biaddress, int offset);
+ public int last() {
+ return lastImpl(this.addr);
+ }
- static native int lastImpl(int biaddress);
+ public int next(int n) {
+ return nextImpl(this.addr, n);
+ }
+
+ public int next() {
+ return nextImpl(this.addr, 1);
+ }
+
+ public int previous() {
+ return previousImpl(this.addr);
+ }
+
+ public void setText(CharacterIterator newText) {
+ this.charIter = newText;
+ StringBuilder sb = new StringBuilder();
+ for (char c = newText.first(); c != CharacterIterator.DONE; c = newText.next()) {
+ sb.append(c);
+ }
+ setTextImpl(this.addr, sb.toString());
+ }
+
+ public void setText(String newText) {
+ setText(new StringCharacterIterator(newText));
+ }
+
+ public boolean isBoundary(int offset) {
+ return isBoundaryImpl(this.addr, offset);
+ }
+
+ public int preceding(int offset) {
+ return precedingImpl(this.addr, offset);
+ }
+
+ public static Locale[] getAvailableLocales() {
+ return Resources.localesFromStrings(getAvailableLocalesImpl());
+ }
+
+ public static NativeBreakIterator getCharacterInstance(Locale where) {
+ return new NativeBreakIterator(getCharacterInstanceImpl(where.toString()), BI_CHAR_INSTANCE);
+ }
+
+ public static NativeBreakIterator getLineInstance(Locale where) {
+ return new NativeBreakIterator(getLineInstanceImpl(where.toString()), BI_LINE_INSTANCE);
+ }
+
+ public static NativeBreakIterator getSentenceInstance(Locale where) {
+ return new NativeBreakIterator(getSentenceInstanceImpl(where.toString()), BI_SENT_INSTANCE);
+ }
+
+ public static NativeBreakIterator getWordInstance(Locale where) {
+ return new NativeBreakIterator(getWordInstanceImpl(where.toString()), BI_WORD_INSTANCE);
+ }
+
+ private static native String[] getAvailableLocalesImpl();
+ private static native int getCharacterInstanceImpl(String locale);
+ private static native int getWordInstanceImpl(String locale);
+ private static native int getLineInstanceImpl(String locale);
+ private static native int getSentenceInstanceImpl(String locale);
+ private static native void closeBreakIteratorImpl(int addr);
+ private static native void setTextImpl(int addr, String text);
+ private static native int cloneImpl(int addr);
+ private static native int precedingImpl(int addr, int offset);
+ private static native boolean isBoundaryImpl(int addr, int offset);
+ private static native int nextImpl(int addr, int n);
+ private static native int previousImpl(int addr);
+ private static native int currentImpl(int addr);
+ private static native int firstImpl(int addr);
+ private static native int followingImpl(int addr, int offset);
+ private static native int lastImpl(int addr);
}
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java b/libcore/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java
index d46c2ec..6f751d5 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java
@@ -31,7 +31,7 @@
import java.util.Currency;
import java.util.Locale;
-public class NativeDecimalFormat {
+public final class NativeDecimalFormat {
/**
* Constants corresponding to the native type UNumberFormatSymbol, for setSymbol.
*/
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/text/RuleBasedBreakIterator.java b/libcore/icu/src/main/java/com/ibm/icu4jni/text/RuleBasedBreakIterator.java
deleted file mode 100644
index e532ac4..0000000
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/text/RuleBasedBreakIterator.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.ibm.icu4jni.text;
-
-import java.text.CharacterIterator;
-import java.text.StringCharacterIterator;
-
-public class RuleBasedBreakIterator extends BreakIterator {
-
- private CharacterIterator charIter;
-
- private int addr;
-
- RuleBasedBreakIterator(int iterAddr, int type) {
- this.addr = iterAddr;
- this.type = type;
- this.charIter = new StringCharacterIterator("");
- }
-
- @Override
- public Object clone() {
- int cloneAddr = NativeBreakIterator.cloneImpl(this.addr);
- RuleBasedBreakIterator rbbi =
- new RuleBasedBreakIterator(cloneAddr, this.type);
-
- rbbi.charIter = this.charIter;
-
- return rbbi;
- }
-
- @Override
- public boolean equals(Object object) {
- if(object == null) {
- return false;
- }
-
- if(!(object instanceof RuleBasedBreakIterator)) {
- return false;
- }
-
- CharacterIterator iter = ((RuleBasedBreakIterator) object).charIter;
-
- boolean result = this.type == ((RuleBasedBreakIterator) object).type;
-
- return result && iter.equals(this.charIter);
- }
-
- @Override
- public int hashCode() {
- return 42; // No-one uses RuleBasedBreakIterator as a hash key.
- }
-
- @Override
- public int current() {
- return NativeBreakIterator.currentImpl(this.addr);
- }
-
- @Override
- public int first() {
- return NativeBreakIterator.firstImpl(this.addr);
- }
-
- @Override
- public int following(int offset) {
- return NativeBreakIterator.followingImpl(this.addr, offset);
- }
-
- @Override
- public CharacterIterator getText() {
- int newLoc = NativeBreakIterator.currentImpl(this.addr);
- this.charIter.setIndex(newLoc);
- return this.charIter;
- }
-
- @Override
- public int last() {
- return NativeBreakIterator.lastImpl(this.addr);
- }
-
- @Override
- public int next(int n) {
- return NativeBreakIterator.nextImpl(this.addr, n);
- }
-
- @Override
- public int next() {
- return NativeBreakIterator.nextImpl(this.addr, 1);
- }
-
- @Override
- public int previous() {
- return NativeBreakIterator.previousImpl(this.addr);
- }
-
- @Override
- public void setText(CharacterIterator newText) {
- this.charIter = newText;
-
- StringBuilder sb = new StringBuilder();
-
- char c = newText.first();
- while(c != CharacterIterator.DONE) {
- sb.append(c);
- c = newText.next();
- }
-
- NativeBreakIterator.setTextImpl(this.addr, sb.toString());
- }
-
- protected void finalize() {
- NativeBreakIterator.closeBreakIteratorImpl(this.addr);
- }
-
- @Override
- public boolean isBoundary(int offset) {
- return NativeBreakIterator.isBoundaryImpl(this.addr, offset);
- }
-
- @Override
- public int preceding(int offset) {
- return NativeBreakIterator.precedingImpl(this.addr, offset);
- }
-
-}
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/util/LocaleData.java b/libcore/icu/src/main/java/com/ibm/icu4jni/util/LocaleData.java
index 87f9bc2..109183d 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/util/LocaleData.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/util/LocaleData.java
@@ -26,7 +26,7 @@
* in the case of arrays. If you ever expose any of these things to user code, you must give
* them a clone rather than the original.
*/
-public class LocaleData {
+public final class LocaleData {
public Integer firstDayOfWeek;
public Integer minimalDaysInFirstWeek;
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java b/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java
index 4a91d62..aae2ff4 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java
@@ -31,7 +31,7 @@
*
* TODO: move the LocaleData stuff into LocaleData and rename this class.
*/
-public class Resources {
+public final class Resources {
// A cache for the locale-specific data.
private static final HashMap<String, LocaleData> localeDataCache =
new HashMap<String, LocaleData>();
diff --git a/libcore/text/src/main/java/java/text/BreakIterator.java b/libcore/text/src/main/java/java/text/BreakIterator.java
index 78870f0..55ef31d 100644
--- a/libcore/text/src/main/java/java/text/BreakIterator.java
+++ b/libcore/text/src/main/java/java/text/BreakIterator.java
@@ -21,8 +21,8 @@
package java.text;
+import com.ibm.icu4jni.text.NativeBreakIterator;
import java.util.Locale;
-
import org.apache.harmony.text.internal.nls.Messages;
/**
@@ -241,7 +241,7 @@
private static final int SHORT_LENGTH = 2;
// the wrapped ICU implementation
- com.ibm.icu4jni.text.BreakIterator wrapped;
+ NativeBreakIterator wrapped;
/**
* Default constructor, just for invocation by a subclass.
@@ -253,7 +253,7 @@
/*
* wrapping constructor
*/
- BreakIterator(com.ibm.icu4jni.text.BreakIterator iterator) {
+ BreakIterator(NativeBreakIterator iterator) {
wrapped = iterator;
}
@@ -263,7 +263,7 @@
* @return all supported locales.
*/
public static Locale[] getAvailableLocales() {
- return com.ibm.icu4jni.text.BreakIterator.getAvailableLocales();
+ return NativeBreakIterator.getAvailableLocales();
}
/**
@@ -273,8 +273,7 @@
* @return a new instance of {@code BreakIterator} using the default locale.
*/
public static BreakIterator getCharacterInstance() {
- return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator
- .getCharacterInstance());
+ return getCharacterInstance(Locale.getDefault());
}
/**
@@ -286,12 +285,7 @@
* @return a new instance of {@code BreakIterator} using the given locale.
*/
public static BreakIterator getCharacterInstance(Locale where) {
- if (where == null) {
- throw new NullPointerException();
- }
-
- return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator
- .getCharacterInstance(where));
+ return new RuleBasedBreakIterator(NativeBreakIterator.getCharacterInstance(where));
}
/**
@@ -301,8 +295,7 @@
* @return a new instance of {@code BreakIterator} using the default locale.
*/
public static BreakIterator getLineInstance() {
- return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator
- .getLineInstance());
+ return getLineInstance(Locale.getDefault());
}
/**
@@ -315,12 +308,7 @@
* @throws NullPointerException if {@code where} is {@code null}.
*/
public static BreakIterator getLineInstance(Locale where) {
- if (where == null) {
- throw new NullPointerException();
- }
-
- return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator
- .getLineInstance(where));
+ return new RuleBasedBreakIterator(NativeBreakIterator.getLineInstance(where));
}
/**
@@ -330,8 +318,7 @@
* @return a new instance of {@code BreakIterator} using the default locale.
*/
public static BreakIterator getSentenceInstance() {
- return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator
- .getSentenceInstance());
+ return getSentenceInstance(Locale.getDefault());
}
/**
@@ -344,12 +331,7 @@
* @throws NullPointerException if {@code where} is {@code null}.
*/
public static BreakIterator getSentenceInstance(Locale where) {
- if (where == null) {
- throw new NullPointerException();
- }
-
- return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator
- .getSentenceInstance(where));
+ return new RuleBasedBreakIterator(NativeBreakIterator.getSentenceInstance(where));
}
/**
@@ -359,8 +341,7 @@
* @return a new instance of {@code BreakIterator} using the default locale.
*/
public static BreakIterator getWordInstance() {
- return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator
- .getWordInstance());
+ return getWordInstance(Locale.getDefault());
}
/**
@@ -373,12 +354,7 @@
* @throws NullPointerException if {@code where} is {@code null}.
*/
public static BreakIterator getWordInstance(Locale where) {
- if (where == null) {
- throw new NullPointerException();
- }
-
- return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator
- .getWordInstance(where));
+ return new RuleBasedBreakIterator(NativeBreakIterator.getWordInstance(where));
}
/**
@@ -521,7 +497,7 @@
public Object clone() {
try {
BreakIterator cloned = (BreakIterator) super.clone();
- cloned.wrapped = (com.ibm.icu4jni.text.BreakIterator) wrapped.clone();
+ cloned.wrapped = (NativeBreakIterator) wrapped.clone();
return cloned;
} catch (CloneNotSupportedException e) {
throw new AssertionError(e); // android-changed
diff --git a/libcore/text/src/main/java/java/text/RuleBasedBreakIterator.java b/libcore/text/src/main/java/java/text/RuleBasedBreakIterator.java
index 2ca6f9b..ed8a7c1 100644
--- a/libcore/text/src/main/java/java/text/RuleBasedBreakIterator.java
+++ b/libcore/text/src/main/java/java/text/RuleBasedBreakIterator.java
@@ -21,17 +21,20 @@
package java.text;
+import com.ibm.icu4jni.text.NativeBreakIterator;
+
/*
- * Default implementation of BreakIterator, wrap
- * com.ibm.icu4jni.text.RuleBasedBreakIterator
- *
+ * Default implementation of BreakIterator. Wraps com.ibm.icu4jni.text.NativeBreakIterator.
+ * We need this because BreakIterator.isBoundary and BreakIterator.preceding are non-abstract,
+ * and we don't have Java implementations of those methods (other than the current ones, which
+ * forward to the wrapped NativeBreakIterator).
*/
class RuleBasedBreakIterator extends BreakIterator {
/*
- * Wrapping construction
+ * Wrapping constructor.
*/
- RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator iterator) {
+ RuleBasedBreakIterator(NativeBreakIterator iterator) {
super(iterator);
}
@@ -201,9 +204,7 @@
@Override
public Object clone() {
RuleBasedBreakIterator cloned = (RuleBasedBreakIterator) super.clone();
- cloned.wrapped = (com.ibm.icu4jni.text.RuleBasedBreakIterator) wrapped
- .clone();
+ cloned.wrapped = (NativeBreakIterator) wrapped.clone();
return cloned;
}
-
}