diff --git a/icu4j/src/com/ibm/icu/dev/test/collator/CollationAPITest.java b/icu4j/src/com/ibm/icu/dev/test/collator/CollationAPITest.java index ef64ca4707..6d381593f1 100644 --- a/icu4j/src/com/ibm/icu/dev/test/collator/CollationAPITest.java +++ b/icu4j/src/com/ibm/icu/dev/test/collator/CollationAPITest.java @@ -103,21 +103,33 @@ public class CollationAPITest extends TestFmwk { String test2 = "abcda"; logln("Use tertiary comparison level testing ...."); + Object obj1 = test1; + Object obj2 = test2; + doAssert((col.compare(obj1, obj2) > 0), "Result should be \"Abcda\" != \"abcda\""); doAssert((!col.equals(test1, test2) ), "Result should be \"Abcda\" != \"abcda\""); doAssert((col.compare(test1, test2) > 0 ), "Result should be \"Abcda\" >>> \"abcda\""); col.setStrength(Collator.SECONDARY); logln("Use secondary comparison level testing ...."); + doAssert((col.compare(obj1, obj2) == 0), "Result should be \"Abcda\" == \"abcda\""); doAssert((col.equals(test1, test2) ), "Result should be \"Abcda\" == \"abcda\""); doAssert((col.compare(test1, test2) == 0), "Result should be \"Abcda\" == \"abcda\""); col.setStrength(Collator.PRIMARY); logln("Use primary comparison level testing ...."); + doAssert((col.compare(obj1, obj2) == 0 ), "Result should be \"Abcda\" == \"abcda\""); doAssert((col.equals(test1, test2) ), "Result should be \"Abcda\" == \"abcda\""); doAssert((col.compare(test1, test2) == 0 ), "Result should be \"Abcda\" == \"abcda\""); logln("The compare tests end."); + + Integer die = new Integer(1); + try { + col.compare(die, test1); + errln("Non-Strings should fail col.compare(Object, Object)"); + } catch (Exception e) { + } } /** @@ -559,4 +571,39 @@ public class CollationAPITest extends TestFmwk { errln("English tailored rules failed"); } } + + public void TestSafeClone() { + String test1 = "abCda"; + String test2 = "abcda"; + + // one default collator & two complex ones + RuleBasedCollator someCollators[] = { + (RuleBasedCollator)Collator.getInstance(Locale.ENGLISH), + (RuleBasedCollator)Collator.getInstance(Locale.KOREA), + (RuleBasedCollator)Collator.getInstance(Locale.JAPAN) + }; + RuleBasedCollator someClonedCollators[] = new RuleBasedCollator[3]; + + // change orig & clone & make sure they are independent + + for (int index = 0; index < someCollators.length; index ++) + { + try { + someClonedCollators[index] + = (RuleBasedCollator)someCollators[index].clone(); + } catch (CloneNotSupportedException e) { + errln("Error cloning collator"); + } + + someClonedCollators[index].setStrength(Collator.TERTIARY); + someCollators[index].setStrength(Collator.PRIMARY); + someClonedCollators[index].setCaseLevel(false); + someCollators[index].setCaseLevel(false); + + doAssert(someClonedCollators[index].compare(test1, test2) > 0, + "Result should be \"abCda\" >>> \"abcda\" "); + doAssert(someCollators[index].compare(test1, test2) == 0, + "Result should be \"abCda\" == \"abcda\" "); + } + } } \ No newline at end of file diff --git a/icu4j/src/com/ibm/icu/text/CollationElementIterator.java b/icu4j/src/com/ibm/icu/text/CollationElementIterator.java index 5064f135f9..6ac4bee931 100755 --- a/icu4j/src/com/ibm/icu/text/CollationElementIterator.java +++ b/icu4j/src/com/ibm/icu/text/CollationElementIterator.java @@ -841,6 +841,7 @@ public final class CollationElementIterator private void updateInternalState() { m_isCodePointHiragana_ = false; + m_buffer_.delete(0, m_buffer_.length()); m_bufferOffset_ = -1; m_CEBufferOffset_ = 0; m_CEBufferSize_ = 0; diff --git a/icu4j/src/com/ibm/icu/text/Collator.java b/icu4j/src/com/ibm/icu/text/Collator.java index 794fa97151..2bc3e64e32 100755 --- a/icu4j/src/com/ibm/icu/text/Collator.java +++ b/icu4j/src/com/ibm/icu/text/Collator.java @@ -5,14 +5,15 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/text/Collator.java,v $ -* $Date: 2002/08/01 21:09:16 $ -* $Revision: 1.10 $ +* $Date: 2002/08/07 20:54:56 $ +* $Revision: 1.11 $ * ******************************************************************************* */ package com.ibm.icu.text; import java.util.Locale; +import java.util.Comparator; /** *

Collator performs locale-sensitive string comparison. A concrete @@ -114,7 +115,7 @@ import java.util.Locale; * @since release 2.2, April 18 2002 * @draft 2.2 */ -public abstract class Collator +public abstract class Collator implements Comparator, Cloneable { // public data members --------------------------------------------------- @@ -360,6 +361,35 @@ public abstract class Collator return m_decomposition_; } + /** + *

+ * Compares the source text String to the target text String according to + * this Collator's rules, strength and decomposition mode. + * Returns an integer less than, + * equal to or greater than zero depending on whether the source String is + * less than, equal to or greater than the target String. See the Collator + * class description for an example of use. + *

+ * @param source the source String. + * @param target the target String. + * @return Returns an integer value. Value is less than zero if source is + * less than target, value is zero if source and target are equal, + * value is greater than zero if source is greater than target. + * @see CollationKey + * @see #getCollationKey + * @exception NullPointerException thrown if either arguments is null. + * IllegalArgumentException thrown if either source or target is + * not of the class String. + * @draft 2.2 + */ + public int compare(Object source, Object target) + { + if (!(source instanceof String) || !(target instanceof String)) { + throw new IllegalArgumentException("Arguments have to be of type String"); + } + return compare((String)source, (String)target); + } + // public other methods ------------------------------------------------- /** @@ -395,7 +425,7 @@ public abstract class Collator * @return 32 bit unique hash code */ public abstract int hashCode(); - + /** *

* Compares the source text String to the target text String according to diff --git a/icu4j/src/com/ibm/icu/text/RuleBasedCollator.java b/icu4j/src/com/ibm/icu/text/RuleBasedCollator.java index 2069a5072c..c7541560db 100755 --- a/icu4j/src/com/ibm/icu/text/RuleBasedCollator.java +++ b/icu4j/src/com/ibm/icu/text/RuleBasedCollator.java @@ -5,8 +5,8 @@ ******************************************************************************* * * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/text/RuleBasedCollator.java,v $ -* $Date: 2002/08/07 18:45:03 $ -* $Revision: 1.14 $ +* $Date: 2002/08/07 20:54:56 $ +* $Revision: 1.15 $ * ******************************************************************************* */ @@ -215,10 +215,25 @@ public final class RuleBasedCollator extends Collator builder.setRules(this); m_rules_ = rules; init(); + initUtilIterators(); } // public methods -------------------------------------------------------- + /** + * Clones the RuleBasedCollator + * @return a new instance of this RuleBasedCollator object + */ + public Object clone() throws CloneNotSupportedException + { + RuleBasedCollator result = (RuleBasedCollator)super.clone(); + // since all collation data in the RuleBasedCollator do not change + // we can safely assign the result.fields to this collator + result.initUtilIterators(); // let the new clone have their own util + // iterators + return result; + } + /** * Return a CollationElementIterator for the given String. * @see CollationElementIterator @@ -1331,6 +1346,7 @@ public final class RuleBasedCollator extends Collator */ RuleBasedCollator() { + initUtilIterators(); } // package private methods ----------------------------------------------- @@ -1489,8 +1505,8 @@ public final class RuleBasedCollator extends Collator */ RuleBasedCollator(Locale locale) // throws Exception { - ResourceBundle rb = ICULocaleData.getLocaleElements(locale); - + ResourceBundle rb = ICULocaleData.getLocaleElements(locale); + initUtilIterators(); if (rb != null) { try { Object elements = rb.getObject("CollationElements"); @@ -1680,6 +1696,14 @@ public final class RuleBasedCollator extends Collator */ private static final int CE_BUFFER_SIZE_ = 512; + /** + * Bunch of utility iterators + */ + private StringCharacterIterator m_srcUtilIter_; + private CollationElementIterator m_srcUtilColEIter_; + private StringCharacterIterator m_tgtUtilIter_; + private CollationElementIterator m_tgtUtilColEIter_; + // private methods ------------------------------------------------------- /** @@ -2531,18 +2555,12 @@ public final class RuleBasedCollator extends Collator { // Preparing the context objects for iterating over strings - StringCharacterIterator siter = new StringCharacterIterator(source, - textoffset, - source.length(), - textoffset); - CollationElementIterator scoleiter = new CollationElementIterator( - siter, this); - StringCharacterIterator titer = new StringCharacterIterator(target, - textoffset, - target.length(), - textoffset); - CollationElementIterator tcoleiter = new CollationElementIterator( - titer, this); + m_srcUtilIter_.setText(source); + m_srcUtilColEIter_.setText(m_srcUtilIter_); + m_srcUtilColEIter_.setExactOffset(textoffset); + m_tgtUtilIter_.setText(target); + m_tgtUtilColEIter_.setText(m_tgtUtilIter_); + m_tgtUtilColEIter_.setExactOffset(textoffset); // Non shifted primary processing is quite simple if (!m_isAlternateHandlingShifted_) { @@ -2551,14 +2569,14 @@ public final class RuleBasedCollator extends Collator int sorder = 0; // We fetch CEs until we hit a non ignorable primary or end. do { - sorder = scoleiter.next(); + sorder = m_srcUtilColEIter_.next(); append(cebuffer, cebuffersize, 0, sorder); sorder &= CE_PRIMARY_MASK_; } while (sorder == CollationElementIterator.IGNORABLE); int torder = 0; do { - torder = tcoleiter.next(); + torder = m_tgtUtilColEIter_.next(); append(cebuffer, cebuffersize, 1, torder); torder &= CE_PRIMARY_MASK_; } while (torder == CollationElementIterator.IGNORABLE); @@ -2571,9 +2589,9 @@ public final class RuleBasedCollator extends Collator break; } if (doHiragana4 && hiraganaresult == 0 - && scoleiter.m_isCodePointHiragana_ != - tcoleiter.m_isCodePointHiragana_) { - if (scoleiter.m_isCodePointHiragana_) { + && m_srcUtilColEIter_.m_isCodePointHiragana_ != + m_tgtUtilColEIter_.m_isCodePointHiragana_) { + if (m_srcUtilColEIter_.m_isCodePointHiragana_) { hiraganaresult = -1; } else { @@ -2592,9 +2610,11 @@ public final class RuleBasedCollator extends Collator } else { // shifted - do a slightly more complicated processing :) while (true) { - int sorder = getPrimaryShiftedCompareCE(scoleiter, lowestpvalue, + int sorder = getPrimaryShiftedCompareCE(m_srcUtilColEIter_, + lowestpvalue, cebuffer, cebuffersize, 0); - int torder = getPrimaryShiftedCompareCE(tcoleiter, lowestpvalue, + int torder = getPrimaryShiftedCompareCE(m_tgtUtilColEIter_, + lowestpvalue, cebuffer, cebuffersize, 1); if (sorder == torder) { if (cebuffer[0][cebuffersize[0] - 1] @@ -3256,4 +3276,14 @@ public final class RuleBasedCollator extends Collator m_isHiragana4_ = m_defaultIsHiragana4_; updateInternalState(); } + + /** + * Initializes utility iterators used by compare + */ + private final void initUtilIterators() { + m_srcUtilIter_ = new StringCharacterIterator(new String("")); + m_srcUtilColEIter_ = new CollationElementIterator(m_srcUtilIter_, this); + m_tgtUtilIter_ = new StringCharacterIterator(new String("")); + m_tgtUtilColEIter_ = new CollationElementIterator(m_tgtUtilIter_, this); + } }